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