34 uint8_t ssd1306_printFixed(uint8_t xpos, uint8_t y,
const char *ch,
EFontStyle style)
37 uint8_t text_index = 0;
38 uint8_t page_offset = 0;
41 ssd1306_lcd.set_block(xpos, y, ssd1306_lcd.width - xpos);
45 if ( (x > ssd1306_lcd.width - s_fixedFont.h.width) || (ch[j] ==
'\0') )
49 if (y >= (ssd1306_lcd.height >> 3))
54 if (page_offset == s_fixedFont.pages)
68 ssd1306_lcd.set_block(xpos, y, ssd1306_lcd.width - xpos);
73 unicode = ssd1306_unicode16FromUtf8(ch[j]);
77 ssd1306_getCharBitmap(unicode, &char_info);
80 if (char_info.
height > page_offset * 8)
82 char_info.
glyph += page_offset * char_info.
width;
83 for( i = char_info.
width; i>0; i--)
86 if ( style == STYLE_NORMAL )
88 data = pgm_read_byte(&char_info.
glyph[0]);
90 else if ( style == STYLE_BOLD )
92 uint8_t temp = pgm_read_byte(&char_info.
glyph[0]);
98 uint8_t temp = pgm_read_byte(&char_info.
glyph[1]);
99 data = (temp & 0xF0) | ldata;
100 ldata = (temp & 0x0F);
102 ssd1306_lcd.send_pixels1(data^s_ssd1306_invertByte);
110 for (i = 0; i < char_info.
spacing; i++)
111 ssd1306_lcd.send_pixels1(s_ssd1306_invertByte);
117 uint8_t ssd1306_printFixed_oldStyle(uint8_t xpos, uint8_t y,
const char *ch,
EFontStyle style)
120 uint8_t text_index = 0;
121 uint8_t page_offset = 0;
124 ssd1306_lcd.set_block(xpos, y, ssd1306_lcd.width - xpos);
130 if( (x > ssd1306_lcd.width - s_fixedFont.h.width) || (ch[j] ==
'\0') )
134 if (y >= (ssd1306_lcd.height >> 3))
139 if (page_offset == s_fixedFont.pages)
153 ssd1306_lcd.set_block(xpos, y, ssd1306_lcd.width - xpos);
156 if ( c >= s_fixedFont.h.ascii_offset )
158 c -= s_fixedFont.h.ascii_offset;
161 offset = (c * s_fixedFont.pages + page_offset) * s_fixedFont.h.width;
162 for( i=s_fixedFont.h.width; i>0; i--)
165 if ( style == STYLE_NORMAL )
167 data = pgm_read_byte(&s_fixedFont.primary_table[offset]);
169 else if ( style == STYLE_BOLD )
171 uint8_t temp = pgm_read_byte(&s_fixedFont.primary_table[offset]);
177 uint8_t temp = pgm_read_byte(&s_fixedFont.primary_table[offset + 1]);
178 data = (temp & 0xF0) | ldata;
179 ldata = (temp & 0x0F);
181 ssd1306_lcd.send_pixels1(data^s_ssd1306_invertByte);
184 x += s_fixedFont.h.width;
191 uint8_t ssd1306_printFixed2x(uint8_t xpos, uint8_t y,
const char ch[],
EFontStyle style)
194 uint8_t text_index = 0;
195 uint8_t page_offset = 0;
198 ssd1306_lcd.set_block(xpos, y, ssd1306_lcd.width - xpos);
204 if( (x > ssd1306_lcd.width - (s_fixedFont.h.width << 1)) || (ch[j] ==
'\0') )
208 if (y >= (ssd1306_lcd.height >> 3))
213 if (page_offset == (s_fixedFont.pages << 1))
227 ssd1306_lcd.set_block(xpos, y, ssd1306_lcd.width - xpos);
235 offset = (c * s_fixedFont.pages + (page_offset >> 1)) * s_fixedFont.h.width;
236 for( i=s_fixedFont.h.width; i>0; i--)
239 if ( style == STYLE_NORMAL )
241 data = pgm_read_byte(&s_fixedFont.primary_table[offset]);
243 else if ( style == STYLE_BOLD )
245 uint8_t temp = pgm_read_byte(&s_fixedFont.primary_table[offset]);
251 uint8_t temp = pgm_read_byte(&s_fixedFont.primary_table[offset + 1]);
252 data = (temp & 0xF0) | ldata;
253 ldata = (temp & 0x0F);
255 if (page_offset & 1) data >>= 4;
256 data = ((data & 0x01) ? 0x03: 0x00) |
257 ((data & 0x02) ? 0x0C: 0x00) |
258 ((data & 0x04) ? 0x30: 0x00) |
259 ((data & 0x08) ? 0xC0: 0x00);
260 ssd1306_lcd.send_pixels1(data^s_ssd1306_invertByte);
261 ssd1306_lcd.send_pixels1(data^s_ssd1306_invertByte);
264 x += (s_fixedFont.h.width << 1);
272 uint8_t ssd1306_printFixedN(uint8_t xpos, uint8_t y,
const char ch[],
EFontStyle style, uint8_t factor)
275 uint8_t text_index = 0;
276 uint8_t page_offset = 0;
279 ssd1306_lcd.set_block(xpos, y, ssd1306_lcd.width - xpos);
283 if( (x > ssd1306_lcd.width - (s_fixedFont.h.width << factor)) || (ch[j] ==
'\0') )
287 if (y >= (ssd1306_lcd.height >> 3))
292 if (page_offset == (s_fixedFont.pages << factor))
306 ssd1306_lcd.set_block(xpos, y, ssd1306_lcd.width - xpos);
311 unicode = ssd1306_unicode16FromUtf8(ch[j]);
315 ssd1306_getCharBitmap(unicode, &char_info);
318 if (char_info.
height > (page_offset >> factor) * 8)
320 char_info.
glyph += (page_offset >> factor) * char_info.
width;
321 for( i=char_info.
width; i>0; i--)
324 if ( style == STYLE_NORMAL )
326 data = pgm_read_byte(char_info.
glyph);
328 else if ( style == STYLE_BOLD )
330 uint8_t temp = pgm_read_byte(char_info.
glyph);
336 uint8_t temp = pgm_read_byte(char_info.
glyph+1);
337 data = (temp & 0xF0) | ldata;
338 ldata = (temp & 0x0F);
343 uint8_t mask = ~((0xFF) << (1<<factor));
348 data >>= ((page_offset & ((1<<factor) - 1))<<(3-factor));
349 for (uint8_t idx = 0; idx < 1<<(3-factor); idx++)
351 accum |= (((data>>idx) & 0x01) ? (mask<<(idx<<factor)) : 0);
355 for (uint8_t z=(1<<factor); z>0; z--)
357 ssd1306_lcd.send_pixels1(data^s_ssd1306_invertByte);
366 for (i = 0; i < (char_info.
spacing << factor); i++)
367 ssd1306_lcd.send_pixels1(s_ssd1306_invertByte);
373 void ssd1306_putPixel_delayed(uint8_t x, uint8_t y, uint8_t complete)
375 static uint8_t lx = 0, ly = 0xFF;
376 static uint8_t pixels = 0;
377 if ((lx != x) || ((ly & 0xF8) != (y & 0xF8)) || (complete))
381 ssd1306_putPixels( lx, ly, pixels );
388 pixels |= (1 << (y & 0x07));
393 void ssd1306_drawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2)
395 lcduint_t dx = x1 > x2 ? (x1 - x2): (x2 - x1);
396 lcduint_t dy = y1 > y2 ? (y1 - y2): (y2 - y1);
411 x1 < x2 ? x1++: x1--;
413 ssd1306_putPixel_delayed( x1, y1, 0 );
415 ssd1306_putPixel_delayed( 0, 0, 1 );
430 if (y1 < y2) y1++;
else y1--;
432 ssd1306_putPixel( x1, y1 );
440 ssd1306_lcd.set_block(x, y >> 3, w);
441 for(j=(h >> 3); j>0; j--)
443 ssd1306_lcd.send_pixels_buffer1(buf,w);
445 ssd1306_lcd.next_page();
453 uint8_t offset = y & 0x07;
454 uint8_t complexFlag = 0;
455 uint8_t mainFlag = 1;
460 if (y >= (
lcdint_t)ssd1306_lcd.height)
return;
462 if (x >= (
lcdint_t)ssd1306_lcd.width)
return;
476 max_pages = (
lcduint_t)(h + 15 - offset) >> 3;
485 pages = ((y + h - 1) >> 3) - (y >> 3) + 1;
487 ssd1306_lcd.set_block(x, y >> 3, w);
488 for(j=0; j < pages; j++)
490 if ( j == (
lcduint_t)(max_pages - 1) ) mainFlag = !offset;
491 for( i=w; i > 0; i--)
494 if ( mainFlag ) data |= (pgm_read_byte(buf) << offset);
495 if ( complexFlag ) data |= (pgm_read_byte(buf - origin_width) >> (8 - offset));
497 ssd1306_lcd.send_pixels1(s_ssd1306_invertByte^data);
499 buf += origin_width - w;
500 complexFlag = offset;
501 ssd1306_lcd.next_page();
507 void ssd1306_setFont6x8(
const uint8_t * progmemFont)
509 s_font6x8 = progmemFont + 4;
520 template <
class O,
class I>
523 this->putPixel(p.
x, p.
y);
526 template <
class O,
class I>
529 this->drawHLine(x1, y1, x2);
530 this->drawHLine(x1, y2, x2);
531 this->drawVLine(x1, y1, y2);
532 this->drawVLine(x2, y1, y2);
535 template <
class O,
class I>
538 this->drawRect(rect.
p1.
x, rect.
p1.
y, rect.
p2.
x, rect.
p2.
y);
541 template <
class O,
class I>
544 lcduint_t dx = x1 > x2 ? (x1 - x2): (x2 - x1);
545 lcduint_t dy = y1 > y2 ? (y1 - y2): (y2 - y1);
560 x1 < x2 ? x1++: x1--;
562 this->putPixel( x1, y1 );
578 if (y1 < y2) y1++;
else y1--;
580 this->putPixel( x1, y1 );
585 template <
class O,
class I>
588 this->drawLine(rect.
p1.
x, rect.
p1.
y, rect.
p2.
x, rect.
p2.
y);
591 template <
class O,
class I>
594 this->fillRect(rect.
p1.
x, rect.
p1.
y, rect.
p2.
x, rect.
p2.
y);
597 template <
class O,
class I>
600 this->m_fontStyle = style;
601 this->m_cursorX = xpos;
605 char c = pgm_read_byte(ch);
612 template <
class O,
class I>
622 template <
class O,
class I>
626 snprintf(intStr,
sizeof(intStr),
"%i", number );
627 this->write( intStr );
631 #define min(x,y) ((x)<(y)?(x):(y)) 635 #define max(x,y) ((x)>(y)?(x):(y)) 638 template <
class O,
class I>
641 return (menu->
height - 16) / display.getFont().getHeader().height;
644 template <
class O,
class I>
647 if ( selection < menu->scrollPosition )
651 else if ( selection - menu->
scrollPosition > getMaxScreenItems<O,I>(display, menu) - 1)
653 return selection - getMaxScreenItems<O,I>(display, menu) + 1;
658 template <
class O,
class I>
663 display.negativeMode();
667 display.positiveMode();
670 display.printFixed(menu->
left + 8, item_top,
671 menu->
items[index], STYLE_NORMAL );
672 display.positiveMode();
675 template <
class O,
class I>
680 display.negativeMode();
684 display.positiveMode();
687 display.setColor( 0x0000 );
688 display.
fillRect( menu->
left + 8 + display.getFont().getTextSize(menu->
items[index]), item_top,
689 menu->
width + menu->
left - 9, item_top + display.getFont().getHeader().height - 1 );
690 display.setColor( 0xFFFF );
691 display.printFixed(menu->
left + 8, item_top,
692 menu->
items[index], STYLE_NORMAL );
693 display.positiveMode();
696 template <
class O,
class I>
710 template <
class O,
class I>
715 for (uint8_t i = menu->scrollPosition; i <
min(menu->count, (menu->scrollPosition + getMaxScreenItems<O,I>( *
this, menu ))); i++)
717 drawMenuItem<O,I>(*
this, menu, i);
719 menu->oldSelection = menu->selection;
722 template <
class O,
class I>
727 for (uint8_t i = menu->scrollPosition; i <
min(menu->count, (menu->scrollPosition + getMaxScreenItems<O,I>( *
this, menu ))); i++)
729 drawMenuItemSmooth<O,I>(*
this, menu, i);
731 menu->oldSelection = menu->selection;
734 template <
class O,
class I>
739 uint8_t scrollPosition = calculateScrollPosition<O,I>( *
this, menu, menu->
selection );
740 if ( scrollPosition != menu->scrollPosition )
747 drawMenuItem<O,I>( *
this, menu, menu->oldSelection);
748 drawMenuItem<O,I>( *
this, menu, menu->selection);
749 menu->oldSelection = menu->selection;
754 template <
class O,
class I>
759 uint8_t scrollPosition = calculateScrollPosition<O,I>( *
this, menu, menu->
selection );
760 if ( scrollPosition != menu->scrollPosition )
762 showMenuSmooth(menu);
766 drawMenuItemSmooth<O,I>( *
this, menu, menu->oldSelection);
767 drawMenuItemSmooth<O,I>( *
this, menu, menu->selection);
768 menu->oldSelection = menu->selection;
773 template <
class O,
class I>
779 template <
class O,
class I>
792 template <
class O,
class I>
805 template <
class O,
class I>
811 template <
class O,
class I>
817 template <
class O,
class I>
823 template <
class O,
class I>
829 template <
class O,
class I>
834 char str[5] =
"100%";
835 if ( progress < 100 )
838 str[1] = progress / 10 +
'0';
839 str[2] = progress % 10 +
'0';
842 if ( this->m_font !=
nullptr )
844 width = this->getFont().getTextSize( str, &height );
846 lcdint_t middle = this->height() / 2;
847 lcdint_t progress_pos = 8 + (int16_t)(this->width() - 16) * progress / 100;
848 uint16_t color = this->m_color;
849 this->m_color = 0x0000;
850 this->fillRect( progress_pos, middle, this->width() - 8, middle + height );
851 this->m_color = color;
852 this->drawRect( progress_pos, middle, this->width() - 8, middle + height );
853 this->fillRect( 8, middle, progress_pos, middle + height );
854 if ( this->m_font !=
nullptr )
856 this->printFixed( this->width() / 2 - width / 2, middle - height, str );
860 template <
class O,
class I>
863 const char *caption,
bool blank)
865 if ( width == 0 ) { width = this->width() - 8; x = 4; }
866 if ( height == 0 ) { height = this->height() - 4; y = 0; }
869 uint16_t color = this->m_color;
870 this->m_color = 0x0000;
871 this->fillRect( x, y, x + width - 1, y + height - 1 );
872 this->m_color = color;
876 y += this->getFont().getHeader().height / 2;
877 height -= this->getFont().getHeader().height / 2;
879 this->drawRect( x, y, x + width - 1, y + height - 1 );
883 lcduint_t twidth = this->getFont().getTextSize( caption, &theight );
884 this->printFixed( x + (width - twidth)/2, y - theight/2, caption );
uint8_t height
char height in pixels
void menuUp(SAppMenu *menu)
void drawRect(lcdint_t x1, lcdint_t y1, lcdint_t x2, lcdint_t y2)
void write(const char *str)
uint8_t menuSelection(SAppMenu *menu)
void createMenu(SAppMenu *menu, const char **items, uint8_t count, const NanoRect &rect={})
#define SSD1306_MORE_CHARS_REQUIRED
void putPixel(const NanoPoint &p)
void drawCanvas(lcdint_t x, lcdint_t y, NanoCanvasOps< 1 > &canvas) __attribute__((noinline))
void drawLine(lcdint_t x1, lcdint_t y1, lcdint_t x2, lcdint_t y2)
void updateMenuSmooth(SAppMenu *menu)
void updateMenu(SAppMenu *menu)
ssd1306_interface_t ssd1306_intf
void showMenuSmooth(SAppMenu *menu)
uint8_t width
char width in pixels
void showMenu(SAppMenu *menu)
void fillRect(const NanoRect &rect)
const uint8_t * glyph
char data, located in progmem.
void drawProgressBar(int8_t progress)
void printFixedPgm(lcdint_t xpos, lcdint_t y, const char *ch, EFontStyle style=STYLE_NORMAL) __attribute__((noinline))
uint8_t spacing
additional spaces after char in pixels
void drawWindow(lcdint_t x, lcdint_t y, lcduint_t width, lcduint_t height, const char *caption, bool blank)
#define ssd1306_swap_data(a, b, type)
void menuDown(SAppMenu *menu)