PFW-1504 fix conflicting UI issues

Proposal to fix some of the issues with the initial implementation
it is safer to use the status line code to print the message so
there aren't any conflicts in the LCD cursor position.

Allow inserting a byte into any position in the LCD status message

Also, add a variable to control from which index in the array
should the message start printing. This is very useful for progress
bars and messages which continually update. I think we can save some
memory by applying this to Mesh Bed Leveling later.

Change in memory:
Flash: +106 bytes
SRAM: +1 byte
This commit is contained in:
Guðni Már Gilbert 2023-03-13 20:33:29 +00:00
parent 320997a1f5
commit 63775dfabb
7 changed files with 55 additions and 17 deletions

View File

@ -546,14 +546,14 @@ void lcd_print(const char* s)
while (*s) lcd_write(*(s++));
}
char lcd_print_pad(const char* s, uint8_t len)
uint8_t lcd_print_pad(const char* s, uint8_t len)
{
while (len && *s) {
lcd_write(*(s++));
--len;
}
lcd_space(len);
return *s;
return len;
}
uint8_t lcd_print_pad_P(const char* s, uint8_t len)

View File

@ -56,7 +56,7 @@ extern void lcd_space(uint8_t n);
extern void lcd_printNumber(unsigned long n, uint8_t base);
extern void lcd_print(const char*);
extern char lcd_print_pad(const char* s, uint8_t len);
extern uint8_t lcd_print_pad(const char* s, uint8_t len);
/// @brief print a string from PROGMEM with left-adjusted padding
/// @param s string from PROGMEM.

View File

