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;
522 this->putPixel(p.
x, p.
y);
527 this->drawHLine(x1, y1, x2);
528 this->drawHLine(x1, y2, x2);
529 this->drawVLine(x1, y1, y2);
530 this->drawVLine(x2, y1, y2);
535 this->drawRect(rect.
p1.
x, rect.
p1.
y, rect.
p2.
x, rect.
p2.
y);
540 lcduint_t dx = x1 > x2 ? (x1 - x2) : (x2 - x1);
541 lcduint_t dy = y1 > y2 ? (y1 - y2) : (y2 - y1);
550 for ( ; y1 <= y2; y1++ )
556 x1 < x2 ? x1++ : x1--;
558 this->putPixel(x1, y1);
568 for ( ; x1 <= x2; x1++ )
579 this->putPixel(x1, y1);
586 this->drawLine(rect.
p1.
x, rect.
p1.
y, rect.
p2.
x, rect.
p2.
y);
591 this->fillRect(rect.
p1.
x, rect.
p1.
y, rect.
p2.
x, rect.
p2.
y);
599 if (options & (2 + 4)) putPixel(xc, yc + r);
600 if (options & (1 + 8)) putPixel(xc, yc - r);
601 if (options & (1 + 2)) putPixel(xc + r, yc);
602 if (options & (4 + 8)) putPixel(xc - r, yc);
612 if (options & (2)) putPixel(xc + x, yc + y);
613 if (options & (4)) putPixel(xc - x, yc + y);
614 if (options & (1)) putPixel(xc + x, yc - y);
615 if (options & (8)) putPixel(xc - x, yc - y);
616 if (options & (2)) putPixel(xc + y, yc + x);
617 if (options & (4)) putPixel(xc - y, yc + x);
618 if (options & (1)) putPixel(xc + y, yc - x);
619 if (options & (8)) putPixel(xc - y, yc - x);
623 template <
class O,
class I>
626 this->m_fontStyle = style;
627 this->m_cursorX = xpos;
631 char c = pgm_read_byte(ch);
651 snprintf(intStr,
sizeof(intStr),
"%i", number);
658 snprintf(intStr,
sizeof(intStr),
"%f", number);
664 const char intStr[2] = {c,
'\0'};
669 #define lcd_gfx_min(x, y) ((x) < (y) ? (x) : (y)) 673 #define lcd_gfx_max(x, y) ((x) > (y) ? (x) : (y)) 678 return (menu->
height - 16) / display.getFont().getHeader().height;
681 template <
class O,
class I>
684 if ( selection < menu->scrollPosition )
688 else if ( selection - menu->
scrollPosition > getMaxScreenItems<O, I>(display, menu) - 1 )
690 return selection - getMaxScreenItems<O, I>(display, menu) + 1;
699 display.invertColors();
702 display.printFixed(menu->
left + 8, item_top, menu->
items[index], STYLE_NORMAL);
705 display.invertColors();
713 display.invertColors();
716 display.setColor(0x0000);
717 display.
fillRect(menu->
left + 8 + display.getFont().getTextSize(menu->
items[index]), item_top,
718 menu->
width + menu->
left - 9, item_top + display.getFont().getHeader().height - 1);
719 display.setColor(0xFFFF);
720 display.printFixed(menu->
left + 8, item_top, menu->
items[index], STYLE_NORMAL);
723 display.invertColors();
727 template <
class O,
class I>
745 for ( uint8_t i = menu->scrollPosition;
746 i <
lcd_gfx_min(menu->count, (menu->scrollPosition + getMaxScreenItems<O, I>(*
this, menu))); i++ )
748 drawMenuItem<O, I>(*
this, menu, i);
750 menu->oldSelection = menu->selection;
757 for ( uint8_t i = menu->scrollPosition;
758 i <
lcd_gfx_min(menu->count, (menu->scrollPosition + getMaxScreenItems<O, I>(*
this, menu))); i++ )
760 drawMenuItemSmooth<O, I>(*
this, menu, i);
762 menu->oldSelection = menu->selection;
769 uint8_t scrollPosition = calculateScrollPosition<O, I>(*
this, menu, menu->
selection);
770 if ( scrollPosition != menu->scrollPosition )
777 drawMenuItem<O, I>(*
this, menu, menu->oldSelection);
778 drawMenuItem<O, I>(*
this, menu, menu->selection);
779 menu->oldSelection = menu->selection;
788 uint8_t scrollPosition = calculateScrollPosition<O, I>(*
this, menu, menu->
selection);
789 if ( scrollPosition != menu->scrollPosition )
791 showMenuSmooth(menu);
795 drawMenuItemSmooth<O, I>(*
this, menu, menu->oldSelection);
796 drawMenuItemSmooth<O, I>(*
this, menu, menu->selection);
797 menu->oldSelection = menu->selection;
855 char str[5] =
"100%";
856 if ( progress < 100 )
859 str[1] = progress / 10 +
'0';
860 str[2] = progress % 10 +
'0';
863 if ( this->m_font !=
nullptr )
865 width = this->getFont().getTextSize(str, &height);
867 lcdint_t middle = this->height() / 2;
868 lcdint_t progress_pos = 8 + (int16_t)(this->width() - 16) * progress / 100;
869 uint16_t color = this->m_color;
870 this->m_color = 0x0000;
871 this->fillRect(progress_pos, middle, this->width() - 8, middle + height);
872 this->m_color = color;
873 this->drawRect(progress_pos, middle, this->width() - 8, middle + height);
874 this->fillRect(8, middle, progress_pos, middle + height);
875 if ( this->m_font !=
nullptr )
877 this->printFixed(this->width() / 2 - width / 2, middle - height, str);
881 template <
class O,
class I>
887 width = this->width() - 8;
892 height = this->height() - 4;
897 uint16_t color = this->m_color;
898 this->m_color = 0x0000;
899 this->fillRect(x, y, x + width - 1, y + height - 1);
900 this->m_color = color;
904 y += this->getFont().getHeader().height / 2;
905 height -= this->getFont().getHeader().height / 2;
907 this->drawRect(x, y, x + width - 1, y + height - 1);
911 lcduint_t twidth = this->getFont().getTextSize(caption, &theight);
912 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)
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 drawCircle(lcdint_t xc, lcdint_t yc, lcdint_t r, uint8_t options=0x0F)
void drawLine(lcdint_t x1, lcdint_t y1, lcdint_t x2, lcdint_t y2)
void updateMenuSmooth(SAppMenu *menu)
void updateMenu(SAppMenu *menu)
void showMenuSmooth(SAppMenu *menu)
#define lcd_gfx_min(a, b)
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)
uint8_t menuSelection(const SAppMenu *menu)
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)