diff --git a/Firmware/lcd.cpp b/Firmware/lcd.cpp index 81f0c6e00..ba8678ca1 100644 --- a/Firmware/lcd.cpp +++ b/Firmware/lcd.cpp @@ -82,7 +82,6 @@ uint8_t lcd_escape[8]; #endif static uint8_t lcd_custom_characters[8] = {0}; -static uint8_t lcd_custom_index = 0; static void lcd_display(void); @@ -101,6 +100,7 @@ static void lcd_no_autoscroll(void); #endif static void lcd_print_custom(uint8_t c); +static void lcd_invalidate_custom_characters(); #ifdef VT100 void lcd_escape_write(uint8_t chr); @@ -244,12 +244,13 @@ void lcd_refresh_noclear(void) lcd_begin(0); } -// Clear display, set cursor position to zero and unshift the display. It does not clear the custom characters memory +// Clear display, set cursor position to zero and unshift the display. It also invalidates all custom characters void lcd_clear(void) { lcd_command(LCD_CLEARDISPLAY, 1600); lcd_currline = 0; lcd_ddram_address = 0; + lcd_invalidate_custom_characters(); } // Set cursor position to zero and in DDRAM. It does not unshift the display. @@ -831,25 +832,36 @@ const CustomCharacter Font[] PROGMEM = { #include "Fonts/FontTable.h" }; +// #define DEBUG_CUSTOM_CHARACTERS + static void lcd_print_custom(uint8_t c) { uint8_t charToSend; // check if we already have the character in the lcd memory - for (uint8_t i = 0; i < lcd_custom_index; i++) { - if (lcd_custom_characters[i] == c) { - // send the found custom character id - charToSend = i; + for (uint8_t i = 0; i < 8; i++) { + if ((lcd_custom_characters[i] & 0x7F) == (c & 0x7F)) { + lcd_custom_characters[i] = c; // mark the custom character as used + charToSend = i; // send the found custom character id +#ifdef DEBUG_CUSTOM_CHARACTERS + printf_P(PSTR("found char %02x at index %u\n"), c, i); +#endif // DEBUG_CUSTOM_CHARACTERS goto sendChar; } } - // character not in memory. - if (lcd_custom_index >= 8) { //ran out of custom characters. Use the alternate character. - charToSend = pgm_read_byte(&Font[c - 0x80].alternate); - } - else { //create a new custom character and send it - lcd_createChar_P(lcd_custom_index, Font[c - 0x80].data); - lcd_custom_characters[lcd_custom_index] = c; - charToSend = lcd_custom_index++; + // in case no empty slot is found, use the alternate character. + charToSend = pgm_read_byte(&Font[c - 0x80].alternate); + + // try to find a slot where it could be placed + for (uint8_t i = 0; i < 8; i++) { + if (lcd_custom_characters[i] == 0x7F) { //found an empty slot. create a new custom character and send it + lcd_createChar_P(i, Font[c - 0x80].data); + lcd_custom_characters[i] = c; // mark the custom character as used +#ifdef DEBUG_CUSTOM_CHARACTERS + printf_P(PSTR("new char %02x at slot %u\n"), c, i); +#endif // DEBUG_CUSTOM_CHARACTERS + charToSend = i; + break; + } } sendChar: @@ -857,6 +869,31 @@ sendChar: lcd_ddram_address++; // no need for preventing ddram overflow } -void lcd_invalidate_custom_characters() { - lcd_custom_index = 0; +static void lcd_invalidate_custom_characters() { + memset(lcd_custom_characters, 0x7F, sizeof(lcd_custom_characters)); +} + +void lcd_frame_start() { + // check all custom characters and discard unused ones + for (uint8_t i = 0; i < 8; i++) { + uint8_t c = lcd_custom_characters[i]; + if (c == 0x7F) { //slot empty + continue; + } + else if (c & 0x80) { //slot was used on the last frame update, mark it as potentially unused this time + lcd_custom_characters[i] = c & 0x7F; + } + else { //character is no longer used (or invalid?), mark it as unused + lcd_custom_characters[i] = 0x7F; + } + + } + +#ifdef DEBUG_CUSTOM_CHARACTERS + printf_P(PSTR("frame start:")); + for (uint8_t i = 0; i < 8; i++) { + printf_P(PSTR(" %02x"), lcd_custom_characters[i]); + } + printf_P(PSTR("\n")); +#endif // DEBUG_CUSTOM_CHARACTERS } diff --git a/Firmware/lcd.h b/Firmware/lcd.h index ed368b2c8..f8a1811ad 100644 --- a/Firmware/lcd.h +++ b/Firmware/lcd.h @@ -189,7 +189,7 @@ struct CustomCharacter { const char alternate; }; -extern void lcd_invalidate_custom_characters(); +extern void lcd_frame_start(); //! @brief Consume click and longpress event inline void lcd_consume_click() diff --git a/Firmware/menu.cpp b/Firmware/menu.cpp index 2ce628042..556b8fca0 100755 --- a/Firmware/menu.cpp +++ b/Firmware/menu.cpp @@ -73,6 +73,7 @@ void menu_start(void) menu_top = lcd_encoder; menu_line = menu_top; menu_clicked = lcd_clicked(); // Consume click event + if (lcd_draw_update) lcd_frame_start(); } void menu_end(void) diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index 7b71dc858..0e3391604 100644 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -627,6 +627,7 @@ void lcdui_print_status_line(void) { //! @endcode void lcdui_print_status_screen(void) { + lcd_frame_start(); lcd_home(); //line 0 //Print the hotend temperature (9 chars total) @@ -680,7 +681,6 @@ void lcdui_print_status_screen(void) #ifndef DEBUG_DISABLE_LCD_STATUS_LINE lcdui_print_status_line(); #endif //DEBUG_DISABLE_LCD_STATUS_LINE - } static void lcdui_refresh(uint8_t clear = true) @@ -2862,6 +2862,7 @@ static const char* lcd_display_message_fullscreen_nonBlocking_P(const char *msg) { const char *msgend = msg; bool multi_screen = false; + lcd_frame_start(); for (uint8_t row = 0; row < LCD_HEIGHT; ++ row) { lcd_set_cursor(0, row);