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