diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index 0acf2e5f77..9569f9acd4 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -3278,7 +3278,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) @@ -3289,18 +3289,43 @@ #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_STATE_1 LOW // What state should trigger USER_GCODE_1 execution (LOW or HIGH) + #define USER_GCODE_PIN_TRIGGER_ALWAYS_1 false // PIN can trigger USER_GCODE_1 even if print job timer is running + #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) + //#define USER_GCODE_PIN_2 -1 // PIN assigned to trigger USER_GCODE_2 execution + #ifdef USER_GCODE_PIN_2 + #define USER_GCODE_PIN_STATE_2 LOW // What state should trigger USER_GCODE_2 execution (LOW or HIGH) + #define USER_GCODE_PIN_TRIGGER_ALWAYS_2 false // PIN can trigger USER_GCODE_2 even if print job timer is running + #endif #define USER_DESC_3 "Preheat for " PREHEAT_2_LABEL #define USER_GCODE_3 "M140 S" STRINGIFY(PREHEAT_2_TEMP_BED) "\nM104 S" STRINGIFY(PREHEAT_2_TEMP_HOTEND) + //#define USER_GCODE_PIN_3 -1 // PIN assigned to trigger USER_GCODE_3 execution + #ifdef USER_GCODE_PIN_3 + #define USER_GCODE_PIN_STATE_3 LOW // What state should trigger USER_GCODE_3 execution (LOW or HIGH) + #define USER_GCODE_PIN_TRIGGER_ALWAYS_3 false // PIN can trigger USER_GCODE_3 even if print job timer is running + #endif #define USER_DESC_4 "Heat Bed/Home/Level" #define USER_GCODE_4 "M140 S" STRINGIFY(PREHEAT_2_TEMP_BED) "\nG28\nG29" + //#define USER_GCODE_PIN_4 -1 // PIN assigned to trigger USER_GCODE_4 execution + #ifdef USER_GCODE_PIN_4 + #define USER_GCODE_PIN_STATE_4 LOW // What state should trigger USER_GCODE_4 execution (LOW or HIGH) + #define USER_GCODE_PIN_TRIGGER_ALWAYS_4 false // PIN can trigger USER_GCODE_4 even if print job timer is running + #endif #define USER_DESC_5 "Home & Info" #define USER_GCODE_5 "G28\nM503" + //#define USER_GCODE_PIN_5 -1 // PIN assigned to trigger USER_GCODE_5 execution + #ifdef USER_GCODE_PIN_5 + #define USER_GCODE_PIN_STATE_5 LOW // What state should trigger USER_GCODE_5 execution (LOW or HIGH) + #define USER_GCODE_PIN_TRIGGER_ALWAYS_5 false // PIN can trigger USER_GCODE_5 even if print job timer is running + #endif #endif /** diff --git a/Marlin/src/MarlinCore.cpp b/Marlin/src/MarlinCore.cpp index f38ba35dd5..81da8f6e13 100644 --- a/Marlin/src/MarlinCore.cpp +++ b/Marlin/src/MarlinCore.cpp @@ -485,6 +485,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 @@ -577,6 +578,101 @@ 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 + const bool printer_not_busy = !printingIsActive(); + #define HAS_CUSTOM_USER_BUTTON(N) ((defined(USER_GCODE_PIN_##N) && USER_GCODE_PIN_##N >= 0) && 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 = 2000UL; \ + static millis_t next_cub_ms_##N; \ + if ((USER_GCODE_PIN_STATE_##N == READ(USER_GCODE_PIN_##N)) \ + && (USER_GCODE_PIN_TRIGGER_ALWAYS_##N || printer_not_busy)) { \ + 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()); @@ -927,7 +1023,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 @@ -1172,6 +1268,86 @@ void setup() { SET_INPUT_PULLUP(HOME_PIN); #endif + #if HAS_CUSTOM_USER_BUTTONS + #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 HAS_CUSTOM_USER_BUTTON(1) + INIT_CUSTOM_USER_BUTTON_PIN(1); + #endif + #if HAS_CUSTOM_USER_BUTTON(2) + INIT_CUSTOM_USER_BUTTON_PIN(2); + #endif + #if HAS_CUSTOM_USER_BUTTON(3) + INIT_CUSTOM_USER_BUTTON_PIN(3); + #endif + #if HAS_CUSTOM_USER_BUTTON(4) + INIT_CUSTOM_USER_BUTTON_PIN(4); + #endif + #if HAS_CUSTOM_USER_BUTTON(5) + INIT_CUSTOM_USER_BUTTON_PIN(5); + #endif + #if HAS_CUSTOM_USER_BUTTON(6) + INIT_CUSTOM_USER_BUTTON_PIN(6); + #endif + #if HAS_CUSTOM_USER_BUTTON(7) + INIT_CUSTOM_USER_BUTTON_PIN(7); + #endif + #if HAS_CUSTOM_USER_BUTTON(8) + INIT_CUSTOM_USER_BUTTON_PIN(8); + #endif + #if HAS_CUSTOM_USER_BUTTON(9) + INIT_CUSTOM_USER_BUTTON_PIN(9); + #endif + #if HAS_CUSTOM_USER_BUTTON(10) + INIT_CUSTOM_USER_BUTTON_PIN(10); + #endif + #if HAS_CUSTOM_USER_BUTTON(11) + INIT_CUSTOM_USER_BUTTON_PIN(11); + #endif + #if HAS_CUSTOM_USER_BUTTON(12) + INIT_CUSTOM_USER_BUTTON_PIN(12); + #endif + #if HAS_CUSTOM_USER_BUTTON(13) + INIT_CUSTOM_USER_BUTTON_PIN(13); + #endif + #if HAS_CUSTOM_USER_BUTTON(14) + INIT_CUSTOM_USER_BUTTON_PIN(14); + #endif + #if HAS_CUSTOM_USER_BUTTON(15) + INIT_CUSTOM_USER_BUTTON_PIN(15); + #endif + #if HAS_CUSTOM_USER_BUTTON(16) + INIT_CUSTOM_USER_BUTTON_PIN(16); + #endif + #if HAS_CUSTOM_USER_BUTTON(17) + INIT_CUSTOM_USER_BUTTON_PIN(17); + #endif + #if HAS_CUSTOM_USER_BUTTON(18) + INIT_CUSTOM_USER_BUTTON_PIN(18); + #endif + #if HAS_CUSTOM_USER_BUTTON(19) + INIT_CUSTOM_USER_BUTTON_PIN(19); + #endif + #if HAS_CUSTOM_USER_BUTTON(20) + INIT_CUSTOM_USER_BUTTON_PIN(20); + #endif + #if HAS_CUSTOM_USER_BUTTON(21) + INIT_CUSTOM_USER_BUTTON_PIN(21); + #endif + #if HAS_CUSTOM_USER_BUTTON(22) + INIT_CUSTOM_USER_BUTTON_PIN(22); + #endif + #if HAS_CUSTOM_USER_BUTTON(23) + INIT_CUSTOM_USER_BUTTON_PIN(23); + #endif + #if HAS_CUSTOM_USER_BUTTON(24) + INIT_CUSTOM_USER_BUTTON_PIN(24); + #endif + #if HAS_CUSTOM_USER_BUTTON(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 9fb3e53c4e..67f5291070 100644 --- a/Marlin/src/inc/Conditionals_post.h +++ b/Marlin/src/inc/Conditionals_post.h @@ -2024,6 +2024,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)