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