SSD1306 OLED display driver  1.5.0
This library is developed to control SSD1306/SSD1331 RGB i2c/spi OLED displays and spi PCD8544 LED display
ssd1306_generic.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 "font6x8.h"
30 #include "ssd1306.h"
31 #include "lcd/lcd_common.h"
32 #include "i2c/ssd1306_i2c.h"
33 #include "spi/ssd1306_spi.h"
34 #include "intf/ssd1306_interface.h"
35 #include "hal/io.h"
36 
37 // TODO: remove
38 #include "lcd/ssd1306_commands.h"
39 
40 #define swap_data(a, b) { uint8_t t = a; a = b; b = t; }
41 
44 uint16_t ssd1306_color = 0xFFFF;
46 static uint8_t s_invertByte = 0x00000000;
47 const uint8_t *s_font6x8 = &ssd1306xled_font6x8[4];
49 
51 {
52  return s_displayHeight;
53 }
54 
56 {
57  return s_displayWidth;
58 }
59 
60 void ssd1306_fillScreen(uint8_t fill_Data)
61 {
62  fill_Data ^= s_invertByte;
63  ssd1306_setRamBlock(0, 0, 0);
64  for(uint8_t m=(s_displayHeight >> 3); m>0; m--)
65  {
66  for(uint8_t n=s_displayWidth; n>0; n--)
67  {
68  ssd1306_sendPixels(fill_Data);
69  }
71  }
73 }
74 
76 {
77  ssd1306_setRamBlock(0, 0, 0);
78  for(uint8_t m=(s_displayHeight >> 3); m>0; m--)
79  {
80  for(uint8_t n=s_displayWidth; n>0; n--)
81  {
82  ssd1306_sendPixels( s_invertByte );
83  }
85  }
87 }
88 
89 
91 {
92  ssd1306_sendCommand(SSD1306_DISPLAYOFF);
93 }
94 
95 
97 {
98  ssd1306_sendCommand(SSD1306_DISPLAYON);
99 }
100 
101 void ssd1306_setContrast(uint8_t contrast)
102 {
104  ssd1306_sendByte(SSD1306_SETCONTRAST);
105  ssd1306_sendByte(contrast);
107 }
108 
109 uint8_t ssd1306_printFixed(uint8_t xpos, uint8_t y, const char *ch, EFontStyle style)
110 {
111  uint8_t i, j=0;
112  uint8_t text_index = 0;
113  uint8_t page_offset = 0;
114  uint8_t x = xpos;
115  y >>= 3;
116  ssd1306_setRamBlock(xpos, y, s_displayWidth - xpos);
117  for(;;)
118  {
119  uint8_t c;
120  uint8_t ldata;
121  uint16_t offset;
122  if( (x > s_displayWidth - s_fixedFont.width) || (ch[j] == '\0') )
123  {
124  x = xpos;
125  y++;
126  if (y >= (s_displayHeight >> 3))
127  {
128  break;
129  }
130  page_offset++;
131  if (page_offset == s_fixedFont.pages)
132  {
133  text_index = j;
134  page_offset = 0;
135  if (ch[j] == '\0')
136  {
137  break;
138  }
139  }
140  else
141  {
142  j = text_index;
143  }
145  ssd1306_setRamBlock(xpos, y, s_displayWidth - xpos);
146  }
147  c = ch[j];
148  if ( c >= s_fixedFont.ascii_offset )
149  {
150  c -= s_fixedFont.ascii_offset;
151  }
152  ldata = 0;
153  offset = (c * s_fixedFont.pages + page_offset) * s_fixedFont.width;
154  for( i=s_fixedFont.width; i>0; i--)
155  {
156  uint8_t data;
157  if ( style == STYLE_NORMAL )
158  {
159  data = pgm_read_byte(&s_fixedFont.data[offset]);
160  }
161  else if ( style == STYLE_BOLD )
162  {
163  uint8_t temp = pgm_read_byte(&s_fixedFont.data[offset]);
164  data = temp | ldata;
165  ldata = temp;
166  }
167  else
168  {
169  uint8_t temp = pgm_read_byte(&s_fixedFont.data[offset + 1]);
170  data = (temp & 0xF0) | ldata;
171  ldata = (temp & 0x0F);
172  }
173  ssd1306_sendPixels(data^s_invertByte);
174  offset++;
175  }
176  x += s_fixedFont.width;
177  j++;
178  }
180  return j;
181 }
182 
183 uint8_t ssd1306_printFixed2x(uint8_t xpos, uint8_t y, const char ch[], EFontStyle style)
184 {
185  uint8_t i, j=0;
186  uint8_t text_index = 0;
187  uint8_t page_offset = 0;
188  uint8_t x = xpos;
189  y >>= 3;
190  ssd1306_setRamBlock(xpos, y, s_displayWidth - xpos);
191  for(;;)
192  {
193  uint8_t c;
194  uint8_t ldata;
195  uint16_t offset;
196  if( (x > s_displayWidth - (s_fixedFont.width << 1)) || (ch[j] == '\0') )
197  {
198  x = xpos;
199  y++;
200  if (y >= (s_displayHeight >> 3))
201  {
202  break;
203  }
204  page_offset++;
205  if (page_offset == (s_fixedFont.pages << 1))
206  {
207  text_index = j;
208  page_offset = 0;
209  if (ch[j] == '\0')
210  {
211  break;
212  }
213  }
214  else
215  {
216  j = text_index;
217  }
219  ssd1306_setRamBlock(xpos, y, s_displayWidth - xpos);
220  }
221  c = ch[j];
222  if ( c >= s_fixedFont.ascii_offset )
223  {
224  c -= s_fixedFont.ascii_offset;
225  }
226  ldata = 0;
227  offset = (c * s_fixedFont.pages + (page_offset >> 1)) * s_fixedFont.width;
228  for( i=s_fixedFont.width; i>0; i--)
229  {
230  uint8_t data;
231  if ( style == STYLE_NORMAL )
232  {
233  data = pgm_read_byte(&s_fixedFont.data[offset]);
234  }
235  else if ( style == STYLE_BOLD )
236  {
237  uint8_t temp = pgm_read_byte(&s_fixedFont.data[offset]);
238  data = temp | ldata;
239  ldata = temp;
240  }
241  else
242  {
243  uint8_t temp = pgm_read_byte(&s_fixedFont.data[offset + 1]);
244  data = (temp & 0xF0) | ldata;
245  ldata = (temp & 0x0F);
246  }
247  if (page_offset & 1) data >>= 4;
248  data = ((data & 0x01) ? 0x03: 0x00) |
249  ((data & 0x02) ? 0x0C: 0x00) |
250  ((data & 0x04) ? 0x30: 0x00) |
251  ((data & 0x08) ? 0xC0: 0x00);
252  ssd1306_sendPixels(data^s_invertByte);
253  ssd1306_sendPixels(data^s_invertByte);
254  offset++;
255  }
256  x += (s_fixedFont.width << 1);
257  j++;
258  }
260  return j;
261 }
262 
263 
264 uint8_t ssd1306_printFixedN(uint8_t xpos, uint8_t y, const char ch[], EFontStyle style, uint8_t factor)
265 {
266  uint8_t i, j=0;
267  uint8_t text_index = 0;
268  uint8_t page_offset = 0;
269  uint8_t x = xpos;
270  y >>= 3;
271  ssd1306_setRamBlock(xpos, y, s_displayWidth - xpos);
272  for(;;)
273  {
274  uint8_t c;
275  uint8_t ldata;
276  uint16_t offset;
277  if( (x > s_displayWidth - (s_fixedFont.width << factor)) || (ch[j] == '\0') )
278  {
279  x = xpos;
280  y++;
281  if (y >= (s_displayHeight >> 3))
282  {
283  break;
284  }
285  page_offset++;
286  if (page_offset == (s_fixedFont.pages << factor))
287  {
288  text_index = j;
289  page_offset = 0;
290  if (ch[j] == '\0')
291  {
292  break;
293  }
294  }
295  else
296  {
297  j = text_index;
298  }
300  ssd1306_setRamBlock(xpos, y, s_displayWidth - xpos);
301  }
302  c = ch[j];
303  if ( c >= s_fixedFont.ascii_offset )
304  {
305  c -= s_fixedFont.ascii_offset;
306  }
307  ldata = 0;
308  offset = (c * s_fixedFont.pages + (page_offset >> factor)) * s_fixedFont.width;
309  for( i=s_fixedFont.width; i>0; i--)
310  {
311  uint8_t data;
312  if ( style == STYLE_NORMAL )
313  {
314  data = pgm_read_byte(&s_fixedFont.data[offset]);
315  }
316  else if ( style == STYLE_BOLD )
317  {
318  uint8_t temp = pgm_read_byte(&s_fixedFont.data[offset]);
319  data = temp | ldata;
320  ldata = temp;
321  }
322  else
323  {
324  uint8_t temp = pgm_read_byte(&s_fixedFont.data[offset + 1]);
325  data = (temp & 0xF0) | ldata;
326  ldata = (temp & 0x0F);
327  }
328  if ( factor > 0 )
329  {
330  uint8_t accum = 0;
331  uint8_t mask = ~((0xFF) << (1<<factor));
332  // N=0 -> right shift is always 0
333  // N=1 -> right shift goes through 0, 4
334  // N=2 -> right shift goes through 0, 2, 4, 6
335  // N=3 -> right shift goes through 0, 1, 2, 3, 4, 5, 6, 7
336  data >>= ((page_offset & ((1<<factor) - 1))<<(3-factor));
337  for (uint8_t idx = 0; idx < 1<<(3-factor); idx++)
338  {
339  accum |= (((data>>idx) & 0x01) ? (mask<<(idx<<factor)) : 0);
340  }
341  data = accum;
342  }
343  for (uint8_t z=(1<<factor); z>0; z--)
344  {
345  ssd1306_sendPixels(data^s_invertByte);
346  }
347  offset++;
348  }
349  x += (s_fixedFont.width << factor);
350  j++;
351  }
353  return j;
354 }
355 
356 
357 uint8_t ssd1306_charF6x8(uint8_t x, uint8_t y, const char ch[], EFontStyle style)
358 {
359  uint8_t i, j=0;
361  while(ch[j] != '\0')
362  {
363  uint8_t ldata;
364  uint8_t c = ch[j] - 32;
365  if ( c > 224 )
366  {
367  c = 0;
368  }
369  if(x > s_displayWidth - 6)
370  {
371  x=0;
372  y++;
373  }
374  ldata = 0;
375  for(i=0;i<6;i++)
376  {
377  uint8_t data;
378  if ( style == STYLE_NORMAL )
379  {
380  data = pgm_read_byte(&s_font6x8[c*6+i]);
381  }
382  else if ( style == STYLE_BOLD )
383  {
384  uint8_t temp = pgm_read_byte(&s_font6x8[c*6+i]);
385  data = temp | ldata;
386  ldata = temp;
387  }
388  else
389  {
390  uint8_t temp = pgm_read_byte(&s_font6x8[c*6+i + 1]);
391  data = (temp & 0xF0) | ldata;
392  ldata = (temp & 0x0F);
393  }
394  ssd1306_sendPixels(data^s_invertByte);
395  }
396  x += 6;
397  j++;
398  }
400  return j;
401 }
402 
403 uint8_t ssd1306_charF12x16(uint8_t xpos, uint8_t y, const char ch[], EFontStyle style)
404 {
405  uint8_t i, j=0;
406  uint8_t text_index = 0;
407  uint8_t odd = 0;
408  uint8_t x = xpos;
409  ssd1306_setRamBlock(xpos, y, s_displayWidth - xpos);
410  for(;;)
411  {
412  uint8_t c;
413  uint8_t ldata;
414  if( (x > s_displayWidth-12) || (ch[j] == '\0') )
415  {
416  x = xpos;
417  y++;
418  if (y >= (s_displayHeight >> 3))
419  {
420  break;
421  }
422  if (odd)
423  {
424  text_index = j;
425  if (ch[j] == '\0')
426  {
427  break;
428  }
429  }
430  else
431  {
432  j = text_index;
433  }
434  odd = !odd;
436  ssd1306_setRamBlock(xpos, y, s_displayWidth - xpos);
437  }
438  c = ch[j] - 32;
439  if ( c > 224 )
440  {
441  c = 0;
442  }
443  ldata = 0;
444  for(i=0;i<6;i++)
445  {
446  uint8_t data;
447  if ( style == STYLE_NORMAL )
448  {
449  data = pgm_read_byte(&s_font6x8[c*6+i]);
450  }
451  else if ( style == STYLE_BOLD )
452  {
453  uint8_t temp = pgm_read_byte(&s_font6x8[c*6+i]);
454  data = temp | ldata;
455  ldata = temp;
456  }
457  else
458  {
459  uint8_t temp = pgm_read_byte(&s_font6x8[c*6+i + 1]);
460  data = (temp & 0xF0) | ldata;
461  ldata = (temp & 0x0F);
462  }
463  if (odd) data >>= 4;
464  data = ((data & 0x01) ? 0x03: 0x00) |
465  ((data & 0x02) ? 0x0C: 0x00) |
466  ((data & 0x04) ? 0x30: 0x00) |
467  ((data & 0x08) ? 0xC0: 0x00);
468  ssd1306_sendPixels(data^s_invertByte);
469  ssd1306_sendPixels(data^s_invertByte);
470  }
471  x += 12;
472  j++;
473  }
475  return j;
476 }
477 
478 uint8_t ssd1306_charF6x8_eol(uint8_t left,
479  uint8_t y,
480  const char ch[],
481  EFontStyle style,
482  uint8_t right)
483 {
484  uint8_t len = ssd1306_charF6x8(left, y, ch, style);
485  uint8_t text_end_pos = len * 6 + left;
486  if (text_end_pos <= right)
487  {
488  ssd1306_clearBlock(text_end_pos, y, right - text_end_pos + 1, 8);
489  }
490  return len;
491 }
492 
493 void ssd1306_setFixedFont(const uint8_t * progmemFont)
494 {
495  s_fixedFont.width = pgm_read_byte(&progmemFont[1]);
496  s_fixedFont.height = pgm_read_byte(&progmemFont[2]);
497  s_fixedFont.pages = (s_fixedFont.height + 7) >> 3;
498  s_fixedFont.ascii_offset = pgm_read_byte(&progmemFont[3]);
499  s_fixedFont.data = progmemFont + 4;
500 }
501 
502 void ssd1306_setFont6x8(const uint8_t * progmemFont)
503 {
504  s_font6x8 = progmemFont + 4;
505 }
506 
507 void ssd1306_putPixel(uint8_t x, uint8_t y)
508 {
509  ssd1306_setRamBlock(x, y >> 3, 1);
510  ssd1306_sendPixels((1 << (y & 0x07))^s_invertByte);
512 }
513 
514 void ssd1306_putPixels(uint8_t x, uint8_t y, uint8_t pixels)
515 {
516  ssd1306_setRamBlock(x, y >> 3, 1);
517  ssd1306_sendPixels(pixels^s_invertByte);
519 }
520 
521 void ssd1306_putPixel_delayed(uint8_t x, uint8_t y, uint8_t complete)
522 {
523  static uint8_t lx = 0, ly = 0xFF;
524  static uint8_t pixels = 0;
525  if ((lx != x) || ((ly & 0xF8) != (y & 0xF8)) || (complete))
526  {
527  if (ly != 0xFF)
528  {
529  ssd1306_putPixels( lx, ly, pixels );
530  }
531  pixels = 0;
532  ly = 0xFF;
533  }
534  if ( !complete )
535  {
536  pixels |= (1 << (y & 0x07));
537  lx = x; ly = y;
538  }
539 }
540 
541 void ssd1306_drawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2)
542 {
543  uint8_t dx = x1 > x2 ? (x1 - x2): (x2 - x1);
544  uint8_t dy = y1 > y2 ? (y1 - y2): (y2 - y1);
545  uint8_t err = 0;
546  if (dy > dx)
547  {
548  if (y1 > y2)
549  {
550  swap_data(x1, x2);
551  swap_data(y1, y2);
552  }
553  for(; y1<=y2; y1++)
554  {
555  err += dx;
556  if (err >= dy)
557  {
558  err -= dy;
559  x1 < x2 ? x1++: x1--;
560  }
561  ssd1306_putPixel_delayed( x1, y1, 0 );
562  }
563  ssd1306_putPixel_delayed( 0, 0, 1 );
564  }
565  else
566  {
567  if (x1 > x2)
568  {
569  swap_data(x1, x2);
570  swap_data(y1, y2);
571  }
572 
573  for(; x1<=x2; x1++)
574  {
575  err += dy;
576  if (err >= dx)
577  {
578  err -= dx;
579  if (y1 < y2) y1++; else y1--;
580  }
581  ssd1306_putPixel( x1, y1 );
582  }
583  }
584 }
585 
586 void ssd1306_drawHLine(uint8_t x1, uint8_t y1, uint8_t x2)
587 {
588  ssd1306_setRamBlock(x1, y1 >> 3, x2 - x1 + 1);
589  for (uint8_t x = x1; x <= x2; x++)
590  {
591  ssd1306_sendPixels((1 << (y1 & 0x07))^s_invertByte);
592  }
594 }
595 
596 void ssd1306_drawVLine(uint8_t x1, uint8_t y1, uint8_t y2)
597 {
598  uint8_t topPage = y1 >> 3;
599  uint8_t bottomPage = y2 >> 3;
600  uint8_t height = y2-y1;
601  uint8_t y;
602  ssd1306_setRamBlock(x1, topPage, 1);
603  if (topPage == bottomPage)
604  {
605  ssd1306_sendPixels( ((0xFF >> (0x07 - height)) << (y1 & 0x07))^s_invertByte );
607  return;
608  }
609  ssd1306_sendPixels( (0xFF << (y1 & 0x07))^s_invertByte );
610  for ( y = (topPage + 1); y <= (bottomPage - 1); y++)
611  {
613  ssd1306_sendPixels( 0xFF^s_invertByte );
614  }
616  ssd1306_sendPixels( (0xFF >> (0x07 - (y2 & 0x07)))^s_invertByte );
618 }
619 
620 void ssd1306_drawRect(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2)
621 {
622  ssd1306_drawHLine(x1+1, y1, x2-1);
623  ssd1306_drawHLine(x1+1, y2, x2-1);
624  ssd1306_drawVLine(x1, y1, y2);
625  ssd1306_drawVLine(x2, y1, y2);
626 }
627 
628 void ssd1306_drawBuffer(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *buf)
629 {
630  uint8_t i, j;
631  ssd1306_setRamBlock(x, y, w);
632  for(j=(h >> 3); j>0; j--)
633  {
634  for(i=w;i>0;i--)
635  {
636  ssd1306_sendPixels(s_invertByte^*buf++);
637  }
639  }
641 }
642 
643 void ssd1306_drawBitmap(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *buf)
644 {
645  uint8_t i, j;
646  uint8_t remainder = (s_displayWidth - x) < w ? (w + x - s_displayWidth): 0;
647  w -= remainder;
648  ssd1306_setRamBlock(x, y, w);
649  for(j=(h >> 3); j>0; j--)
650  {
651  for(i=w;i>0;i--)
652  {
653  ssd1306_sendPixels(s_invertByte^pgm_read_byte(buf++));
654  }
655  buf += remainder;
657  }
659 }
660 
661 void gfx_drawMonoBitmap(lcdint_t x, lcdint_t y, lcduint_t w, lcduint_t h, const uint8_t *buf)
662 {
663  lcduint_t origin_width = w;
664  uint8_t offset = y & 0x07;
665  uint8_t complexFlag = 0;
666  uint8_t mainFlag = 1;
667  uint8_t max_pages;
668  uint8_t pages;
669  lcduint_t i, j;
670  if (y + (lcdint_t)h <= 0) return;
671  if (y >= s_displayHeight) return;
672  if (x + (lcdint_t)w <= 0) return;
673  if (x >= s_displayWidth) return;
674  if (y < 0)
675  {
676  buf += ((lcduint_t)((-y) + 7) >> 3) * w;
677  h += y;
678  y = 0;
679  complexFlag = 1;
680  }
681  if (x < 0)
682  {
683  buf += -x;
684  w += x;
685  x = 0;
686  }
687  max_pages = (lcduint_t)(h + 15 - offset) >> 3;
688  if ((lcduint_t)((lcduint_t)y + h) > (lcduint_t)s_displayHeight)
689  {
690  h = (lcduint_t)(s_displayHeight - (lcduint_t)y);
691  }
692  if ((lcduint_t)((lcduint_t)x + w) > (lcduint_t)s_displayWidth)
693  {
694  w = (lcduint_t)(s_displayWidth - (lcduint_t)x);
695  }
696  pages = ((y + h - 1) >> 3) - (y >> 3) + 1;
697 
698  ssd1306_setRamBlock(x, y >> 3, w);
699  for(j=0; j < pages; j++)
700  {
701  if ( j == max_pages - 1 ) mainFlag = !offset;
702  for( i=w; i > 0; i--)
703  {
704  uint8_t data = 0;
705  if ( mainFlag ) data |= (pgm_read_byte(buf) << offset);
706  if ( complexFlag ) data |= (pgm_read_byte(buf - origin_width) >> (8 - offset));
707  buf++;
708  ssd1306_sendPixels(s_invertByte^data);
709  }
710  buf += origin_width - w;
711  complexFlag = offset;
713  }
715 }
716 
717 
718 void ssd1306_clearBlock(uint8_t x, uint8_t y, uint8_t w, uint8_t h)
719 {
720  uint8_t i, j;
721  ssd1306_setRamBlock(x, y, w);
722  for(j=(h >> 3); j>0; j--)
723  {
724  for(i=w;i>0;i--)
725  {
726  ssd1306_sendPixels(s_invertByte);
727  }
729  }
731 }
732 
733 
734 void ssd1306_drawSpriteEx(uint8_t x, uint8_t y, uint8_t w, const uint8_t *sprite)
735 {
736  uint8_t i;
737  ssd1306_setRamBlock(x,y,w);
738  for(i=0;i<w;i++)
739  {
740  ssd1306_sendPixels(s_invertByte^pgm_read_byte(&sprite[i]));
741  }
743 }
744 
745 
747 {
748  uint8_t offsety = sprite->y & 0x7;
749  if (sprite->y < s_displayHeight)
750  {
751  ssd1306_setRamBlock(sprite->x, sprite->y >> 3, sprite->w);
752  for (uint8_t i=0; i < sprite->w; i++)
753  {
754  ssd1306_sendPixels( s_invertByte^(pgm_read_byte( &sprite->data[i] ) << offsety) );
755  }
757  }
758  if (offsety && (sprite->y + 8 < s_displayHeight))
759  {
760  ssd1306_setRamBlock(sprite->x, (sprite->y >> 3) + 1, sprite->w);
761  for (uint8_t i=0; i < sprite->w; i++)
762  {
763  ssd1306_sendPixels( s_invertByte^(pgm_read_byte( &sprite->data[i] ) >> (8 - offsety)) );
764  }
766  }
767  sprite->lx = sprite->x;
768  sprite->ly = sprite->y;
769 }
770 
771 
773 {
774  uint8_t posy = sprite->y >> 3;
775  uint8_t offsety = sprite->y & 0x7;
776  ssd1306_setRamBlock(sprite->x, posy, sprite->w);
777  for (uint8_t i=sprite->w; i > 0; i--)
778  {
779  ssd1306_sendPixels( s_invertByte );
780  }
782  if (offsety)
783  {
784  ssd1306_setRamBlock(sprite->x, posy + 1, sprite->w);
785  for (uint8_t i=sprite->w; i > 0; i--)
786  {
787  ssd1306_sendPixels( s_invertByte );
788  }
789  }
791 }
792 
793 
795 {
796  uint8_t y1 = sprite->ly >> 3;
797  uint8_t y2 = (sprite->ly + 7) >> 3;
798  if (sprite->ly < sprite->y)
799  y2 = min(y2, (uint8_t)((sprite->y >> 3) - 1));
800  else if (sprite->y + 8 > sprite->ly)
801  y1 = max(y1, (sprite->ly + 7) >> 3);
802  for(uint8_t y = y1; y <= y2; y++)
803  {
804  ssd1306_setRamBlock(sprite->lx, y, sprite->w);
805  for(uint8_t x = sprite->w; x > 0; x--)
806  {
807  ssd1306_sendPixels( s_invertByte );
808  }
810  }
811  if (sprite->lx != sprite->x)
812  {
813  uint8_t x1 = sprite->lx;
814  uint8_t x2 = sprite->lx + sprite->w - 1;
815  if (sprite->x < sprite->lx)
816  x1 = max(x1, sprite->x + sprite->w);
817  else
818  x2 = min((uint8_t)(sprite->x - 1), x2);
819  for(uint8_t y = sprite->ly >> 3; y <= (sprite->ly + 7) >> 3; y++)
820  {
821  ssd1306_setRamBlock(x1, y, x2 - x1 + 1 );
822  for(uint8_t x = x2 - x1 + 1; x > 0; x--)
823  {
824  ssd1306_sendPixels( s_invertByte );
825  }
827  }
828  }
829 }
830 
831 SPRITE ssd1306_createSprite(uint8_t x, uint8_t y, uint8_t w, const uint8_t *data)
832 {
833  return (SPRITE){x,y,w,x,y,data,NULL};
834 }
835 
836 void ssd1306_replaceSprite(SPRITE *sprite, const uint8_t *data)
837 {
838  sprite->data = data;
839 }
840 
842 {
844  {
845  ssd1306_sendCommand(SSD1306_INVERTDISPLAY);
846  }
847 }
848 
850 {
852  {
853  ssd1306_sendCommand(SSD1306_NORMALDISPLAY);
854  }
855 }
856 
857 void ssd1306_flipHorizontal(uint8_t mode)
858 {
860  {
861  ssd1306_sendCommand( SSD1306_SEGREMAP | (mode ? 0x00: 0x01 ) );
862  }
863 }
864 
865 void ssd1306_flipVertical(uint8_t mode)
866 {
868  {
869  ssd1306_sendCommand( mode ? SSD1306_COMSCANINC : SSD1306_COMSCANDEC );
870  }
871 }
872 
874 {
875  s_invertByte = 0xFF;
876 }
877 
879 {
880  s_invertByte = 0x00;
881 }
void ssd1306_setFixedFont(const uint8_t *progmemFont)
unsigned int lcduint_t
Definition: io.h:42
const uint8_t * data
Pointer to PROGMEM data, representing sprite image.
uint8_t ssd1306_charF6x8_eol(uint8_t left, uint8_t y, const char ch[], EFontStyle style, uint8_t right)
void ssd1306_eraseSprite(SPRITE *sprite)
void ssd1306_invertMode()
void ssd1306_drawRect(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2)
void ssd1306_drawSprite(SPRITE *sprite)
void ssd1306_flipVertical(uint8_t mode)
performs vertical flip
uint8_t ssd1306_charF6x8(uint8_t x, uint8_t y, const char ch[], EFontStyle style)
uint8_t s_displayWidth
void ssd1306_putPixels(uint8_t x, uint8_t y, uint8_t pixels)
void ssd1306_fillScreen(uint8_t fill_Data)
uint8_t ssd1306_printFixed(uint8_t xpos, uint8_t y, const char *ch, EFontStyle style)
SFixedFontInfo s_fixedFont
Definition: tiler.h:39
void ssd1306_clearBlock(uint8_t x, uint8_t y, uint8_t w, uint8_t h)
void ssd1306_displayOn()
const PROGMEM uint8_t ssd1306xled_font6x8[]
Definition: ssd1306_fonts.c:41
void ssd1306_drawVLine(uint8_t x1, uint8_t y1, uint8_t y2)
uint8_t ascii_offset
ascii offset
uint8_t ssd1306_displayWidth()
uint8_t ssd1306_printFixedN(uint8_t xpos, uint8_t y, const char ch[], EFontStyle style, uint8_t factor)
void ssd1306_flipHorizontal(uint8_t mode)
performs horizontal flip
void ssd1306_drawBitmap(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *buf)
void ssd1306_putPixel(uint8_t x, uint8_t y)
void(* ssd1306_endTransmission)(void)
uint8_t g_lcd_type
#define max(a, b)
uint8_t y
draw position Y on the screen
#define min(a, b)
int lcdint_t
Definition: io.h:40
uint8_t width
width in pixels
void gfx_drawMonoBitmap(lcdint_t x, lcdint_t y, lcduint_t w, lcduint_t h, const uint8_t *buf)
void ssd1306_clearScreen()
uint8_t x
draw position X on the screen
void(* ssd1306_sendByte)(uint8_t data)
void ssd1306_setFont6x8(const uint8_t *progmemFont)
void ssd1306_drawHLine(uint8_t x1, uint8_t y1, uint8_t x2)
uint8_t w
sprite width
void ssd1306_sendCommand(uint8_t command)
void(* ssd1306_commandStart)(void)
void ssd1306_drawSpriteEx(uint8_t x, uint8_t y, uint8_t w, const uint8_t *sprite)
void(* ssd1306_setRamBlock)(uint8_t x, uint8_t y, uint8_t w)
Definition: lcd_common.c:29
void ssd1306_positiveMode()
uint8_t s_displayHeight
uint8_t ssd1306_charF12x16(uint8_t xpos, uint8_t y, const char ch[], EFontStyle style)
uint8_t lx
last draw position X on the screen
uint8_t ssd1306_displayHeight()
void(* ssd1306_nextRamPage)(void)
Definition: lcd_common.c:30
void ssd1306_negativeMode()
void ssd1306_eraseTrace(SPRITE *sprite)
const uint8_t * data
font chars bits
void(* ssd1306_sendPixels)(uint8_t data)
Definition: lcd_common.c:31
EFontStyle
uint8_t pages
height in pages (each page height is 8-pixels)
void ssd1306_drawBuffer(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *buf)
uint8_t ssd1306_printFixed2x(uint8_t xpos, uint8_t y, const char ch[], EFontStyle style)
void ssd1306_replaceSprite(SPRITE *sprite, const uint8_t *data)
void ssd1306_normalMode()
uint8_t ly
last draw position Y on the screen
void ssd1306_displayOff()
void ssd1306_setContrast(uint8_t contrast)
SPRITE ssd1306_createSprite(uint8_t x, uint8_t y, uint8_t w, const uint8_t *data)
void ssd1306_drawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2)
uint8_t height
height in pixels