diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index c5f56f18d0..ee6223ab39 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -3191,7 +3191,7 @@ #endif /** - * User-defined menu items that execute custom GCode + * User-defined menu items (up to 25 may be used) that execute custom GCode */ //#define CUSTOM_USER_MENUS #if ENABLED(CUSTOM_USER_MENUS) @@ -3202,6 +3202,11 @@ #define USER_DESC_1 "Home & UBL Info" #define USER_GCODE_1 "G28\nG29 W" + //#define USER_GCODE_PIN_1 -1 // PIN assigned to trigger USER_GCODE_1 execution + #ifdef USER_GCODE_PIN_1 + #define USER_GCODE_PIN_INIT_1 // Init the PIN state at reboot + #define USER_GCODE_PIN_STATE_1 LOW // What state should trigger USER_GCODE_1 execution (LOW or HIGH) + #endif #define USER_DESC_2 "Preheat for " PREHEAT_1_LABEL #define USER_GCODE_2 "M140 S" STRINGIFY(PREHEAT_1_TEMP_BED) "\nM104 S" STRINGIFY(PREHEAT_1_TEMP_HOTEND) diff --git a/Marlin/src/MarlinCore.cpp b/Marlin/src/MarlinCore.cpp index c6c6ef9b0d..716de5fbd0 100644 --- a/Marlin/src/MarlinCore.cpp +++ b/Marlin/src/MarlinCore.cpp @@ -481,6 +481,7 @@ void startOrResumeJob() { * - Check if CHDK_PIN needs to go LOW * - Check for KILL button held down * - Check for HOME button held down + * - Check for CUSTOM USER button held down * - Check if cooling fan needs to be switched on * - Check if an idle but hot extruder needs filament extruded (EXTRUDER_RUNOUT_PREVENT) * - Pulse FET_SAFETY_PIN if it exists @@ -573,6 +574,100 @@ inline void manage_inactivity(const bool ignore_stepper_queue=false) { } #endif + #if HAS_CUSTOM_USER_BUTTONS + // Handle a custom user button if defined as part of a user-defined menu item + // Debug macro on https://godbolt.org/z/SJDZmp + #define HAS_CUSTOM_USER_BUTTON(N) (defined(USER_GCODE_PIN_##N) && defined(USER_GCODE_PIN_STATE_##N) && defined(USER_GCODE_##N) && defined(USER_DESC_##N)) + #define CHECK_CUSTOM_USER_BUTTON(N) do{ \ + constexpr millis_t CUB_DEBOUNCE_DELAY_##N = 1000UL; \ + static millis_t next_cub_ms_##N; \ + if (USER_GCODE_PIN_STATE_##N == READ(USER_GCODE_PIN_##N)) { \ + const millis_t ms = millis(); \ + if (ELAPSED(ms, next_cub_ms_##N)) { \ + next_cub_ms_##N = ms + CUB_DEBOUNCE_DELAY_##N; \ + LCD_MESSAGEPGM_P(USER_DESC_##N); \ + queue.inject_P(USER_GCODE_##N); \ + } \ + } \ + }while(0) + + #if HAS_CUSTOM_USER_BUTTON(1) + CHECK_CUSTOM_USER_BUTTON(1); + #endif + #if HAS_CUSTOM_USER_BUTTON(2) + CHECK_CUSTOM_USER_BUTTON(2); + #endif + #if HAS_CUSTOM_USER_BUTTON(3) + CHECK_CUSTOM_USER_BUTTON(3); + #endif + #if HAS_CUSTOM_USER_BUTTON(4) + CHECK_CUSTOM_USER_BUTTON(4); + #endif + #if HAS_CUSTOM_USER_BUTTON(5) + CHECK_CUSTOM_USER_BUTTON(5); + #endif + #if HAS_CUSTOM_USER_BUTTON(6) + CHECK_CUSTOM_USER_BUTTON(6); + #endif + #if HAS_CUSTOM_USER_BUTTON(7) + CHECK_CUSTOM_USER_BUTTON(7); + #endif + #if HAS_CUSTOM_USER_BUTTON(8) + CHECK_CUSTOM_USER_BUTTON(8); + #endif + #if HAS_CUSTOM_USER_BUTTON(9) + CHECK_CUSTOM_USER_BUTTON(9); + #endif + #if HAS_CUSTOM_USER_BUTTON(10) + CHECK_CUSTOM_USER_BUTTON(10); + #endif + #if HAS_CUSTOM_USER_BUTTON(11) + CHECK_CUSTOM_USER_BUTTON(11); + #endif + #if HAS_CUSTOM_USER_BUTTON(12) + CHECK_CUSTOM_USER_BUTTON(12); + #endif + #if HAS_CUSTOM_USER_BUTTON(13) + CHECK_CUSTOM_USER_BUTTON(13); + #endif + #if HAS_CUSTOM_USER_BUTTON(14) + CHECK_CUSTOM_USER_BUTTON(14); + #endif + #if HAS_CUSTOM_USER_BUTTON(15) + CHECK_CUSTOM_USER_BUTTON(15); + #endif + #if HAS_CUSTOM_USER_BUTTON(16) + CHECK_CUSTOM_USER_BUTTON(16); + #endif + #if HAS_CUSTOM_USER_BUTTON(17) + CHECK_CUSTOM_USER_BUTTON(17); + #endif + #if HAS_CUSTOM_USER_BUTTON(18) + CHECK_CUSTOM_USER_BUTTON(18); + #endif + #if HAS_CUSTOM_USER_BUTTON(19) + CHECK_CUSTOM_USER_BUTTON(19); + #endif + #if HAS_CUSTOM_USER_BUTTON(20) + CHECK_CUSTOM_USER_BUTTON(20); + #endif + #if HAS_CUSTOM_USER_BUTTON(21) + CHECK_CUSTOM_USER_BUTTON(21); + #endif + #if HAS_CUSTOM_USER_BUTTON(22) + CHECK_CUSTOM_USER_BUTTON(22); + #endif + #if HAS_CUSTOM_USER_BUTTON(23) + CHECK_CUSTOM_USER_BUTTON(23); + #endif + #if HAS_CUSTOM_USER_BUTTON(24) + CHECK_CUSTOM_USER_BUTTON(24); + #endif + #if HAS_CUSTOM_USER_BUTTON(25) + CHECK_CUSTOM_USER_BUTTON(25); + #endif + #endif + TERN_(USE_CONTROLLER_FAN, controllerFan.update()); // Check if fan should be turned on to cool stepper drivers down TERN_(AUTO_POWER_CONTROL, powerManager.check()); @@ -920,7 +1015,7 @@ inline void tmc_standby_setup() { /** * Marlin entry-point: Set up before the program loop - * - Set up the kill pin, filament runout, power hold + * - Set up the kill pin, filament runout, power hold, custom user buttons * - Start the serial port * - Print startup messages and diagnostics * - Get EEPROM or default settings @@ -1148,6 +1243,87 @@ void setup() { SET_INPUT_PULLUP(HOME_PIN); #endif + #if HAS_CUSTOM_USER_BUTTONS + #define INIT_CUSTOM_USER_BUTTON_PINS(N) (ENABLED(USER_GCODE_PIN_INIT_##N) && defined(USER_GCODE_PIN_##N) && defined(USER_GCODE_PIN_STATE_##N)) + #define INIT_CUSTOM_USER_BUTTON_PIN(N) do{ SET_INPUT(USER_GCODE_PIN_##N); WRITE(USER_GCODE_PIN_##N, !USER_GCODE_PIN_STATE_##N); }while(0) + + #if INIT_CUSTOM_USER_BUTTON_PINS(1) + INIT_CUSTOM_USER_BUTTON_PIN(1); + #endif + #if INIT_CUSTOM_USER_BUTTON_PINS(2) + INIT_CUSTOM_USER_BUTTON_PIN(2); + #endif + #if INIT_CUSTOM_USER_BUTTON_PINS(3) + INIT_CUSTOM_USER_BUTTON_PIN(3); + #endif + #if INIT_CUSTOM_USER_BUTTON_PINS(4) + INIT_CUSTOM_USER_BUTTON_PIN(4); + #endif + #if INIT_CUSTOM_USER_BUTTON_PINS(5) + INIT_CUSTOM_USER_BUTTON_PIN(5); + #endif + #if INIT_CUSTOM_USER_BUTTON_PINS(6) + INIT_CUSTOM_USER_BUTTON_PIN(6); + #endif + #if INIT_CUSTOM_USER_BUTTON_PINS(7) + INIT_CUSTOM_USER_BUTTON_PIN(7); + #endif + #if INIT_CUSTOM_USER_BUTTON_PINS(8) + INIT_CUSTOM_USER_BUTTON_PIN(8); + #endif + #if INIT_CUSTOM_USER_BUTTON_PINS(9) + INIT_CUSTOM_USER_BUTTON_PIN(9); + #endif + #if INIT_CUSTOM_USER_BUTTON_PINS(10) + INIT_CUSTOM_USER_BUTTON_PIN(10); + #endif + #if INIT_CUSTOM_USER_BUTTON_PINS(11) + INIT_CUSTOM_USER_BUTTON_PIN(11); + #endif + #if INIT_CUSTOM_USER_BUTTON_PINS(12) + INIT_CUSTOM_USER_BUTTON_PIN(12); + #endif + #if INIT_CUSTOM_USER_BUTTON_PINS(13) + INIT_CUSTOM_USER_BUTTON_PIN(13); + #endif + #if INIT_CUSTOM_USER_BUTTON_PINS(14) + INIT_CUSTOM_USER_BUTTON_PIN(14); + #endif + #if INIT_CUSTOM_USER_BUTTON_PINS(15) + INIT_CUSTOM_USER_BUTTON_PIN(15); + #endif + #if INIT_CUSTOM_USER_BUTTON_PINS(16) + INIT_CUSTOM_USER_BUTTON_PIN(16); + #endif + #if INIT_CUSTOM_USER_BUTTON_PINS(17) + INIT_CUSTOM_USER_BUTTON_PIN(17); + #endif + #if INIT_CUSTOM_USER_BUTTON_PINS(18) + INIT_CUSTOM_USER_BUTTON_PIN(18); + #endif + #if INIT_CUSTOM_USER_BUTTON_PINS(19) + INIT_CUSTOM_USER_BUTTON_PIN(19); + #endif + #if INIT_CUSTOM_USER_BUTTON_PINS(20) + INIT_CUSTOM_USER_BUTTON_PIN(20); + #endif + #if INIT_CUSTOM_USER_BUTTON_PINS(21) + INIT_CUSTOM_USER_BUTTON_PIN(21); + #endif + #if INIT_CUSTOM_USER_BUTTON_PINS(22) + INIT_CUSTOM_USER_BUTTON_PIN(22); + #endif + #if INIT_CUSTOM_USER_BUTTON_PINS(23) + INIT_CUSTOM_USER_BUTTON_PIN(23); + #endif + #if INIT_CUSTOM_USER_BUTTON_PINS(24) + INIT_CUSTOM_USER_BUTTON_PIN(24); + #endif + #if INIT_CUSTOM_USER_BUTTON_PINS(25) + INIT_CUSTOM_USER_BUTTON_PIN(25); + #endif + #endif + #if PIN_EXISTS(STAT_LED_RED) OUT_WRITE(STAT_LED_RED_PIN, LOW); // OFF #endif diff --git a/Marlin/src/inc/Conditionals_post.h b/Marlin/src/inc/Conditionals_post.h index c9a29b351c..e0901fc620 100644 --- a/Marlin/src/inc/Conditionals_post.h +++ b/Marlin/src/inc/Conditionals_post.h @@ -1966,6 +1966,9 @@ #if PIN_EXISTS(PHOTOGRAPH) #define HAS_PHOTOGRAPH 1 #endif +#if ENABLED(CUSTOM_USER_MENUS) + #define HAS_CUSTOM_USER_BUTTONS 1 +#endif // Digital control #if PIN_EXISTS(STEPPER_RESET)