SSD1306 OLED display driver 1.7.8 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;
44 extern SFixedFontInfo s_fixedFont;
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 }
59 ssd1306_lcd.next_page();
60 }
61 ssd1306_intf.stop();
62 }
63
64 void ssd1306_clearScreen()
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 }
73 ssd1306_lcd.next_page();
74 }
75 ssd1306_intf.stop();
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_printFixed2x(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 << 1)) || (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 << 1))
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 >= 32 )
201 {
202 c -= 32;
203 }
204 ldata = 0;
205 offset = (c * s_fixedFont.pages + (page_offset >> 1)) * 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 if (page_offset & 1) data >>= 4;
226 data = ((data & 0x01) ? 0x03: 0x00) |
227 ((data & 0x02) ? 0x0C: 0x00) |
228 ((data & 0x04) ? 0x30: 0x00) |
229 ((data & 0x08) ? 0xC0: 0x00);
230 ssd1306_lcd.send_pixels1(data^s_ssd1306_invertByte);
231 ssd1306_lcd.send_pixels1(data^s_ssd1306_invertByte);
232 offset++;
233 }
234 x += (s_fixedFont.h.width << 1);
235 j++;
236 }
237 ssd1306_intf.stop();
238 return j;
239 }
240
241
242 uint8_t ssd1306_printFixedN(uint8_t xpos, uint8_t y, const char ch[], EFontStyle style, uint8_t factor)
243 {
244 uint8_t i, j=0;
245 uint8_t text_index = 0;
246 uint8_t page_offset = 0;
247 uint8_t x = xpos;
248 y >>= 3;
249 ssd1306_lcd.set_block(xpos, y, ssd1306_lcd.width - xpos);
250 for(;;)
251 {
252 uint8_t ldata;
253 if( (x > ssd1306_lcd.width - (s_fixedFont.h.width << factor)) || (ch[j] == '\0') )
254 {
255 x = xpos;
256 y++;
257 if (y >= (ssd1306_lcd.height >> 3))
258 {
259 break;
260 }
261 page_offset++;
262 if (page_offset == (s_fixedFont.pages << factor))
263 {
264 text_index = j;
265 page_offset = 0;
266 if (ch[j] == '\0')
267 {
268 break;
269 }
270 }
271 else
272 {
273 j = text_index;
274 }
275 ssd1306_intf.stop();
276 ssd1306_lcd.set_block(xpos, y, ssd1306_lcd.width - xpos);
277 }
278 uint16_t unicode;
279 do
280 {
281 unicode = ssd1306_unicode16FromUtf8(ch[j]);
282 j++;
283 } while ( unicode == SSD1306_MORE_CHARS_REQUIRED );
284 SCharInfo char_info;
285 ssd1306_getCharBitmap(unicode, &char_info);
286 ldata = 0;
287 x += ((char_info.width + char_info.spacing) << factor);
288 if (char_info.height > (page_offset >> factor) * 8)
289 {
290 char_info.glyph += (page_offset >> factor) * char_info.width;
291 for( i=char_info.width; i>0; i--)
292 {
293 uint8_t data;
294 if ( style == STYLE_NORMAL )
295 {
296 data = pgm_read_byte(char_info.glyph);
297 }
298 else if ( style == STYLE_BOLD )
299 {
300 uint8_t temp = pgm_read_byte(char_info.glyph);
301 data = temp | ldata;
302 ldata = temp;
303 }
304 else
305 {
306 uint8_t temp = pgm_read_byte(char_info.glyph+1);
307 data = (temp & 0xF0) | ldata;
308 ldata = (temp & 0x0F);
309 }
310 if ( factor > 0 )
311 {
312 uint8_t accum = 0;
313 uint8_t mask = ~((0xFF) << (1<<factor));
314 // N=0 -> right shift is always 0
315 // N=1 -> right shift goes through 0, 4
316 // N=2 -> right shift goes through 0, 2, 4, 6
317 // N=3 -> right shift goes through 0, 1, 2, 3, 4, 5, 6, 7
318 data >>= ((page_offset & ((1<<factor) - 1))<<(3-factor));
319 for (uint8_t idx = 0; idx < 1<<(3-factor); idx++)
320 {
321 accum |= (((data>>idx) & 0x01) ? (mask<<(idx<<factor)) : 0);
322 }
323 data = accum;
324 }
325 for (uint8_t z=(1<<factor); z>0; z--)
326 {
327 ssd1306_lcd.send_pixels1(data^s_ssd1306_invertByte);
328 }
329 char_info.glyph++;
330 }
331 }
332 else
333 {
334 char_info.spacing += char_info.width;
335 }
336 for (i = 0; i < (char_info.spacing << factor); i++)
337 ssd1306_lcd.send_pixels1(s_ssd1306_invertByte);
338 }
339 ssd1306_intf.stop();
340 return j;
341 }
342
343 size_t ssd1306_write(uint8_t ch)
344 {
345 if (ch == '\r')
346 {
347 ssd1306_cursorX = 0;
348 return 0;
349 }
350 else if ( (ssd1306_cursorX > ssd1306_lcd.width - s_fixedFont.h.width) || (ch == '\n') )
351 {
352 ssd1306_cursorX = 0;
353 ssd1306_cursorY += s_fixedFont.h.height;
354 if ( ssd1306_cursorY > ssd1306_lcd.height - s_fixedFont.h.height )
355 {
356 ssd1306_cursorY = 0;
357 }
358 ssd1306_clearBlock(0, ssd1306_cursorY >> 3, ssd1306_lcd.width, s_fixedFont.h.height);
359 if (ch == '\n')
360 {
361 return 0;
362 }
363 }
364 uint16_t unicode = ssd1306_unicode16FromUtf8(ch);
365 if (unicode == SSD1306_MORE_CHARS_REQUIRED) return 0;
366 SCharInfo char_info;
367 ssd1306_getCharBitmap(unicode, &char_info);
368 ssd1306_drawBitmap( ssd1306_cursorX,
369 ssd1306_cursorY >> 3,
370 char_info.width,
371 char_info.height,
372 char_info.glyph );
373 ssd1306_cursorX += char_info.width + char_info.spacing;
374 return 1;
375 }
376
377 size_t ssd1306_print(const char ch[])
378 {
379 size_t n = 0;
380 while (*ch)
381 {
382 n += ssd1306_write(*ch);
383 ch++;
384 }
385 return n;
386 }
387
388 uint8_t ssd1306_charF6x8(uint8_t x, uint8_t y, const char ch[], EFontStyle style)
389 {
390 uint8_t i, j=0;
391 ssd1306_lcd.set_block(x, y, ssd1306_lcd.width - x);
392 while(ch[j] != '\0')
393 {
394 uint8_t ldata;
395 uint8_t c = ch[j] - 32;
396 if ( c > 224 )
397 {
398 c = 0;
399 }
400 if(x > ssd1306_lcd.width - 6)
401 {
402 x=0;
403 y++;
404 }
405 ldata = 0;
406 for(i=0;i<6;i++)
407 {
408 uint8_t data;
409 if ( style == STYLE_NORMAL )
410 {
411 data = pgm_read_byte(&s_font6x8[c*6+i]);
412 }
413 else if ( style == STYLE_BOLD )
414 {
415 uint8_t temp = pgm_read_byte(&s_font6x8[c*6+i]);
416 data = temp | ldata;
417 ldata = temp;
418 }
419 else
420 {
421 uint8_t temp = pgm_read_byte(&s_font6x8[c*6+i + 1]);
422 data = (temp & 0xF0) | ldata;
423 ldata = (temp & 0x0F);
424 }
425 ssd1306_lcd.send_pixels1(data^s_ssd1306_invertByte);
426 }
427 x += 6;
428 j++;
429 }
430 ssd1306_intf.stop();
431 return j;
432 }
433
434 uint8_t ssd1306_charF12x16(uint8_t xpos, uint8_t y, const char ch[], EFontStyle style)
435 {
436 uint8_t i, j=0;
437 uint8_t text_index = 0;
438 uint8_t odd = 0;
439 uint8_t x = xpos;
440 ssd1306_lcd.set_block(xpos, y, ssd1306_lcd.width - xpos);
441 for(;;)
442 {
443 uint8_t c;
444 uint8_t ldata;
445 if( (x > ssd1306_lcd.width-12) || (ch[j] == '\0') )
446 {
447 x = xpos;
448 y++;
449 if (y >= (ssd1306_lcd.height >> 3))
450 {
451 break;
452 }
453 if (odd)
454 {
455 text_index = j;
456 if (ch[j] == '\0')
457 {
458 break;
459 }
460 }
461 else
462 {
463 j = text_index;
464 }
465 odd = !odd;
466 ssd1306_intf.stop();
467 ssd1306_lcd.set_block(xpos, y, ssd1306_lcd.width - xpos);
468 }
469 c = ch[j] - 32;
470 if ( c > 224 )
471 {
472 c = 0;
473 }
474 ldata = 0;
475 for(i=0;i<6;i++)
476 {
477 uint8_t data;
478 if ( style == STYLE_NORMAL )
479 {
480 data = pgm_read_byte(&s_font6x8[c*6+i]);
481 }
482 else if ( style == STYLE_BOLD )
483 {
484 uint8_t temp = pgm_read_byte(&s_font6x8[c*6+i]);
485 data = temp | ldata;
486 ldata = temp;
487 }
488 else
489 {
490 uint8_t temp = pgm_read_byte(&s_font6x8[c*6+i + 1]);
491 data = (temp & 0xF0) | ldata;
492 ldata = (temp & 0x0F);
493 }
494 if (odd) data >>= 4;
495 data = ((data & 0x01) ? 0x03: 0x00) |
496 ((data & 0x02) ? 0x0C: 0x00) |
497 ((data & 0x04) ? 0x30: 0x00) |
498 ((data & 0x08) ? 0xC0: 0x00);
499 ssd1306_lcd.send_pixels1(data^s_ssd1306_invertByte);
500 ssd1306_lcd.send_pixels1(data^s_ssd1306_invertByte);
501 }
502 x += 12;
503 j++;
504 }
505 ssd1306_intf.stop();
506 return j;
507 }
508
509 uint8_t ssd1306_charF6x8_eol(uint8_t left,
510 uint8_t y,
511 const char ch[],
512 EFontStyle style,
513 uint8_t right)
514 {
515 uint8_t len = ssd1306_charF6x8(left, y, ch, style);
516 uint8_t text_end_pos = len * 6 + left;
517 if (text_end_pos <= right)
518 {
519 ssd1306_clearBlock(text_end_pos, y, right - text_end_pos + 1, 8);
520 }
521 return len;
522 }
523
524 void ssd1306_putPixel(uint8_t x, uint8_t y)
525 {
526 ssd1306_lcd.set_block(x, y >> 3, 1);
527 ssd1306_lcd.send_pixels1((1 << (y & 0x07))^s_ssd1306_invertByte);
528 ssd1306_intf.stop();
529 }
530
531 void ssd1306_putPixels(uint8_t x, uint8_t y, uint8_t pixels)
532 {
533 ssd1306_lcd.set_block(x, y >> 3, 1);
534 ssd1306_lcd.send_pixels1(pixels^s_ssd1306_invertByte);
535 ssd1306_intf.stop();
536 }
537
538 void ssd1306_putPixel_delayed(uint8_t x, uint8_t y, uint8_t complete)
539 {
540 static uint8_t lx = 0, ly = 0xFF;
541 static uint8_t pixels = 0;
542 if ((lx != x) || ((ly & 0xF8) != (y & 0xF8)) || (complete))
543 {
544 if (ly != 0xFF)
545 {
546 ssd1306_putPixels( lx, ly, pixels );
547 }
548 pixels = 0;
549 ly = 0xFF;
550 }
551 if ( !complete )
552 {
553 pixels |= (1 << (y & 0x07));
554 lx = x; ly = y;
555 }
556 }
557
558 void ssd1306_drawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2)
559 {
560 lcduint_t dx = x1 > x2 ? (x1 - x2): (x2 - x1);
561 lcduint_t dy = y1 > y2 ? (y1 - y2): (y2 - y1);
562 lcduint_t err = 0;
563 if (dy > dx)
564 {
565 if (y1 > y2)
566 {
567 ssd1306_swap_data(x1, x2, uint8_t);
568 ssd1306_swap_data(y1, y2, uint8_t);
569 }
570 for(; y1<=y2; y1++)
571 {
572 err += dx;
573 if (err >= dy)
574 {
575 err -= dy;
576 x1 < x2 ? x1++: x1--;
577 }
578 ssd1306_putPixel_delayed( x1, y1, 0 );
579 }
580 ssd1306_putPixel_delayed( 0, 0, 1 );
581 }
582 else
583 {
584 if (x1 > x2)
585 {
586 ssd1306_swap_data(x1, x2, uint8_t);
587 ssd1306_swap_data(y1, y2, uint8_t);
588 }
589 for(; x1<=x2; x1++)
590 {
591 err += dy;
592 if (err >= dx)
593 {
594 err -= dx;
595 if (y1 < y2) y1++; else y1--;
596 }
597 ssd1306_putPixel( x1, y1 );
598 }
599 }
600 }
601
602 void ssd1306_drawHLine(uint8_t x1, uint8_t y1, uint8_t x2)
603 {
604 ssd1306_lcd.set_block(x1, y1 >> 3, x2 - x1 + 1);
605 for (uint8_t x = x1; x <= x2; x++)
606 {
607 ssd1306_lcd.send_pixels1((1 << (y1 & 0x07))^s_ssd1306_invertByte);
608 }
609 ssd1306_intf.stop();
610 }
611
612 void ssd1306_drawVLine(uint8_t x1, uint8_t y1, uint8_t y2)
613 {
614 uint8_t topPage = y1 >> 3;
615 uint8_t bottomPage = y2 >> 3;
616 uint8_t height = y2-y1;
617 uint8_t y;
618 ssd1306_lcd.set_block(x1, topPage, 1);
619 if (topPage == bottomPage)
620 {
621 ssd1306_lcd.send_pixels1( ((0xFF >> (0x07 - height)) << (y1 & 0x07))^s_ssd1306_invertByte );
622 ssd1306_intf.stop();
623 return;
624 }
625 ssd1306_lcd.send_pixels1( (0xFF << (y1 & 0x07))^s_ssd1306_invertByte );
626 for ( y = (topPage + 1); y <= (bottomPage - 1); y++)
627 {
628 ssd1306_lcd.next_page();
629 ssd1306_lcd.send_pixels1( 0xFF^s_ssd1306_invertByte );
630 }
631 ssd1306_lcd.next_page();
632 ssd1306_lcd.send_pixels1( (0xFF >> (0x07 - (y2 & 0x07)))^s_ssd1306_invertByte );
633 ssd1306_intf.stop();
634 }
635
636 void ssd1306_drawRect(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2)
637 {
638 ssd1306_drawHLine(x1+1, y1, x2-1);
639 ssd1306_drawHLine(x1+1, y2, x2-1);
640 ssd1306_drawVLine(x1, y1, y2);
641 ssd1306_drawVLine(x2, y1, y2);
642 }
643
644 void ssd1306_drawBufferFast(lcdint_t x, lcdint_t y, lcduint_t w, lcduint_t h, const uint8_t *buf)
645 {
646 uint8_t j;
647 ssd1306_lcd.set_block(x, y >> 3, w);
648 for(j=(h >> 3); j>0; j--)
649 {
650 ssd1306_lcd.send_pixels_buffer1(buf,w);
651 buf+=w;
652 ssd1306_lcd.next_page();
653 }
654 ssd1306_intf.stop();
655 }
656
657 void ssd1306_drawBuffer(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *buf)
658 {
659 uint8_t i, j;
660 ssd1306_lcd.set_block(x, y, w);
661 for(j=(h >> 3); j>0; j--)
662 {
663 for(i=w;i>0;i--)
664 {
665 ssd1306_lcd.send_pixels1(s_ssd1306_invertByte^*buf++);
666 }
667 ssd1306_lcd.next_page();
668 }
669 ssd1306_intf.stop();
670 }
671
672 void ssd1306_drawBitmap(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *buf)
673 {
674 uint8_t i, j;
675 uint8_t remainder = (ssd1306_lcd.width - x) < w ? (w + x - ssd1306_lcd.width): 0;
676 w -= remainder;
677 ssd1306_lcd.set_block(x, y, w);
678 for(j=(h >> 3); j>0; j--)
679 {
680 for(i=w;i>0;i--)
681 {
682 ssd1306_lcd.send_pixels1(s_ssd1306_invertByte^pgm_read_byte(buf++));
683 }
684 buf += remainder;
685 ssd1306_lcd.next_page();
686 }
687 ssd1306_intf.stop();
688 }
689
690 void gfx_drawMonoBitmap(lcdint_t x, lcdint_t y, lcduint_t w, lcduint_t h, const uint8_t *buf)
691 {
692 lcduint_t origin_width = w;
693 uint8_t offset = y & 0x07;
694 uint8_t complexFlag = 0;
695 uint8_t mainFlag = 1;
696 uint8_t max_pages;
697 uint8_t pages;
698 lcduint_t i, j;
699 if (y + (lcdint_t)h <= 0) return;
700 if (y >= ssd1306_lcd.height) return;
701 if (x + (lcdint_t)w <= 0) return;
702 if (x >= ssd1306_lcd.width) return;
703 if (y < 0)
704 {
705 buf += ((lcduint_t)((-y) + 7) >> 3) * w;
706 h += y;
707 y = 0;
708 complexFlag = 1;
709 }
710 if (x < 0)
711 {
712 buf += -x;
713 w += x;
714 x = 0;
715 }
716 max_pages = (lcduint_t)(h + 15 - offset) >> 3;
717 if ((lcduint_t)((lcduint_t)y + h) > (lcduint_t)ssd1306_lcd.height)
718 {
719 h = (lcduint_t)(ssd1306_lcd.height - (lcduint_t)y);
720 }
721 if ((lcduint_t)((lcduint_t)x + w) > (lcduint_t)ssd1306_lcd.width)
722 {
723 w = (lcduint_t)(ssd1306_lcd.width - (lcduint_t)x);
724 }
725 pages = ((y + h - 1) >> 3) - (y >> 3) + 1;
726
727 ssd1306_lcd.set_block(x, y >> 3, w);
728 for(j=0; j < pages; j++)
729 {
730 if ( j == max_pages - 1 ) mainFlag = !offset;
731 for( i=w; i > 0; i--)
732 {
733 uint8_t data = 0;
734 if ( mainFlag ) data |= (pgm_read_byte(buf) << offset);
735 if ( complexFlag ) data |= (pgm_read_byte(buf - origin_width) >> (8 - offset));
736 buf++;
737 ssd1306_lcd.send_pixels1(s_ssd1306_invertByte^data);
738 }
739 buf += origin_width - w;
740 complexFlag = offset;
741 ssd1306_lcd.next_page();
742 }
743 ssd1306_intf.stop();
744 }
745
746
747 void ssd1306_clearBlock(uint8_t x, uint8_t y, uint8_t w, uint8_t h)
748 {
749 uint8_t i, j;
750 ssd1306_lcd.set_block(x, y, w);
751 for(j=(h >> 3); j>0; j--)
752 {
753 for(i=w;i>0;i--)
754 {
755 ssd1306_lcd.send_pixels1(s_ssd1306_invertByte);
756 }
757 ssd1306_lcd.next_page();
758 }
759 ssd1306_intf.stop();
760 }
761
762
763 void ssd1306_drawSpriteEx(uint8_t x, uint8_t y, uint8_t w, const uint8_t *sprite)
764 {
765 uint8_t i;
766 ssd1306_lcd.set_block(x,y,w);
767 for(i=0;i<w;i++)
768 {
769 ssd1306_lcd.send_pixels1(s_ssd1306_invertByte^pgm_read_byte(&sprite[i]));
770 }
771 ssd1306_intf.stop();
772 }
773
774
775 void ssd1306_drawSprite(SPRITE *sprite)
776 {
777 uint8_t offsety = sprite->y & 0x7;
778 if (sprite->y < ssd1306_lcd.height)
779 {
780 ssd1306_lcd.set_block(sprite->x, sprite->y >> 3, sprite->w);
781 for (uint8_t i=0; i < sprite->w; i++)
782 {
783 ssd1306_lcd.send_pixels1( s_ssd1306_invertByte^(pgm_read_byte( &sprite->data[i] ) << offsety) );
784 }
785 ssd1306_intf.stop();
786 }
787 if (offsety && (sprite->y + 8 < ssd1306_lcd.height))
788 {
789 ssd1306_lcd.set_block(sprite->x, (sprite->y >> 3) + 1, sprite->w);
790 for (uint8_t i=0; i < sprite->w; i++)
791 {
792 ssd1306_lcd.send_pixels1( s_ssd1306_invertByte^(pgm_read_byte( &sprite->data[i] ) >> (8 - offsety)) );
793 }
794 ssd1306_intf.stop();
795 }
796 sprite->lx = sprite->x;
797 sprite->ly = sprite->y;
798 }
799
800
801 void ssd1306_eraseSprite(SPRITE *sprite)
802 {
803 uint8_t posy = sprite->y >> 3;
804 uint8_t offsety = sprite->y & 0x7;
805 ssd1306_lcd.set_block(sprite->x, posy, sprite->w);
806 for (uint8_t i=sprite->w; i > 0; i--)
807 {
808 ssd1306_lcd.send_pixels1( s_ssd1306_invertByte );
809 }
810 ssd1306_intf.stop();
811 if (offsety)
812 {
813 ssd1306_lcd.set_block(sprite->x, posy + 1, sprite->w);
814 for (uint8_t i=sprite->w; i > 0; i--)
815 {
816 ssd1306_lcd.send_pixels1( s_ssd1306_invertByte );
817 }
818 }
819 ssd1306_intf.stop();
820 }
821
822
823 void ssd1306_eraseTrace(SPRITE *sprite)
824 {
825 uint8_t y1 = sprite->ly >> 3;
826 uint8_t y2 = (sprite->ly + 7) >> 3;
827 if (sprite->ly < sprite->y)
828 y2 = min(y2, (uint8_t)((sprite->y >> 3) - 1));
829 else if (sprite->y + 8 > sprite->ly)
830 y1 = max(y1, (sprite->ly + 7) >> 3);
831 for(uint8_t y = y1; y <= y2; y++)
832 {
833 ssd1306_lcd.set_block(sprite->lx, y, sprite->w);
834 for(uint8_t x = sprite->w; x > 0; x--)
835 {
836 ssd1306_lcd.send_pixels1( s_ssd1306_invertByte );
837 }
838 ssd1306_intf.stop();
839 }
840 if (sprite->lx != sprite->x)
841 {
842 uint8_t x1 = sprite->lx;
843 uint8_t x2 = sprite->lx + sprite->w - 1;
844 if (sprite->x < sprite->lx)
845 x1 = max(x1, sprite->x + sprite->w);
846 else
847 x2 = min((uint8_t)(sprite->x - 1), x2);
848 for(uint8_t y = sprite->ly >> 3; y <= (sprite->ly + 7) >> 3; y++)
849 {
850 ssd1306_lcd.set_block(x1, y, x2 - x1 + 1 );
851 for(uint8_t x = x2 - x1 + 1; x > 0; x--)
852 {
853 ssd1306_lcd.send_pixels1( s_ssd1306_invertByte );
854 }
855 ssd1306_intf.stop();
856 }
857 }
858 }
859
860 SPRITE ssd1306_createSprite(uint8_t x, uint8_t y, uint8_t w, const uint8_t *data)
861 {
862 return (SPRITE){x,y,w,x,y,data,NULL};
863 }
864
865 void ssd1306_replaceSprite(SPRITE *sprite, const uint8_t *data)
866 {
867 sprite->data = data;
868 }
869
870 void ssd1306_negativeMode()
871 {
872 s_ssd1306_invertByte = 0xFF;
873 }
874
875 void ssd1306_positiveMode()
876 {
877 s_ssd1306_invertByte = 0x00;
878 }
879
880 void ssd1306_setFont6x8(const uint8_t * progmemFont)
881 {
882 s_font6x8 = progmemFont + 4;
883 }
884
ssd1306_drawBuffer
void ssd1306_drawBuffer(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *buf)
Definition: ssd1306_1bit.c:657
ssd1306_charF6x8
uint8_t ssd1306_charF6x8(uint8_t x, uint8_t y, const char ch[], EFontStyle style)
Definition: ssd1306_1bit.c:388
ssd1306_putPixels
void ssd1306_putPixels(uint8_t x, uint8_t y, uint8_t pixels)
Definition: ssd1306_1bit.c:531
SCharInfo::height
uint8_t height
char height in pixels
Definition: nano_gfx_types.h:110
ssd1306_positiveMode
void ssd1306_positiveMode()
Definition: ssd1306_1bit.c:875
SPRITE::data
const uint8_t * data
Pointer to PROGMEM data, representing sprite image.
Definition: nano_gfx_types.h:148
ssd1306_createSprite
SPRITE ssd1306_createSprite(uint8_t x, uint8_t y, uint8_t w, const uint8_t *data)
Definition: ssd1306_1bit.c:860
lcd_common.h
SFixedFontInfo::primary_table
const uint8_t * primary_table
font chars bits
Definition: nano_gfx_types.h:100
SCharInfo
Definition: nano_gfx_types.h:107
ssd1306_printFixed2x
uint8_t ssd1306_printFixed2x(uint8_t xpos, uint8_t y, const char ch[], EFontStyle style)
Definition: ssd1306_1bit.c:161
ssd1306.h
ssd1306_drawLine
void ssd1306_drawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2)
Definition: ssd1306_1bit.c:558
ssd1306_printFixed
uint8_t ssd1306_printFixed(uint8_t xpos, uint8_t y, const char *ch, EFontStyle style)
Definition: ssd1306_1bit.c:78
ssd1306_interface_t::stop
void(* stop)(void)
Definition: ssd1306_interface.h:65
ssd1306_drawSprite
void ssd1306_drawSprite(SPRITE *sprite)
Definition: ssd1306_1bit.c:775
SFontHeaderRecord::width
uint8_t width
width in pixels
Definition: nano_gfx_types.h:79
ssd1306_drawRect
void ssd1306_drawRect(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2)
Definition: ssd1306_1bit.c:636
ssd1306_lcd_t::set_block
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
ssd1306_fillScreen
void ssd1306_fillScreen(uint8_t fill_Data)
Definition: ssd1306_1bit.c:49
lcduint_t
unsigned int lcduint_t
Definition: io.h:65
ssd1306_getCharBitmap
void ssd1306_getCharBitmap(uint16_t ch, SCharInfo *info)
returns char data for currently set (active) font.
Definition: ssd1306_generic.c:93
io.h
ssd1306_i2c.h
ssd1306_eraseTrace
void ssd1306_eraseTrace(SPRITE *sprite)
Definition: ssd1306_1bit.c:823
ssd1306_lcd_t::send_pixels_buffer1
void(* send_pixels_buffer1)(const uint8_t *buffer, uint16_t len)
Definition: lcd_common.h:135
ssd1306_drawBitmap
void ssd1306_drawBitmap(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *buf)
Definition: ssd1306_1bit.c:672
ssd1306xled_font6x8
const PROGMEM uint8_t ssd1306xled_font6x8[]
Definition: ssd1306_fonts.c:41
ssd1306_lcd_t::send_pixels1
void(* send_pixels1)(uint8_t data)
Definition: lcd_common.h:128
SFontHeaderRecord::height
uint8_t height
height in pixels
Definition: nano_gfx_types.h:80
SFixedFontInfo
Definition: nano_gfx_types.h:94
gfx_drawMonoBitmap
void gfx_drawMonoBitmap(lcdint_t x, lcdint_t y, lcduint_t w, lcduint_t h, const uint8_t *buf)
Definition: ssd1306_1bit.c:690
SPRITE
Definition: nano_gfx_types.h:135
ssd1306_spi.h
ssd1306_commands.h
ssd1306_lcd
ssd1306_lcd_t ssd1306_lcd
Definition: lcd_common.c:32
ssd1306_print
size_t ssd1306_print(const char ch[])
Prints null-terminated string to display at current cursor position.
Definition: ssd1306_1bit.c:377
ssd1306_charF12x16
uint8_t ssd1306_charF12x16(uint8_t xpos, uint8_t y, const char ch[], EFontStyle style)
Definition: ssd1306_1bit.c:434
ssd1306_eraseSprite
void ssd1306_eraseSprite(SPRITE *sprite)
Definition: ssd1306_1bit.c:801
ssd1306_drawVLine
void ssd1306_drawVLine(uint8_t x1, uint8_t y1, uint8_t y2)
Definition: ssd1306_1bit.c:612
ssd1306_intf
ssd1306_interface_t ssd1306_intf
Definition: ssd1306_interface.c:29
max
#define max(a, b)
Definition: nano_gfx_types.h:40
SPRITE::y
uint8_t y
draw position Y on the screen
Definition: nano_gfx_types.h:140
min
#define min(a, b)
Definition: nano_gfx_types.h:35
ssd1306_lcd_t::height
lcduint_t height
Definition: lcd_common.h:97
SCharInfo::width
uint8_t width
char width in pixels
Definition: nano_gfx_types.h:109
ssd1306_drawSpriteEx
void ssd1306_drawSpriteEx(uint8_t x, uint8_t y, uint8_t w, const uint8_t *sprite)
Definition: ssd1306_1bit.c:763
s_fixedFont
SFixedFontInfo s_fixedFont
Definition: tiler.h:44
SFixedFontInfo::h
SFontHeaderRecord h
record, containing information on font
Definition: nano_gfx_types.h:96
ssd1306_interface.h
SPRITE::x
uint8_t x
draw position X on the screen
Definition: nano_gfx_types.h:138
ssd1306_fonts.h
SCharInfo::glyph
const uint8_t * glyph
char data, located in progmem.
Definition: nano_gfx_types.h:112
ssd1306_printFixedN
uint8_t ssd1306_printFixedN(uint8_t xpos, uint8_t y, const char ch[], EFontStyle style, uint8_t factor)
Definition: ssd1306_1bit.c:242
SPRITE::w
uint8_t w
sprite width
Definition: nano_gfx_types.h:142
ssd1306_drawHLine
void ssd1306_drawHLine(uint8_t x1, uint8_t y1, uint8_t x2)
Definition: ssd1306_1bit.c:602
SSD1306_MORE_CHARS_REQUIRED
#define SSD1306_MORE_CHARS_REQUIRED
Definition: ssd1306_fonts.h:44
ssd1306_lcd_t::next_page
void(* next_page)(void)
Definition: lcd_common.h:122
SCharInfo::spacing
uint8_t spacing
additional spaces after char in pixels
Definition: nano_gfx_types.h:111
SPRITE::lx
uint8_t lx
last draw position X on the screen
Definition: nano_gfx_types.h:144
ssd1306_clearBlock
void ssd1306_clearBlock(uint8_t x, uint8_t y, uint8_t w, uint8_t h)
Definition: ssd1306_1bit.c:747
ssd1306_setFont6x8
void ssd1306_setFont6x8(const uint8_t *progmemFont)
Definition: ssd1306_1bit.c:880
ssd1306_lcd_t::width
lcduint_t width
Definition: lcd_common.h:94
ssd1306_charF6x8_eol
uint8_t ssd1306_charF6x8_eol(uint8_t left, uint8_t y, const char ch[], EFontStyle style, uint8_t right)
Definition: ssd1306_1bit.c:509
ssd1306_clearScreen
void ssd1306_clearScreen()
Definition: ssd1306_1bit.c:64
ssd1306_replaceSprite
void ssd1306_replaceSprite(SPRITE *sprite, const uint8_t *data)
Definition: ssd1306_1bit.c:865
EFontStyle
EFontStyle
Definition: nano_gfx_types.h:58
ssd1306_drawBufferFast
void ssd1306_drawBufferFast(lcdint_t x, lcdint_t y, lcduint_t w, lcduint_t h, const uint8_t *buf)
Definition: ssd1306_1bit.c:644
SFixedFontInfo::pages
uint8_t pages
height in pages (each page height is 8-pixels)
Definition: nano_gfx_types.h:98
ssd1306_swap_data
#define ssd1306_swap_data(a, b, type)
Definition: io.h:69
SPRITE::ly
uint8_t ly
last draw position Y on the screen
Definition: nano_gfx_types.h:146
ssd1306_negativeMode
void ssd1306_negativeMode()
Definition: ssd1306_1bit.c:870
ssd1306_putPixel
void ssd1306_putPixel(uint8_t x, uint8_t y)
Definition: ssd1306_1bit.c:524
ssd1306_write
size_t ssd1306_write(uint8_t ch)
Prints single character to display at current cursor position.
Definition: ssd1306_1bit.c:343