SSD1306 OLED display driver  1.7.8
This library is developed to control SSD1306/SSD1331/SSD1351/IL9163/PCD8554 RGB i2c/spi LED displays
ssd1306_1bit.c
1 /*
2  MIT License
3 
4  Copyright (c) 2016-2018, Alexey Dynda
5 
6  Permission is hereby granted, free of charge, to any person obtaining a copy
7  of this software and associated documentation files (the "Software"), to deal
8  in the Software without restriction, including without limitation the rights
9  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  copies of the Software, and to permit persons to whom the Software is
11  furnished to do so, subject to the following conditions:
12 
13  The above copyright notice and this permission notice shall be included in all
14  copies or substantial portions of the Software.
15 
16  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  SOFTWARE.
23 */
24 
28 
29 #include "ssd1306.h"
30 #include "ssd1306_fonts.h"
31 #include "lcd/lcd_common.h"
32 #include "intf/i2c/ssd1306_i2c.h"
33 #include "intf/spi/ssd1306_spi.h"
34 #include "intf/ssd1306_interface.h"
35 #include "ssd1306_hal/io.h"
36 
37 // TODO: remove
38 #include "lcd/ssd1306_commands.h"
39 
40 uint8_t s_ssd1306_invertByte = 0x00000000;
41 const uint8_t *s_font6x8 = &ssd1306xled_font6x8[4];
42 extern lcduint_t ssd1306_cursorX;
43 extern lcduint_t ssd1306_cursorY;
45 #ifdef CONFIG_SSD1306_UNICODE_ENABLE
46 extern uint8_t g_ssd1306_unicode;
47 #endif
48 
49 void ssd1306_fillScreen(uint8_t fill_Data)
50 {
51  fill_Data ^= s_ssd1306_invertByte;
52  ssd1306_lcd.set_block(0, 0, 0);
53  for(uint8_t m=(ssd1306_lcd.height >> 3); m>0; m--)
54  {
55  for(uint8_t n=ssd1306_lcd.width; n>0; n--)
56  {
57  ssd1306_lcd.send_pixels1(fill_Data);
58  }
60  }
62 }
63 
65 {
66  ssd1306_lcd.set_block(0, 0, 0);
67  for(uint8_t m=(ssd1306_lcd.height >> 3); m>0; m--)
68  {
69  for(uint8_t n=ssd1306_lcd.width; n>0; n--)
70  {
71  ssd1306_lcd.send_pixels1( s_ssd1306_invertByte );
72  }
74  }
76 }
77 
78 uint8_t ssd1306_printFixed(uint8_t xpos, uint8_t y, const char *ch, EFontStyle style)
79 {
80  uint8_t i, j=0;
81  uint8_t text_index = 0;
82  uint8_t page_offset = 0;
83  uint8_t x = xpos;
84  y >>= 3;
85  ssd1306_lcd.set_block(xpos, y, ssd1306_lcd.width - xpos);
86  for(;;)
87  {
88  uint8_t ldata;
89  if ((x > ssd1306_lcd.width - s_fixedFont.h.width) || (ch[j] == '\0'))
90  {
91  x = xpos;
92  y++;
93  if (y >= (ssd1306_lcd.height >> 3))
94  {
95  break;
96  }
97  page_offset++;
98  if (page_offset == s_fixedFont.pages)
99  {
100  text_index = j;
101  page_offset = 0;
102  if (ch[j] == '\0')
103  {
104  break;
105  }
106  }
107  else
108  {
109  j = text_index;
110  }
111  ssd1306_intf.stop();
112  ssd1306_lcd.set_block(xpos, y, ssd1306_lcd.width - xpos);
113  }
114  uint16_t unicode;
115  do
116  {
117  unicode = ssd1306_unicode16FromUtf8(ch[j]);
118  j++;
119  } while ( unicode == SSD1306_MORE_CHARS_REQUIRED );
120  SCharInfo char_info;
121  ssd1306_getCharBitmap(unicode, &char_info);
122  ldata = 0;
123  x += char_info.width + char_info.spacing;
124  if (char_info.height > page_offset * 8)
125  {
126  char_info.glyph += page_offset * char_info.width;
127  for( i = char_info.width; i>0; i--)
128  {
129  uint8_t data;
130  if ( style == STYLE_NORMAL )
131  {
132  data = pgm_read_byte(&char_info.glyph[0]);
133  }
134  else if ( style == STYLE_BOLD )
135  {
136  uint8_t temp = pgm_read_byte(&char_info.glyph[0]);
137  data = temp | ldata;
138  ldata = temp;
139  }
140  else
141  {
142  uint8_t temp = pgm_read_byte(&char_info.glyph[1]);
143  data = (temp & 0xF0) | ldata;
144  ldata = (temp & 0x0F);
145  }
146  ssd1306_lcd.send_pixels1(data^s_ssd1306_invertByte);
147  char_info.glyph++;
148  }
149  }
150  else
151  {
152  char_info.spacing += char_info.width;
153  }
154  for (i = 0; i < char_info.spacing; i++)
155  ssd1306_lcd.send_pixels1(s_ssd1306_invertByte);
156  }
157  ssd1306_intf.stop();
158  return j;
159 }
160 
161 uint8_t ssd1306_printFixed2x(uint8_t xpos, uint8_t y, const char ch[], EFontStyle style)
162 {
163  uint8_t i, j=0;
164  uint8_t text_index = 0;
165  uint8_t page_offset = 0;
166  uint8_t x = xpos;
167  y >>= 3;
168  ssd1306_lcd.set_block(xpos, y, ssd1306_lcd.width - xpos);
169  for(;;)
170  {
171  uint8_t c;
172  uint8_t ldata;
173  uint16_t offset;
174  if( (x > ssd1306_lcd.width - (s_fixedFont.h.width << 1)) || (ch[j] == '\0') )
175  {
176  x = xpos;
177  y++;
178  if (y >= (ssd1306_lcd.height >> 3))
179  {
180  break;
181  }
182  page_offset++;
183  if (page_offset == (s_fixedFont.pages << 1))
184  {
185  text_index = j;
186  page_offset = 0;
187  if (ch[j] == '\0')
188  {
189  break;
190  }
191  }
192  else
193  {
194  j = text_index;
195  }
196  ssd1306_intf.stop();
197  ssd1306_lcd.set_block(xpos, y, ssd1306_lcd.width - xpos);
198  }
199  c = ch[j];
200  if ( c >= 32 )
201  {
202  c -= 32;
203  }
204  ldata = 0;
205  offset = (c * s_fixedFont.pages + (page_offset >> 1)) * s_fixedFont.h.width;
206  for( i=s_fixedFont.h.width; i>0; i--)
207  {
208  uint8_t data;
209  if ( style == STYLE_NORMAL )
210  {
211  data = pgm_read_byte(&s_fixedFont.primary_table[offset]);
212  }
213  else if ( style == STYLE_BOLD )
214  {
215  uint8_t temp = pgm_read_byte(&s_fixedFont.primary_table[offset]);
216  data = temp | ldata;
217  ldata = temp;
218  }
219  else
220  {
221  uint8_t temp = pgm_read_byte(&s_fixedFont.primary_table[offset + 1]);
222  data = (temp & 0xF0) | ldata;
223  ldata = (temp & 0x0F);
224  }
225  if (page_offset & 1) data >>= 4;
226  data = ((data & 0x01) ? 0x03: 0x00) |
227  ((data & 0x02) ? 0x0C: 0x00) |
228  ((data & 0x04) ? 0x30: 0x00) |
229  ((data & 0x08) ? 0xC0: 0x00);
230  ssd1306_lcd.send_pixels1(data^s_ssd1306_invertByte);
231  ssd1306_lcd.send_pixels1(data^s_ssd1306_invertByte);
232  offset++;
233  }
234  x += (s_fixedFont.h.width << 1);
235  j++;
236  }
237  ssd1306_intf.stop();
238  return j;
239 }
240 
241 
242 uint8_t ssd1306_printFixedN(uint8_t xpos, uint8_t y, const char ch[], EFontStyle style, uint8_t factor)
243 {
244  uint8_t i, j=0;
245  uint8_t text_index = 0;
246  uint8_t page_offset = 0;
247  uint8_t x = xpos;
248  y >>= 3;
249  ssd1306_lcd.set_block(xpos, y, ssd1306_lcd.width - xpos);
250  for(;;)
251  {
252  uint8_t ldata;
253  if( (x > ssd1306_lcd.width - (s_fixedFont.h.width << factor)) || (ch[j] == '\0') )
254  {
255  x = xpos;
256  y++;
257  if (y >= (ssd1306_lcd.height >> 3))
258  {
259  break;
260  }
261  page_offset++;
262  if (page_offset == (s_fixedFont.pages << factor))
263  {
264  text_index = j;
265  page_offset = 0;
266  if (ch[j] == '\0')
267  {
268  break;
269  }
270  }
271  else
272  {
273  j = text_index;
274  }
275  ssd1306_intf.stop();
276  ssd1306_lcd.set_block(xpos, y, ssd1306_lcd.width - xpos);
277  }
278  uint16_t unicode;
279  do
280  {
281  unicode = ssd1306_unicode16FromUtf8(ch[j]);
282  j++;
283  } while ( unicode == SSD1306_MORE_CHARS_REQUIRED );
284  SCharInfo char_info;
285  ssd1306_getCharBitmap(unicode, &char_info);
286  ldata = 0;
287  x += ((char_info.width + char_info.spacing) << factor);
288  if (char_info.height > (page_offset >> factor) * 8)
289  {
290  char_info.glyph += (page_offset >> factor) * char_info.width;
291  for( i=char_info.width; i>0; i--)
292  {
293  uint8_t data;
294  if ( style == STYLE_NORMAL )
295  {
296  data = pgm_read_byte(char_info.glyph);
297  }
298  else if ( style == STYLE_BOLD )
299  {
300  uint8_t temp = pgm_read_byte(char_info.glyph);
301  data = temp | ldata;
302  ldata = temp;
303  }
304  else
305  {
306  uint8_t temp = pgm_read_byte(char_info.glyph+1);
307  data = (temp & 0xF0) | ldata;
308  ldata = (temp & 0x0F);
309  }
310  if ( factor > 0 )
311  {
312  uint8_t accum = 0;
313  uint8_t mask = ~((0xFF) << (1<<factor));
314  // N=0 -> right shift is always 0
315  // N=1 -> right shift goes through 0, 4
316  // N=2 -> right shift goes through 0, 2, 4, 6
317  // N=3 -> right shift goes through 0, 1, 2, 3, 4, 5, 6, 7
318  data >>= ((page_offset & ((1<<factor) - 1))<<(3-factor));
319  for (uint8_t idx = 0; idx < 1<<(3-factor); idx++)
320  {
321  accum |= (((data>>idx) & 0x01) ? (mask<<(idx<<factor)) : 0);
322  }
323  data = accum;
324  }
325  for (uint8_t z=(1<<factor); z>0; z--)
326  {
327  ssd1306_lcd.send_pixels1(data^s_ssd1306_invertByte);
328  }
329  char_info.glyph++;
330  }
331  }
332  else
333  {
334  char_info.spacing += char_info.width;
335  }
336  for (i = 0; i < (char_info.spacing << factor); i++)
337  ssd1306_lcd.send_pixels1(s_ssd1306_invertByte);
338  }
339  ssd1306_intf.stop();
340  return j;
341 }
342 
343 size_t ssd1306_write(uint8_t ch)
344 {
345  if (ch == '\r')
346  {
347  ssd1306_cursorX = 0;
348  return 0;
349  }
350  else if ( (ssd1306_cursorX > ssd1306_lcd.width - s_fixedFont.h.width) || (ch == '\n') )
351  {
352  ssd1306_cursorX = 0;
353  ssd1306_cursorY += s_fixedFont.h.height;
354  if ( ssd1306_cursorY > ssd1306_lcd.height - s_fixedFont.h.height )
355  {
356  ssd1306_cursorY = 0;
357  }
358  ssd1306_clearBlock(0, ssd1306_cursorY >> 3, ssd1306_lcd.width, s_fixedFont.h.height);
359  if (ch == '\n')
360  {
361  return 0;
362  }
363  }
364  uint16_t unicode = ssd1306_unicode16FromUtf8(ch);
365  if (unicode == SSD1306_MORE_CHARS_REQUIRED) return 0;
366  SCharInfo char_info;
367  ssd1306_getCharBitmap(unicode, &char_info);
368  ssd1306_drawBitmap( ssd1306_cursorX,
369  ssd1306_cursorY >> 3,
370  char_info.width,
371  char_info.height,
372  char_info.glyph );
373  ssd1306_cursorX += char_info.width + char_info.spacing;
374  return 1;
375 }
376 
377 size_t ssd1306_print(const char ch[])
378 {
379  size_t n = 0;
380  while (*ch)
381  {
382  n += ssd1306_write(*ch);
383  ch++;
384  }
385  return n;
386 }
387 
388 uint8_t ssd1306_charF6x8(uint8_t x, uint8_t y, const char ch[], EFontStyle style)
389 {
390  uint8_t i, j=0;
392  while(ch[j] != '\0')
393  {
394  uint8_t ldata;
395  uint8_t c = ch[j] - 32;
396  if ( c > 224 )
397  {
398  c = 0;
399  }
400  if(x > ssd1306_lcd.width - 6)
401  {
402  x=0;
403  y++;
404  }
405  ldata = 0;
406  for(i=0;i<6;i++)
407  {
408  uint8_t data;
409  if ( style == STYLE_NORMAL )
410  {
411  data = pgm_read_byte(&s_font6x8[c*6+i]);
412  }
413  else if ( style == STYLE_BOLD )
414  {
415  uint8_t temp = pgm_read_byte(&s_font6x8[c*6+i]);
416  data = temp | ldata;
417  ldata = temp;
418  }
419  else
420  {
421  uint8_t temp = pgm_read_byte(&s_font6x8[c*6+i + 1]);
422  data = (temp & 0xF0) | ldata;
423  ldata = (temp & 0x0F);
424  }
425  ssd1306_lcd.send_pixels1(data^s_ssd1306_invertByte);
426  }
427  x += 6;
428  j++;
429  }
430  ssd1306_intf.stop();
431  return j;
432 }
433 
434 uint8_t ssd1306_charF12x16(uint8_t xpos, uint8_t y, const char ch[], EFontStyle style)
435 {
436  uint8_t i, j=0;
437  uint8_t text_index = 0;
438  uint8_t odd = 0;
439  uint8_t x = xpos;
440  ssd1306_lcd.set_block(xpos, y, ssd1306_lcd.width - xpos);
441  for(;;)
442  {
443  uint8_t c;
444  uint8_t ldata;
445  if( (x > ssd1306_lcd.width-12) || (ch[j] == '\0') )
446  {
447  x = xpos;
448  y++;
449  if (y >= (ssd1306_lcd.height >> 3))
450  {
451  break;
452  }
453  if (odd)
454  {
455  text_index = j;
456  if (ch[j] == '\0')
457  {
458  break;
459  }
460  }
461  else
462  {
463  j = text_index;
464  }
465  odd = !odd;
466  ssd1306_intf.stop();
467  ssd1306_lcd.set_block(xpos, y, ssd1306_lcd.width - xpos);
468  }
469  c = ch[j] - 32;
470  if ( c > 224 )
471  {
472  c = 0;
473  }
474  ldata = 0;
475  for(i=0;i<6;i++)
476  {
477  uint8_t data;
478  if ( style == STYLE_NORMAL )
479  {
480  data = pgm_read_byte(&s_font6x8[c*6+i]);
481  }
482  else if ( style == STYLE_BOLD )
483  {
484  uint8_t temp = pgm_read_byte(&s_font6x8[c*6+i]);
485  data = temp | ldata;
486  ldata = temp;
487  }
488  else
489  {
490  uint8_t temp = pgm_read_byte(&s_font6x8[c*6+i + 1]);
491  data = (temp & 0xF0) | ldata;
492  ldata = (temp & 0x0F);
493  }
494  if (odd) data >>= 4;
495  data = ((data & 0x01) ? 0x03: 0x00) |
496  ((data & 0x02) ? 0x0C: 0x00) |
497  ((data & 0x04) ? 0x30: 0x00) |
498  ((data & 0x08) ? 0xC0: 0x00);
499  ssd1306_lcd.send_pixels1(data^s_ssd1306_invertByte);
500  ssd1306_lcd.send_pixels1(data^s_ssd1306_invertByte);
501  }
502  x += 12;
503  j++;
504  }
505  ssd1306_intf.stop();
506  return j;
507 }
508 
509 uint8_t ssd1306_charF6x8_eol(uint8_t left,
510  uint8_t y,
511  const char ch[],
512  EFontStyle style,
513  uint8_t right)
514 {
515  uint8_t len = ssd1306_charF6x8(left, y, ch, style);
516  uint8_t text_end_pos = len * 6 + left;
517  if (text_end_pos <= right)
518  {
519  ssd1306_clearBlock(text_end_pos, y, right - text_end_pos + 1, 8);
520  }
521  return len;
522 }
523 
524 void ssd1306_putPixel(uint8_t x, uint8_t y)
525 {
526  ssd1306_lcd.set_block(x, y >> 3, 1);
527  ssd1306_lcd.send_pixels1((1 << (y & 0x07))^s_ssd1306_invertByte);
528  ssd1306_intf.stop();
529 }
530 
531 void ssd1306_putPixels(uint8_t x, uint8_t y, uint8_t pixels)
532 {
533  ssd1306_lcd.set_block(x, y >> 3, 1);
534  ssd1306_lcd.send_pixels1(pixels^s_ssd1306_invertByte);
535  ssd1306_intf.stop();
536 }
537 
538 void ssd1306_putPixel_delayed(uint8_t x, uint8_t y, uint8_t complete)
539 {
540  static uint8_t lx = 0, ly = 0xFF;
541  static uint8_t pixels = 0;
542  if ((lx != x) || ((ly & 0xF8) != (y & 0xF8)) || (complete))
543  {
544  if (ly != 0xFF)
545  {
546  ssd1306_putPixels( lx, ly, pixels );
547  }
548  pixels = 0;
549  ly = 0xFF;
550  }
551  if ( !complete )
552  {
553  pixels |= (1 << (y & 0x07));
554  lx = x; ly = y;
555  }
556 }
557 
558 void ssd1306_drawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2)
559 {
560  lcduint_t dx = x1 > x2 ? (x1 - x2): (x2 - x1);
561  lcduint_t dy = y1 > y2 ? (y1 - y2): (y2 - y1);
562  lcduint_t err = 0;
563  if (dy > dx)
564  {
565  if (y1 > y2)
566  {
567  ssd1306_swap_data(x1, x2, uint8_t);
568  ssd1306_swap_data(y1, y2, uint8_t);
569  }
570  for(; y1<=y2; y1++)
571  {
572  err += dx;
573  if (err >= dy)
574  {
575  err -= dy;
576  x1 < x2 ? x1++: x1--;
577  }
578  ssd1306_putPixel_delayed( x1, y1, 0 );
579  }
580  ssd1306_putPixel_delayed( 0, 0, 1 );
581  }
582  else
583  {
584  if (x1 > x2)
585  {
586  ssd1306_swap_data(x1, x2, uint8_t);
587  ssd1306_swap_data(y1, y2, uint8_t);
588  }
589  for(; x1<=x2; x1++)
590  {
591  err += dy;
592  if (err >= dx)
593  {
594  err -= dx;
595  if (y1 < y2) y1++; else y1--;
596  }
597  ssd1306_putPixel( x1, y1 );
598  }
599  }
600 }
601 
602 void ssd1306_drawHLine(uint8_t x1, uint8_t y1, uint8_t x2)
603 {
604  ssd1306_lcd.set_block(x1, y1 >> 3, x2 - x1 + 1);
605  for (uint8_t x = x1; x <= x2; x++)
606  {
607  ssd1306_lcd.send_pixels1((1 << (y1 & 0x07))^s_ssd1306_invertByte);
608  }
609  ssd1306_intf.stop();
610 }
611 
612 void ssd1306_drawVLine(uint8_t x1, uint8_t y1, uint8_t y2)
613 {
614  uint8_t topPage = y1 >> 3;
615  uint8_t bottomPage = y2 >> 3;
616  uint8_t height = y2-y1;
617  uint8_t y;
618  ssd1306_lcd.set_block(x1, topPage, 1);
619  if (topPage == bottomPage)
620  {
621  ssd1306_lcd.send_pixels1( ((0xFF >> (0x07 - height)) << (y1 & 0x07))^s_ssd1306_invertByte );
622  ssd1306_intf.stop();
623  return;
624  }
625  ssd1306_lcd.send_pixels1( (0xFF << (y1 & 0x07))^s_ssd1306_invertByte );
626  for ( y = (topPage + 1); y <= (bottomPage - 1); y++)
627  {
629  ssd1306_lcd.send_pixels1( 0xFF^s_ssd1306_invertByte );
630  }
632  ssd1306_lcd.send_pixels1( (0xFF >> (0x07 - (y2 & 0x07)))^s_ssd1306_invertByte );
633  ssd1306_intf.stop();
634 }
635 
636 void ssd1306_drawRect(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2)
637 {
638  ssd1306_drawHLine(x1+1, y1, x2-1);
639  ssd1306_drawHLine(x1+1, y2, x2-1);
640  ssd1306_drawVLine(x1, y1, y2);
641  ssd1306_drawVLine(x2, y1, y2);
642 }
643 
644 void ssd1306_drawBufferFast(lcdint_t x, lcdint_t y, lcduint_t w, lcduint_t h, const uint8_t *buf)
645 {
646  uint8_t j;
647  ssd1306_lcd.set_block(x, y >> 3, w);
648  for(j=(h >> 3); j>0; j--)
649  {
651  buf+=w;
653  }
654  ssd1306_intf.stop();
655 }
656 
657 void ssd1306_drawBuffer(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *buf)
658 {
659  uint8_t i, j;
660  ssd1306_lcd.set_block(x, y, w);
661  for(j=(h >> 3); j>0; j--)
662  {
663  for(i=w;i>0;i--)
664  {
665  ssd1306_lcd.send_pixels1(s_ssd1306_invertByte^*buf++);
666  }
668  }
669  ssd1306_intf.stop();
670 }
671 
672 void ssd1306_drawBitmap(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *buf)
673 {
674  uint8_t i, j;
675  uint8_t remainder = (ssd1306_lcd.width - x) < w ? (w + x - ssd1306_lcd.width): 0;
676  w -= remainder;
677  ssd1306_lcd.set_block(x, y, w);
678  for(j=(h >> 3); j>0; j--)
679  {
680  for(i=w;i>0;i--)
681  {
682  ssd1306_lcd.send_pixels1(s_ssd1306_invertByte^pgm_read_byte(buf++));
683  }
684  buf += remainder;
686  }
687  ssd1306_intf.stop();
688 }
689 
690 void gfx_drawMonoBitmap(lcdint_t x, lcdint_t y, lcduint_t w, lcduint_t h, const uint8_t *buf)
691 {
692  lcduint_t origin_width = w;
693  uint8_t offset = y & 0x07;
694  uint8_t complexFlag = 0;
695  uint8_t mainFlag = 1;
696  uint8_t max_pages;
697  uint8_t pages;
698  lcduint_t i, j;
699  if (y + (lcdint_t)h <= 0) return;
700  if (y >= ssd1306_lcd.height) return;
701  if (x + (lcdint_t)w <= 0) return;
702  if (x >= ssd1306_lcd.width) return;
703  if (y < 0)
704  {
705  buf += ((lcduint_t)((-y) + 7) >> 3) * w;
706  h += y;
707  y = 0;
708  complexFlag = 1;
709  }
710  if (x < 0)
711  {
712  buf += -x;
713  w += x;
714  x = 0;
715  }
716  max_pages = (lcduint_t)(h + 15 - offset) >> 3;
717  if ((lcduint_t)((lcduint_t)y + h) > (lcduint_t)ssd1306_lcd.height)
718  {
719  h = (lcduint_t)(ssd1306_lcd.height - (lcduint_t)y);
720  }
721  if ((lcduint_t)((lcduint_t)x + w) > (lcduint_t)ssd1306_lcd.width)
722  {
723  w = (lcduint_t)(ssd1306_lcd.width - (lcduint_t)x);
724  }
725  pages = ((y + h - 1) >> 3) - (y >> 3) + 1;
726 
727  ssd1306_lcd.set_block(x, y >> 3, w);
728  for(j=0; j < pages; j++)
729  {
730  if ( j == max_pages - 1 ) mainFlag = !offset;
731  for( i=w; i > 0; i--)
732  {
733  uint8_t data = 0;
734  if ( mainFlag ) data |= (pgm_read_byte(buf) << offset);
735  if ( complexFlag ) data |= (pgm_read_byte(buf - origin_width) >> (8 - offset));
736  buf++;
737  ssd1306_lcd.send_pixels1(s_ssd1306_invertByte^data);
738  }
739  buf += origin_width - w;
740  complexFlag = offset;
742  }
743  ssd1306_intf.stop();
744 }
745 
746 
747 void ssd1306_clearBlock(uint8_t x, uint8_t y, uint8_t w, uint8_t h)
748 {
749  uint8_t i, j;
750  ssd1306_lcd.set_block(x, y, w);
751  for(j=(h >> 3); j>0; j--)
752  {
753  for(i=w;i>0;i--)
754  {
755  ssd1306_lcd.send_pixels1(s_ssd1306_invertByte);
756  }
758  }
759  ssd1306_intf.stop();
760 }
761 
762 
763 void ssd1306_drawSpriteEx(uint8_t x, uint8_t y, uint8_t w, const uint8_t *sprite)
764 {
765  uint8_t i;
766  ssd1306_lcd.set_block(x,y,w);
767  for(i=0;i<w;i++)
768  {
769  ssd1306_lcd.send_pixels1(s_ssd1306_invertByte^pgm_read_byte(&sprite[i]));
770  }
771  ssd1306_intf.stop();
772 }
773 
774 
776 {
777  uint8_t offsety = sprite->y & 0x7;
778  if (sprite->y < ssd1306_lcd.height)
779  {
780  ssd1306_lcd.set_block(sprite->x, sprite->y >> 3, sprite->w);
781  for (uint8_t i=0; i < sprite->w; i++)
782  {
783  ssd1306_lcd.send_pixels1( s_ssd1306_invertByte^(pgm_read_byte( &sprite->data[i] ) << offsety) );
784  }
785  ssd1306_intf.stop();
786  }
787  if (offsety && (sprite->y + 8 < ssd1306_lcd.height))
788  {
789  ssd1306_lcd.set_block(sprite->x, (sprite->y >> 3) + 1, sprite->w);
790  for (uint8_t i=0; i < sprite->w; i++)
791  {
792  ssd1306_lcd.send_pixels1( s_ssd1306_invertByte^(pgm_read_byte( &sprite->data[i] ) >> (8 - offsety)) );
793  }
794  ssd1306_intf.stop();
795  }
796  sprite->lx = sprite->x;
797  sprite->ly = sprite->y;
798 }
799 
800 
802 {
803  uint8_t posy = sprite->y >> 3;
804  uint8_t offsety = sprite->y & 0x7;
805  ssd1306_lcd.set_block(sprite->x, posy, sprite->w);
806  for (uint8_t i=sprite->w; i > 0; i--)
807  {
808  ssd1306_lcd.send_pixels1( s_ssd1306_invertByte );
809  }
810  ssd1306_intf.stop();
811  if (offsety)
812  {
813  ssd1306_lcd.set_block(sprite->x, posy + 1, sprite->w);
814  for (uint8_t i=sprite->w; i > 0; i--)
815  {
816  ssd1306_lcd.send_pixels1( s_ssd1306_invertByte );
817  }
818  }
819  ssd1306_intf.stop();
820 }
821 
822 
824 {
825  uint8_t y1 = sprite->ly >> 3;
826  uint8_t y2 = (sprite->ly + 7) >> 3;
827  if (sprite->ly < sprite->y)
828  y2 = min(y2, (uint8_t)((sprite->y >> 3) - 1));
829  else if (sprite->y + 8 > sprite->ly)
830  y1 = max(y1, (sprite->ly + 7) >> 3);
831  for(uint8_t y = y1; y <= y2; y++)
832  {
833  ssd1306_lcd.set_block(sprite->lx, y, sprite->w);
834  for(uint8_t x = sprite->w; x > 0; x--)
835  {
836  ssd1306_lcd.send_pixels1( s_ssd1306_invertByte );
837  }
838  ssd1306_intf.stop();
839  }
840  if (sprite->lx != sprite->x)
841  {
842  uint8_t x1 = sprite->lx;
843  uint8_t x2 = sprite->lx + sprite->w - 1;
844  if (sprite->x < sprite->lx)
845  x1 = max(x1, sprite->x + sprite->w);
846  else
847  x2 = min((uint8_t)(sprite->x - 1), x2);
848  for(uint8_t y = sprite->ly >> 3; y <= (sprite->ly + 7) >> 3; y++)
849  {
850  ssd1306_lcd.set_block(x1, y, x2 - x1 + 1 );
851  for(uint8_t x = x2 - x1 + 1; x > 0; x--)
852  {
853  ssd1306_lcd.send_pixels1( s_ssd1306_invertByte );
854  }
855  ssd1306_intf.stop();
856  }
857  }
858 }
859 
860 SPRITE ssd1306_createSprite(uint8_t x, uint8_t y, uint8_t w, const uint8_t *data)
861 {
862  return (SPRITE){x,y,w,x,y,data,NULL};
863 }
864 
865 void ssd1306_replaceSprite(SPRITE *sprite, const uint8_t *data)
866 {
867  sprite->data = data;
868 }
869 
871 {
872  s_ssd1306_invertByte = 0xFF;
873 }
874 
876 {
877  s_ssd1306_invertByte = 0x00;
878 }
879 
880 void ssd1306_setFont6x8(const uint8_t * progmemFont)
881 {
882  s_font6x8 = progmemFont + 4;
883 }
884 
void ssd1306_drawBuffer(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *buf)
Definition: ssd1306_1bit.c:657
uint8_t ssd1306_charF6x8(uint8_t x, uint8_t y, const char ch[], EFontStyle style)
Definition: ssd1306_1bit.c:388
void ssd1306_putPixels(uint8_t x, uint8_t y, uint8_t pixels)
Definition: ssd1306_1bit.c:531
uint8_t height
char height in pixels
void ssd1306_positiveMode()
Definition: ssd1306_1bit.c:875
const uint8_t * data
Pointer to PROGMEM data, representing sprite image.
SPRITE ssd1306_createSprite(uint8_t x, uint8_t y, uint8_t w, const uint8_t *data)
Definition: ssd1306_1bit.c:860
const uint8_t * primary_table
font chars bits
uint8_t ssd1306_printFixed2x(uint8_t xpos, uint8_t y, const char ch[], EFontStyle style)
Definition: ssd1306_1bit.c:161
void ssd1306_drawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2)
Definition: ssd1306_1bit.c:558
uint8_t ssd1306_printFixed(uint8_t xpos, uint8_t y, const char *ch, EFontStyle style)
Definition: ssd1306_1bit.c:78
void ssd1306_drawSprite(SPRITE *sprite)
Definition: ssd1306_1bit.c:775
uint8_t width
width in pixels
void ssd1306_drawRect(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2)
Definition: ssd1306_1bit.c:636
void(* set_block)(lcduint_t x, lcduint_t y, lcduint_t w)
Sets block in RAM of lcd display controller to write data to.
Definition: lcd_common.h:114
void ssd1306_fillScreen(uint8_t fill_Data)
Definition: ssd1306_1bit.c:49
unsigned int lcduint_t
Definition: io.h:65
void ssd1306_getCharBitmap(uint16_t ch, SCharInfo *info)
returns char data for currently set (active) font.
void ssd1306_eraseTrace(SPRITE *sprite)
Definition: ssd1306_1bit.c:823
void(* send_pixels_buffer1)(const uint8_t *buffer, uint16_t len)
Definition: lcd_common.h:135
void ssd1306_drawBitmap(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *buf)
Definition: ssd1306_1bit.c:672
const PROGMEM uint8_t ssd1306xled_font6x8[]
Definition: ssd1306_fonts.c:41
void(* send_pixels1)(uint8_t data)
Definition: lcd_common.h:128
uint8_t height
height in pixels
void gfx_drawMonoBitmap(lcdint_t x, lcdint_t y, lcduint_t w, lcduint_t h, const uint8_t *buf)
Definition: ssd1306_1bit.c:690
ssd1306_lcd_t ssd1306_lcd
Definition: lcd_common.c:32
size_t ssd1306_print(const char ch[])
Prints null-terminated string to display at current cursor position.
Definition: ssd1306_1bit.c:377
uint8_t ssd1306_charF12x16(uint8_t xpos, uint8_t y, const char ch[], EFontStyle style)
Definition: ssd1306_1bit.c:434
void ssd1306_eraseSprite(SPRITE *sprite)
Definition: ssd1306_1bit.c:801
void ssd1306_drawVLine(uint8_t x1, uint8_t y1, uint8_t y2)
Definition: ssd1306_1bit.c:612
ssd1306_interface_t ssd1306_intf
#define max(a, b)
uint8_t y
draw position Y on the screen
#define min(a, b)
lcduint_t height
Definition: lcd_common.h:97
uint8_t width
char width in pixels
void ssd1306_drawSpriteEx(uint8_t x, uint8_t y, uint8_t w, const uint8_t *sprite)
Definition: ssd1306_1bit.c:763
SFixedFontInfo s_fixedFont
Definition: tiler.h:44
SFontHeaderRecord h
record, containing information on font
uint8_t x
draw position X on the screen
const uint8_t * glyph
char data, located in progmem.
uint8_t ssd1306_printFixedN(uint8_t xpos, uint8_t y, const char ch[], EFontStyle style, uint8_t factor)
Definition: ssd1306_1bit.c:242
uint8_t w
sprite width
void ssd1306_drawHLine(uint8_t x1, uint8_t y1, uint8_t x2)
Definition: ssd1306_1bit.c:602
#define SSD1306_MORE_CHARS_REQUIRED
Definition: ssd1306_fonts.h:44
void(* next_page)(void)
Definition: lcd_common.h:122
uint8_t spacing
additional spaces after char in pixels
uint8_t lx
last draw position X on the screen
void ssd1306_clearBlock(uint8_t x, uint8_t y, uint8_t w, uint8_t h)
Definition: ssd1306_1bit.c:747
void ssd1306_setFont6x8(const uint8_t *progmemFont)
Definition: ssd1306_1bit.c:880
lcduint_t width
Definition: lcd_common.h:94
uint8_t ssd1306_charF6x8_eol(uint8_t left, uint8_t y, const char ch[], EFontStyle style, uint8_t right)
Definition: ssd1306_1bit.c:509
void ssd1306_clearScreen()
Definition: ssd1306_1bit.c:64
void ssd1306_replaceSprite(SPRITE *sprite, const uint8_t *data)
Definition: ssd1306_1bit.c:865
EFontStyle
void ssd1306_drawBufferFast(lcdint_t x, lcdint_t y, lcduint_t w, lcduint_t h, const uint8_t *buf)
Definition: ssd1306_1bit.c:644
uint8_t pages
height in pages (each page height is 8-pixels)
#define ssd1306_swap_data(a, b, type)
Definition: io.h:69
uint8_t ly
last draw position Y on the screen
void ssd1306_negativeMode()
Definition: ssd1306_1bit.c:870
void ssd1306_putPixel(uint8_t x, uint8_t y)
Definition: ssd1306_1bit.c:524
size_t ssd1306_write(uint8_t ch)
Prints single character to display at current cursor position.
Definition: ssd1306_1bit.c:343