diff --git a/Marlin/ultralcd.cpp b/Marlin/ultralcd.cpp index 26fe69dca..f15801e7c 100755 --- a/Marlin/ultralcd.cpp +++ b/Marlin/ultralcd.cpp @@ -90,50 +90,25 @@ uint16_t max_display_update_time = 0; #if ENABLED(ULTIPANEL) - // place-holders for Ki and Kd edits - float raw_Ki, raw_Kd; - - /** - * REVERSE_MENU_DIRECTION - * - * To reverse the menu direction we need a general way to reverse - * the direction of the encoder everywhere. So encoderDirection is - * added to allow the encoder to go the other way. - * - * This behavior is limited to scrolling Menus and SD card listings, - * and is disabled in other contexts. - */ - #if ENABLED(REVERSE_MENU_DIRECTION) - int8_t encoderDirection = 1; - #define ENCODER_DIRECTION_NORMAL() (encoderDirection = 1) - #define ENCODER_DIRECTION_MENUS() (encoderDirection = -1) - #else - #define ENCODER_DIRECTION_NORMAL() ; - #define ENCODER_DIRECTION_MENUS() ; + #ifndef TALL_FONT_CORRECTION + #define TALL_FONT_CORRECTION 0 #endif - int8_t encoderDiff; // updated from interrupt context and added to encoderPosition every LCD update - - millis_t manual_move_start_time = 0; - int8_t manual_move_axis = (int8_t)NO_AXIS; - #if EXTRUDERS > 1 - int8_t manual_move_e_index = 0; - #else - #define manual_move_e_index 0 - #endif - - bool encoderRateMultiplierEnabled; - int32_t lastEncoderMovementMillis; - - #if ENABLED(AUTO_BED_LEVELING_UBL) - #include "ubl.h" - #endif + // Function pointer to menu functions. + typedef void (*screenFunc_t)(); #if HAS_POWER_SWITCH extern bool powersupply; #endif - const float manual_feedrate_mm_m[] = MANUAL_FEEDRATE; + #if ENABLED(AUTO_BED_LEVELING_UBL) + #include "ubl.h" + #endif + + //////////////////////////////////////////// + ///////////////// Menu Tree //////////////// + //////////////////////////////////////////// + void lcd_main_menu(); void lcd_tune_menu(); void lcd_prepare_menu(); @@ -145,13 +120,6 @@ uint16_t max_display_update_time = 0; void lcd_control_motion_menu(); void lcd_control_filament_menu(); - #if ENABLED(DAC_STEPPER_CURRENT) - void dac_driver_commit(); - void dac_driver_getValues(); - void lcd_dac_menu(); - void lcd_dac_write_eeprom(); - #endif - #if ENABLED(LCD_INFO_MENU) #if ENABLED(PRINTCOUNTER) void lcd_info_stats_menu(); @@ -173,6 +141,13 @@ uint16_t max_display_update_time = 0; void lcd_filament_change_resume_message(); #endif + #if ENABLED(DAC_STEPPER_CURRENT) + void dac_driver_commit(); + void dac_driver_getValues(); + void lcd_dac_menu(); + void lcd_dac_write_eeprom(); + #endif + #if HAS_LCD_CONTRAST void lcd_set_contrast(); #endif @@ -189,10 +164,10 @@ uint16_t max_display_update_time = 0; #include "mesh_bed_leveling.h" #endif - // Function pointer to menu functions. - typedef void (*screenFunc_t)(); + //////////////////////////////////////////// + //////////// Menu System Actions /////////// + //////////////////////////////////////////// - // Different types of actions that can be used in menu items. #define menu_action_back(dummy) _menu_action_back() void _menu_action_back(); void menu_action_submenu(screenFunc_t data); @@ -230,7 +205,9 @@ uint16_t max_display_update_time = 0; void menu_action_sddirectory(const char* filename, char* longFilename); #endif - /* Helper macros for menus */ + //////////////////////////////////////////// + //////////// Menu System Macros //////////// + //////////////////////////////////////////// #ifndef ENCODER_FEEDRATE_DEADZONE #define ENCODER_FEEDRATE_DEADZONE 10 @@ -242,59 +219,6 @@ uint16_t max_display_update_time = 0; #define ENCODER_PULSES_PER_STEP 1 #endif - #ifndef TALL_FONT_CORRECTION - #define TALL_FONT_CORRECTION 0 - #endif - - /** - * START_SCREEN_OR_MENU generates init code for a screen or menu - * - * encoderLine is the position based on the encoder - * encoderTopLine is the top menu line to display - * _lcdLineNr is the index of the LCD line (e.g., 0-3) - * _menuLineNr is the menu item to draw and process - * _thisItemNr is the index of each MENU_ITEM or STATIC_ITEM - * _countedItems is the total number of items in the menu (after one call) - */ - #define START_SCREEN_OR_MENU(LIMIT) \ - ENCODER_DIRECTION_MENUS(); \ - encoderRateMultiplierEnabled = false; \ - if (encoderPosition > 0x8000) encoderPosition = 0; \ - static int8_t _countedItems = 0; \ - int8_t encoderLine = encoderPosition / (ENCODER_STEPS_PER_MENU_ITEM); \ - if (_countedItems > 0 && encoderLine >= _countedItems - (LIMIT)) { \ - encoderLine = max(0, _countedItems - (LIMIT)); \ - encoderPosition = encoderLine * (ENCODER_STEPS_PER_MENU_ITEM); \ - } - - #define SCREEN_OR_MENU_LOOP() \ - int8_t _menuLineNr = encoderTopLine, _thisItemNr; \ - for (int8_t _lcdLineNr = 0; _lcdLineNr < LCD_HEIGHT - (TALL_FONT_CORRECTION); _lcdLineNr++, _menuLineNr++) { \ - _thisItemNr = 0 - - /** - * START_SCREEN Opening code for a screen having only static items. - * Do simplified scrolling of the entire screen. - * - * START_MENU Opening code for a screen with menu items. - * Scroll as-needed to keep the selected line in view. - */ - #define START_SCREEN() \ - START_SCREEN_OR_MENU(LCD_HEIGHT - (TALL_FONT_CORRECTION)); \ - encoderTopLine = encoderLine; \ - bool _skipStatic = false; \ - SCREEN_OR_MENU_LOOP() - - #define START_MENU() \ - START_SCREEN_OR_MENU(1); \ - screen_changed = false; \ - NOMORE(encoderTopLine, encoderLine); \ - if (encoderLine >= encoderTopLine + LCD_HEIGHT - (TALL_FONT_CORRECTION)) { \ - encoderTopLine = encoderLine - (LCD_HEIGHT - (TALL_FONT_CORRECTION) - 1); \ - } \ - bool _skipStatic = true; \ - SCREEN_OR_MENU_LOOP() - /** * MENU_ITEM generates draw & handler code for a menu item, potentially calling: * @@ -352,17 +276,11 @@ uint16_t max_display_update_time = 0; } \ ++_thisItemNr - #define END_SCREEN() \ - } \ - _countedItems = _thisItemNr - - #define END_MENU() \ - } \ - _countedItems = _thisItemNr; \ - UNUSED(_skipStatic) - #if ENABLED(ENCODER_RATE_MULTIPLIER) + bool encoderRateMultiplierEnabled; + #define ENCODER_RATE_MULTIPLY(F) (encoderRateMultiplierEnabled = F) + //#define ENCODER_RATE_MULTIPLIER_DEBUG // If defined, output the encoder steps per second value /** @@ -375,7 +293,9 @@ uint16_t max_display_update_time = 0; _MENU_ITEM_PART_2(type, ## __VA_ARGS__); \ } while(0) - #endif //ENCODER_RATE_MULTIPLIER + #else // !ENCODER_RATE_MULTIPLIER + #define ENCODER_RATE_MULTIPLY(F) NOOP + #endif // !ENCODER_RATE_MULTIPLIER #define MENU_ITEM_DUMMY() do { _thisItemNr++; } while(0) #define MENU_ITEM_EDIT(type, label, ...) MENU_ITEM(setting_edit_ ## type, label, PSTR(label), ## __VA_ARGS__) @@ -391,43 +311,137 @@ uint16_t max_display_update_time = 0; #define MENU_MULTIPLIER_ITEM_EDIT_ACCESSOR(type, label, ...) MENU_ITEM(setting_edit_accessor_ ## type, label, PSTR(label), ## __VA_ARGS__) #endif //!ENCODER_RATE_MULTIPLIER - /** Used variables to keep track of the menu */ - volatile uint8_t buttons; //the last checked buttons in a bit array. - #if ENABLED(REPRAPWORLD_KEYPAD) - volatile uint8_t buttons_reprapworld_keypad; // to store the keypad shift register values + /** + * START_SCREEN_OR_MENU generates init code for a screen or menu + * + * encoderLine is the position based on the encoder + * encoderTopLine is the top menu line to display + * _lcdLineNr is the index of the LCD line (e.g., 0-3) + * _menuLineNr is the menu item to draw and process + * _thisItemNr is the index of each MENU_ITEM or STATIC_ITEM + * _countedItems is the total number of items in the menu (after one call) + */ + #define START_SCREEN_OR_MENU(LIMIT) \ + ENCODER_DIRECTION_MENUS(); \ + ENCODER_RATE_MULTIPLY(false); \ + if (encoderPosition > 0x8000) encoderPosition = 0; \ + static int8_t _countedItems = 0; \ + int8_t encoderLine = encoderPosition / (ENCODER_STEPS_PER_MENU_ITEM); \ + if (_countedItems > 0 && encoderLine >= _countedItems - (LIMIT)) { \ + encoderLine = max(0, _countedItems - (LIMIT)); \ + encoderPosition = encoderLine * (ENCODER_STEPS_PER_MENU_ITEM); \ + } + + #define SCREEN_OR_MENU_LOOP() \ + int8_t _menuLineNr = encoderTopLine, _thisItemNr; \ + for (int8_t _lcdLineNr = 0; _lcdLineNr < LCD_HEIGHT - (TALL_FONT_CORRECTION); _lcdLineNr++, _menuLineNr++) { \ + _thisItemNr = 0 + + /** + * START_SCREEN Opening code for a screen having only static items. + * Do simplified scrolling of the entire screen. + * + * START_MENU Opening code for a screen with menu items. + * Scroll as-needed to keep the selected line in view. + */ + #define START_SCREEN() \ + START_SCREEN_OR_MENU(LCD_HEIGHT - (TALL_FONT_CORRECTION)); \ + encoderTopLine = encoderLine; \ + bool _skipStatic = false; \ + SCREEN_OR_MENU_LOOP() + + #define START_MENU() \ + START_SCREEN_OR_MENU(1); \ + screen_changed = false; \ + NOMORE(encoderTopLine, encoderLine); \ + if (encoderLine >= encoderTopLine + LCD_HEIGHT - (TALL_FONT_CORRECTION)) { \ + encoderTopLine = encoderLine - (LCD_HEIGHT - (TALL_FONT_CORRECTION) - 1); \ + } \ + bool _skipStatic = true; \ + SCREEN_OR_MENU_LOOP() + + #define END_SCREEN() \ + } \ + _countedItems = _thisItemNr + + #define END_MENU() \ + } \ + _countedItems = _thisItemNr; \ + UNUSED(_skipStatic) + + //////////////////////////////////////////// + ///////////// Global Variables ///////////// + //////////////////////////////////////////// + + /** + * REVERSE_MENU_DIRECTION + * + * To reverse the menu direction we need a general way to reverse + * the direction of the encoder everywhere. So encoderDirection is + * added to allow the encoder to go the other way. + * + * This behavior is limited to scrolling Menus and SD card listings, + * and is disabled in other contexts. + */ + #if ENABLED(REVERSE_MENU_DIRECTION) + int8_t encoderDirection = 1; + #define ENCODER_DIRECTION_NORMAL() (encoderDirection = 1) + #define ENCODER_DIRECTION_MENUS() (encoderDirection = -1) + #else + #define ENCODER_DIRECTION_NORMAL() ; + #define ENCODER_DIRECTION_MENUS() ; #endif - #if ENABLED(LCD_HAS_SLOW_BUTTONS) - volatile uint8_t slow_buttons; // Bits of the pressed buttons. - #endif - int8_t encoderTopLine; /* scroll offset in the current menu */ - millis_t next_button_update_ms; - uint8_t lastEncoderBits; + // Encoder Movement + volatile int8_t encoderDiff; // Updated in lcd_buttons_update, added to encoderPosition every LCD update uint32_t encoderPosition; - #if PIN_EXISTS(SD_DETECT) - uint8_t lcd_sd_status; + millis_t lastEncoderMovementMillis = 0; + + // Button States + bool lcd_clicked, wait_for_unclick; + volatile uint8_t buttons; + millis_t next_button_update_ms; + #if ENABLED(REPRAPWORLD_KEYPAD) + volatile uint8_t buttons_reprapworld_keypad; + #endif + #if ENABLED(LCD_HAS_SLOW_BUTTONS) + volatile uint8_t slow_buttons; #endif + // Menu System Navigation + screenFunc_t currentScreen = lcd_status_screen; + int8_t encoderTopLine; typedef struct { screenFunc_t menu_function; uint32_t encoder_position; } menuPosition; - - screenFunc_t currentScreen = lcd_status_screen; // pointer to the currently active menu handler - - menuPosition screen_history[10]; + menuPosition screen_history[6]; uint8_t screen_history_depth = 0; - bool screen_changed; + bool screen_changed, defer_return_to_status; - // LCD and menu clicks - bool lcd_clicked, wait_for_unclick, defer_return_to_status; - - // Variables used when editing values. - const char* editLabel; - void* editValue; - void* editSetter; + // Value Editing + const char *editLabel; + void *editValue, *editSetter; int32_t minEditValue, maxEditValue; - screenFunc_t callbackFunc; // call this after editing + screenFunc_t callbackFunc; + + // Manual Moves + const float manual_feedrate_mm_m[] = MANUAL_FEEDRATE; + millis_t manual_move_start_time = 0; + int8_t manual_move_axis = (int8_t)NO_AXIS; + #if EXTRUDERS > 1 + int8_t manual_move_e_index = 0; + #else + #define manual_move_e_index 0 + #endif + + #if PIN_EXISTS(SD_DETECT) + uint8_t lcd_sd_status; + #endif + + #if ENABLED(PIDTEMP) + float raw_Ki, raw_Kd; // place-holders for Ki and Kd edits + #endif /** * General function to go directly to a screen @@ -528,7 +542,7 @@ void lcd_status_screen() { #if ENABLED(ULTIPANEL) ENCODER_DIRECTION_NORMAL(); - encoderRateMultiplierEnabled = false; + ENCODER_RATE_MULTIPLY(false); #endif #if ENABLED(LCD_PROGRESS_BAR) @@ -2186,28 +2200,28 @@ void kill_screen(const char* lcd_msg) { PID_PARAM(Kd, e) = scalePID_d(raw_Kd); thermalManager.updatePID(); } - #define _PIDTEMP_BASE_FUNCTIONS(N) \ + #define _DEFINE_PIDTEMP_BASE_FUNCS(N) \ void copy_and_scalePID_i_E ## N() { copy_and_scalePID_i(N); } \ void copy_and_scalePID_d_E ## N() { copy_and_scalePID_d(N); } #if ENABLED(PID_AUTOTUNE_MENU) - #define _PIDTEMP_FUNCTIONS(N) \ - _PIDTEMP_BASE_FUNCTIONS(N); \ - void lcd_autotune_callback_E ## N() { _lcd_autotune(N); } + #define DEFINE_PIDTEMP_FUNCS(N) \ + _DEFINE_PIDTEMP_BASE_FUNCS(N); \ + void lcd_autotune_callback_E ## N() { _lcd_autotune(N); } typedef void _pid_##N##_void #else - #define _PIDTEMP_FUNCTIONS(N) _PIDTEMP_BASE_FUNCTIONS(N) + #define DEFINE_PIDTEMP_FUNCS(N) _DEFINE_PIDTEMP_BASE_FUNCS(N) typedef void _pid_##N##_void #endif - _PIDTEMP_FUNCTIONS(0) + DEFINE_PIDTEMP_FUNCS(0); #if ENABLED(PID_PARAMS_PER_HOTEND) #if HOTENDS > 1 - _PIDTEMP_FUNCTIONS(1) + DEFINE_PIDTEMP_FUNCS(1); #if HOTENDS > 2 - _PIDTEMP_FUNCTIONS(2) + DEFINE_PIDTEMP_FUNCS(2); #if HOTENDS > 3 - _PIDTEMP_FUNCTIONS(3) + DEFINE_PIDTEMP_FUNCS(3); #if HOTENDS > 4 - _PIDTEMP_FUNCTIONS(4) + DEFINE_PIDTEMP_FUNCS(4); #endif // HOTENDS > 4 #endif // HOTENDS > 3 #endif // HOTENDS > 2 @@ -2660,7 +2674,7 @@ void kill_screen(const char* lcd_msg) { void lcd_sdcard_menu() { ENCODER_DIRECTION_MENUS(); if (!lcdDrawUpdate && !lcd_clicked) return; // nothing to do (so don't thrash the SD card) - uint16_t fileCnt = card.getnrfilenames(); + const uint16_t fileCnt = card.getnrfilenames(); START_MENU(); MENU_BACK(MSG_MAIN); card.getWorkDirName(); @@ -2675,11 +2689,11 @@ void kill_screen(const char* lcd_msg) { for (uint16_t i = 0; i < fileCnt; i++) { if (_menuLineNr == _thisItemNr) { - #if ENABLED(SDCARD_RATHERRECENTFIRST) && DISABLED(SDCARD_SORT_ALPHA) - int nr = fileCnt - 1 - i; - #else - int nr = i; - #endif + const uint16_t nr = + #if ENABLED(SDCARD_RATHERRECENTFIRST) && DISABLED(SDCARD_SORT_ALPHA) + fileCnt - 1 - + #endif + i; #if ENABLED(SDCARD_SORT_ALPHA) card.getfilename_sorted(nr); @@ -3104,9 +3118,9 @@ void kill_screen(const char* lcd_msg) { * * Functions for editing single values * - * The "menu_edit_type" macro generates the functions needed to edit a numerical value. + * The "DEFINE_MENU_EDIT_TYPE" macro generates the functions needed to edit a numerical value. * - * For example, menu_edit_type(int, int3, itostr3, 1) expands into these functions: + * For example, DEFINE_MENU_EDIT_TYPE(int, int3, itostr3, 1) expands into these functions: * * bool _menu_edit_int3(); * void menu_edit_int3(); // edit int (interactively) @@ -3131,7 +3145,7 @@ void kill_screen(const char* lcd_msg) { * Values that are get/set via functions (As opposed to global variables) can use the accessor form: * MENU_ITEM_EDIT_ACCESSOR(int3, MSG_SPEED, get_feedrate_percentage, set_feedrate_percentage, 10, 999) */ - #define menu_edit_type(_type, _name, _strFunc, _scale) \ + #define DEFINE_MENU_EDIT_TYPE(_type, _name, _strFunc, _scale) \ bool _menu_edit_ ## _name () { \ ENCODER_DIRECTION_NORMAL(); \ if ((int32_t)encoderPosition < 0) encoderPosition = 0; \ @@ -3189,15 +3203,15 @@ void kill_screen(const char* lcd_msg) { } \ typedef void _name - menu_edit_type(int, int3, itostr3, 1); - menu_edit_type(float, float3, ftostr3, 1.0); - menu_edit_type(float, float32, ftostr32, 100.0); - menu_edit_type(float, float43, ftostr43sign, 1000.0); - menu_edit_type(float, float5, ftostr5rj, 0.01); - menu_edit_type(float, float51, ftostr51sign, 10.0); - menu_edit_type(float, float52, ftostr52sign, 100.0); - menu_edit_type(float, float62, ftostr62rj, 100.0); - menu_edit_type(unsigned long, long5, ftostr5rj, 0.01); + DEFINE_MENU_EDIT_TYPE(int, int3, itostr3, 1); + DEFINE_MENU_EDIT_TYPE(float, float3, ftostr3, 1.0); + DEFINE_MENU_EDIT_TYPE(float, float32, ftostr32, 100.0); + DEFINE_MENU_EDIT_TYPE(float, float43, ftostr43sign, 1000.0); + DEFINE_MENU_EDIT_TYPE(float, float5, ftostr5rj, 0.01); + DEFINE_MENU_EDIT_TYPE(float, float51, ftostr51sign, 10.0); + DEFINE_MENU_EDIT_TYPE(float, float52, ftostr52sign, 100.0); + DEFINE_MENU_EDIT_TYPE(float, float62, ftostr62rj, 100.0); + DEFINE_MENU_EDIT_TYPE(unsigned long, long5, ftostr5rj, 0.01); /** * @@ -3466,7 +3480,7 @@ void lcd_update() { #if ENABLED(SDSUPPORT) && PIN_EXISTS(SD_DETECT) - bool sd_status = IS_SD_INSERTED; + const bool sd_status = IS_SD_INSERTED; if (sd_status != lcd_sd_status && lcd_detected()) { if (sd_status) { @@ -3489,7 +3503,7 @@ void lcd_update() { #endif //SDSUPPORT && SD_DETECT_PIN - millis_t ms = millis(); + const millis_t ms = millis(); if (ELAPSED(ms, next_lcd_update_ms) #if ENABLED(DOGLCD) || drawing_screen @@ -3759,6 +3773,7 @@ void lcd_reset_alert_level() { lcd_status_message_level = 0; } * Warning: This function is called from interrupt context! */ void lcd_buttons_update() { + static uint8_t lastEncoderBits; millis_t now = millis(); if (ELAPSED(now, next_button_update_ms)) {