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