SSD1306 OLED display driver  1.7.13
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 gfx_drawMonoBitmap(lcdint_t x, lcdint_t y, lcduint_t w, lcduint_t h, const uint8_t *buf)
765 {
766  lcduint_t origin_width = w;
767  uint8_t offset = y & 0x07;
768  uint8_t complexFlag = 0;
769  uint8_t mainFlag = 1;
770  uint8_t max_pages;
771  uint8_t pages;
772  lcduint_t i, j;
773  if (y + (lcdint_t)h <= 0) return;
774  if (y >= ssd1306_lcd.height) return;
775  if (x + (lcdint_t)w <= 0) return;
776  if (x >= ssd1306_lcd.width) return;
777  if (y < 0)
778  {
779  buf += ((lcduint_t)((-y) + 7) >> 3) * w;
780  h += y;
781  y = 0;
782  complexFlag = 1;
783  }
784  if (x < 0)
785  {
786  buf += -x;
787  w += x;
788  x = 0;
789  }
790  max_pages = (lcduint_t)(h + 15 - offset) >> 3;
791  if ((lcduint_t)((lcduint_t)y + h) > (lcduint_t)ssd1306_lcd.height)
792  {
793  h = (lcduint_t)(ssd1306_lcd.height - (lcduint_t)y);
794  }
795  if ((lcduint_t)((lcduint_t)x + w) > (lcduint_t)ssd1306_lcd.width)
796  {
797  w = (lcduint_t)(ssd1306_lcd.width - (lcduint_t)x);
798  }
799  pages = ((y + h - 1) >> 3) - (y >> 3) + 1;
800 
801  ssd1306_lcd.set_block(x, y >> 3, w);
802  for(j=0; j < pages; j++)
803  {
804  if ( j == max_pages - 1 ) mainFlag = !offset;
805  for( i=w; i > 0; i--)
806  {
807  uint8_t data = 0;
808  if ( mainFlag ) data |= (pgm_read_byte(buf) << offset);
809  if ( complexFlag ) data |= (pgm_read_byte(buf - origin_width) >> (8 - offset));
810  buf++;
811  ssd1306_lcd.send_pixels1(s_ssd1306_invertByte^data);
812  }
813  buf += origin_width - w;
814  complexFlag = offset;
816  }
817  ssd1306_intf.stop();
818 }
819 
820 
821 void ssd1306_clearBlock(uint8_t x, uint8_t y, uint8_t w, uint8_t h)
822 {
823  uint8_t i, j;
824  ssd1306_lcd.set_block(x, y, w);
825  for(j=(h >> 3); j>0; j--)
826  {
827  for(i=w;i>0;i--)
828  {
829  ssd1306_lcd.send_pixels1(s_ssd1306_invertByte);
830  }
832  }
833  ssd1306_intf.stop();
834 }
835 
836 
837 void ssd1306_drawSpriteEx(uint8_t x, uint8_t y, uint8_t w, const uint8_t *sprite)
838 {
839  uint8_t i;
840  ssd1306_lcd.set_block(x,y,w);
841  for(i=0;i<w;i++)
842  {
843  ssd1306_lcd.send_pixels1(s_ssd1306_invertByte^pgm_read_byte(&sprite[i]));
844  }
845  ssd1306_intf.stop();
846 }
847 
848 
850 {
851  uint8_t offsety = sprite->y & 0x7;
852  if (sprite->y < ssd1306_lcd.height)
853  {
854  ssd1306_lcd.set_block(sprite->x, sprite->y >> 3, sprite->w);
855  for (uint8_t i=0; i < sprite->w; i++)
856  {
857  ssd1306_lcd.send_pixels1( s_ssd1306_invertByte^(pgm_read_byte( &sprite->data[i] ) << offsety) );
858  }
859  ssd1306_intf.stop();
860  }
861  if (offsety && (sprite->y + 8 < ssd1306_lcd.height))
862  {
863  ssd1306_lcd.set_block(sprite->x, (sprite->y >> 3) + 1, sprite->w);
864  for (uint8_t i=0; i < sprite->w; i++)
865  {
866  ssd1306_lcd.send_pixels1( s_ssd1306_invertByte^(pgm_read_byte( &sprite->data[i] ) >> (8 - offsety)) );
867  }
868  ssd1306_intf.stop();
869  }
870  sprite->lx = sprite->x;
871  sprite->ly = sprite->y;
872 }
873 
874 
876 {
877  uint8_t posy = sprite->y >> 3;
878  uint8_t offsety = sprite->y & 0x7;
879  ssd1306_lcd.set_block(sprite->x, posy, sprite->w);
880  for (uint8_t i=sprite->w; i > 0; i--)
881  {
882  ssd1306_lcd.send_pixels1( s_ssd1306_invertByte );
883  }
884  ssd1306_intf.stop();
885  if (offsety)
886  {
887  ssd1306_lcd.set_block(sprite->x, posy + 1, sprite->w);
888  for (uint8_t i=sprite->w; i > 0; i--)
889  {
890  ssd1306_lcd.send_pixels1( s_ssd1306_invertByte );
891  }
892  }
893  ssd1306_intf.stop();
894 }
895 
896 
898 {
899  uint8_t y1 = sprite->ly >> 3;
900  uint8_t y2 = (sprite->ly + 7) >> 3;
901  if (sprite->ly < sprite->y)
902  y2 = min(y2, (uint8_t)((sprite->y >> 3) - 1));
903  else if (sprite->y + 8 > sprite->ly)
904  y1 = max(y1, (sprite->ly + 7) >> 3);
905  for(uint8_t y = y1; y <= y2; y++)
906  {
907  ssd1306_lcd.set_block(sprite->lx, y, sprite->w);
908  for(uint8_t x = sprite->w; x > 0; x--)
909  {
910  ssd1306_lcd.send_pixels1( s_ssd1306_invertByte );
911  }
912  ssd1306_intf.stop();
913  }
914  if (sprite->lx != sprite->x)
915  {
916  uint8_t x1 = sprite->lx;
917  uint8_t x2 = sprite->lx + sprite->w - 1;
918  if (sprite->x < sprite->lx)
919  x1 = max(x1, sprite->x + sprite->w);
920  else
921  x2 = min((uint8_t)(sprite->x - 1), x2);
922  for(uint8_t y = sprite->ly >> 3; y <= (sprite->ly + 7) >> 3; y++)
923  {
924  ssd1306_lcd.set_block(x1, y, x2 - x1 + 1 );
925  for(uint8_t x = x2 - x1 + 1; x > 0; x--)
926  {
927  ssd1306_lcd.send_pixels1( s_ssd1306_invertByte );
928  }
929  ssd1306_intf.stop();
930  }
931  }
932 }
933 
934 SPRITE ssd1306_createSprite(uint8_t x, uint8_t y, uint8_t w, const uint8_t *data)
935 {
936  return (SPRITE){x,y,w,x,y,data,NULL};
937 }
938 
939 void ssd1306_replaceSprite(SPRITE *sprite, const uint8_t *data)
940 {
941  sprite->data = data;
942 }
943 
945 {
946  s_ssd1306_invertByte = 0xFF;
947 }
948 
950 {
951  s_ssd1306_invertByte = 0x00;
952 }
953 
954 void ssd1306_setFont6x8(const uint8_t * progmemFont)
955 {
956  s_font6x8 = progmemFont + 4;
957 }
958 
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:949
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:934
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_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:849
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:897
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:764
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:954
void ssd1306_eraseSprite(SPRITE *sprite)
Definition: ssd1306_1bit.c:875
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:837
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:821
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:939
#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:944
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