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