@ -305,6 +305,7 @@ bool MMU2::VerifyFilamentEnteredPTFE() {
}
Disable_E0();
TryLoadUnloadProgressbarDeinit();
if (fsensorState) {
IncrementLoadFails();

View File

@ -283,16 +283,19 @@ void ReportProgressHook(CommandInProgress cip, uint16_t ec) {
}
void TryLoadUnloadProgressbarInit() {
// Clear the status line
lcd_set_cursor(0, 3);
lcd_space(LCD_WIDTH);
lcd_clearstatus();
}
void TryLoadUnloadProgressbarDeinit() {
// Delay the next status message just so
// the user can see the results clearly
lcd_reset_status_message_timeout();
lcd_clearstatus();
}
void TryLoadUnloadProgressbar(uint8_t col, bool sensorState) {
// Set the cursor position each time in case some other
// part of the firmware changes the cursor position
lcd_putc_at(col, 3, sensorState ? '-' : LCD_STR_SOLID_BLOCK[0]);
lcd_reset_status_message_timeout();
lcd_insert_char_into_status(col, sensorState ? '-' : LCD_STR_SOLID_BLOCK[0]);
if (!lcd_update_enabled) lcdui_print_status_line();
}
void IncrementLoadFails(){

View File

@ -38,6 +38,9 @@ void ReportProgressHook(CommandInProgress cip, uint16_t ec);
/// @brief Clear the status line and setup the LCD cursor
void TryLoadUnloadProgressbarInit();
/// @brief Clear the status line and setup the LCD cursor
void TryLoadUnloadProgressbarDeinit();
/// @brief Add one block to the progress bar
/// @param col pixel position on the LCD status line, should range from 0 to (LCD_WIDTH - 1)
/// @param sensorState if true, filament is not present, else filament is present. This controls which character to render

View File

@ -78,6 +78,7 @@ static float manual_feedrate[] = MANUAL_FEEDRATE;
/* LCD message status */
static LongTimer lcd_status_message_timeout;
static uint8_t lcd_status_message_level;
static uint8_t lcd_status_message_idx = 0;
static char lcd_status_message[LCD_WIDTH + 1];
/* !Configuration settings */
@ -542,7 +543,7 @@ void lcdui_print_status_line(void) {
{
// If printing from SD, show what we are printing
const char* longFilenameOLD = (card.longFilename[0] ? card.longFilename : card.filename);
if( lcd_print_pad(&longFilenameOLD[scrollstuff], LCD_WIDTH) )
if( lcd_print_pad(&longFilenameOLD[scrollstuff], LCD_WIDTH) == 0)
{
scrollstuff++;
} else {
@ -556,13 +557,18 @@ void lcdui_print_status_line(void) {
return; // Nothing to do, waiting for delay to expire
}
lcd_set_cursor(lcd_status_message_idx, 3);
switch (custom_message_type) {
case CustomMsg::M117: // M117 Set the status line message on the LCD
case CustomMsg::Status: // Nothing special, print status message normally
case CustomMsg::M0Wait: // M0/M1 Wait command working even from SD
case CustomMsg::FilamentLoading: // If loading filament, print status
case CustomMsg::MMUProgress: // MMU Progress Codes
lcd_print_pad(lcd_status_message, LCD_WIDTH);
{
const uint8_t padding = lcd_print_pad(&lcd_status_message[lcd_status_message_idx], LCD_WIDTH - lcd_status_message_idx);
lcd_status_message_idx = LCD_WIDTH - padding;
}
break;
case CustomMsg::MeshBedLeveling: // If mesh bed leveling in progress, show the status
if (custom_message_state > 10) {
@ -684,6 +690,12 @@ void lcdui_print_status_screen(void)
}
static void lcdui_refresh(uint8_t clear = true)
{
clear ? lcd_refresh() : lcd_refresh_noclear();
lcd_status_message_idx = 0; // Re-draw message from beginning
}
// Main status screen. It's up to the implementation specific part to show what is needed. As this is very display dependent
void lcd_status_screen() // NOT static due to using inside "Marlin_main" module ("manage_inactivity()")
{
@ -727,13 +739,15 @@ void lcd_status_screen() // NOT static due to using ins
ReInitLCD++;
if (ReInitLCD == 30)
{
lcd_refresh(); // to maybe revive the LCD if static electricity killed it.
ReInitLCD = 0 ;
lcdui_refresh();
}
else
{
if ((ReInitLCD % 10) == 0)
lcd_refresh_noclear(); //to maybe revive the LCD if static electricity killed it.
{
lcdui_refresh(false); //to maybe revive the LCD if static electricity killed it.
}
}
lcdui_print_status_screen();
@ -988,7 +1002,7 @@ void lcd_commands()
void lcd_return_to_status()
{
lcd_refresh(); // to maybe revive the LCD if static electricity killed it.
lcdui_refresh(false); // to maybe revive the LCD if static electricity killed it.
menu_goto(lcd_status_screen, 0, true);
menu_depth = 0;
eFilamentAction = FilamentAction::None; // i.e. non-autoLoad
@ -5759,7 +5773,7 @@ void lcd_sdcard_menu()
if (_md->isDir)
lcd_print(LCD_STR_FOLDER[0]);
if( lcd_print_pad(&_md->scrollPointer[_md->offset], len) )
if( lcd_print_pad(&_md->scrollPointer[_md->offset], len) == 0)
{
_md->lcd_scrollTimer.start();
_md->offset++;
@ -7039,6 +7053,7 @@ static void lcd_updatestatus(const char *message, bool progmem = false)
strncpy(lcd_status_message, message, LCD_WIDTH);
lcd_status_message[LCD_WIDTH] = 0;
lcd_status_message_idx = 0; // Print message from beginning
SERIAL_PROTOCOLLNRPGM(MSG_LCD_STATUS_CHANGED);
@ -7052,6 +7067,19 @@ void lcd_setstatus(const char* message)
lcd_updatestatus(message);
}
void lcd_insert_char_into_status(uint8_t position, const char message)
{
if (position > LCD_WIDTH - 1) return;
lcd_status_message[position] = message;
lcd_draw_update = 1; // force redraw
}
void lcd_clearstatus()
{
memset(lcd_status_message, 0, sizeof(lcd_status_message));
lcd_status_message_idx = 0;
}
void lcd_setstatuspgm(const char* message)
{
if (lcd_message_check(LCD_STATUS_NONE))
@ -7243,7 +7271,7 @@ void menu_lcd_lcdupdate_func(void)
lcd_return_to_status();
lcd_draw_update = 2;
}
if (lcd_draw_update == 2) lcd_clear();
if (lcd_draw_update == 2) lcdui_refresh();
if (lcd_draw_update) lcd_draw_update--;
lcd_next_update_millis = _millis() + LCD_UPDATE_INTERVAL;
}

View File

@ -20,6 +20,9 @@ void ultralcd_init();
#define LCD_STATUS_DELAYED_TIMEOUT 4000
// Set the current status message (equivalent to LCD_STATUS_NONE)
void lcdui_print_status_line(void);
void lcd_clearstatus();
void lcd_insert_char_into_status(uint8_t position, const char message);
void lcd_setstatus(const char* message);
void lcd_setstatuspgm(const char* message);
void lcd_setstatus_serial(const char* message);