1
0
mirror of https://github.com/MarlinFirmware/Marlin.git synced 2024-11-27 22:08:02 +00:00

Merge pull request #8913 from thinkyhead/bf2_multitool_M600

[2.0.x] Multi extruder support for M600 / LCD
This commit is contained in:
Scott Lahteine 2017-12-27 04:40:50 -06:00 committed by GitHub
commit f8156d2d2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 150 additions and 47 deletions

View File

@ -24,14 +24,15 @@
#if ENABLED(ADVANCED_PAUSE_FEATURE) #if ENABLED(ADVANCED_PAUSE_FEATURE)
#include "../../../feature/pause.h"
#include "../../gcode.h" #include "../../gcode.h"
#include "../../../feature/pause.h"
#include "../../../module/motion.h" #include "../../../module/motion.h"
#include "../../parser.h"
#include "../../../module/printcounter.h" #include "../../../module/printcounter.h"
#if EXTRUDERS > 1
#include "../../../module/tool_change.h"
#endif
/** /**
* M600: Pause for filament change * M600: Pause for filament change
* *
@ -42,6 +43,7 @@
* U[distance] - Retract distance for removal (negative value) (manual reload) * U[distance] - Retract distance for removal (negative value) (manual reload)
* L[distance] - Extrude distance for insertion (positive value) (manual reload) * L[distance] - Extrude distance for insertion (positive value) (manual reload)
* B[count] - Number of times to beep, -1 for indefinite (if equipped with a buzzer) * B[count] - Number of times to beep, -1 for indefinite (if equipped with a buzzer)
* T[toolhead] - Select extruder for filament change
* *
* Default values are used for omitted arguments. * Default values are used for omitted arguments.
* *
@ -54,6 +56,18 @@ void GcodeSuite::M600() {
if (axis_unhomed_error()) home_all_axes(); if (axis_unhomed_error()) home_all_axes();
#endif #endif
#if EXTRUDERS > 1
// Change toolhead if specified
uint8_t active_extruder_before_filament_change = -1;
if (parser.seen('T')) {
const uint8_t extruder = parser.value_byte();
if (active_extruder != extruder) {
active_extruder_before_filament_change = active_extruder;
tool_change(extruder, 0, true);
}
}
#endif
// Initial retract before move to filament change position // Initial retract before move to filament change position
const float retract = parser.seen('E') ? parser.value_axis_units(E_AXIS) : 0 const float retract = parser.seen('E') ? parser.value_axis_units(E_AXIS) : 0
#ifdef PAUSE_PARK_RETRACT_LENGTH #ifdef PAUSE_PARK_RETRACT_LENGTH
@ -61,16 +75,12 @@ void GcodeSuite::M600() {
#endif #endif
; ;
// Lift Z axis
if (parser.seenval('Z'))
park_point.z = parser.linearval('Z');
// Move XY axes to filament change position or given position // Move XY axes to filament change position or given position
if (parser.seenval('X')) if (parser.seenval('X')) park_point.x = parser.linearval('X');
park_point.x = parser.linearval('X'); if (parser.seenval('Y')) park_point.y = parser.linearval('Y');
if (parser.seenval('Y')) // Lift Z axis
park_point.y = parser.linearval('Y'); if (parser.seenval('Z')) park_point.z = parser.linearval('Z');
#if HOTENDS > 1 && DISABLED(DUAL_X_CARRIAGE) #if HOTENDS > 1 && DISABLED(DUAL_X_CARRIAGE)
park_point.x += (active_extruder ? hotend_offset[X_AXIS][active_extruder] : 0); park_point.x += (active_extruder ? hotend_offset[X_AXIS][active_extruder] : 0);
@ -106,6 +116,12 @@ void GcodeSuite::M600() {
resume_print(load_length, ADVANCED_PAUSE_EXTRUDE_LENGTH, beep_count); resume_print(load_length, ADVANCED_PAUSE_EXTRUDE_LENGTH, beep_count);
} }
#if EXTRUDERS > 1
// Restore toolhead if it was changed
if (active_extruder_before_filament_change >= 0)
tool_change(active_extruder_before_filament_change, 0, true);
#endif
// Resume the print job timer if it was running // Resume the print job timer if it was running
if (job_running) print_job_timer.start(); if (job_running) print_job_timer.start();
} }

View File

@ -295,7 +295,8 @@ uint16_t max_display_update_time = 0;
*/ */
#define _MENU_ITEM_PART_1(TYPE, ...) \ #define _MENU_ITEM_PART_1(TYPE, ...) \
if (_menuLineNr == _thisItemNr) { \ if (_menuLineNr == _thisItemNr) { \
if (lcd_clicked && encoderLine == _thisItemNr) { if (encoderLine == _thisItemNr && lcd_clicked) { \
lcd_clicked = false
#define _MENU_ITEM_PART_2(TYPE, LABEL, ...) \ #define _MENU_ITEM_PART_2(TYPE, LABEL, ...) \
menu_action_ ## TYPE(__VA_ARGS__); \ menu_action_ ## TYPE(__VA_ARGS__); \
@ -499,6 +500,12 @@ uint16_t max_display_update_time = 0;
float raw_Ki, raw_Kd; // place-holders for Ki and Kd edits float raw_Ki, raw_Kd; // place-holders for Ki and Kd edits
#endif #endif
inline bool use_click() {
const bool click = lcd_clicked;
lcd_clicked = false;
return click;
}
/** /**
* General function to go directly to a screen * General function to go directly to a screen
*/ */
@ -678,7 +685,7 @@ void lcd_status_screen() {
#if ENABLED(ULTIPANEL) #if ENABLED(ULTIPANEL)
if (lcd_clicked) { if (use_click()) {
#if ENABLED(FILAMENT_LCD_DISPLAY) && ENABLED(SDSUPPORT) #if ENABLED(FILAMENT_LCD_DISPLAY) && ENABLED(SDSUPPORT)
previous_lcd_status_ms = millis(); // get status message to show up for a while previous_lcd_status_ms = millis(); // get status message to show up for a while
#endif #endif
@ -861,7 +868,7 @@ void kill_screen(const char* lcd_msg) {
static void progress_bar_test() { static void progress_bar_test() {
static int8_t bar_percent = 0; static int8_t bar_percent = 0;
if (lcd_clicked) { if (use_click()) {
lcd_goto_previous_menu(); lcd_goto_previous_menu();
lcd_set_custom_characters(CHARSET_MENU); lcd_set_custom_characters(CHARSET_MENU);
return; return;
@ -1088,7 +1095,7 @@ void kill_screen(const char* lcd_msg) {
#if ENABLED(BABYSTEPPING) #if ENABLED(BABYSTEPPING)
void _lcd_babystep(const AxisEnum axis, const char* msg) { void _lcd_babystep(const AxisEnum axis, const char* msg) {
if (lcd_clicked) { return lcd_goto_previous_menu_no_defer(); } if (use_click()) { return lcd_goto_previous_menu_no_defer(); }
ENCODER_DIRECTION_NORMAL(); ENCODER_DIRECTION_NORMAL();
if (encoderPosition) { if (encoderPosition) {
const int16_t babystep_increment = (int32_t)encoderPosition * (BABYSTEP_MULTIPLICATOR); const int16_t babystep_increment = (int32_t)encoderPosition * (BABYSTEP_MULTIPLICATOR);
@ -1111,7 +1118,7 @@ void kill_screen(const char* lcd_msg) {
#if ENABLED(BABYSTEP_ZPROBE_OFFSET) #if ENABLED(BABYSTEP_ZPROBE_OFFSET)
void lcd_babystep_zoffset() { void lcd_babystep_zoffset() {
if (lcd_clicked) { return lcd_goto_previous_menu_no_defer(); } if (use_click()) { return lcd_goto_previous_menu_no_defer(); }
defer_return_to_status = true; defer_return_to_status = true;
ENCODER_DIRECTION_NORMAL(); ENCODER_DIRECTION_NORMAL();
if (encoderPosition) { if (encoderPosition) {
@ -1239,11 +1246,14 @@ void kill_screen(const char* lcd_msg) {
#if ENABLED(ADVANCED_PAUSE_FEATURE) #if ENABLED(ADVANCED_PAUSE_FEATURE)
void lcd_enqueue_filament_change() { void lcd_enqueue_filament_change(
#if EXTRUDERS > 1
const uint8_t extruder
#endif
) {
#if ENABLED(PREVENT_COLD_EXTRUSION) #if ENABLED(PREVENT_COLD_EXTRUSION)
if (!DEBUGGING(DRYRUN) && !thermalManager.allow_cold_extrude && if (!DEBUGGING(DRYRUN) && thermalManager.tooColdToExtrude(active_extruder)) {
thermalManager.degTargetHotend(active_extruder) < thermalManager.extrude_min_temp) {
lcd_save_previous_screen(); lcd_save_previous_screen();
lcd_goto_screen(lcd_advanced_pause_toocold_menu); lcd_goto_screen(lcd_advanced_pause_toocold_menu);
return; return;
@ -1251,8 +1261,41 @@ void kill_screen(const char* lcd_msg) {
#endif #endif
lcd_advanced_pause_show_message(ADVANCED_PAUSE_MESSAGE_INIT); lcd_advanced_pause_show_message(ADVANCED_PAUSE_MESSAGE_INIT);
#if EXTRUDERS <= 1
enqueue_and_echo_commands_P(PSTR("M600 B0")); enqueue_and_echo_commands_P(PSTR("M600 B0"));
#else
char *command_M600;
switch (extruder) {
case 0: command_M600 = PSTR("M600 B0 T0"); break;
case 1: command_M600 = PSTR("M600 B0 T1"); break;
#if EXTRUDERS > 2
case 2: command_M600 = PSTR("M600 B0 T2"); break;
#if EXTRUDERS > 3
case 3: command_M600 = PSTR("M600 B0 T3"); break;
#if EXTRUDERS > 4
case 4: command_M600 = PSTR("M600 B0 T4"); break;
#endif // EXTRUDERS > 4
#endif // EXTRUDERS > 3
#endif // EXTRUDERS > 2
} }
enqueue_and_echo_commands_P(command_M600);
#endif // EXTRUDERS > 1
}
#if EXTRUDERS > 1
void lcd_enqueue_filament_change_e0() { lcd_enqueue_filament_change(0); }
void lcd_enqueue_filament_change_e1() { lcd_enqueue_filament_change(1); }
#if EXTRUDERS > 2
void lcd_enqueue_filament_change_e2() { lcd_enqueue_filament_change(2); }
#if EXTRUDERS > 3
void lcd_enqueue_filament_change_e3() { lcd_enqueue_filament_change(3); }
#if EXTRUDERS > 4
void lcd_enqueue_filament_change_e4() { lcd_enqueue_filament_change(4); }
#endif // EXTRUDERS > 4
#endif // EXTRUDERS > 3
#endif // EXTRUDERS > 2
#endif // EXTRUDERS > 1
#endif // ADVANCED_PAUSE_FEATURE #endif // ADVANCED_PAUSE_FEATURE
@ -1397,9 +1440,28 @@ void kill_screen(const char* lcd_msg) {
// Change filament // Change filament
// //
#if ENABLED(ADVANCED_PAUSE_FEATURE) #if ENABLED(ADVANCED_PAUSE_FEATURE)
#if EXTRUDERS > 1
if (!thermalManager.tooColdToExtrude(0))
MENU_ITEM(function, MSG_FILAMENTCHANGE " " MSG_E1, lcd_enqueue_filament_change_e0);
if (!thermalManager.tooColdToExtrude(1))
MENU_ITEM(function, MSG_FILAMENTCHANGE " " MSG_E2, lcd_enqueue_filament_change_e1);
#if EXTRUDERS > 2
if (!thermalManager.tooColdToExtrude(2))
MENU_ITEM(function, MSG_FILAMENTCHANGE " " MSG_E3, lcd_enqueue_filament_change_e2);
#if EXTRUDERS > 3
if (!thermalManager.tooColdToExtrude(3))
MENU_ITEM(function, MSG_FILAMENTCHANGE " " MSG_E4, lcd_enqueue_filament_change_e3);
#if EXTRUDERS > 4
if (!thermalManager.tooColdToExtrude(4))
MENU_ITEM(function, MSG_FILAMENTCHANGE " " MSG_E5, lcd_enqueue_filament_change_e4);
#endif // EXTRUDERS > 4
#endif // EXTRUDERS > 3
#endif // EXTRUDERS > 2
#else
if (!thermalManager.tooColdToExtrude(active_extruder)) if (!thermalManager.tooColdToExtrude(active_extruder))
MENU_ITEM(function, MSG_FILAMENTCHANGE, lcd_enqueue_filament_change); MENU_ITEM(function, MSG_FILAMENTCHANGE, lcd_enqueue_filament_change);
#endif #endif
#endif
END_MENU(); END_MENU();
} }
@ -1793,7 +1855,7 @@ void kill_screen(const char* lcd_msg) {
void _lcd_level_bed_get_z() { void _lcd_level_bed_get_z() {
ENCODER_DIRECTION_NORMAL(); ENCODER_DIRECTION_NORMAL();
if (lcd_clicked) { if (use_click()) {
// //
// Save the current Z position and move // Save the current Z position and move
@ -1873,7 +1935,7 @@ void kill_screen(const char* lcd_msg) {
*/ */
void _lcd_level_bed_homing_done() { void _lcd_level_bed_homing_done() {
if (lcdDrawUpdate) lcd_implementation_drawedit(PSTR(MSG_LEVEL_BED_WAITING)); if (lcdDrawUpdate) lcd_implementation_drawedit(PSTR(MSG_LEVEL_BED_WAITING));
if (lcd_clicked) { if (use_click()) {
manual_probe_index = 0; manual_probe_index = 0;
_lcd_level_goto_next_point(); _lcd_level_goto_next_point();
} }
@ -2364,7 +2426,7 @@ void kill_screen(const char* lcd_msg) {
if (!(axis_known_position[X_AXIS] && axis_known_position[Y_AXIS] && axis_known_position[Z_AXIS])) if (!(axis_known_position[X_AXIS] && axis_known_position[Y_AXIS] && axis_known_position[Z_AXIS]))
return lcd_goto_screen(_lcd_ubl_map_homing); return lcd_goto_screen(_lcd_ubl_map_homing);
if (lcd_clicked) return _lcd_ubl_map_lcd_edit_cmd(); if (use_click()) return _lcd_ubl_map_lcd_edit_cmd();
ENCODER_DIRECTION_NORMAL(); ENCODER_DIRECTION_NORMAL();
if (encoderPosition) { if (encoderPosition) {
@ -2588,9 +2650,30 @@ void kill_screen(const char* lcd_msg) {
// Change filament // Change filament
// //
#if ENABLED(ADVANCED_PAUSE_FEATURE) #if ENABLED(ADVANCED_PAUSE_FEATURE)
if (!thermalManager.tooColdToExtrude(active_extruder) && !IS_SD_FILE_OPEN) if (!IS_SD_FILE_OPEN) {
#if EXTRUDERS > 1
if (!thermalManager.tooColdToExtrude(0))
MENU_ITEM(function, MSG_FILAMENTCHANGE " " MSG_E1, lcd_enqueue_filament_change_e0);
if (!thermalManager.tooColdToExtrude(1))
MENU_ITEM(function, MSG_FILAMENTCHANGE " " MSG_E2, lcd_enqueue_filament_change_e1);
#if EXTRUDERS > 2
if (!thermalManager.tooColdToExtrude(2))
MENU_ITEM(function, MSG_FILAMENTCHANGE " " MSG_E3, lcd_enqueue_filament_change_e2);
#if EXTRUDERS > 3
if (!thermalManager.tooColdToExtrude(3))
MENU_ITEM(function, MSG_FILAMENTCHANGE " " MSG_E4, lcd_enqueue_filament_change_e3);
#if EXTRUDERS > 4
if (!thermalManager.tooColdToExtrude(4))
MENU_ITEM(function, MSG_FILAMENTCHANGE " " MSG_E5, lcd_enqueue_filament_change_e4);
#endif // EXTRUDERS > 4
#endif // EXTRUDERS > 3
#endif // EXTRUDERS > 2
#else
if (!thermalManager.tooColdToExtrude(active_extruder))
MENU_ITEM(function, MSG_FILAMENTCHANGE, lcd_enqueue_filament_change); MENU_ITEM(function, MSG_FILAMENTCHANGE, lcd_enqueue_filament_change);
#endif #endif
}
#endif // ADVANCED_PAUSE_FEATURE
#if TEMP_SENSOR_0 != 0 #if TEMP_SENSOR_0 != 0
@ -2833,7 +2916,7 @@ void kill_screen(const char* lcd_msg) {
*/ */
void _lcd_move_xyz(const char* name, AxisEnum axis) { void _lcd_move_xyz(const char* name, AxisEnum axis) {
if (lcd_clicked) { return lcd_goto_previous_menu(); } if (use_click()) { return lcd_goto_previous_menu(); }
ENCODER_DIRECTION_NORMAL(); ENCODER_DIRECTION_NORMAL();
if (encoderPosition && !processing_manual_move) { if (encoderPosition && !processing_manual_move) {
gcode.refresh_cmd_timeout(); gcode.refresh_cmd_timeout();
@ -2917,7 +3000,7 @@ void kill_screen(const char* lcd_msg) {
int8_t eindex=-1 int8_t eindex=-1
#endif #endif
) { ) {
if (lcd_clicked) { return lcd_goto_previous_menu(); } if (use_click()) { return lcd_goto_previous_menu(); }
ENCODER_DIRECTION_NORMAL(); ENCODER_DIRECTION_NORMAL();
if (encoderPosition) { if (encoderPosition) {
if (!processing_manual_move) { if (!processing_manual_move) {
@ -2999,7 +3082,7 @@ void kill_screen(const char* lcd_msg) {
_manual_move_func_ptr = func; _manual_move_func_ptr = func;
START_MENU(); START_MENU();
if (LCD_HEIGHT >= 4) { if (LCD_HEIGHT >= 4) {
switch(axis) { switch (axis) {
case X_AXIS: case X_AXIS:
STATIC_ITEM(MSG_MOVE_X, true, true); break; STATIC_ITEM(MSG_MOVE_X, true, true); break;
case Y_AXIS: case Y_AXIS:
@ -3802,7 +3885,7 @@ void kill_screen(const char* lcd_msg) {
* *
*/ */
void lcd_info_stats_menu() { void lcd_info_stats_menu() {
if (lcd_clicked) { return lcd_goto_previous_menu(); } if (use_click()) { return lcd_goto_previous_menu(); }
char buffer[21]; char buffer[21];
printStatistics stats = print_job_timer.getStats(); printStatistics stats = print_job_timer.getStats();
@ -3836,7 +3919,7 @@ void kill_screen(const char* lcd_msg) {
* *
*/ */
void lcd_info_thermistors_menu() { void lcd_info_thermistors_menu() {
if (lcd_clicked) { return lcd_goto_previous_menu(); } if (use_click()) { return lcd_goto_previous_menu(); }
START_SCREEN(); START_SCREEN();
#define THERMISTOR_ID TEMP_SENSOR_0 #define THERMISTOR_ID TEMP_SENSOR_0
#include "thermistornames.h" #include "thermistornames.h"
@ -3897,7 +3980,7 @@ void kill_screen(const char* lcd_msg) {
* *
*/ */
void lcd_info_board_menu() { void lcd_info_board_menu() {
if (lcd_clicked) { return lcd_goto_previous_menu(); } if (use_click()) { return lcd_goto_previous_menu(); }
START_SCREEN(); START_SCREEN();
STATIC_ITEM(BOARD_NAME, true, true); // MyPrinterController STATIC_ITEM(BOARD_NAME, true, true); // MyPrinterController
STATIC_ITEM(MSG_INFO_BAUDRATE ": " STRINGIFY(BAUDRATE), true); // Baud: 250000 STATIC_ITEM(MSG_INFO_BAUDRATE ": " STRINGIFY(BAUDRATE), true); // Baud: 250000
@ -3918,7 +4001,7 @@ void kill_screen(const char* lcd_msg) {
* *
*/ */
void lcd_info_printer_menu() { void lcd_info_printer_menu() {
if (lcd_clicked) { return lcd_goto_previous_menu(); } if (use_click()) { return lcd_goto_previous_menu(); }
START_SCREEN(); START_SCREEN();
STATIC_ITEM(MSG_MARLIN, true, true); // Marlin STATIC_ITEM(MSG_MARLIN, true, true); // Marlin
STATIC_ITEM(SHORT_BUILD_VERSION, true); // x.x.x-Branch STATIC_ITEM(SHORT_BUILD_VERSION, true); // x.x.x-Branch
@ -4317,7 +4400,7 @@ void kill_screen(const char* lcd_msg) {
if (liveEdit) (*callbackFunc)(); \ if (liveEdit) (*callbackFunc)(); \
if (lcd_clicked) lcd_goto_previous_menu(); \ if (lcd_clicked) lcd_goto_previous_menu(); \
} \ } \
return lcd_clicked; \ return use_click(); \
} \ } \
void menu_edit_ ## _name() { _menu_edit_ ## _name(); } \ void menu_edit_ ## _name() { _menu_edit_ ## _name(); } \
void menu_edit_callback_ ## _name() { if (_menu_edit_ ## _name()) (*callbackFunc)(); } \ void menu_edit_callback_ ## _name() { if (_menu_edit_ ## _name()) (*callbackFunc)(); } \
@ -4778,12 +4861,13 @@ void lcd_update() {
if ((lcdDrawUpdate || IS_DRAWING) && (!bbr2 || bbr2 > max_display_update_time)) { if ((lcdDrawUpdate || IS_DRAWING) && (!bbr2 || bbr2 > max_display_update_time)) {
// Change state of drawing flag between screen updates
if (!IS_DRAWING) switch (lcdDrawUpdate) { if (!IS_DRAWING) switch (lcdDrawUpdate) {
case LCDVIEW_CALL_NO_REDRAW: case LCDVIEW_CALL_NO_REDRAW:
lcdDrawUpdate = LCDVIEW_NONE; lcdDrawUpdate = LCDVIEW_NONE;
break; break;
case LCDVIEW_CLEAR_CALL_REDRAW: // set by handlers, then altered after (rarely occurs here) case LCDVIEW_CLEAR_CALL_REDRAW:
case LCDVIEW_CALL_REDRAW_NEXT: // set by handlers, then altered after (never occurs here?) case LCDVIEW_CALL_REDRAW_NEXT:
lcdDrawUpdate = LCDVIEW_REDRAW_NOW; lcdDrawUpdate = LCDVIEW_REDRAW_NOW;
case LCDVIEW_REDRAW_NOW: // set above, or by a handler through LCDVIEW_CALL_REDRAW_NEXT case LCDVIEW_REDRAW_NOW: // set above, or by a handler through LCDVIEW_CALL_REDRAW_NEXT
case LCDVIEW_NONE: case LCDVIEW_NONE:
@ -4795,7 +4879,7 @@ void lcd_update() {
#endif #endif
#if ENABLED(ULTIPANEL) #if ENABLED(ULTIPANEL)
#define CURRENTSCREEN() (*currentScreen)(), lcd_clicked = false #define CURRENTSCREEN() (*currentScreen)()
#else #else
#define CURRENTSCREEN() lcd_status_screen() #define CURRENTSCREEN() lcd_status_screen()
#endif #endif
@ -4820,6 +4904,10 @@ void lcd_update() {
CURRENTSCREEN(); CURRENTSCREEN();
#endif #endif
#if ENABLED(ULTIPANEL)
lcd_clicked = false;
#endif
// Keeping track of the longest time for an individual LCD update. // Keeping track of the longest time for an individual LCD update.
// Used to do screen throttling when the planner starts to fill up. // Used to do screen throttling when the planner starts to fill up.
NOLESS(max_display_update_time, millis() - ms); NOLESS(max_display_update_time, millis() - ms);
@ -4835,17 +4923,16 @@ void lcd_update() {
#endif // ULTIPANEL #endif // ULTIPANEL
// Change state of drawing flag between screen updates
if (!IS_DRAWING) switch (lcdDrawUpdate) { if (!IS_DRAWING) switch (lcdDrawUpdate) {
case LCDVIEW_CLEAR_CALL_REDRAW: case LCDVIEW_CLEAR_CALL_REDRAW:
lcd_implementation_clear(); lcd_implementation_clear(); break;
case LCDVIEW_CALL_REDRAW_NEXT:
lcdDrawUpdate = LCDVIEW_REDRAW_NOW;
break;
case LCDVIEW_REDRAW_NOW: case LCDVIEW_REDRAW_NOW:
lcdDrawUpdate = LCDVIEW_NONE; lcdDrawUpdate = LCDVIEW_NONE;
break;
case LCDVIEW_NONE: case LCDVIEW_NONE:
break; case LCDVIEW_CALL_REDRAW_NEXT:
case LCDVIEW_CALL_NO_REDRAW:
default: break;
} // switch } // switch
} // ELAPSED(ms, next_lcd_update_ms) } // ELAPSED(ms, next_lcd_update_ms)