From a16f3baecc6cd5da2fe71faac49650b5ff766cd7 Mon Sep 17 00:00:00 2001 From: vivian-ng Date: Fri, 14 Feb 2020 14:22:52 +0900 Subject: [PATCH 01/11] Add ESPAsyncTCP to lib_ignore (#16844) --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 5ea93ab8e0de..450fc32eb9d1 100644 --- a/platformio.ini +++ b/platformio.ini @@ -762,7 +762,7 @@ lib_deps = ${common.lib_deps} ESP3DLib=https://github.com/luc-github/ESP3DLib.git arduinoWebSockets=https://github.com/Links2004/arduinoWebSockets.git ESP32SSDP=https://github.com/luc-github/ESP32SSDP.git -lib_ignore = LiquidCrystal, LiquidTWI2, SailfishLCD, SailfishRGB_LED +lib_ignore = LiquidCrystal, LiquidTWI2, SailfishLCD, SailfishRGB_LED, ESPAsyncTCP src_filter = ${common.default_src_filter} + upload_speed = 115200 #upload_port = marlinesp.local From ff0c931e470970a9bbbcefaa2f183fc6733ec2a9 Mon Sep 17 00:00:00 2001 From: Giuliano Zaro <3684609+GMagician@users.noreply.github.com> Date: Fri, 14 Feb 2020 06:28:18 +0100 Subject: [PATCH 02/11] Add RAMPS 1.4.4 to AGCM4 (#16606) --- .github/workflows/test-builds.yml | 2 +- Marlin/src/HAL/HAL_SAMD51/timers.h | 2 +- Marlin/src/core/boards.h | 6 +- Marlin/src/pins/pins.h | 7 + Marlin/src/pins/samd/pins_RAMPS_144.h | 611 ++++++++++++++++++ .../share/tests/SAMD51_grandcentral_m4-tests | 7 + 6 files changed, 632 insertions(+), 3 deletions(-) create mode 100644 Marlin/src/pins/samd/pins_RAMPS_144.h diff --git a/.github/workflows/test-builds.yml b/.github/workflows/test-builds.yml index 301165fcd0ba..59722e3ca5a3 100644 --- a/.github/workflows/test-builds.yml +++ b/.github/workflows/test-builds.yml @@ -32,6 +32,7 @@ jobs: - megaatmega2560 - teensy31 - teensy35 + - SAMD51_grandcentral_m4 # Extended AVR Environments @@ -75,7 +76,6 @@ jobs: #- mks_robin_lite #- mks_robin_mini #- mks_robin_nano - #- SAMD51_grandcentral_m4 steps: diff --git a/Marlin/src/HAL/HAL_SAMD51/timers.h b/Marlin/src/HAL/HAL_SAMD51/timers.h index 9bd2e03d6f66..7ebd1b1406ce 100644 --- a/Marlin/src/HAL/HAL_SAMD51/timers.h +++ b/Marlin/src/HAL/HAL_SAMD51/timers.h @@ -29,7 +29,7 @@ typedef uint32_t hal_timer_t; #define HAL_TIMER_TYPE_MAX 0xFFFFFFFF -#define HAL_TIMER_RATE SystemCoreClock // frequency of timers peripherals +#define HAL_TIMER_RATE F_CPU // frequency of timers peripherals #define STEP_TIMER_NUM 0 // index of timer to use for stepper (also +1 for 32bits counter) #define PULSE_TIMER_NUM STEP_TIMER_NUM diff --git a/Marlin/src/core/boards.h b/Marlin/src/core/boards.h index 904c25d86849..4ba9840d812f 100644 --- a/Marlin/src/core/boards.h +++ b/Marlin/src/core/boards.h @@ -295,7 +295,6 @@ #define BOARD_GTM32_MINI_A30 4022 // STM32F103VET6 controller #define BOARD_GTM32_REV_B 4023 // STM32F103VET6 controller - // // ARM Cortex-M4F // @@ -340,6 +339,11 @@ #define BOARD_MRR_ESPE 6002 #define BOARD_E4D_BOX 6003 // E4d@BOX +// +// SAMD51 ARM Cortex M4 +// +#define BOARD_AGCM4_RAMPS_144 6100 // RAMPS 1.4.4 + // // Simulations // diff --git a/Marlin/src/pins/pins.h b/Marlin/src/pins/pins.h index 941b21bbbf87..3ba15c1326b2 100644 --- a/Marlin/src/pins/pins.h +++ b/Marlin/src/pins/pins.h @@ -578,6 +578,13 @@ #elif MB(E4D_BOX) #include "esp32/pins_E4D.h" // ESP32 env:esp32 +// +// Adafruit Grand Central M4 (SAMD51 ARM Cortex-M4) +// + +#elif MB(AGCM4_RAMPS_144) + #include "samd/pins_RAMPS_144.h" // SAMD51 env:SAMD51_grandcentral_m4 + // // Linux Native Debug board // diff --git a/Marlin/src/pins/samd/pins_RAMPS_144.h b/Marlin/src/pins/samd/pins_RAMPS_144.h new file mode 100644 index 000000000000..107ef9f57e95 --- /dev/null +++ b/Marlin/src/pins/samd/pins_RAMPS_144.h @@ -0,0 +1,611 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#pragma once + +/** + * AGCM4 with RAMPS v1.4.4 pin assignments + */ + +#ifndef ARDUINO_GRAND_CENTRAL_M4 + #error "Oops! Select 'Adafruit Grand Central M4' in 'Tools > Board.'" +#endif + +#ifndef BOARD_INFO_NAME + #define BOARD_INFO_NAME "AGCM4 RAMPS 1.4.4" +#endif + +// +// Servos +// +#define SERVO0_PIN 11 +#define SERVO1_PIN 6 +#define SERVO2_PIN 5 +#define SERVO3_PIN 4 + +// +// EEPROM +// +#define E2END 0x7FFF // 32Kb (24lc256) +#define I2C_EEPROM // EEPROM on I2C-0 + +// +// Limit Switches +// +#define X_MIN_PIN 3 +#define X_MAX_PIN 2 +#define Y_MIN_PIN 14 +#define Y_MAX_PIN 15 +#define Z_MIN_PIN 18 +#define Z_MAX_PIN 19 + +// +// Z Probe (when not Z_MIN_PIN) +// +#ifndef Z_MIN_PROBE_PIN + #define Z_MIN_PROBE_PIN 18 +#endif + +// +// Steppers +// +#define X_STEP_PIN 67 // Mega/Due:54 - AGCM4:67 +#define X_DIR_PIN 68 // Mega/Due:55 - AGCM4:68 +#define X_ENABLE_PIN 38 +#ifndef X_CS_PIN + #define X_CS_PIN 47 +#endif + +#define Y_STEP_PIN 73 // Mega/Due:60 - AGCM4:73 +#define Y_DIR_PIN 74 // Mega/Due:61 - AGCM4:74 +#define Y_ENABLE_PIN 69 // Mega/Due:56 - AGCM4:69 +#ifndef Y_CS_PIN + #define Y_CS_PIN 45 +#endif + +#define Z_STEP_PIN 46 +#define Z_DIR_PIN 48 +#define Z_ENABLE_PIN 54 // Mega/Due:62 - AGCM4:54 +#ifndef Z_CS_PIN + #define Z_CS_PIN 32 +#endif + +#define Z2_STEP_PIN 36 +#define Z2_DIR_PIN 34 +#define Z2_ENABLE_PIN 30 +#ifndef Z2_CS_PIN + #define Z2_CS_PIN 22 +#endif + +#define E0_STEP_PIN 26 +#define E0_DIR_PIN 28 +#define E0_ENABLE_PIN 24 +#ifndef E0_CS_PIN + #define E0_CS_PIN 43 +#endif + +// +// Temperature Sensors +// +#define TEMP_0_PIN 13 +#define TEMP_BED_PIN 14 +#define TEMP_CHAMBER_PIN 15 + +// +// Heaters / Fans +// +#define HEATER_0_PIN 10 +#define HEATER_BED_PIN 8 +#define FAN_PIN 9 +#define FAN1_PIN 7 +#define FAN2_PIN 12 + +// +// Misc. Functions +// +#define SDSS 53 +#define LED_PIN 13 + +#ifndef FILWIDTH_PIN + #define FILWIDTH_PIN 5 // Analog Input on AUX2 +#endif + +// RAMPS 1.4 DIO 4 on the servos connector +#ifndef FIL_RUNOUT_PIN + #define FIL_RUNOUT_PIN 4 +#endif + +#ifndef PS_ON_PIN + #define PS_ON_PIN 39 +#endif + +#if ENABLED(CASE_LIGHT_ENABLE) && !defined(CASE_LIGHT_PIN) && !defined(SPINDLE_LASER_ENA_PIN) + #if NUM_SERVOS <= 1 // Prefer the servo connector + #define CASE_LIGHT_PIN 6 // Hardware PWM + #endif +#endif + +// +// M3/M4/M5 - Spindle/Laser Control +// +#if HAS_CUTTER && !defined(SPINDLE_LASER_ENA_PIN) + #if !NUM_SERVOS // Use servo connector if possible + #define SPINDLE_LASER_ENA_PIN 4 // Pullup or pulldown! + #define SPINDLE_LASER_PWM_PIN 6 // Hardware PWM + #define SPINDLE_DIR_PIN 5 + #else + #error "No auto-assignable Spindle/Laser pins available." + #endif +#endif + +// +// TMC software SPI +// +#if ENABLED(TMC_USE_SW_SPI) + #ifndef TMC_SW_MOSI + #define TMC_SW_MOSI 58 // Mega/Due:66 - AGCM4:58 + #endif + #ifndef TMC_SW_MISO + #define TMC_SW_MISO 44 + #endif + #ifndef TMC_SW_SCK + #define TMC_SW_SCK 56 // Mega/Due:64 - AGCM4:56 + #endif +#endif + +#if HAS_TMC220x + /** + * TMC2208/TMC2209 stepper drivers + * + * Hardware serial communication ports. + * If undefined software serial is used according to the pins below + */ + //#define X_HARDWARE_SERIAL Serial1 + //#define X2_HARDWARE_SERIAL Serial1 + //#define Y_HARDWARE_SERIAL Serial1 + //#define Y2_HARDWARE_SERIAL Serial1 + //#define Z_HARDWARE_SERIAL Serial1 + //#define Z2_HARDWARE_SERIAL Serial1 + //#define E0_HARDWARE_SERIAL Serial1 + //#define E1_HARDWARE_SERIAL Serial1 + //#define E2_HARDWARE_SERIAL Serial1 + //#define E3_HARDWARE_SERIAL Serial1 + //#define E4_HARDWARE_SERIAL Serial1 + + // + // Software serial + // + + #ifndef X_SERIAL_TX_PIN + #define X_SERIAL_TX_PIN 47 + #endif + #ifndef X_SERIAL_RX_PIN + #define X_SERIAL_RX_PIN 47 + #endif + #ifndef X2_SERIAL_TX_PIN + #define X2_SERIAL_TX_PIN -1 + #endif + #ifndef X2_SERIAL_RX_PIN + #define X2_SERIAL_RX_PIN -1 + #endif + + #ifndef Y_SERIAL_TX_PIN + #define Y_SERIAL_TX_PIN 45 + #endif + #ifndef Y_SERIAL_RX_PIN + #define Y_SERIAL_RX_PIN 45 + #endif + #ifndef Y2_SERIAL_TX_PIN + #define Y2_SERIAL_TX_PIN -1 + #endif + #ifndef Y2_SERIAL_RX_PIN + #define Y2_SERIAL_RX_PIN -1 + #endif + + #ifndef Z_SERIAL_TX_PIN + #define Z_SERIAL_TX_PIN 32 + #endif + #ifndef Z_SERIAL_RX_PIN + #define Z_SERIAL_RX_PIN 32 + #endif + #ifndef Z2_SERIAL_TX_PIN + #define Z2_SERIAL_TX_PIN 22 + #endif + #ifndef Z2_SERIAL_RX_PIN + #define Z2_SERIAL_RX_PIN 22 + #endif + + #ifndef E0_SERIAL_TX_PIN + #define E0_SERIAL_TX_PIN 43 + #endif + #ifndef E0_SERIAL_RX_PIN + #define E0_SERIAL_RX_PIN 43 + #endif + #ifndef E1_SERIAL_TX_PIN + #define E1_SERIAL_TX_PIN -1 + #endif + #ifndef E1_SERIAL_RX_PIN + #define E1_SERIAL_RX_PIN -1 + #endif + #ifndef E2_SERIAL_TX_PIN + #define E2_SERIAL_TX_PIN -1 + #endif + #ifndef E2_SERIAL_RX_PIN + #define E2_SERIAL_RX_PIN -1 + #endif + #ifndef E3_SERIAL_TX_PIN + #define E3_SERIAL_TX_PIN -1 + #endif + #ifndef E3_SERIAL_RX_PIN + #define E3_SERIAL_RX_PIN -1 + #endif + #ifndef E4_SERIAL_TX_PIN + #define E4_SERIAL_TX_PIN -1 + #endif + #ifndef E4_SERIAL_RX_PIN + #define E4_SERIAL_RX_PIN -1 + #endif + #ifndef E5_SERIAL_TX_PIN + #define E5_SERIAL_TX_PIN -1 + #endif + #ifndef E5_SERIAL_RX_PIN + #define E5_SERIAL_RX_PIN -1 + #endif + #ifndef E6_SERIAL_TX_PIN + #define E6_SERIAL_TX_PIN -1 + #endif + #ifndef E6_SERIAL_RX_PIN + #define E6_SERIAL_RX_PIN -1 + #endif + #ifndef E7_SERIAL_TX_PIN + #define E7_SERIAL_TX_PIN -1 + #endif + #ifndef E7_SERIAL_RX_PIN + #define E7_SERIAL_RX_PIN -1 + #endif +#endif + +////////////////////////// +// LCDs and Controllers // +////////////////////////// + +#if HAS_SPI_LCD + + // + // LCD Display output pins + // + #if ENABLED(REPRAPWORLD_GRAPHICAL_LCD) + + // TO TEST + // #define LCD_PINS_RS 49 // CS chip select /SS chip slave select + // #define LCD_PINS_ENABLE 51 // SID (MOSI) + // #define LCD_PINS_D4 52 // SCK (CLK) clock + + #elif BOTH(NEWPANEL, PANEL_ONE) + + // TO TEST + // #define LCD_PINS_RS 40 + // #define LCD_PINS_ENABLE 42 + // #define LCD_PINS_D4 57 // Mega/Due:65 - AGCM4:57 + // #define LCD_PINS_D5 58 // Mega/Due:66 - AGCM4:58 + // #define LCD_PINS_D6 44 + // #define LCD_PINS_D7 56 // Mega/Due:64 - AGCM4:56 + + #else + + #if ENABLED(CR10_STOCKDISPLAY) + + // TO TEST + // #define LCD_PINS_RS 27 + // #define LCD_PINS_ENABLE 29 + // #define LCD_PINS_D4 25 + + #if DISABLED(NEWPANEL) + // TO TEST + // #define BEEPER_PIN 37 + #endif + + #elif ENABLED(ZONESTAR_LCD) + + // TO TEST + // #define LCD_PINS_RS 56 // Mega/Due:64 - AGCM4:56 + // #define LCD_PINS_ENABLE 44 + // #define LCD_PINS_D4 55 // Mega/Due:63 - AGCM4:55 + // #define LCD_PINS_D5 40 + // #define LCD_PINS_D6 42 + // #define LCD_PINS_D7 57 // Mega/Due:65 - AGCM4:57 + + #else + + #if EITHER(MKS_12864OLED, MKS_12864OLED_SSD1306) + // TO TEST + // #define LCD_PINS_DC 25 // Set as output on init + // #define LCD_PINS_RS 27 // Pull low for 1s to init + // DOGM SPI LCD Support + // #define DOGLCD_CS 16 + // #define DOGLCD_MOSI 17 + // #define DOGLCD_SCK 23 + // #define DOGLCD_A0 LCD_PINS_DC + #else + #define LCD_PINS_RS 16 + #define LCD_PINS_ENABLE 17 + #define LCD_PINS_D4 23 + #define LCD_PINS_D5 25 + #define LCD_PINS_D6 27 + #endif + + #define LCD_PINS_D7 29 + + #if DISABLED(NEWPANEL) + #define BEEPER_PIN 33 + #endif + + #endif + + #if DISABLED(NEWPANEL) + // Buttons attached to a shift register + // Not wired yet + //#define SHIFT_CLK 38 + //#define SHIFT_LD 42 + //#define SHIFT_OUT 40 + //#define SHIFT_EN 17 + #endif + + #endif + + // + // LCD Display input pins + // + #if ENABLED(NEWPANEL) + + #if ENABLED(REPRAP_DISCOUNT_SMART_CONTROLLER) + + #define BEEPER_PIN 37 + + #if ENABLED(CR10_STOCKDISPLAY) + // TO TEST + // #define BTN_EN1 17 + // #define BTN_EN2 23 + #else + #define BTN_EN1 31 + #define BTN_EN2 33 + #endif + + #define BTN_ENC 35 + #ifndef SD_DETECT_PIN + #define SD_DETECT_PIN 49 + #endif + #define KILL_PIN 41 + + #if ENABLED(BQ_LCD_SMART_CONTROLLER) + // TO TEST + // #define LCD_BACKLIGHT_PIN 39 + #endif + + #elif ENABLED(REPRAPWORLD_GRAPHICAL_LCD) + + // TO TEST + // #define BTN_EN1 56 // Mega/Due:64 - AGCM4:56 + // #define BTN_EN2 72 // Mega/Due:59 - AGCM4:72 + // #define BTN_ENC 55 + // #define SD_DETECT_PIN 42 + + #elif ENABLED(LCD_I2C_PANELOLU2) + + // TO TEST + // #define BTN_EN1 47 + // #define BTN_EN2 43 + // #define BTN_ENC 32 + // #define LCD_SDSS SDSS + // #define KILL_PIN 41 + + #elif ENABLED(LCD_I2C_VIKI) + + // TO TEST + // #define BTN_EN1 40 // http://files.panucatt.com/datasheets/viki_wiring_diagram.pdf explains 40/42. + // #define BTN_EN2 42 + // #define BTN_ENC -1 + + // #define LCD_SDSS SDSS + // #define SD_DETECT_PIN 49 + + #elif ANY(VIKI2, miniVIKI) + + // TO TEST + // #define DOGLCD_CS 45 + // #define DOGLCD_A0 44 + // #define LCD_SCREEN_ROT_180 + + // #define BEEPER_PIN 33 + // #define STAT_LED_RED_PIN 32 + // #define STAT_LED_BLUE_PIN 35 + + // #define BTN_EN1 22 + // #define BTN_EN2 7 + // #define BTN_ENC 39 + + // #define SD_DETECT_PIN -1 // Pin 49 for display SD interface, 72 for easy adapter board + // #define KILL_PIN 31 + + #elif ENABLED(ELB_FULL_GRAPHIC_CONTROLLER) + + // TO TEST + // #define DOGLCD_CS 29 + // #define DOGLCD_A0 27 + + // #define BEEPER_PIN 23 + // #define LCD_BACKLIGHT_PIN 33 + + // #define BTN_EN1 35 + // #define BTN_EN2 37 + // #define BTN_ENC 31 + + // #define LCD_SDSS SDSS + // #define SD_DETECT_PIN 49 + // #define KILL_PIN 41 + + #elif EITHER(MKS_MINI_12864, FYSETC_MINI_12864) + + // TO TEST + //#define BEEPER_PIN 37 + //#define BTN_ENC 35 + //#define SD_DETECT_PIN 49 + + //#ifndef KILL_PIN + // #define KILL_PIN 41 + //#endif + + #if ENABLED(MKS_MINI_12864) // Added in Marlin 1.1.6 + + // TO TEST + // #define DOGLCD_A0 27 + // #define DOGLCD_CS 25 + + // GLCD features + // Uncomment screen orientation + // #define LCD_SCREEN_ROT_90 + // #define LCD_SCREEN_ROT_180 + // #define LCD_SCREEN_ROT_270 + + // not connected to a pin + // #define LCD_BACKLIGHT_PIN 57 // backlight LED on A11/D? (Mega/Due:65 - AGCM4:57) + + // #define BTN_EN1 31 + // #define BTN_EN2 33 + + #elif ENABLED(FYSETC_MINI_12864) + + // From https://wiki.fysetc.com/Mini12864_Panel/?fbclid=IwAR1FyjuNdVOOy9_xzky3qqo_WeM5h-4gpRnnWhQr_O1Ef3h0AFnFXmCehK8 + + // TO TEST + // #define DOGLCD_A0 16 + // #define DOGLCD_CS 17 + + // #define BTN_EN1 33 + // #define BTN_EN2 31 + + //#define FORCE_SOFT_SPI // Use this if default of hardware SPI causes display problems + // results in LCD soft SPI mode 3, SD soft SPI mode 0 + + // #define LCD_RESET_PIN 23 // Must be high or open for LCD to operate normally. + + #if EITHER(FYSETC_MINI_12864_1_2, FYSETC_MINI_12864_2_0) + #ifndef RGB_LED_R_PIN + // TO TEST + // #define RGB_LED_R_PIN 25 + #endif + #ifndef RGB_LED_G_PIN + // TO TEST + // #define RGB_LED_G_PIN 27 + #endif + #ifndef RGB_LED_B_PIN + // TO TEST + // #define RGB_LED_B_PIN 29 + #endif + #elif ENABLED(FYSETC_MINI_12864_2_1) + // TO TEST + // #define NEOPIXEL_PIN 25 + #endif + + #endif + + #elif ENABLED(MINIPANEL) + + // TO TEST + // #define BEEPER_PIN 42 + // not connected to a pin + // #define LCD_BACKLIGHT_PIN 57 // backlight LED on A11/D? (Mega/Due:65 - AGCM4:57) + + // #define DOGLCD_A0 44 + // #define DOGLCD_CS 58 // Mega/Due:66 - AGCM4:58 + + // GLCD features + // Uncomment screen orientation + // #define LCD_SCREEN_ROT_90 + // #define LCD_SCREEN_ROT_180 + // #define LCD_SCREEN_ROT_270 + + // #define BTN_EN1 40 + // #define BTN_EN2 55 // Mega/Due:63 - AGCM4:55 + // #define BTN_ENC 72 // Mega/Due:59 - AGCM4:72 + + // #define SD_DETECT_PIN 49 + // #define KILL_PIN 56 // Mega/Due:64 - AGCM4:56 + + #elif ENABLED(ZONESTAR_LCD) + + // TO TEST + // #define ADC_KEYPAD_PIN 12 + + #elif ENABLED(AZSMZ_12864) + + // TO TEST + + #else + + // Beeper on AUX-4 + // #define BEEPER_PIN 33 + + // Buttons are directly attached to AUX-2 + #if ENABLED(REPRAPWORLD_KEYPAD) + // TO TEST + // #define SHIFT_OUT 40 + // #define SHIFT_CLK 44 + // #define SHIFT_LD 42 + // #define BTN_EN1 56 // Mega/Due:64 - AGCM4:56 + // #define BTN_EN2 72 // Mega/Due:59 - AGCM4:72 + // #define BTN_ENC 55 // Mega/Due:63 - AGCM4:55 + #elif ENABLED(PANEL_ONE) + // TO TEST + // #define BTN_EN1 72 // AUX2 PIN 3 (Mega/Due:59 - AGCM4:72) + // #define BTN_EN2 55 // AUX2 PIN 4 (Mega/Due:63 - AGCM4:55) + // #define BTN_ENC 49 // AUX3 PIN 7 + #else + // TO TEST + // #define BTN_EN1 37 + // #define BTN_EN2 35 + // #define BTN_ENC 31 + #endif + + #if ENABLED(G3D_PANEL) + // TO TEST + // #define SD_DETECT_PIN 49 + // #define KILL_PIN 41 + #endif + + #endif + #endif // NEWPANEL + +#endif // HAS_SPI_LCD + +// +// SD Support +// +#ifndef SDCARD_CONNECTION + #define SDCARD_CONNECTION ONBOARD +#endif + +#if SD_CONNECTION_IS(ONBOARD) + #undef SDSS + #define SDSS 83 + #undef SD_DETECT_PIN + #define SD_DETECT_PIN 95 +#endif diff --git a/buildroot/share/tests/SAMD51_grandcentral_m4-tests b/buildroot/share/tests/SAMD51_grandcentral_m4-tests index 898a58560472..f7157b1ed8b1 100644 --- a/buildroot/share/tests/SAMD51_grandcentral_m4-tests +++ b/buildroot/share/tests/SAMD51_grandcentral_m4-tests @@ -6,5 +6,12 @@ # exit on first failure set -e +# +# Build with the default configurations +# +restore_configs +opt_set MOTHERBOARD BOARD_AGCM4_RAMPS_144 +exec_test $1 $2 "Build Grand Central M4 Default Configuration" + # clean up restore_configs From 00ba053c90ebbe6d430a48912bc3e00c8a1041c8 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Thu, 13 Feb 2020 23:39:27 -0600 Subject: [PATCH 03/11] Clean up host actions code (#16856) --- Marlin/src/feature/host_actions.cpp | 96 ++++++++++++++++------------- Marlin/src/feature/host_actions.h | 10 +-- Marlin/src/feature/pause.cpp | 41 +++++------- Marlin/src/feature/pause.h | 17 ++--- Marlin/src/feature/runout.cpp | 6 +- Marlin/src/gcode/host/M876.cpp | 2 + 6 files changed, 85 insertions(+), 87 deletions(-) diff --git a/Marlin/src/feature/host_actions.cpp b/Marlin/src/feature/host_actions.cpp index 3633a7b75f5b..c9e87a62377b 100644 --- a/Marlin/src/feature/host_actions.cpp +++ b/Marlin/src/feature/host_actions.cpp @@ -84,70 +84,78 @@ void host_action(const char * const pstr, const bool eol) { if (eol) SERIAL_EOL(); } - void host_action_prompt_plus(const char * const ptype, const char * const pstr, const bool eol=true) { + void host_action_prompt_plus(const char * const ptype, const char * const pstr, const char extra_char='\0') { host_action_prompt(ptype, false); SERIAL_CHAR(' '); serialprintPGM(pstr); - if (eol) SERIAL_EOL(); + if (extra_char != '\0') SERIAL_CHAR(extra_char); + SERIAL_EOL(); + } + void host_action_prompt_begin(const PromptReason reason, const char * const pstr, const char extra_char/*='\0'*/) { + host_action_prompt_end(); + host_prompt_reason = reason; + host_action_prompt_plus(PSTR("begin"), pstr, extra_char); } - void host_action_prompt_begin(const char * const pstr, const bool eol/*=true*/) { host_action_prompt_plus(PSTR("begin"), pstr, eol); } void host_action_prompt_button(const char * const pstr) { host_action_prompt_plus(PSTR("button"), pstr); } void host_action_prompt_end() { host_action_prompt(PSTR("end")); } void host_action_prompt_show() { host_action_prompt(PSTR("show")); } - void host_prompt_do(const PromptReason reason, const char * const pstr, const char * const pbtn/*=nullptr*/) { - host_prompt_reason = reason; - host_action_prompt_end(); - host_action_prompt_begin(pstr); - if (pbtn) host_action_prompt_button(pbtn); + void host_prompt_do(const PromptReason reason, const char * const pstr, const char * const btn1/*=nullptr*/, const char * const btn2/*=nullptr*/) { + host_action_prompt_begin(reason, pstr); + if (btn1) host_action_prompt_button(btn1); + if (btn2) host_action_prompt_button(btn2); host_action_prompt_show(); } - inline void say_m876_response(const char * const pstr) { - SERIAL_ECHOPGM("M876 Responding PROMPT_"); - serialprintPGM(pstr); - SERIAL_EOL(); + void filament_load_host_prompt() { + const bool disable_to_continue = (false + #if HAS_FILAMENT_SENSOR + || runout.filament_ran_out + #endif + ); + host_prompt_do(PROMPT_FILAMENT_RUNOUT, PSTR("Paused"), PSTR("PurgeMore"), + disable_to_continue ? PSTR("DisableRunout") : CONTINUE_STR + ); } + // + // Handle responses from the host, such as: + // - Filament runout responses: Purge More, Continue + // - General "Continue" response + // - Resume Print response + // - Dismissal of info + // void host_response_handler(const uint8_t response) { #ifdef DEBUG_HOST_ACTIONS - SERIAL_ECHOLNPAIR("M876 Handle Reason: ", host_prompt_reason); - SERIAL_ECHOLNPAIR("M876 Handle Response: ", response); + static const char m876_prefix[] PROGMEM = "M876 Handle Re"; + serialprintPGM(m876_prefix); SERIAL_ECHOLNPAIR("ason: ", host_prompt_reason); + serialprintPGM(m876_prefix); SERIAL_ECHOLNPAIR("sponse: ", response); #endif const char *msg = PSTR("UNKNOWN STATE"); const PromptReason hpr = host_prompt_reason; - host_prompt_reason = PROMPT_NOT_DEFINED; + host_prompt_reason = PROMPT_NOT_DEFINED; // Reset now ahead of logic switch (hpr) { case PROMPT_FILAMENT_RUNOUT: msg = PSTR("FILAMENT_RUNOUT"); - if (response == 0) { - #if ENABLED(ADVANCED_PAUSE_FEATURE) - pause_menu_response = PAUSE_RESPONSE_EXTRUDE_MORE; - #endif - host_action_prompt_end(); // Close current prompt - host_action_prompt_begin(PSTR("Paused")); - host_action_prompt_button(PSTR("Purge More")); - if (false + switch (response) { + + case 0: // "Purge More" button + #if HAS_LCD_MENU && ENABLED(ADVANCED_PAUSE_FEATURE) + pause_menu_response = PAUSE_RESPONSE_EXTRUDE_MORE; // Simulate menu selection (menu exits, doesn't extrude more) + #endif + filament_load_host_prompt(); // Initiate another host prompt. (NOTE: The loop in load_filament may also do this!) + break; + + case 1: // "Continue" / "Disable Runout" button + #if HAS_LCD_MENU && ENABLED(ADVANCED_PAUSE_FEATURE) + pause_menu_response = PAUSE_RESPONSE_RESUME_PRINT; // Simulate menu selection + #endif #if HAS_FILAMENT_SENSOR - || runout.filament_ran_out + if (runout.filament_ran_out) { // Disable a triggered sensor + runout.enabled = false; + runout.reset(); + } #endif - ) - host_action_prompt_button(PSTR("DisableRunout")); - else { - host_prompt_reason = PROMPT_FILAMENT_RUNOUT; - host_action_prompt_button(CONTINUE_STR); - } - host_action_prompt_show(); - } - else if (response == 1) { - #if HAS_FILAMENT_SENSOR - if (runout.filament_ran_out) { - runout.enabled = false; - runout.reset(); - } - #endif - #if ENABLED(ADVANCED_PAUSE_FEATURE) - pause_menu_response = PAUSE_RESPONSE_RESUME_PRINT; - #endif + break; } break; case PROMPT_USER_CONTINUE: @@ -168,7 +176,9 @@ void host_action(const char * const pstr, const bool eol) { break; default: break; } - say_m876_response(msg); + SERIAL_ECHOPGM("M876 Responding PROMPT_"); + serialprintPGM(msg); + SERIAL_EOL(); } #endif // HOST_PROMPT_SUPPORT diff --git a/Marlin/src/feature/host_actions.h b/Marlin/src/feature/host_actions.h index 939f0be2de67..d90a21b1f1e4 100644 --- a/Marlin/src/feature/host_actions.h +++ b/Marlin/src/feature/host_actions.h @@ -61,13 +61,15 @@ void host_action(const char * const pstr, const bool eol=true); void host_response_handler(const uint8_t response); void host_action_notify(const char * const message); - void host_action_prompt_begin(const char * const pstr, const bool eol=true); + void host_action_prompt_begin(const PromptReason reason, const char * const pstr, const char extra_char='\0'); void host_action_prompt_button(const char * const pstr); void host_action_prompt_end(); void host_action_prompt_show(); - void host_prompt_do(const PromptReason type, const char * const pstr, const char * const pbtn=nullptr); - inline void host_prompt_open(const PromptReason reason, const char * const pstr, const char * const pbtn=nullptr) { - if (host_prompt_reason == PROMPT_NOT_DEFINED) host_prompt_do(reason, pstr, pbtn); + void host_prompt_do(const PromptReason reason, const char * const pstr, const char * const btn1=nullptr, const char * const btn2=nullptr); + inline void host_prompt_open(const PromptReason reason, const char * const pstr, const char * const btn1=nullptr, const char * const btn2=nullptr) { + if (host_prompt_reason == PROMPT_NOT_DEFINED) host_prompt_do(reason, pstr, btn1, btn2); } + void filament_load_host_prompt(); + #endif diff --git a/Marlin/src/feature/pause.cpp b/Marlin/src/feature/pause.cpp index 0bf8fe4b9889..5a7cde204669 100644 --- a/Marlin/src/feature/pause.cpp +++ b/Marlin/src/feature/pause.cpp @@ -67,9 +67,10 @@ static xyze_pos_t resume_position; -PauseMode pause_mode = PAUSE_MODE_PAUSE_PRINT; - -PauseMenuResponse pause_menu_response; +#if HAS_LCD_MENU + PauseMenuResponse pause_menu_response; + PauseMode pause_mode = PAUSE_MODE_PAUSE_PRINT; +#endif fil_change_settings_t fc_settings[EXTRUDERS]; @@ -85,7 +86,11 @@ fil_change_settings_t fc_settings[EXTRUDERS]; #if HAS_BUZZER static void filament_change_beep(const int8_t max_beep_count, const bool init=false) { - if (pause_mode == PAUSE_MODE_PAUSE_PRINT) return; + + #if HAS_LCD_MENU + if (pause_mode == PAUSE_MODE_PAUSE_PRINT) return; + #endif + static millis_t next_buzz = 0; static int8_t runout_beep = 0; @@ -186,11 +191,7 @@ bool load_filament(const float &slow_load_length/*=0*/, const float &fast_load_l + active_extruder #endif ; - host_prompt_reason = PROMPT_USER_CONTINUE; - host_action_prompt_end(); - host_action_prompt_begin(PSTR("Load Filament T"), false); - SERIAL_CHAR(tool); - SERIAL_EOL(); + host_action_prompt_begin(PROMPT_USER_CONTINUE, PSTR("Load Filament T"), tool); host_action_prompt_button(CONTINUE_STR); host_action_prompt_show(); #endif @@ -247,10 +248,10 @@ bool load_filament(const float &slow_load_length/*=0*/, const float &fast_load_l wait_for_user = true; #if ENABLED(HOST_PROMPT_SUPPORT) - host_prompt_do(PROMPT_USER_CONTINUE, PSTR("Filament Purge Running..."), CONTINUE_STR); + host_prompt_do(PROMPT_USER_CONTINUE, PSTR("Filament Purging..."), CONTINUE_STR); #endif #if ENABLED(EXTENSIBLE_UI) - ExtUI::onUserConfirmRequired_P(PSTR("Filament Purge Running...")); + ExtUI::onUserConfirmRequired_P(PSTR("Filament Purging...")); #endif for (float purge_count = purge_length; purge_count > 0 && wait_for_user; --purge_count) do_pause_e_move(1, ADVANCED_PAUSE_PURGE_FEEDRATE); @@ -269,27 +270,13 @@ bool load_filament(const float &slow_load_length/*=0*/, const float &fast_load_l do_pause_e_move(purge_length, ADVANCED_PAUSE_PURGE_FEEDRATE); } - // Show "Purge More" / "Resume" menu and wait for reply #if ENABLED(HOST_PROMPT_SUPPORT) - host_prompt_reason = PROMPT_FILAMENT_RUNOUT; - host_action_prompt_end(); // Close current prompt - host_action_prompt_begin(PSTR("Paused")); - host_action_prompt_button(PSTR("PurgeMore")); - if (false - #if HAS_FILAMENT_SENSOR - || runout.filament_ran_out - #endif - ) - host_action_prompt_button(PSTR("DisableRunout")); - else { - host_prompt_reason = PROMPT_FILAMENT_RUNOUT; - host_action_prompt_button(CONTINUE_STR); - } - host_action_prompt_show(); + filament_load_host_prompt(); // Initiate another host prompt. (NOTE: host_response_handler may also do this!) #endif #if HAS_LCD_MENU if (show_lcd) { + // Show "Purge More" / "Resume" menu and wait for reply KEEPALIVE_STATE(PAUSED_FOR_USER); wait_for_user = false; lcd_pause_show_message(PAUSE_MESSAGE_OPTION); diff --git a/Marlin/src/feature/pause.h b/Marlin/src/feature/pause.h index f88dd349c59e..5ac67a565c36 100644 --- a/Marlin/src/feature/pause.h +++ b/Marlin/src/feature/pause.h @@ -59,14 +59,15 @@ enum PauseMessage : char { PAUSE_MESSAGE_HEATING }; -enum PauseMenuResponse : char { - PAUSE_RESPONSE_WAIT_FOR, - PAUSE_RESPONSE_EXTRUDE_MORE, - PAUSE_RESPONSE_RESUME_PRINT -}; - -extern PauseMode pause_mode; -extern PauseMenuResponse pause_menu_response; +#if HAS_LCD_MENU + enum PauseMenuResponse : char { + PAUSE_RESPONSE_WAIT_FOR, + PAUSE_RESPONSE_EXTRUDE_MORE, + PAUSE_RESPONSE_RESUME_PRINT + }; + extern PauseMenuResponse pause_menu_response; + extern PauseMode pause_mode; +#endif extern fil_change_settings_t fc_settings[EXTRUDERS]; diff --git a/Marlin/src/feature/runout.cpp b/Marlin/src/feature/runout.cpp index 3acda2f7a254..3cf81303ddbe 100644 --- a/Marlin/src/feature/runout.cpp +++ b/Marlin/src/feature/runout.cpp @@ -92,11 +92,7 @@ void event_filament_runout() { //action:out_of_filament #if ENABLED(HOST_PROMPT_SUPPORT) - host_prompt_reason = PROMPT_FILAMENT_RUNOUT; - host_action_prompt_end(); - host_action_prompt_begin(PSTR("FilamentRunout T"), false); - SERIAL_CHAR(tool); - SERIAL_EOL(); + host_action_prompt_begin(PROMPT_FILAMENT_RUNOUT, PSTR("FilamentRunout T"), tool); host_action_prompt_show(); #endif diff --git a/Marlin/src/gcode/host/M876.cpp b/Marlin/src/gcode/host/M876.cpp index 8e83185e0246..fe0ca1541abe 100644 --- a/Marlin/src/gcode/host/M876.cpp +++ b/Marlin/src/gcode/host/M876.cpp @@ -31,7 +31,9 @@ * M876: Handle Prompt Response */ void GcodeSuite::M876() { + if (parser.seenval('S')) host_response_handler((uint8_t)parser.value_int()); + } #endif // HOST_PROMPT_SUPPORT && !EMERGENCY_PARSER From 073e4443e8b8624078138a0c6f422cccc2959a86 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Fri, 14 Feb 2020 00:05:06 -0600 Subject: [PATCH 04/11] Optimize "Dismiss" string --- Marlin/src/MarlinCore.cpp | 2 +- Marlin/src/feature/host_actions.cpp | 3 ++- Marlin/src/feature/host_actions.h | 2 +- Marlin/src/feature/pause.cpp | 4 ++-- Marlin/src/gcode/sdcard/M24_M25.cpp | 2 +- Marlin/src/lcd/ultralcd.cpp | 2 +- 6 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Marlin/src/MarlinCore.cpp b/Marlin/src/MarlinCore.cpp index ecfdcc21b3da..b1e895d97f81 100644 --- a/Marlin/src/MarlinCore.cpp +++ b/Marlin/src/MarlinCore.cpp @@ -345,7 +345,7 @@ void disable_all_steppers() { void event_probe_recover() { #if ENABLED(HOST_PROMPT_SUPPORT) - host_prompt_do(PROMPT_INFO, PSTR("G29 Retrying"), PSTR("Dismiss")); + host_prompt_do(PROMPT_INFO, PSTR("G29 Retrying"), DISMISS_STR); #endif #ifdef ACTION_ON_G29_RECOVER host_action(PSTR(ACTION_ON_G29_RECOVER)); diff --git a/Marlin/src/feature/host_actions.cpp b/Marlin/src/feature/host_actions.cpp index c9e87a62377b..2108f4e7f427 100644 --- a/Marlin/src/feature/host_actions.cpp +++ b/Marlin/src/feature/host_actions.cpp @@ -64,7 +64,8 @@ void host_action(const char * const pstr, const bool eol) { #if ENABLED(HOST_PROMPT_SUPPORT) - const char CONTINUE_STR[] PROGMEM = "Continue"; + const char CONTINUE_STR[] PROGMEM = "Continue", + DISMISS_STR[] PROGMEM = "Dismiss"; #if HAS_RESUME_CONTINUE extern bool wait_for_user; diff --git a/Marlin/src/feature/host_actions.h b/Marlin/src/feature/host_actions.h index d90a21b1f1e4..3667b7f4308e 100644 --- a/Marlin/src/feature/host_actions.h +++ b/Marlin/src/feature/host_actions.h @@ -46,7 +46,7 @@ void host_action(const char * const pstr, const bool eol=true); #if ENABLED(HOST_PROMPT_SUPPORT) - extern const char CONTINUE_STR[]; + extern const char CONTINUE_STR[], DISMISS_STR[]; enum PromptReason : uint8_t { PROMPT_NOT_DEFINED, diff --git a/Marlin/src/feature/pause.cpp b/Marlin/src/feature/pause.cpp index 5a7cde204669..9fd279fe5d61 100644 --- a/Marlin/src/feature/pause.cpp +++ b/Marlin/src/feature/pause.cpp @@ -396,7 +396,7 @@ bool pause_print(const float &retract, const xyz_pos_t &park_point, const float #endif #if ENABLED(HOST_PROMPT_SUPPORT) - host_prompt_open(PROMPT_INFO, PSTR("Pause"), PSTR("Dismiss")); + host_prompt_open(PROMPT_INFO, PSTR("Pause"), DISMISS_STR); #endif if (!DEBUGGING(DRYRUN) && unload_length && thermalManager.targetTooColdToExtrude(active_extruder)) { @@ -667,7 +667,7 @@ void resume_print(const float &slow_load_length/*=0*/, const float &fast_load_le --did_pause_print; #if ENABLED(HOST_PROMPT_SUPPORT) - host_prompt_open(PROMPT_INFO, PSTR("Resuming"), PSTR("Dismiss")); + host_prompt_open(PROMPT_INFO, PSTR("Resuming"), DISMISS_STR); #endif #if ENABLED(SDSUPPORT) diff --git a/Marlin/src/gcode/sdcard/M24_M25.cpp b/Marlin/src/gcode/sdcard/M24_M25.cpp index 02ba5acb3928..967b6dfdf37e 100644 --- a/Marlin/src/gcode/sdcard/M24_M25.cpp +++ b/Marlin/src/gcode/sdcard/M24_M25.cpp @@ -74,7 +74,7 @@ void GcodeSuite::M24() { host_action_resume(); #endif #if ENABLED(HOST_PROMPT_SUPPORT) - host_prompt_open(PROMPT_INFO, PSTR("Resuming SD"), PSTR("Dismiss")); + host_prompt_open(PROMPT_INFO, PSTR("Resuming SD"), DISMISS_STR); #endif #endif diff --git a/Marlin/src/lcd/ultralcd.cpp b/Marlin/src/lcd/ultralcd.cpp index 717a3f05d826..8ad02acfbaf7 100644 --- a/Marlin/src/lcd/ultralcd.cpp +++ b/Marlin/src/lcd/ultralcd.cpp @@ -1504,7 +1504,7 @@ void MarlinUI::update() { host_action_cancel(); #endif #if ENABLED(HOST_PROMPT_SUPPORT) - host_prompt_open(PROMPT_INFO, PSTR("UI Aborted"), PSTR("Dismiss")); + host_prompt_open(PROMPT_INFO, PSTR("UI Aborted"), DISMISS_STR); #endif print_job_timer.stop(); set_status_P(GET_TEXT(MSG_PRINT_ABORTED)); From 0b984519c30f453fdb5b4efb8008a07c69688824 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Fri, 14 Feb 2020 05:14:37 -0600 Subject: [PATCH 05/11] Clean up stepper and babystep (#16857) --- Marlin/src/HAL/HAL_ESP32/i2s.cpp | 4 +- Marlin/src/feature/babystep.cpp | 8 -- Marlin/src/feature/babystep.h | 10 +- Marlin/src/module/planner.cpp | 110 +++++++++++++++++-- Marlin/src/module/planner.h | 97 ++--------------- Marlin/src/module/stepper.cpp | 173 ++++++++++++++++-------------- Marlin/src/module/stepper.h | 75 +++++-------- Marlin/src/module/temperature.cpp | 5 +- 8 files changed, 242 insertions(+), 240 deletions(-) diff --git a/Marlin/src/HAL/HAL_ESP32/i2s.cpp b/Marlin/src/HAL/HAL_ESP32/i2s.cpp index de5ef397ddb2..9f72fcbb0fdb 100644 --- a/Marlin/src/HAL/HAL_ESP32/i2s.cpp +++ b/Marlin/src/HAL/HAL_ESP32/i2s.cpp @@ -153,8 +153,8 @@ void stepperTask(void* parameter) { remaining--; } else { - Stepper::stepper_pulse_phase_isr(); - remaining = Stepper::stepper_block_phase_isr(); + Stepper::pulse_phase_isr(); + remaining = Stepper::block_phase_isr(); } } } diff --git a/Marlin/src/feature/babystep.cpp b/Marlin/src/feature/babystep.cpp index c6e7628a154e..eedd8f6196c8 100644 --- a/Marlin/src/feature/babystep.cpp +++ b/Marlin/src/feature/babystep.cpp @@ -49,14 +49,6 @@ void Babystep::step_axis(const AxisEnum axis) { } } -void Babystep::task() { - #if EITHER(BABYSTEP_XY, I2C_POSITION_ENCODERS) - LOOP_XYZ(axis) step_axis((AxisEnum)axis); - #else - step_axis(Z_AXIS); - #endif -} - void Babystep::add_mm(const AxisEnum axis, const float &mm) { add_steps(axis, mm * planner.settings.axis_steps_per_mm[axis]); } diff --git a/Marlin/src/feature/babystep.h b/Marlin/src/feature/babystep.h index 3322b4a24633..63ea0e3e24a0 100644 --- a/Marlin/src/feature/babystep.h +++ b/Marlin/src/feature/babystep.h @@ -55,7 +55,15 @@ class Babystep { static void add_steps(const AxisEnum axis, const int16_t distance); static void add_mm(const AxisEnum axis, const float &mm); - static void task(); + + // + // Called by the Temperature ISR to + // apply accumulated babysteps to the axes. + // + static inline void task() { + LOOP_L_N(axis, BS_TODO_AXIS(Z_AXIS)) step_axis((AxisEnum)axis); + } + private: static void step_axis(const AxisEnum axis); }; diff --git a/Marlin/src/module/planner.cpp b/Marlin/src/module/planner.cpp index 72dfeed46ff3..b39ac993b40b 100644 --- a/Marlin/src/module/planner.cpp +++ b/Marlin/src/module/planner.cpp @@ -709,6 +709,59 @@ void Planner::init() { #define MINIMAL_STEP_RATE 120 +/** + * Get the current block for processing + * and mark the block as busy. + * Return nullptr if the buffer is empty + * or if there is a first-block delay. + * + * WARNING: Called from Stepper ISR context! + */ +block_t* Planner::get_current_block() { + // Get the number of moves in the planner queue so far + const uint8_t nr_moves = movesplanned(); + + // If there are any moves queued ... + if (nr_moves) { + + // If there is still delay of delivery of blocks running, decrement it + if (delay_before_delivering) { + --delay_before_delivering; + // If the number of movements queued is less than 3, and there is still time + // to wait, do not deliver anything + if (nr_moves < 3 && delay_before_delivering) return nullptr; + delay_before_delivering = 0; + } + + // If we are here, there is no excuse to deliver the block + block_t * const block = &block_buffer[block_buffer_tail]; + + // No trapezoid calculated? Don't execute yet. + if (TEST(block->flag, BLOCK_BIT_RECALCULATE)) return nullptr; + + #if HAS_SPI_LCD + block_buffer_runtime_us -= block->segment_time_us; // We can't be sure how long an active block will take, so don't count it. + #endif + + // As this block is busy, advance the nonbusy block pointer + block_buffer_nonbusy = next_block_index(block_buffer_tail); + + // Push block_buffer_planned pointer, if encountered. + if (block_buffer_tail == block_buffer_planned) + block_buffer_planned = block_buffer_nonbusy; + + // Return the block + return block; + } + + // The queue became empty + #if HAS_SPI_LCD + clear_block_buffer_runtime(); // paranoia. Buffer is empty now - so reset accumulated time to zero. + #endif + + return nullptr; +} + /** * Calculate trapezoid parameters, multiplying the entry- and exit-speeds * by the provided factors. @@ -1498,8 +1551,7 @@ void Planner::quick_stop() { // must be handled: The tail could change between the read and the assignment // so this must be enclosed in a critical section - const bool was_enabled = STEPPER_ISR_ENABLED(); - if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT(); + const bool was_enabled = stepper.suspend(); // Drop all queue entries block_buffer_nonbusy = block_buffer_planned = block_buffer_head = block_buffer_tail; @@ -1517,7 +1569,7 @@ void Planner::quick_stop() { cleaning_buffer_counter = 1000; // Reenable Stepper ISR - if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT(); + if (was_enabled) stepper.wake_up(); // And stop the stepper ISR stepper.quick_stop(); @@ -1548,13 +1600,12 @@ float Planner::get_axis_position_mm(const AxisEnum axis) { if (axis == CORE_AXIS_1 || axis == CORE_AXIS_2) { // Protect the access to the position. - const bool was_enabled = STEPPER_ISR_ENABLED(); - if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT(); + const bool was_enabled = stepper.suspend(); const int32_t p1 = stepper.position(CORE_AXIS_1), p2 = stepper.position(CORE_AXIS_2); - if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT(); + if (was_enabled) stepper.wake_up(); // ((a1+a2)+(a1-a2))/2 -> (a1+a2+a1-a2)/2 -> (a1+a1)/2 -> a1 // ((a1+a2)-(a1-a2))/2 -> (a1+a2-a1+a2)/2 -> (a2+a2)/2 -> a2 @@ -2004,13 +2055,12 @@ bool Planner::_populate_block(block_t * const block, bool split_move, #if HAS_SPI_LCD // Protect the access to the position. - const bool was_enabled = STEPPER_ISR_ENABLED(); - if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT(); + const bool was_enabled = stepper.suspend(); block_buffer_runtime_us += segment_time_us; block->segment_time_us = segment_time_us; - if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT(); + if (was_enabled) stepper.wake_up(); #endif block->nominal_speed_sqr = sq(block->millimeters * inverse_secs); // (mm/sec)^2 Always > 0 @@ -2822,6 +2872,48 @@ void Planner::set_max_jerk(const AxisEnum axis, float targetValue) { #endif } +#if HAS_SPI_LCD + + uint16_t Planner::block_buffer_runtime() { + #ifdef __AVR__ + // Protect the access to the variable. Only required for AVR, as + // any 32bit CPU offers atomic access to 32bit variables + const bool was_enabled = stepper.suspend(); + #endif + + millis_t bbru = block_buffer_runtime_us; + + #ifdef __AVR__ + // Reenable Stepper ISR + if (was_enabled) stepper.wake_up(); + #endif + + // To translate µs to ms a division by 1000 would be required. + // We introduce 2.4% error here by dividing by 1024. + // Doesn't matter because block_buffer_runtime_us is already too small an estimation. + bbru >>= 10; + // limit to about a minute. + NOMORE(bbru, 0xFFFFul); + return bbru; + } + + void Planner::clear_block_buffer_runtime() { + #ifdef __AVR__ + // Protect the access to the variable. Only required for AVR, as + // any 32bit CPU offers atomic access to 32bit variables + const bool was_enabled = stepper.suspend(); + #endif + + block_buffer_runtime_us = 0; + + #ifdef __AVR__ + // Reenable Stepper ISR + if (was_enabled) stepper.wake_up(); + #endif + } + +#endif + #if ENABLED(AUTOTEMP) void Planner::autotemp_M104_M109() { diff --git a/Marlin/src/module/planner.h b/Marlin/src/module/planner.h index 37f0112cc81e..6942ec602876 100644 --- a/Marlin/src/module/planner.h +++ b/Marlin/src/module/planner.h @@ -763,60 +763,18 @@ class Planner { FORCE_INLINE static bool has_blocks_queued() { return (block_buffer_head != block_buffer_tail); } /** - * The current block. nullptr if the buffer is empty. - * This also marks the block as busy. + * Get the current block for processing + * and mark the block as busy. + * Return nullptr if the buffer is empty + * or if there is a first-block delay. + * * WARNING: Called from Stepper ISR context! */ - static block_t* get_current_block() { - - // Get the number of moves in the planner queue so far - const uint8_t nr_moves = movesplanned(); - - // If there are any moves queued ... - if (nr_moves) { - - // If there is still delay of delivery of blocks running, decrement it - if (delay_before_delivering) { - --delay_before_delivering; - // If the number of movements queued is less than 3, and there is still time - // to wait, do not deliver anything - if (nr_moves < 3 && delay_before_delivering) return nullptr; - delay_before_delivering = 0; - } - - // If we are here, there is no excuse to deliver the block - block_t * const block = &block_buffer[block_buffer_tail]; - - // No trapezoid calculated? Don't execute yet. - if (TEST(block->flag, BLOCK_BIT_RECALCULATE)) return nullptr; - - #if HAS_SPI_LCD - block_buffer_runtime_us -= block->segment_time_us; // We can't be sure how long an active block will take, so don't count it. - #endif - - // As this block is busy, advance the nonbusy block pointer - block_buffer_nonbusy = next_block_index(block_buffer_tail); - - // Push block_buffer_planned pointer, if encountered. - if (block_buffer_tail == block_buffer_planned) - block_buffer_planned = block_buffer_nonbusy; - - // Return the block - return block; - } - - // The queue became empty - #if HAS_SPI_LCD - clear_block_buffer_runtime(); // paranoia. Buffer is empty now - so reset accumulated time to zero. - #endif - - return nullptr; - } + static block_t* get_current_block(); /** * "Discard" the block and "release" the memory. * Called when the current block is no longer needed. - * NB: There MUST be a current block to call this function!! */ FORCE_INLINE static void discard_current_block() { if (has_blocks_queued()) @@ -824,47 +782,8 @@ class Planner { } #if HAS_SPI_LCD - - static uint16_t block_buffer_runtime() { - #ifdef __AVR__ - // Protect the access to the variable. Only required for AVR, as - // any 32bit CPU offers atomic access to 32bit variables - bool was_enabled = STEPPER_ISR_ENABLED(); - if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT(); - #endif - - millis_t bbru = block_buffer_runtime_us; - - #ifdef __AVR__ - // Reenable Stepper ISR - if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT(); - #endif - - // To translate µs to ms a division by 1000 would be required. - // We introduce 2.4% error here by dividing by 1024. - // Doesn't matter because block_buffer_runtime_us is already too small an estimation. - bbru >>= 10; - // limit to about a minute. - NOMORE(bbru, 0xFFFFul); - return bbru; - } - - static void clear_block_buffer_runtime() { - #ifdef __AVR__ - // Protect the access to the variable. Only required for AVR, as - // any 32bit CPU offers atomic access to 32bit variables - bool was_enabled = STEPPER_ISR_ENABLED(); - if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT(); - #endif - - block_buffer_runtime_us = 0; - - #ifdef __AVR__ - // Reenable Stepper ISR - if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT(); - #endif - } - + static uint16_t block_buffer_runtime(); + static void clear_block_buffer_runtime(); #endif #if ENABLED(AUTOTEMP) diff --git a/Marlin/src/module/stepper.cpp b/Marlin/src/module/stepper.cpp index bc08e3537747..6e0a318fcb2b 100644 --- a/Marlin/src/module/stepper.cpp +++ b/Marlin/src/module/stepper.cpp @@ -203,11 +203,8 @@ uint32_t Stepper::advance_divisor = 0, bool Stepper::bezier_2nd_half; // =false If Bézier curve has been initialized or not #endif -uint32_t Stepper::nextMainISR = 0; - #if ENABLED(LIN_ADVANCE) - constexpr uint32_t LA_ADV_NEVER = 0xFFFFFFFF; uint32_t Stepper::nextAdvanceISR = LA_ADV_NEVER, Stepper::LA_isr_rate = LA_ADV_NEVER; uint16_t Stepper::LA_current_adv_steps = 0, @@ -402,13 +399,13 @@ constexpr uint32_t NS_TO_PULSE_TIMER_TICKS(uint32_t NS) { return (NS + (NS_PER_P #define PULSE_HIGH_TICK_COUNT hal_timer_t(NS_TO_PULSE_TIMER_TICKS(_MIN_PULSE_HIGH_NS - _MIN(_MIN_PULSE_HIGH_NS, TIMER_SETUP_NS))) #define PULSE_LOW_TICK_COUNT hal_timer_t(NS_TO_PULSE_TIMER_TICKS(_MIN_PULSE_LOW_NS - _MIN(_MIN_PULSE_LOW_NS, TIMER_SETUP_NS))) -#define USING_TIMED_PULSE() hal_timer_t end_tick_count = 0 -#define START_TIMED_PULSE(DIR) (end_tick_count = HAL_timer_get_count(PULSE_TIMER_NUM) + PULSE_##DIR##_TICK_COUNT) -#define AWAIT_TIMED_PULSE() while (HAL_timer_get_count(PULSE_TIMER_NUM) < end_tick_count) { } +#define USING_TIMED_PULSE() hal_timer_t start_pulse_count = 0 +#define START_TIMED_PULSE(DIR) (start_pulse_count = HAL_timer_get_count(PULSE_TIMER_NUM)) +#define AWAIT_TIMED_PULSE(DIR) while (PULSE_##DIR##_TICK_COUNT > HAL_timer_get_count(PULSE_TIMER_NUM) - start_pulse_count) { } #define START_HIGH_PULSE() START_TIMED_PULSE(HIGH) +#define AWAIT_HIGH_PULSE() AWAIT_TIMED_PULSE(HIGH) #define START_LOW_PULSE() START_TIMED_PULSE(LOW) -#define AWAIT_HIGH_PULSE() AWAIT_TIMED_PULSE() -#define AWAIT_LOW_PULSE() AWAIT_TIMED_PULSE() +#define AWAIT_LOW_PULSE() AWAIT_TIMED_PULSE(LOW) #if MINIMUM_STEPPER_PRE_DIR_DELAY > 0 #define DIR_WAIT_BEFORE() DELAY_NS(MINIMUM_STEPPER_PRE_DIR_DELAY) @@ -422,11 +419,6 @@ constexpr uint32_t NS_TO_PULSE_TIMER_TICKS(uint32_t NS) { return (NS + (NS_PER_P #define DIR_WAIT_AFTER() #endif -void Stepper::wake_up() { - // TCNT1 = 0; - ENABLE_STEPPER_DRIVER_INTERRUPT(); -} - /** * Set the stepper direction of each axis * @@ -1334,6 +1326,9 @@ HAL_STEP_TIMER_ISR() { #endif void Stepper::isr() { + + static uint32_t nextMainISR = 0; // Interval until the next main Stepper Pulse phase (0 = Now) + #ifndef __AVR__ // Disable interrupts, to avoid ISR preemption while we reprogram the period // (AVR enters the ISR with global interrupts disabled, so no need to do it here) @@ -1357,35 +1352,35 @@ void Stepper::isr() { // Enable ISRs to reduce USART processing latency ENABLE_ISRS(); - // Run main stepping pulse phase ISR if we have to - if (!nextMainISR) Stepper::stepper_pulse_phase_isr(); + if (!nextMainISR) pulse_phase_isr(); // 0 = Do coordinated axes Stepper pulses #if ENABLED(LIN_ADVANCE) - // Run linear advance stepper ISR if we have to - if (!nextAdvanceISR) nextAdvanceISR = Stepper::advance_isr(); + if (!nextAdvanceISR) nextAdvanceISR = advance_isr(); // 0 = Do Linear Advance E Stepper pulses #endif // ^== Time critical. NOTHING besides pulse generation should be above here!!! - // Run main stepping block processing ISR if we have to - if (!nextMainISR) nextMainISR = Stepper::stepper_block_phase_isr(); + if (!nextMainISR) nextMainISR = block_phase_isr(); // Manage acc/deceleration, get next block - uint32_t interval = + // Get the interval to the next ISR call + const uint32_t interval = _MIN( + nextMainISR // Time until the next Stepper ISR #if ENABLED(LIN_ADVANCE) - _MIN(nextAdvanceISR, nextMainISR) // Nearest time interval - #else - nextMainISR // Remaining stepper ISR time + , nextAdvanceISR // Come back early for Linear Advance? #endif - ; + , uint32_t(HAL_TIMER_TYPE_MAX) // Come back in a very long time + ); - // Limit the value to the maximum possible value of the timer - NOMORE(interval, uint32_t(HAL_TIMER_TYPE_MAX)); + // + // Compute remaining time for each ISR phase + // NEVER : The phase is idle + // Zero : The phase will occur on the next ISR call + // Non-zero : The phase will occur on a future ISR call + // - // Compute the time remaining for the main isr nextMainISR -= interval; #if ENABLED(LIN_ADVANCE) - // Compute the time remaining for the advance isr if (nextAdvanceISR != LA_ADV_NEVER) nextAdvanceISR -= interval; #endif @@ -1471,7 +1466,7 @@ void Stepper::isr() { * call to this method that might cause variation in the timing. The aim * is to keep pulse timing as regular as possible. */ -void Stepper::stepper_pulse_phase_isr() { +void Stepper::pulse_phase_isr() { // If we must abort the current block, do so! if (abort_current_block) { @@ -1548,7 +1543,7 @@ void Stepper::stepper_pulse_phase_isr() { // Don't step E here - But remember the number of steps to perform motor_direction(E_AXIS) ? --LA_steps : ++LA_steps; #else - step_needed.e = delta_error.e >= 0; + step_needed.e = true; #endif } #elif HAS_E0_STEP @@ -1604,20 +1599,14 @@ void Stepper::stepper_pulse_phase_isr() { #if DISABLED(LIN_ADVANCE) #if ENABLED(MIXING_EXTRUDER) - if (delta_error.e >= 0) { delta_error.e -= advance_divisor; E_STEP_WRITE(mixer.get_stepper(), INVERT_E_STEP_PIN); } - - #else // !MIXING_EXTRUDER - - #if HAS_E0_STEP - PULSE_STOP(E); - #endif - - #endif // !MIXING_EXTRUDER - #endif // !LIN_ADVANCE + #elif HAS_E0_STEP + PULSE_STOP(E); + #endif + #endif #if ISR_MULTI_STEPS if (events_to_do) START_LOW_PULSE(); @@ -1630,10 +1619,10 @@ void Stepper::stepper_pulse_phase_isr() { // properly schedules blocks from the planner. This is executed after creating // the step pulses, so it is not time critical, as pulses are already done. -uint32_t Stepper::stepper_block_phase_isr() { +uint32_t Stepper::block_phase_isr() { - // If no queued movements, just wait 1ms for the next move - uint32_t interval = (STEPPER_TIMER_RATE) / 1000; + // If no queued movements, just wait 1ms for the next block + uint32_t interval = (STEPPER_TIMER_RATE) / 1000UL; // If there is a current block if (current_block) { @@ -1667,16 +1656,14 @@ uint32_t Stepper::stepper_block_phase_isr() { // acc_step_rate is in steps/second // step_rate to timer interval and steps per stepper isr - interval = calc_timer_interval(acc_step_rate, oversampling_factor, &steps_per_isr); + interval = calc_timer_interval(acc_step_rate, &steps_per_isr); acceleration_time += interval; #if ENABLED(LIN_ADVANCE) - if (LA_use_advance_lead) { - // Fire ISR if final adv_rate is reached - if (LA_steps && LA_isr_rate != current_block->advance_speed) nextAdvanceISR = 0; - } - else if (LA_steps) nextAdvanceISR = 0; - #endif // LIN_ADVANCE + // Fire ISR if final adv_rate is reached + if (LA_steps && (!LA_use_advance_lead || LA_isr_rate != current_block->advance_speed)) + initiateLA(); + #endif } // Are we in Deceleration phase ? else if (step_events_completed > decelerate_after) { @@ -1712,32 +1699,32 @@ uint32_t Stepper::stepper_block_phase_isr() { // step_rate is in steps/second // step_rate to timer interval and steps per stepper isr - interval = calc_timer_interval(step_rate, oversampling_factor, &steps_per_isr); + interval = calc_timer_interval(step_rate, &steps_per_isr); deceleration_time += interval; #if ENABLED(LIN_ADVANCE) if (LA_use_advance_lead) { // Wake up eISR on first deceleration loop and fire ISR if final adv_rate is reached if (step_events_completed <= decelerate_after + steps_per_isr || (LA_steps && LA_isr_rate != current_block->advance_speed)) { - nextAdvanceISR = 0; + initiateLA(); LA_isr_rate = current_block->advance_speed; } } - else if (LA_steps) nextAdvanceISR = 0; - #endif // LIN_ADVANCE + else if (LA_steps) initiateLA(); + #endif } // We must be in cruise phase otherwise else { #if ENABLED(LIN_ADVANCE) // If there are any esteps, fire the next advance_isr "now" - if (LA_steps && LA_isr_rate != current_block->advance_speed) nextAdvanceISR = 0; + if (LA_steps && LA_isr_rate != current_block->advance_speed) initiateLA(); #endif // Calculate the ticks_nominal for this nominal speed, if not done yet if (ticks_nominal < 0) { // step_rate to timer interval and loops for the nominal speed - ticks_nominal = calc_timer_interval(current_block->nominal_rate, oversampling_factor, &steps_per_isr); + ticks_nominal = calc_timer_interval(current_block->nominal_rate, &steps_per_isr); } // The timer interval is just the nominal value for the nominal speed @@ -1846,17 +1833,17 @@ uint32_t Stepper::stepper_block_phase_isr() { // No acceleration / deceleration time elapsed so far acceleration_time = deceleration_time = 0; - uint8_t oversampling = 0; // Assume we won't use it + uint8_t oversampling = 0; // Assume no axis smoothing (via oversampling) #if ENABLED(ADAPTIVE_STEP_SMOOTHING) - // At this point, we must decide if we can use Stepper movement axis smoothing. + // Decide if axis smoothing is possible uint32_t max_rate = current_block->nominal_rate; // Get the maximum rate (maximum event speed) - while (max_rate < MIN_STEP_ISR_FREQUENCY) { - max_rate <<= 1; - if (max_rate >= MAX_STEP_ISR_FREQUENCY_1X) break; - ++oversampling; + while (max_rate < MIN_STEP_ISR_FREQUENCY) { // As long as more ISRs are possible... + max_rate <<= 1; // Try to double the rate + if (max_rate >= MAX_STEP_ISR_FREQUENCY_1X) break; // Don't exceed the estimated ISR limit + ++oversampling; // Increase the oversampling (used for left-shift) } - oversampling_factor = oversampling; + oversampling_factor = oversampling; // For all timer interval calculations #endif // Based on the oversampling factor, do the calculations @@ -1894,8 +1881,7 @@ uint32_t Stepper::stepper_block_phase_isr() { if ((LA_use_advance_lead = current_block->use_advance_lead)) { LA_final_adv_steps = current_block->final_adv_steps; LA_max_adv_steps = current_block->max_adv_steps; - //Start the ISR - nextAdvanceISR = 0; + initiateLA(); // Start the ISR LA_isr_rate = current_block->advance_speed; } else LA_isr_rate = LA_ADV_NEVER; @@ -1954,7 +1940,7 @@ uint32_t Stepper::stepper_block_phase_isr() { #endif // Calculate the initial timer interval - interval = calc_timer_interval(current_block->initial_rate, oversampling_factor, &steps_per_isr); + interval = calc_timer_interval(current_block->initial_rate, &steps_per_isr); } } @@ -2054,6 +2040,7 @@ uint32_t Stepper::stepper_block_phase_isr() { return interval; } + #endif // LIN_ADVANCE // Check if the given block is busy or not - Must not be called from ISR contexts @@ -2093,7 +2080,7 @@ void Stepper::init() { digipot_motor = 255 * (motor_current[i] / 2.5); dac084s085::setValue(i, digipot_motor); } - #endif//MB(ALLIGATOR) + #endif // Init Microstepping Pins #if HAS_MICROSTEPS @@ -2287,7 +2274,7 @@ void Stepper::init() { #if DISABLED(I2S_STEPPER_STREAM) HAL_timer_start(STEP_TIMER_NUM, 122); // Init Stepper ISR to 122 Hz for quick starting - ENABLE_STEPPER_DRIVER_INTERRUPT(); + wake_up(); sei(); #endif @@ -2341,19 +2328,43 @@ int32_t Stepper::position(const AxisEnum axis) { #ifdef __AVR__ // Protect the access to the position. Only required for AVR, as // any 32bit CPU offers atomic access to 32bit variables - const bool was_enabled = STEPPER_ISR_ENABLED(); - if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT(); + const bool was_enabled = suspend(); #endif const int32_t v = count_position[axis]; #ifdef __AVR__ // Reenable Stepper ISR - if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT(); + if (was_enabled) wake_up(); #endif return v; } +// Set the current position in steps +void Stepper::set_position(const int32_t &a, const int32_t &b, const int32_t &c, const int32_t &e) { + planner.synchronize(); + const bool was_enabled = suspend(); + _set_position(a, b, c, e); + if (was_enabled) wake_up(); +} + +void Stepper::set_axis_position(const AxisEnum a, const int32_t &v) { + planner.synchronize(); + + #ifdef __AVR__ + // Protect the access to the position. Only required for AVR, as + // any 32bit CPU offers atomic access to 32bit variables + const bool was_enabled = suspend(); + #endif + + count_position[a] = v; + + #ifdef __AVR__ + // Reenable Stepper ISR + if (was_enabled) wake_up(); + #endif +} + // Signal endstops were triggered - This function can be called from // an ISR context (Temperature, Stepper or limits ISR), so we must // be very careful here. If the interrupt being preempted was the @@ -2362,8 +2373,7 @@ int32_t Stepper::position(const AxisEnum axis) { // is properly canceled void Stepper::endstop_triggered(const AxisEnum axis) { - const bool was_enabled = STEPPER_ISR_ENABLED(); - if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT(); + const bool was_enabled = suspend(); endstops_trigsteps[axis] = ( #if IS_CORE (axis == CORE_AXIS_2 @@ -2378,22 +2388,21 @@ void Stepper::endstop_triggered(const AxisEnum axis) { // Discard the rest of the move if there is a current block quick_stop(); - if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT(); + if (was_enabled) wake_up(); } int32_t Stepper::triggered_position(const AxisEnum axis) { #ifdef __AVR__ // Protect the access to the position. Only required for AVR, as // any 32bit CPU offers atomic access to 32bit variables - const bool was_enabled = STEPPER_ISR_ENABLED(); - if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT(); + const bool was_enabled = suspend(); #endif const int32_t v = endstops_trigsteps[axis]; #ifdef __AVR__ // Reenable Stepper ISR - if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT(); + if (was_enabled) wake_up(); #endif return v; @@ -2403,14 +2412,13 @@ void Stepper::report_positions() { #ifdef __AVR__ // Protect the access to the position. - const bool was_enabled = STEPPER_ISR_ENABLED(); - if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT(); + const bool was_enabled = suspend(); #endif const xyz_long_t pos = count_position; #ifdef __AVR__ - if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT(); + if (was_enabled) wake_up(); #endif #if CORE_IS_XY || CORE_IS_XZ || ENABLED(DELTA) || IS_SCARA @@ -2571,16 +2579,21 @@ void Stepper::report_positions() { Z_STEP_WRITE(INVERT_Z_STEP_PIN); // Restore direction bits + DIR_WAIT_BEFORE(); + X_DIR_WRITE(old_dir.x); Y_DIR_WRITE(old_dir.y); Z_DIR_WRITE(old_dir.z); + DIR_WAIT_AFTER(); + #endif } break; default: break; } + sei(); } diff --git a/Marlin/src/module/stepper.h b/Marlin/src/module/stepper.h index 6b8d0f362890..ed07bfd5df32 100644 --- a/Marlin/src/module/stepper.h +++ b/Marlin/src/module/stepper.h @@ -321,13 +321,13 @@ class Stepper { static bool bezier_2nd_half; // If Bézier curve has been initialized or not #endif - static uint32_t nextMainISR; // time remaining for the next Step ISR #if ENABLED(LIN_ADVANCE) + static constexpr uint32_t LA_ADV_NEVER = 0xFFFFFFFF; static uint32_t nextAdvanceISR, LA_isr_rate; static uint16_t LA_current_adv_steps, LA_final_adv_steps, LA_max_adv_steps; // Copy from current executed block. Needed because current_block is set to NULL "too early". static int8_t LA_steps; static bool LA_use_advance_lead; - #endif // LIN_ADVANCE + #endif static int32_t ticks_nominal; #if DISABLED(S_CURVE_ACCELERATION) @@ -351,28 +351,36 @@ class Stepper { public: - // - // Constructor / initializer - // - Stepper() {}; - // Initialize stepper hardware static void init(); - // Interrupt Service Routines + // Interrupt Service Routine and phases + + // The stepper subsystem goes to sleep when it runs out of things to execute. + // Call this to notify the subsystem that it is time to go to work. + static inline void wake_up() { ENABLE_STEPPER_DRIVER_INTERRUPT(); } + + static inline bool is_awake() { return STEPPER_ISR_ENABLED(); } + + static inline bool suspend() { + const bool awake = is_awake(); + if (awake) DISABLE_STEPPER_DRIVER_INTERRUPT(); + return awake; + } // The ISR scheduler static void isr(); - // The stepper pulse phase ISR - static void stepper_pulse_phase_isr(); + // The stepper pulse ISR phase + static void pulse_phase_isr(); - // The stepper block processing phase ISR - static uint32_t stepper_block_phase_isr(); + // The stepper block processing ISR phase + static uint32_t block_phase_isr(); #if ENABLED(LIN_ADVANCE) - // The Linear advance stepper ISR + // The Linear advance ISR phase static uint32_t advance_isr(); + FORCE_INLINE static void initiateLA() { nextAdvanceISR = 0; } #endif // Check if the given block is busy or not - Must not be called from ISR contexts @@ -381,13 +389,14 @@ class Stepper { // Get the position of a stepper, in steps static int32_t position(const AxisEnum axis); + // Set the current position in steps + static void set_position(const int32_t &a, const int32_t &b, const int32_t &c, const int32_t &e); + static inline void set_position(const xyze_long_t &abce) { set_position(abce.a, abce.b, abce.c, abce.e); } + static void set_axis_position(const AxisEnum a, const int32_t &v); + // Report the positions of the steppers, in steps static void report_positions(); - // The stepper subsystem goes to sleep when it runs out of things to execute. Call this - // to notify the subsystem that it is time to go to work. - static void wake_up(); - // Quickly stop all steppers FORCE_INLINE static void quick_stop() { abort_current_block = true; } @@ -453,34 +462,6 @@ class Stepper { static void refresh_motor_power(); #endif - // Set the current position in steps - static inline void set_position(const int32_t &a, const int32_t &b, const int32_t &c, const int32_t &e) { - planner.synchronize(); - const bool was_enabled = STEPPER_ISR_ENABLED(); - if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT(); - _set_position(a, b, c, e); - if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT(); - } - static inline void set_position(const xyze_long_t &abce) { set_position(abce.a, abce.b, abce.c, abce.e); } - - static inline void set_axis_position(const AxisEnum a, const int32_t &v) { - planner.synchronize(); - - #ifdef __AVR__ - // Protect the access to the position. Only required for AVR, as - // any 32bit CPU offers atomic access to 32bit variables - const bool was_enabled = STEPPER_ISR_ENABLED(); - if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT(); - #endif - - count_position[a] = v; - - #ifdef __AVR__ - // Reenable Stepper ISR - if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT(); - #endif - } - // Set direction bits for all steppers static void set_directions(); @@ -490,11 +471,11 @@ class Stepper { static void _set_position(const int32_t &a, const int32_t &b, const int32_t &c, const int32_t &e); FORCE_INLINE static void _set_position(const abce_long_t &spos) { _set_position(spos.a, spos.b, spos.c, spos.e); } - FORCE_INLINE static uint32_t calc_timer_interval(uint32_t step_rate, uint8_t scale, uint8_t* loops) { + FORCE_INLINE static uint32_t calc_timer_interval(uint32_t step_rate, uint8_t* loops) { uint32_t timer; // Scale the frequency, as requested by the caller - step_rate <<= scale; + step_rate <<= oversampling_factor; uint8_t multistep = 1; #if DISABLED(DISABLE_MULTI_STEPPING) diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index f07f943213c2..cfb799001072 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -65,15 +65,12 @@ #include "../libs/private_spi.h" #endif -#if EITHER(BABYSTEPPING, PID_EXTRUSION_SCALING) +#if ENABLED(PID_EXTRUSION_SCALING) #include "stepper.h" #endif #if ENABLED(BABYSTEPPING) #include "../feature/babystep.h" - #if ENABLED(BABYSTEP_ALWAYS_AVAILABLE) - #include "../gcode/gcode.h" - #endif #endif #include "printcounter.h" From 63dd0f249d3a82f8f253a1bd0f7c2edb7d4447e4 Mon Sep 17 00:00:00 2001 From: George Fu Date: Fri, 14 Feb 2020 21:18:57 +0800 Subject: [PATCH 06/11] Fysetc S6 pins / LCD updates (#16830) --- Marlin/Configuration_adv.h | 4 +++- .../extensible_ui/lib/ftdi_eve_touch_ui/compat.h | 4 ++++ .../lib/ftdi_eve_touch_ui/pin_mappings.h | 9 +++++++++ Marlin/src/pins/stm32/pins_FYSETC_S6.h | 14 ++++++++++---- 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index 2e0a5b5c50fc..cb2bdc08b4c5 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -1333,9 +1333,11 @@ //#define AO_EXP1_PINMAP // AlephObjects CLCD UI EXP1 mapping //#define AO_EXP2_PINMAP // AlephObjects CLCD UI EXP2 mapping //#define CR10_TFT_PINMAP // Rudolph Riedel's CR10 pin mapping + //#define S6_TFT_PINMAP // FYSETC S6 pin mapping + //#define OTHER_PIN_LAYOUT // Define pins manually below #if ENABLED(OTHER_PIN_LAYOUT) - // The pins for CS and MOD_RESET (PD) must be chosen. + // Pins for CS and MOD_RESET (PD) must be chosen #define CLCD_MOD_RESET 9 #define CLCD_SPI_CS 10 diff --git a/Marlin/src/lcd/extensible_ui/lib/ftdi_eve_touch_ui/compat.h b/Marlin/src/lcd/extensible_ui/lib/ftdi_eve_touch_ui/compat.h index 90fd615a5d73..c3e8052a0e51 100644 --- a/Marlin/src/lcd/extensible_ui/lib/ftdi_eve_touch_ui/compat.h +++ b/Marlin/src/lcd/extensible_ui/lib/ftdi_eve_touch_ui/compat.h @@ -37,6 +37,10 @@ #ifdef __MARLIN_FIRMWARE__ // __MARLIN_FIRMWARE__ exists when compiled within Marlin. #include "pin_mappings.h" + #undef max + #define max(a,b) ((a)>(b)?(a):(b)) + #undef min + #define min(a,b) ((a)<(b)?(a):(b)) #else namespace UI { static inline uint32_t safe_millis() {return millis();}; diff --git a/Marlin/src/lcd/extensible_ui/lib/ftdi_eve_touch_ui/pin_mappings.h b/Marlin/src/lcd/extensible_ui/lib/ftdi_eve_touch_ui/pin_mappings.h index d474644b8c75..548c6c7439d4 100644 --- a/Marlin/src/lcd/extensible_ui/lib/ftdi_eve_touch_ui/pin_mappings.h +++ b/Marlin/src/lcd/extensible_ui/lib/ftdi_eve_touch_ui/pin_mappings.h @@ -27,6 +27,15 @@ * without adding new pin definitions to the board. */ +#ifdef S6_TFT_PINMAP + #ifndef __MARLIN_FIRMWARE__ + #error "This pin mapping requires Marlin." + #endif + + #define CLCD_SPI_CS PC7 + #define CLCD_MOD_RESET PC6 +#endif + #ifdef CR10_TFT_PINMAP #ifndef __MARLIN_FIRMWARE__ #error "This pin mapping requires Marlin." diff --git a/Marlin/src/pins/stm32/pins_FYSETC_S6.h b/Marlin/src/pins/stm32/pins_FYSETC_S6.h index 4b85e6097cd9..16f176a376f7 100644 --- a/Marlin/src/pins/stm32/pins_FYSETC_S6.h +++ b/Marlin/src/pins/stm32/pins_FYSETC_S6.h @@ -48,6 +48,11 @@ #define E2END 0xFFF // 4KB #endif +// +// Servos +// +#define SERVO0_PIN PA3 + // // Limit Switches // @@ -59,10 +64,11 @@ #define Z_MAX_PIN PA3 // -// Servos -// share with Z_MAX_PIN +// Filament Sensor // -#define SERVO0_PIN PA3 +#ifndef FIL_RUNOUT_PIN + #define FIL_RUNOUT_PIN PA1 +#endif // // Steppers @@ -160,6 +166,7 @@ //#define KILL_PIN PC5 #define SDSS PA4 +#define SD_DETECT_PIN PB10 // // LCD / Controller @@ -189,7 +196,6 @@ #define BTN_EN1 PC6 #define BTN_EN2 PC7 - #define SD_DETECT_PIN PB10 #define LCD_SDSS PA4 From 150237f7125c20aba6e81f93d04e48d166abe8a6 Mon Sep 17 00:00:00 2001 From: thinkyhead Date: Sat, 15 Feb 2020 00:03:59 +0000 Subject: [PATCH 07/11] [cron] Bump distribution date (2020-02-15) --- Marlin/src/inc/Version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/src/inc/Version.h b/Marlin/src/inc/Version.h index d1938116fd10..41dd9ffb8ec8 100644 --- a/Marlin/src/inc/Version.h +++ b/Marlin/src/inc/Version.h @@ -42,7 +42,7 @@ * version was tagged. */ #ifndef STRING_DISTRIBUTION_DATE - #define STRING_DISTRIBUTION_DATE "2020-02-14" + #define STRING_DISTRIBUTION_DATE "2020-02-15" #endif /** From 1087e318e517571e166241222eff6ae7074bb49d Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Sat, 15 Feb 2020 01:45:24 -0600 Subject: [PATCH 08/11] Fix a BORG compile warning --- Marlin/src/pins/stm32/pins_THE_BORG.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Marlin/src/pins/stm32/pins_THE_BORG.h b/Marlin/src/pins/stm32/pins_THE_BORG.h index 08da40029c5a..bfc9507c451e 100644 --- a/Marlin/src/pins/stm32/pins_THE_BORG.h +++ b/Marlin/src/pins/stm32/pins_THE_BORG.h @@ -30,7 +30,9 @@ #define BOARD_INFO_NAME "The-Borge" #define DEFAULT_MACHINE_NAME BOARD_INFO_NAME -#define E2END 0xFFF // EEPROM end address +#ifndef E2END + #define E2END 0xFFF // EEPROM end address +#endif // Ignore temp readings during development. //#define BOGUS_TEMPERATURE_GRACE_PERIOD 2000 From 71ec89a112b941818beed6ee54ac5cca444eff61 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Sat, 15 Feb 2020 01:23:36 -0600 Subject: [PATCH 09/11] Fix mftest -b and -u. Add --help. --- buildroot/share/git/mftest | 46 ++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/buildroot/share/git/mftest b/buildroot/share/git/mftest index 6db441478675..f647b8a2a6c8 100755 --- a/buildroot/share/git/mftest +++ b/buildroot/share/git/mftest @@ -1,8 +1,8 @@ #!/usr/bin/env bash # # mftest Select a test to apply and build -# mftest -b Build the auto-detected environment -# mftest -u Upload the auto-detected environment +# mftest -b [#] Build the auto-detected environment +# mftest -u [#] Upload the auto-detected environment # mftest [name] [index] [-y] Set config options and optionally build a test # @@ -38,15 +38,27 @@ case $TESTENV in m256) TESTENV='megaatmega2560' ;; mega) TESTENV='megaatmega2560' ;; stm) TESTENV='STM32F103RE' ;; - f1) TESTENV='STM32F103RE' ;; - f4) TESTENV='STM32F4' ;; - f7) TESTENV='STM32F7' ;; - s6) TESTENV='FYSETC_S6' ;; + f1) TESTENV='STM32F103RE' ;; + f4) TESTENV='STM32F4' ;; + f7) TESTENV='STM32F7' ;; + s6) TESTENV='FYSETC_S6' ;; teensy) TESTENV='teensy31' ;; t31) TESTENV='teensy31' ;; t32) TESTENV='teensy31' ;; t35) TESTENV='teensy35' ;; t36) TESTENV='teensy35' ;; + +-h|--help) echo -e "$(basename $0) : Marlin Firmware test, build, and upload\n" + echo "Usage: $(basename $0) ................. Select env and test to apply / run" + echo " $(basename $0) [-y] env ........ Select a test for env to apply / run" + echo " $(basename $0) [-y] env test ... Apply / run the specified env test" + echo " $(basename $0) -b [variant] .... Auto-build the specified variant" + echo " $(basename $0) -u [variant] .... Auto-build and upload the specified variant" + echo + echo "env shortcuts: tree due esp lin lpc|lpc8 lpc9 m128 m256|mega stm|f1 f4 f7 s6 teensy|t31|t32 t35|t36" + exit + ;; + # Build with the last-built env -r) [[ -f "$STATE_FILE" ]] || { echo "No previous (-r) build state found." ; exit 1 ; } read TESTENV <"$STATE_FILE" @@ -54,26 +66,26 @@ case $TESTENV in exit ;; - -[bu]) MB=$( grep "define MOTHERBOARD" Marlin/Configuration.h | awk '{ print $3 }' | $SED 's/BOARD_//' ) - [[ -z $MB ]] && { echo "Error - Unable to read MOTHERBOARD setting." ; exit 1 ; } - BLINE=$( grep "define BOARD_$MB" Marlin/src/core/boards.h ) + -[bu]) MB=$( grep -E "^\s*#define MOTHERBOARD" Marlin/Configuration.h | awk '{ print $3 }' | $SED 's/BOARD_//' ) + [[ -z $MB ]] && { echo "Error - Can't read MOTHERBOARD setting." ; exit 1 ; } + BLINE=$( grep -E "define\s+BOARD_$MB\b" Marlin/src/core/boards.h ) BNUM=$( $SED -E 's/^.+BOARD_[^ ]+ +([0-9]+).+$/\1/' <<<"$BLINE" ) BDESC=$( $SED -E 's/^.+\/\/ *(.+)$/\1/' <<<"$BLINE" ) - [[ -z $BNUM ]] && { echo "Error - Unable to $MB in boards list." ; exit 1 ; } - readarray -t ENVS <<< $( grep -A1 "MB($MB)" Marlin/src/pins/pins.h | $SED -n '2 p' | grep -oE 'env:[^ ]+' | $SED -E 's/env://' ) - [[ -z $ENVS ]] && { echo "Error - Unable to find target(s) for $MB ($BNUM)." ; exit 1 ; } + [[ -z $BNUM ]] && { echo "Error - Can't find $MB in boards list." ; exit 1 ; } + readarray -t ENVS <<< $( grep -EA1 "MB\(.*\b$MB\b.*\)" Marlin/src/pins/pins.h | $SED -n '2 p' | grep -oE 'env:[^ ]+' | $SED -E 's/env://' ) + [[ -z $ENVS ]] && { echo "Error - Can't find target(s) for $MB ($BNUM)." ; exit 1 ; } ECOUNT=${#ENVS[*]} if [[ $ECOUNT == 1 ]]; then TARGET=$ENVS else - # - # List env names and numbers. Get selection. - # if [[ $CHOICE == 0 ]]; then + # + # List env names and numbers. Get selection. + # echo "Available targets for \"$BDESC\" | $MB ($BNUM):" - IND=0 ; for ENV in "${ENVS[@]}"; do echo " $IND) $ENV" ; done + IND=0 ; for ENV in "${ENVS[@]}"; do let IND++ ; echo " $IND) $ENV" ; done if [[ $ECOUNT > 1 ]]; then for (( ; ; )) @@ -87,7 +99,7 @@ case $TESTENV in fi else echo "Detected \"$BDESC\" | $MB ($BNUM)." - [[ $CHOICE > $ECOUNT ]] && { echo "Environment selection is out of range." ; exit 1 ; } + [[ $CHOICE > $ECOUNT ]] && { echo "Environment selection out of range." ; exit 1 ; } fi TARGET="${ENVS[$CHOICE-1]}" echo "Selected $TARGET" From efdaf940a557e38a0446421309c862c8d7fccd3e Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Sat, 15 Feb 2020 02:35:36 -0600 Subject: [PATCH 10/11] Fix byte-to-percent display Fixes #16866 --- Marlin/src/lcd/menu/menu.h | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/Marlin/src/lcd/menu/menu.h b/Marlin/src/lcd/menu/menu.h index 4020385a1508..de531e5a324e 100644 --- a/Marlin/src/lcd/menu/menu.h +++ b/Marlin/src/lcd/menu/menu.h @@ -234,10 +234,10 @@ template class TMenuEditItem : MenuEditItemBase { private: typedef typename NAME::type_t type_t; - static inline float unscale(const float value) { return value * (1.0f / NAME::scale); } - static inline float scale(const float value) { return value * NAME::scale; } - static void load(void *ptr, const int32_t value) { *((type_t*)ptr) = unscale(value); } + static inline float scale(const float value) { return NAME::scale(value); } + static inline float unscale(const float value) { return NAME::unscale(value); } static const char* to_string(const int32_t value) { return NAME::strfunc(unscale(value)); } + static void load(void *ptr, const int32_t value) { *((type_t*)ptr) = unscale(value); } public: FORCE_INLINE static void draw(const bool sel, const uint8_t row, PGM_P const pstr, type_t * const data, ...) { MenuEditItemBase::draw(sel, row, pstr, NAME::strfunc(*(data))); @@ -266,16 +266,17 @@ class TMenuEditItem : MenuEditItemBase { // Provide a set of Edit Item Types which encompass a primitive // type, a string function, and a scale factor for edit and display. // These items call the Edit Item draw method passing the prepared string. -#define DEFINE_MENU_EDIT_ITEM_TYPE(TYPE, NAME, STRFUNC, SCALE) \ - struct MenuEditItemInfo_##NAME { \ - typedef TYPE type_t; \ - static constexpr float scale = SCALE; \ +#define DEFINE_MENU_EDIT_ITEM_TYPE(TYPE, NAME, STRFUNC, SCALE, V...) \ + struct MenuEditItemInfo_##NAME { \ + typedef TYPE type_t; \ + static inline float scale(const float value) { return value * (SCALE) + (V+0); } \ + static inline float unscale(const float value) { return value / (SCALE) + (V+0); } \ static inline const char* strfunc(const float value) { return STRFUNC((TYPE)value); } \ - }; \ + }; \ typedef TMenuEditItem MenuItem_##NAME // TYPE NAME STRFUNC SCALE -DEFINE_MENU_EDIT_ITEM_TYPE(uint8_t, percent, ui8tostr4pct, 100.0/255); // 100% right-justified +DEFINE_MENU_EDIT_ITEM_TYPE(uint8_t, percent, ui8tostr4pct, 100.0/255, 0.5); // 100% right-justified DEFINE_MENU_EDIT_ITEM_TYPE(int16_t, int3, i16tostr3, 1 ); // 123, -12 right-justified DEFINE_MENU_EDIT_ITEM_TYPE(int16_t, int4, i16tostr4sign, 1 ); // 1234, -123 right-justified DEFINE_MENU_EDIT_ITEM_TYPE(int8_t, int8, i8tostr3, 1 ); // 123, -12 right-justified From 5584da388c4a425207dd8460bf66538b29954bc2 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Sat, 15 Feb 2020 02:44:34 -0600 Subject: [PATCH 11/11] Conceal float rounding errors on display Fix #16866 --- Marlin/src/lcd/menu/menu.h | 52 +++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/Marlin/src/lcd/menu/menu.h b/Marlin/src/lcd/menu/menu.h index de531e5a324e..5299fefde2b7 100644 --- a/Marlin/src/lcd/menu/menu.h +++ b/Marlin/src/lcd/menu/menu.h @@ -266,35 +266,35 @@ class TMenuEditItem : MenuEditItemBase { // Provide a set of Edit Item Types which encompass a primitive // type, a string function, and a scale factor for edit and display. // These items call the Edit Item draw method passing the prepared string. -#define DEFINE_MENU_EDIT_ITEM_TYPE(TYPE, NAME, STRFUNC, SCALE, V...) \ - struct MenuEditItemInfo_##NAME { \ - typedef TYPE type_t; \ - static inline float scale(const float value) { return value * (SCALE) + (V+0); } \ - static inline float unscale(const float value) { return value / (SCALE) + (V+0); } \ - static inline const char* strfunc(const float value) { return STRFUNC((TYPE)value); } \ - }; \ +#define DEFINE_MENU_EDIT_ITEM_TYPE(TYPE, NAME, FIX, STRFUNC, SCALE, V...) \ + struct MenuEditItemInfo_##NAME { \ + typedef TYPE type_t; \ + static inline float scale(const float value) { return value * (SCALE) + (V+0); } \ + static inline float unscale(const float value) { return value / (SCALE) + (V+0); } \ + static inline const char* strfunc(const float value) { return STRFUNC((TYPE)(FIX ? FIXFLOAT(value) : value)); } \ + }; \ typedef TMenuEditItem MenuItem_##NAME // TYPE NAME STRFUNC SCALE -DEFINE_MENU_EDIT_ITEM_TYPE(uint8_t, percent, ui8tostr4pct, 100.0/255, 0.5); // 100% right-justified -DEFINE_MENU_EDIT_ITEM_TYPE(int16_t, int3, i16tostr3, 1 ); // 123, -12 right-justified -DEFINE_MENU_EDIT_ITEM_TYPE(int16_t, int4, i16tostr4sign, 1 ); // 1234, -123 right-justified -DEFINE_MENU_EDIT_ITEM_TYPE(int8_t, int8, i8tostr3, 1 ); // 123, -12 right-justified -DEFINE_MENU_EDIT_ITEM_TYPE(uint8_t, uint8, ui8tostr3, 1 ); // 123 right-justified -DEFINE_MENU_EDIT_ITEM_TYPE(uint16_t, uint16_3, ui16tostr3, 1 ); // 123 right-justified -DEFINE_MENU_EDIT_ITEM_TYPE(uint16_t, uint16_4, ui16tostr4, 0.1 ); // 1234 right-justified -DEFINE_MENU_EDIT_ITEM_TYPE(uint16_t, uint16_5, ui16tostr5, 0.01 ); // 12345 right-justified -DEFINE_MENU_EDIT_ITEM_TYPE(float, float3, ftostr3, 1 ); // 123 right-justified -DEFINE_MENU_EDIT_ITEM_TYPE(float, float52, ftostr42_52, 100 ); // _2.34, 12.34, -2.34 or 123.45, -23.45 -DEFINE_MENU_EDIT_ITEM_TYPE(float, float43, ftostr43sign, 1000 ); // 1.234 -DEFINE_MENU_EDIT_ITEM_TYPE(float, float5, ftostr5rj, 1 ); // 12345 right-justified -DEFINE_MENU_EDIT_ITEM_TYPE(float, float5_25, ftostr5rj, 0.04f ); // 12345 right-justified (25 increment) -DEFINE_MENU_EDIT_ITEM_TYPE(float, float51, ftostr51rj, 10 ); // 1234.5 right-justified -DEFINE_MENU_EDIT_ITEM_TYPE(float, float41sign, ftostr41sign, 10 ); // +123.4 -DEFINE_MENU_EDIT_ITEM_TYPE(float, float51sign, ftostr51sign, 10 ); // +1234.5 -DEFINE_MENU_EDIT_ITEM_TYPE(float, float52sign, ftostr52sign, 100 ); // +123.45 -DEFINE_MENU_EDIT_ITEM_TYPE(uint32_t, long5, ftostr5rj, 0.01f ); // 12345 right-justified -DEFINE_MENU_EDIT_ITEM_TYPE(uint32_t, long5_25, ftostr5rj, 0.04f ); // 12345 right-justified (25 increment) +DEFINE_MENU_EDIT_ITEM_TYPE(uint8_t, percent, 0, ui8tostr4pct, 100.0/255, 0.5); // 100% right-justified +DEFINE_MENU_EDIT_ITEM_TYPE(int16_t, int3, 0, i16tostr3, 1 ); // 123, -12 right-justified +DEFINE_MENU_EDIT_ITEM_TYPE(int16_t, int4, 0, i16tostr4sign, 1 ); // 1234, -123 right-justified +DEFINE_MENU_EDIT_ITEM_TYPE(int8_t, int8, 0, i8tostr3, 1 ); // 123, -12 right-justified +DEFINE_MENU_EDIT_ITEM_TYPE(uint8_t, uint8, 0, ui8tostr3, 1 ); // 123 right-justified +DEFINE_MENU_EDIT_ITEM_TYPE(uint16_t, uint16_3, 0, ui16tostr3, 1 ); // 123 right-justified +DEFINE_MENU_EDIT_ITEM_TYPE(uint16_t, uint16_4, 0, ui16tostr4, 0.1 ); // 1234 right-justified +DEFINE_MENU_EDIT_ITEM_TYPE(uint16_t, uint16_5, 0, ui16tostr5, 0.01 ); // 12345 right-justified +DEFINE_MENU_EDIT_ITEM_TYPE(float, float3, 1, ftostr3, 1 ); // 123 right-justified +DEFINE_MENU_EDIT_ITEM_TYPE(float, float52, 1, ftostr42_52, 100 ); // _2.34, 12.34, -2.34 or 123.45, -23.45 +DEFINE_MENU_EDIT_ITEM_TYPE(float, float43, 1, ftostr43sign, 1000 ); // 1.234 +DEFINE_MENU_EDIT_ITEM_TYPE(float, float5, 1, ftostr5rj, 1 ); // 12345 right-justified +DEFINE_MENU_EDIT_ITEM_TYPE(float, float5_25, 1, ftostr5rj, 0.04f ); // 12345 right-justified (25 increment) +DEFINE_MENU_EDIT_ITEM_TYPE(float, float51, 1, ftostr51rj, 10 ); // 1234.5 right-justified +DEFINE_MENU_EDIT_ITEM_TYPE(float, float41sign, 1, ftostr41sign, 10 ); // +123.4 +DEFINE_MENU_EDIT_ITEM_TYPE(float, float51sign, 1, ftostr51sign, 10 ); // +1234.5 +DEFINE_MENU_EDIT_ITEM_TYPE(float, float52sign, 1, ftostr52sign, 100 ); // +123.45 +DEFINE_MENU_EDIT_ITEM_TYPE(uint32_t, long5, 0, ftostr5rj, 0.01f ); // 12345 right-justified +DEFINE_MENU_EDIT_ITEM_TYPE(uint32_t, long5_25, 0, ftostr5rj, 0.04f ); // 12345 right-justified (25 increment) class MenuItem_bool : public MenuEditItemBase { public: