diff --git a/.gitignore b/.gitignore index 62f73a7c0d..f7d49cc1ed 100755 --- a/.gitignore +++ b/.gitignore @@ -19,9 +19,9 @@ # along with this program. If not, see . # -# Our automatic versioning scheme generates the following file -# NEVER put it in the repository +# Generated files _Version.h +bdf2u8g # # OS diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 4750b49e85..78a5dad7e8 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -418,7 +418,7 @@ #define TEMP_SENSOR_CHAMBER 0 // Dummy thermistor constant temperature readings, for use with 998 and 999 -#define DUMMY_THERMISTOR_998_VALUE 25 +#define DUMMY_THERMISTOR_998_VALUE 25 #define DUMMY_THERMISTOR_999_VALUE 100 // Resistor values when using MAX31865 sensors (-5) on TEMP_SENSOR_0 / 1 @@ -1317,10 +1317,11 @@ #define G26_MESH_VALIDATION #if ENABLED(G26_MESH_VALIDATION) #define MESH_TEST_NOZZLE_SIZE 0.4 // (mm) Diameter of primary nozzle. - #define MESH_TEST_LAYER_HEIGHT 0.2 // (mm) Default layer height for the G26 Mesh Validation Tool. - #define MESH_TEST_HOTEND_TEMP 205 // (°C) Default nozzle temperature for the G26 Mesh Validation Tool. - #define MESH_TEST_BED_TEMP 60 // (°C) Default bed temperature for the G26 Mesh Validation Tool. - #define G26_XY_FEEDRATE 20 // (mm/s) Feedrate for XY Moves for the G26 Mesh Validation Tool. + #define MESH_TEST_LAYER_HEIGHT 0.2 // (mm) Default layer height for G26. + #define MESH_TEST_HOTEND_TEMP 205 // (°C) Default nozzle temperature for G26. + #define MESH_TEST_BED_TEMP 60 // (°C) Default bed temperature for G26. + #define G26_XY_FEEDRATE 20 // (mm/s) Feedrate for G26 XY moves. + #define G26_XY_FEEDRATE_TRAVEL 100 // (mm/s) Feedrate for G26 XY travel moves. #define G26_RETRACT_MULTIPLIER 1.0 // G26 Q (retraction) used by default between mesh test elements. #endif @@ -1707,6 +1708,9 @@ * View the current statistics with M78. */ #define PRINTCOUNTER +#if ENABLED(PRINTCOUNTER) + #define PRINTCOUNTER_SAVE_INTERVAL 60 // (minutes) EEPROM save interval during print +#endif /** * Password @@ -1751,9 +1755,9 @@ * Select the language to display on the LCD. These languages are available: * * en, an, bg, ca, cz, da, de, el, el_gr, es, eu, fi, fr, gl, hr, hu, it, - * jp_kana, ko_KR, nl, pl, pt, pt_br, ro, ru, sk, tr, uk, vi, zh_CN, zh_TW, test + * jp_kana, ko_KR, nl, pl, pt, pt_br, ro, ru, sk, sv, tr, uk, vi, zh_CN, zh_TW * - * :{ 'en':'English', 'an':'Aragonese', 'bg':'Bulgarian', 'ca':'Catalan', 'cz':'Czech', 'da':'Danish', 'de':'German', 'el':'Greek', 'el_gr':'Greek (Greece)', 'es':'Spanish', 'eu':'Basque-Euskera', 'fi':'Finnish', 'fr':'French', 'gl':'Galician', 'hr':'Croatian', 'hu':'Hungarian', 'it':'Italian', 'jp_kana':'Japanese', 'ko_KR':'Korean (South Korea)', 'nl':'Dutch', 'pl':'Polish', 'pt':'Portuguese', 'pt_br':'Portuguese (Brazilian)', 'ro':'Romanian', 'ru':'Russian', 'sk':'Slovak', 'tr':'Turkish', 'uk':'Ukrainian', 'vi':'Vietnamese', 'zh_CN':'Chinese (Simplified)', 'zh_TW':'Chinese (Traditional)', 'test':'TEST' } + * :{ 'en':'English', 'an':'Aragonese', 'bg':'Bulgarian', 'ca':'Catalan', 'cz':'Czech', 'da':'Danish', 'de':'German', 'el':'Greek', 'el_gr':'Greek (Greece)', 'es':'Spanish', 'eu':'Basque-Euskera', 'fi':'Finnish', 'fr':'French', 'gl':'Galician', 'hr':'Croatian', 'hu':'Hungarian', 'it':'Italian', 'jp_kana':'Japanese', 'ko_KR':'Korean (South Korea)', 'nl':'Dutch', 'pl':'Polish', 'pt':'Portuguese', 'pt_br':'Portuguese (Brazilian)', 'ro':'Romanian', 'ru':'Russian', 'sk':'Slovak', 'sv':'Swedish', 'tr':'Turkish', 'uk':'Ukrainian', 'vi':'Vietnamese', 'zh_CN':'Chinese (Simplified)', 'zh_TW':'Chinese (Traditional)' } */ #define LCD_LANGUAGE en diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index f4c23b7eac..6b8eb332f4 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -163,7 +163,7 @@ #if ENABLED(CHAMBER_VENT) #define CHAMBER_VENT_SERVO_NR 1 // Index of the vent servo #define HIGH_EXCESS_HEAT_LIMIT 5 // How much above target temp to consider there is excess heat in the chamber - #define LOW_EXCESS_HEAT_LIMIT 3 + #define LOW_EXCESS_HEAT_LIMIT 3 #define MIN_COOLING_SLOPE_TIME_CHAMBER_VENT 20 #define MIN_COOLING_SLOPE_DEG_CHAMBER_VENT 1.5 #endif @@ -284,8 +284,8 @@ // DEFAULT_Kf and PID_FAN_SCALING_LIN_FACTOR are calculated accordingly. #define PID_FAN_SCALING_AT_FULL_SPEED 13.0 //=PID_FAN_SCALING_LIN_FACTOR*255+DEFAULT_Kf - #define PID_FAN_SCALING_AT_MIN_SPEED 6.0 //=PID_FAN_SCALING_LIN_FACTOR*PID_FAN_SCALING_MIN_SPEED+DEFAULT_Kf - #define PID_FAN_SCALING_MIN_SPEED 10.0 // Minimum fan speed at which to enable PID_FAN_SCALING + #define PID_FAN_SCALING_AT_MIN_SPEED 6.0 //=PID_FAN_SCALING_LIN_FACTOR*PID_FAN_SCALING_MIN_SPEED+DEFAULT_Kf + #define PID_FAN_SCALING_MIN_SPEED 10.0 // Minimum fan speed at which to enable PID_FAN_SCALING #define DEFAULT_Kf (255.0*PID_FAN_SCALING_AT_MIN_SPEED-PID_FAN_SCALING_AT_FULL_SPEED*PID_FAN_SCALING_MIN_SPEED)/(255.0-PID_FAN_SCALING_MIN_SPEED) #define PID_FAN_SCALING_LIN_FACTOR (PID_FAN_SCALING_AT_FULL_SPEED-DEFAULT_Kf)/255.0 @@ -1523,6 +1523,19 @@ #endif #endif // HAS_DGUS_LCD +// +// Specify additional languages for the UI. Default specified by LCD_LANGUAGE. +// +#if EITHER(DOGLCD, TOUCH_UI_FTDI_EVE) + //#define LCD_LANGUAGE_2 fr + //#define LCD_LANGUAGE_3 de + //#define LCD_LANGUAGE_4 es + //#define LCD_LANGUAGE_5 it + #ifdef LCD_LANGUAGE_2 + //#define LCD_LANGUAGE_AUTO_SAVE // Automatically save language to EEPROM on change + #endif +#endif + // // Touch UI for the FTDI Embedded Video Engine (EVE) // @@ -1598,13 +1611,6 @@ // Use a smaller font when labels don't fit buttons #define TOUCH_UI_FIT_TEXT - // Allow language selection from menu at run-time (otherwise use LCD_LANGUAGE) - //#define LCD_LANGUAGE_1 en - //#define LCD_LANGUAGE_2 fr - //#define LCD_LANGUAGE_3 de - //#define LCD_LANGUAGE_4 es - //#define LCD_LANGUAGE_5 it - // Use a numeric passcode for "Screen lock" keypad. // (recommended for smaller displays) //#define TOUCH_UI_PASSCODE @@ -2050,21 +2056,21 @@ */ #define FWRETRACT #if ENABLED(FWRETRACT) - #define FWRETRACT_AUTORETRACT // Override slicer retractions + #define FWRETRACT_AUTORETRACT // Override slicer retractions #if ENABLED(FWRETRACT_AUTORETRACT) - #define MIN_AUTORETRACT 0.1 // (mm) Don't convert E moves under this length - #define MAX_AUTORETRACT 10.0 // (mm) Don't convert E moves over this length + #define MIN_AUTORETRACT 0.1 // (mm) Don't convert E moves under this length + #define MAX_AUTORETRACT 10.0 // (mm) Don't convert E moves over this length #endif - #define RETRACT_LENGTH 3 // (mm) Default retract length (positive value) - #define RETRACT_LENGTH_SWAP 13 // (mm) Default swap retract length (positive value) - #define RETRACT_FEEDRATE 45 // (mm/s) Default feedrate for retracting - #define RETRACT_ZRAISE 0 // (mm) Default retract Z-raise - #define RETRACT_RECOVER_LENGTH 0 // (mm) Default additional recover length (added to retract length on recover) - #define RETRACT_RECOVER_LENGTH_SWAP 0 // (mm) Default additional swap recover length (added to retract length on recover from toolchange) - #define RETRACT_RECOVER_FEEDRATE 8 // (mm/s) Default feedrate for recovering from retraction - #define RETRACT_RECOVER_FEEDRATE_SWAP 8 // (mm/s) Default feedrate for recovering from swap retraction + #define RETRACT_LENGTH 3 // (mm) Default retract length (positive value) + #define RETRACT_LENGTH_SWAP 13 // (mm) Default swap retract length (positive value) + #define RETRACT_FEEDRATE 45 // (mm/s) Default feedrate for retracting + #define RETRACT_ZRAISE 0 // (mm) Default retract Z-raise + #define RETRACT_RECOVER_LENGTH 0 // (mm) Default additional recover length (added to retract length on recover) + #define RETRACT_RECOVER_LENGTH_SWAP 0 // (mm) Default additional swap recover length (added to retract length on recover from toolchange) + #define RETRACT_RECOVER_FEEDRATE 8 // (mm/s) Default feedrate for recovering from retraction + #define RETRACT_RECOVER_FEEDRATE_SWAP 8 // (mm/s) Default feedrate for recovering from swap retraction #if ENABLED(MIXING_EXTRUDER) - //#define RETRACT_SYNC_MIXING // Retract and restore all mixing steppers simultaneously + //#define RETRACT_SYNC_MIXING // Retract and restore all mixing steppers simultaneously #endif #endif @@ -3292,6 +3298,8 @@ //#define GCODE_QUOTED_STRINGS // Support for quoted string parameters #endif +//#define MEATPACK // Support for MeatPack G-code compression (https://github.com/scottmudge/OctoPrint-MeatPack) + //#define GCODE_CASE_INSENSITIVE // Accept G-code sent to the firmware in lowercase //#define REPETIER_GCODE_M360 // Add commands originally from Repetier FW @@ -3341,7 +3349,7 @@ //#define USER_SCRIPT_RETURN // Return to status screen after a script #define USER_DESC_1 "Home & UBL Info" - #define USER_GCODE_1 "G29NW" + #define USER_GCODE_1 "G28\nG29W" #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) @@ -3350,7 +3358,7 @@ #define USER_GCODE_3 "M140 S" STRINGIFY(PREHEAT_2_TEMP_BED) "\nM104 S" STRINGIFY(PREHEAT_2_TEMP_HOTEND) #define USER_DESC_4 "Heat Bed/Home/Level" - #define USER_GCODE_4 "M140 S" STRINGIFY(PREHEAT_2_TEMP_BED) "\nG29N" + #define USER_GCODE_4 "M140 S" STRINGIFY(PREHEAT_2_TEMP_BED) "\nG28\nG29" #define USER_DESC_5 "Home & Info" #define USER_GCODE_5 "G28\nM503" diff --git a/Marlin/src/HAL/AVR/HAL.cpp b/Marlin/src/HAL/AVR/HAL.cpp index 58d57c8ee5..4c45a5d78e 100644 --- a/Marlin/src/HAL/AVR/HAL.cpp +++ b/Marlin/src/HAL/AVR/HAL.cpp @@ -24,6 +24,13 @@ #include "../../inc/MarlinConfig.h" #include "HAL.h" +#ifdef USBCON + DefaultSerial MSerial(false, Serial); + #ifdef BLUETOOTH + BTSerial btSerial(false, bluetoothSerial); + #endif +#endif + // ------------------------ // Public Variables // ------------------------ diff --git a/Marlin/src/HAL/AVR/HAL.h b/Marlin/src/HAL/AVR/HAL.h index c7dfc3a8cb..ed913254ad 100644 --- a/Marlin/src/HAL/AVR/HAL.h +++ b/Marlin/src/HAL/AVR/HAL.h @@ -82,7 +82,15 @@ typedef int8_t pin_t; // Serial ports #ifdef USBCON - #define MYSERIAL0 TERN(BLUETOOTH, bluetoothSerial, Serial) + #include "../../core/serial_hook.h" + typedef ForwardSerial0Type< decltype(Serial) > DefaultSerial; + extern DefaultSerial MSerial; + #ifdef BLUETOOTH + typedef ForwardSerial0Type< decltype(bluetoothSerial) > BTSerial; + extern BTSerial btSerial; + #endif + + #define MYSERIAL0 TERN(BLUETOOTH, btSerial, MSerial) #else #if !WITHIN(SERIAL_PORT, -1, 3) #error "SERIAL_PORT must be from -1 to 3. Please update your configuration." diff --git a/Marlin/src/HAL/AVR/MarlinSerial.cpp b/Marlin/src/HAL/AVR/MarlinSerial.cpp index 185ce94757..84ffe7cce2 100644 --- a/Marlin/src/HAL/AVR/MarlinSerial.cpp +++ b/Marlin/src/HAL/AVR/MarlinSerial.cpp @@ -454,7 +454,7 @@ void MarlinSerial::flush() { } template -void MarlinSerial::write(const uint8_t c) { +size_t MarlinSerial::write(const uint8_t c) { if (Cfg::TX_SIZE == 0) { _written = true; @@ -480,7 +480,7 @@ void MarlinSerial::write(const uint8_t c) { // location". This makes sure flush() won't return until the bytes // actually got written B_TXC = 1; - return; + return 1; } const uint8_t i = (tx_buffer.head + 1) & (Cfg::TX_SIZE - 1); @@ -510,6 +510,7 @@ void MarlinSerial::write(const uint8_t c) { // Enable TX ISR - Non atomic, but it will eventually enable TX ISR B_UDRIE = 1; } + return 1; } template @@ -556,161 +557,6 @@ void MarlinSerial::flushTX() { } } -/** - * Imports from print.h - */ - -template -void MarlinSerial::print(char c, int base) { - print((long)c, base); -} - -template -void MarlinSerial::print(unsigned char b, int base) { - print((unsigned long)b, base); -} - -template -void MarlinSerial::print(int n, int base) { - print((long)n, base); -} - -template -void MarlinSerial::print(unsigned int n, int base) { - print((unsigned long)n, base); -} - -template -void MarlinSerial::print(long n, int base) { - if (base == 0) write(n); - else if (base == 10) { - if (n < 0) { print('-'); n = -n; } - printNumber(n, 10); - } - else - printNumber(n, base); -} - -template -void MarlinSerial::print(unsigned long n, int base) { - if (base == 0) write(n); - else printNumber(n, base); -} - -template -void MarlinSerial::print(double n, int digits) { - printFloat(n, digits); -} - -template -void MarlinSerial::println() { - print('\r'); - print('\n'); -} - -template -void MarlinSerial::println(const String& s) { - print(s); - println(); -} - -template -void MarlinSerial::println(const char c[]) { - print(c); - println(); -} - -template -void MarlinSerial::println(char c, int base) { - print(c, base); - println(); -} - -template -void MarlinSerial::println(unsigned char b, int base) { - print(b, base); - println(); -} - -template -void MarlinSerial::println(int n, int base) { - print(n, base); - println(); -} - -template -void MarlinSerial::println(unsigned int n, int base) { - print(n, base); - println(); -} - -template -void MarlinSerial::println(long n, int base) { - print(n, base); - println(); -} - -template -void MarlinSerial::println(unsigned long n, int base) { - print(n, base); - println(); -} - -template -void MarlinSerial::println(double n, int digits) { - print(n, digits); - println(); -} - -// Private Methods - -template -void MarlinSerial::printNumber(unsigned long n, uint8_t base) { - if (n) { - unsigned char buf[8 * sizeof(long)]; // Enough space for base 2 - int8_t i = 0; - while (n) { - buf[i++] = n % base; - n /= base; - } - while (i--) - print((char)(buf[i] + (buf[i] < 10 ? '0' : 'A' - 10))); - } - else - print('0'); -} - -template -void MarlinSerial::printFloat(double number, uint8_t digits) { - // Handle negative numbers - if (number < 0.0) { - print('-'); - number = -number; - } - - // Round correctly so that print(1.999, 2) prints as "2.00" - double rounding = 0.5; - LOOP_L_N(i, digits) rounding *= 0.1; - number += rounding; - - // Extract the integer part of the number and print it - unsigned long int_part = (unsigned long)number; - double remainder = number - (double)int_part; - print(int_part); - - // Print the decimal point, but only if there are digits beyond - if (digits) { - print('.'); - // Extract digits from the remainder one at a time - while (digits--) { - remainder *= 10.0; - int toPrint = int(remainder); - print(toPrint); - remainder -= toPrint; - } - } -} - // Hookup ISR handlers ISR(SERIAL_REGNAME(USART, SERIAL_PORT, _RX_vect)) { MarlinSerial>::store_rxd_char(); @@ -720,11 +566,9 @@ ISR(SERIAL_REGNAME(USART, SERIAL_PORT, _UDRE_vect)) { MarlinSerial>::_tx_udr_empty_irq(); } -// Preinstantiate -template class MarlinSerial>; - -// Instantiate -MarlinSerial> customizedSerial1; +// Because of the template definition above, it's required to instantiate the template to have all method generated +template class MarlinSerial< MarlinSerialCfg >; +MSerialT customizedSerial1(MSerialT::HasEmergencyParser); #ifdef SERIAL_PORT_2 @@ -737,12 +581,8 @@ MarlinSerial> customizedSerial1; MarlinSerial>::_tx_udr_empty_irq(); } - // Preinstantiate - template class MarlinSerial>; - - // Instantiate - MarlinSerial> customizedSerial2; - + template class MarlinSerial< MarlinSerialCfg >; + MSerialT2 customizedSerial2(MSerialT2::HasEmergencyParser); #endif #ifdef MMU2_SERIAL_PORT @@ -755,12 +595,8 @@ MarlinSerial> customizedSerial1; MarlinSerial>::_tx_udr_empty_irq(); } - // Preinstantiate - template class MarlinSerial>; - - // Instantiate - MarlinSerial> mmuSerial; - + template class MarlinSerial< MarlinSerialCfg >; + MSerialT3 mmuSerial(MSerialT3::HasEmergencyParser); #endif #ifdef LCD_SERIAL_PORT @@ -773,11 +609,8 @@ MarlinSerial> customizedSerial1; MarlinSerial>::_tx_udr_empty_irq(); } - // Preinstantiate - template class MarlinSerial>; - - // Instantiate - MarlinSerial> lcdSerial; + template class MarlinSerial< LCDSerialCfg >; + MSerialT4 lcdSerial(MSerialT4::HasEmergencyParser); #if HAS_DGUS_LCD || ENABLED(DGUS_LCD_UI_CREALITY_TOUCH) template @@ -796,7 +629,7 @@ MarlinSerial> customizedSerial1; // For AT90USB targets use the UART for BT interfacing #if defined(USBCON) && ENABLED(BLUETOOTH) - HardwareSerial bluetoothSerial; + MSerialT5 bluetoothSerial(false); #endif #endif // __AVR__ diff --git a/Marlin/src/HAL/AVR/MarlinSerial.h b/Marlin/src/HAL/AVR/MarlinSerial.h index 28ffe899d9..17de771fdc 100644 --- a/Marlin/src/HAL/AVR/MarlinSerial.h +++ b/Marlin/src/HAL/AVR/MarlinSerial.h @@ -34,6 +34,7 @@ #include #include "../../inc/MarlinConfigPre.h" +#include "../../core/serial_hook.h" #ifndef SERIAL_PORT #define SERIAL_PORT 0 @@ -135,10 +136,6 @@ UART_DECL(3); #endif - #define DEC 10 - #define HEX 16 - #define OCT 8 - #define BIN 2 #define BYTE 0 // Templated type selector @@ -202,60 +199,30 @@ static FORCE_INLINE void atomic_set_rx_tail(ring_buffer_pos_t value); static FORCE_INLINE ring_buffer_pos_t atomic_read_rx_tail(); - public: - + public: FORCE_INLINE static void store_rxd_char(); FORCE_INLINE static void _tx_udr_empty_irq(); - public: - MarlinSerial() {}; - static void begin(const long); - static void end(); - static int peek(); - static int read(); - static void flush(); - static ring_buffer_pos_t available(); - static void write(const uint8_t c); - static void flushTX(); - #if HAS_DGUS_LCD || ENABLED(DGUS_LCD_UI_CREALITY_TOUCH) - static ring_buffer_pos_t get_tx_buffer_free(); - #endif + public: + static void begin(const long); + static void end(); + static int peek(); + static int read(); + static void flush(); + static ring_buffer_pos_t available(); + static size_t write(const uint8_t c); + static void flushTX(); + #if HAS_DGUS_LCD || ENABLED(DGUS_LCD_UI_CREALITY_TOUCH) + static ring_buffer_pos_t get_tx_buffer_free(); + #endif - static inline bool emergency_parser_enabled() { return Cfg::EMERGENCYPARSER; } + enum { HasEmergencyParser = Cfg::EMERGENCYPARSER }; + static inline bool emergency_parser_enabled() { return Cfg::EMERGENCYPARSER; } - FORCE_INLINE static uint8_t dropped() { return Cfg::DROPPED_RX ? rx_dropped_bytes : 0; } - FORCE_INLINE static uint8_t buffer_overruns() { return Cfg::RX_OVERRUNS ? rx_buffer_overruns : 0; } - FORCE_INLINE static uint8_t framing_errors() { return Cfg::RX_FRAMING_ERRORS ? rx_framing_errors : 0; } - FORCE_INLINE static ring_buffer_pos_t rxMaxEnqueued() { return Cfg::MAX_RX_QUEUED ? rx_max_enqueued : 0; } - - FORCE_INLINE static void write(const char* str) { while (*str) write(*str++); } - FORCE_INLINE static void write(const uint8_t* buffer, size_t size) { while (size--) write(*buffer++); } - FORCE_INLINE static void print(const String& s) { for (int i = 0; i < (int)s.length(); i++) write(s[i]); } - FORCE_INLINE static void print(const char* str) { write(str); } - - static void print(char, int = BYTE); - static void print(unsigned char, int = BYTE); - static void print(int, int = DEC); - static void print(unsigned int, int = DEC); - static void print(long, int = DEC); - static void print(unsigned long, int = DEC); - static void print(double, int = 2); - - static void println(const String& s); - static void println(const char[]); - static void println(char, int = BYTE); - static void println(unsigned char, int = BYTE); - static void println(int, int = DEC); - static void println(unsigned int, int = DEC); - static void println(long, int = DEC); - static void println(unsigned long, int = DEC); - static void println(double, int = 2); - static void println(); - operator bool() { return true; } - - private: - static void printNumber(unsigned long, const uint8_t); - static void printFloat(double, uint8_t); + FORCE_INLINE static uint8_t dropped() { return Cfg::DROPPED_RX ? rx_dropped_bytes : 0; } + FORCE_INLINE static uint8_t buffer_overruns() { return Cfg::RX_OVERRUNS ? rx_buffer_overruns : 0; } + FORCE_INLINE static uint8_t framing_errors() { return Cfg::RX_FRAMING_ERRORS ? rx_framing_errors : 0; } + FORCE_INLINE static ring_buffer_pos_t rxMaxEnqueued() { return Cfg::MAX_RX_QUEUED ? rx_max_enqueued : 0; } }; template @@ -270,12 +237,13 @@ static constexpr bool RX_FRAMING_ERRORS = ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS); static constexpr bool MAX_RX_QUEUED = ENABLED(SERIAL_STATS_MAX_RX_QUEUED); }; - extern MarlinSerial> customizedSerial1; + + typedef Serial0Type< MarlinSerial< MarlinSerialCfg > > MSerialT; + extern MSerialT customizedSerial1; #ifdef SERIAL_PORT_2 - - extern MarlinSerial> customizedSerial2; - + typedef Serial0Type< MarlinSerial< MarlinSerialCfg > > MSerialT2; + extern MSerialT2 customizedSerial2; #endif #endif // !USBCON @@ -294,7 +262,8 @@ static constexpr bool RX_OVERRUNS = false; }; - extern MarlinSerial> mmuSerial; + typedef Serial0Type< MarlinSerial< MMU2SerialCfg > > MSerialT3; + extern MSerial3 mmuSerial; #endif #ifdef LCD_SERIAL_PORT @@ -322,11 +291,13 @@ #endif }; - extern MarlinSerial> lcdSerial; + typedef Serial0Type< MarlinSerial< LCDSerialCfg > > MSerialT4; + extern MSerialT4 lcdSerial; #endif // Use the UART for Bluetooth in AT90USB configurations #if defined(USBCON) && ENABLED(BLUETOOTH) - extern HardwareSerial bluetoothSerial; + typedef Serial0Type MSerialT5; + extern MSerialT5 bluetoothSerial; #endif diff --git a/Marlin/src/HAL/DUE/HAL.cpp b/Marlin/src/HAL/DUE/HAL.cpp index 6ce85a4643..2ae70843f0 100644 --- a/Marlin/src/HAL/DUE/HAL.cpp +++ b/Marlin/src/HAL/DUE/HAL.cpp @@ -102,4 +102,11 @@ uint16_t HAL_adc_get_result() { return HAL_adc_result; } +// Forward the default serial port +DefaultSerial MSerial(false, Serial); + +DefaultSerial1 MSerial1(false, Serial1); +DefaultSerial2 MSerial2(false, Serial2); +DefaultSerial3 MSerial3(false, Serial3); + #endif // ARDUINO_ARCH_SAM diff --git a/Marlin/src/HAL/DUE/HAL.h b/Marlin/src/HAL/DUE/HAL.h index 4783947f6f..78c8a800b9 100644 --- a/Marlin/src/HAL/DUE/HAL.h +++ b/Marlin/src/HAL/DUE/HAL.h @@ -36,9 +36,20 @@ #include -#define _MSERIAL(X) Serial##X +#include "../../core/serial_hook.h" +typedef ForwardSerial0Type< decltype(Serial) > DefaultSerial; +extern DefaultSerial MSerial; + +typedef ForwardSerial0Type< decltype(Serial1) > DefaultSerial1; +typedef ForwardSerial0Type< decltype(Serial2) > DefaultSerial2; +typedef ForwardSerial0Type< decltype(Serial3) > DefaultSerial3; +extern DefaultSerial1 MSerial1; +extern DefaultSerial2 MSerial2; +extern DefaultSerial3 MSerial3; + +#define _MSERIAL(X) MSerial##X #define MSERIAL(X) _MSERIAL(X) -#define Serial0 Serial +#define MSerial0 MSerial // Define MYSERIAL0/1 before MarlinSerial includes! #if SERIAL_PORT == -1 || ENABLED(EMERGENCY_PARSER) @@ -61,7 +72,7 @@ #ifdef MMU2_SERIAL_PORT #if WITHIN(MMU2_SERIAL_PORT, 0, 3) - #define MMU2_SERIAL MSERIAL(SERIAL_PORT) + #define MMU2_SERIAL MSERIAL(MMU2_SERIAL_PORT) #else #error "MMU2_SERIAL_PORT must be from 0 to 3. Please update your configuration." #endif @@ -83,16 +94,6 @@ // On AVR this is in math.h? #define square(x) ((x)*(x)) -#ifndef strncpy_P - #define strncpy_P(dest, src, num) strncpy((dest), (src), (num)) -#endif - -// Fix bug in pgm_read_ptr -#undef pgm_read_ptr -#define pgm_read_ptr(addr) (*((void**)(addr))) -#undef pgm_read_word -#define pgm_read_word(addr) (*((uint16_t*)(addr))) - typedef int8_t pin_t; #define SHARED_SERVOS HAS_SERVOS diff --git a/Marlin/src/HAL/DUE/MarlinSerial.cpp b/Marlin/src/HAL/DUE/MarlinSerial.cpp index c9a372eeb1..50b84c0b1d 100644 --- a/Marlin/src/HAL/DUE/MarlinSerial.cpp +++ b/Marlin/src/HAL/DUE/MarlinSerial.cpp @@ -382,7 +382,7 @@ void MarlinSerial::flush() { } template -void MarlinSerial::write(const uint8_t c) { +size_t MarlinSerial::write(const uint8_t c) { _written = true; if (Cfg::TX_SIZE == 0) { @@ -400,7 +400,7 @@ void MarlinSerial::write(const uint8_t c) { // XOFF char at the RX isr, but it is properly handled there if (!(HWUART->UART_IMR & UART_IMR_TXRDY) && (HWUART->UART_SR & UART_SR_TXRDY)) { HWUART->UART_THR = c; - return; + return 1; } const uint8_t i = (tx_buffer.head + 1) & (Cfg::TX_SIZE - 1); @@ -428,6 +428,7 @@ void MarlinSerial::write(const uint8_t c) { // Enable TX isr - Non atomic, but it will eventually enable TX isr HWUART->UART_IER = UART_IER_TXRDY; } + return 1; } template @@ -473,169 +474,16 @@ void MarlinSerial::flushTX() { } } -/** - * Imports from print.h - */ - -template -void MarlinSerial::print(char c, int base) { - print((long)c, base); -} - -template -void MarlinSerial::print(unsigned char b, int base) { - print((unsigned long)b, base); -} - -template -void MarlinSerial::print(int n, int base) { - print((long)n, base); -} - -template -void MarlinSerial::print(unsigned int n, int base) { - print((unsigned long)n, base); -} - -template -void MarlinSerial::print(long n, int base) { - if (base == 0) write(n); - else if (base == 10) { - if (n < 0) { print('-'); n = -n; } - printNumber(n, 10); - } - else - printNumber(n, base); -} - -template -void MarlinSerial::print(unsigned long n, int base) { - if (base == 0) write(n); - else printNumber(n, base); -} - -template -void MarlinSerial::print(double n, int digits) { - printFloat(n, digits); -} - -template -void MarlinSerial::println() { - print('\r'); - print('\n'); -} - -template -void MarlinSerial::println(const String& s) { - print(s); - println(); -} - -template -void MarlinSerial::println(const char c[]) { - print(c); - println(); -} - -template -void MarlinSerial::println(char c, int base) { - print(c, base); - println(); -} - -template -void MarlinSerial::println(unsigned char b, int base) { - print(b, base); - println(); -} - -template -void MarlinSerial::println(int n, int base) { - print(n, base); - println(); -} - -template -void MarlinSerial::println(unsigned int n, int base) { - print(n, base); - println(); -} - -template -void MarlinSerial::println(long n, int base) { - print(n, base); - println(); -} - -template -void MarlinSerial::println(unsigned long n, int base) { - print(n, base); - println(); -} - -template -void MarlinSerial::println(double n, int digits) { - print(n, digits); - println(); -} - -// Private Methods -template -void MarlinSerial::printNumber(unsigned long n, uint8_t base) { - if (n) { - unsigned char buf[8 * sizeof(long)]; // Enough space for base 2 - int8_t i = 0; - while (n) { - buf[i++] = n % base; - n /= base; - } - while (i--) - print((char)(buf[i] + (buf[i] < 10 ? '0' : 'A' - 10))); - } - else - print('0'); -} - -template -void MarlinSerial::printFloat(double number, uint8_t digits) { - // Handle negative numbers - if (number < 0.0) { - print('-'); - number = -number; - } - - // Round correctly so that print(1.999, 2) prints as "2.00" - double rounding = 0.5; - LOOP_L_N(i, digits) rounding *= 0.1; - number += rounding; - - // Extract the integer part of the number and print it - unsigned long int_part = (unsigned long)number; - double remainder = number - (double)int_part; - print(int_part); - - // Print the decimal point, but only if there are digits beyond - if (digits) { - print('.'); - // Extract digits from the remainder one at a time - while (digits--) { - remainder *= 10.0; - int toPrint = int(remainder); - print(toPrint); - remainder -= toPrint; - } - } -} // If not using the USB port as serial port #if SERIAL_PORT >= 0 - template class MarlinSerial>; // Define - MarlinSerial> customizedSerial1; // Instantiate + template class MarlinSerial< MarlinSerialCfg >; + MSerialT customizedSerial1(MarlinSerialCfg::EMERGENCYPARSER); #endif #if defined(SERIAL_PORT_2) && SERIAL_PORT_2 >= 0 - template class MarlinSerial>; // Define - MarlinSerial> customizedSerial2; // Instantiate + template class MarlinSerial< MarlinSerialCfg >; + MSerialT2 customizedSerial2(MarlinSerialCfg::EMERGENCYPARSER); #endif #endif // ARDUINO_ARCH_SAM diff --git a/Marlin/src/HAL/DUE/MarlinSerial.h b/Marlin/src/HAL/DUE/MarlinSerial.h index a194eba2f3..7fc21264bb 100644 --- a/Marlin/src/HAL/DUE/MarlinSerial.h +++ b/Marlin/src/HAL/DUE/MarlinSerial.h @@ -30,11 +30,7 @@ #include #include "../../inc/MarlinConfigPre.h" - -#define DEC 10 -#define HEX 16 -#define OCT 8 -#define BIN 2 +#include "../../core/serial_hook.h" // Define constants and variables for buffering incoming serial data. We're // using a ring buffer (I think), in which rx_buffer_head is the index of the @@ -119,7 +115,7 @@ public: static int read(); static void flush(); static ring_buffer_pos_t available(); - static void write(const uint8_t c); + static size_t write(const uint8_t c); static void flushTX(); static inline bool emergency_parser_enabled() { return Cfg::EMERGENCYPARSER; } @@ -128,35 +124,6 @@ public: FORCE_INLINE static uint8_t buffer_overruns() { return Cfg::RX_OVERRUNS ? rx_buffer_overruns : 0; } FORCE_INLINE static uint8_t framing_errors() { return Cfg::RX_FRAMING_ERRORS ? rx_framing_errors : 0; } FORCE_INLINE static ring_buffer_pos_t rxMaxEnqueued() { return Cfg::MAX_RX_QUEUED ? rx_max_enqueued : 0; } - - FORCE_INLINE static void write(const char* str) { while (*str) write(*str++); } - FORCE_INLINE static void write(const uint8_t* buffer, size_t size) { while (size--) write(*buffer++); } - FORCE_INLINE static void print(const String& s) { for (int i = 0; i < (int)s.length(); i++) write(s[i]); } - FORCE_INLINE static void print(const char* str) { write(str); } - - static void print(char, int = 0); - static void print(unsigned char, int = 0); - static void print(int, int = DEC); - static void print(unsigned int, int = DEC); - static void print(long, int = DEC); - static void print(unsigned long, int = DEC); - static void print(double, int = 2); - - static void println(const String& s); - static void println(const char[]); - static void println(char, int = 0); - static void println(unsigned char, int = 0); - static void println(int, int = DEC); - static void println(unsigned int, int = DEC); - static void println(long, int = DEC); - static void println(unsigned long, int = DEC); - static void println(double, int = 2); - static void println(); - operator bool() { return true; } - -private: - static void printNumber(unsigned long, const uint8_t); - static void printFloat(double, uint8_t); }; // Serial port configuration @@ -174,9 +141,11 @@ struct MarlinSerialCfg { }; #if SERIAL_PORT >= 0 - extern MarlinSerial> customizedSerial1; + typedef Serial0Type< MarlinSerial< MarlinSerialCfg > > MSerialT; + extern MSerialT customizedSerial1; #endif #if defined(SERIAL_PORT_2) && SERIAL_PORT_2 >= 0 - extern MarlinSerial> customizedSerial2; + typedef Serial0Type< MarlinSerial< MarlinSerialCfg > > MSerialT2; + extern MSerialT2 customizedSerial2; #endif diff --git a/Marlin/src/HAL/DUE/MarlinSerialUSB.cpp b/Marlin/src/HAL/DUE/MarlinSerialUSB.cpp index a41dbfeb7a..d85aaf14b0 100644 --- a/Marlin/src/HAL/DUE/MarlinSerialUSB.cpp +++ b/Marlin/src/HAL/DUE/MarlinSerialUSB.cpp @@ -50,10 +50,6 @@ extern "C" { // Pending character static int pending_char = -1; -#if ENABLED(EMERGENCY_PARSER) - static EmergencyParser::State emergency_state; // = EP_RESET -#endif - // Public Methods void MarlinSerialUSB::begin(const long) {} @@ -111,13 +107,13 @@ bool MarlinSerialUSB::available() { void MarlinSerialUSB::flush() { } void MarlinSerialUSB::flushTX() { } -void MarlinSerialUSB::write(const uint8_t c) { +size_t MarlinSerialUSB::write(const uint8_t c) { /* Do not even bother sending anything if USB CDC is not enumerated or not configured on the PC side or there is no program on the PC listening to our messages */ if (!usb_task_cdc_isenabled() || !usb_task_cdc_dtr_active()) - return; + return 0; /* Wait until the PC has read the pending to be sent data */ while (usb_task_cdc_isenabled() && @@ -129,161 +125,20 @@ void MarlinSerialUSB::write(const uint8_t c) { or not configured on the PC side or there is no program on the PC listening to our messages at this point */ if (!usb_task_cdc_isenabled() || !usb_task_cdc_dtr_active()) - return; + return 0; // Fifo full // udi_cdc_signal_overrun(); udi_cdc_putc(c); -} - -/** - * Imports from print.h - */ - -void MarlinSerialUSB::print(char c, int base) { - print((long)c, base); -} - -void MarlinSerialUSB::print(unsigned char b, int base) { - print((unsigned long)b, base); -} - -void MarlinSerialUSB::print(int n, int base) { - print((long)n, base); -} - -void MarlinSerialUSB::print(unsigned int n, int base) { - print((unsigned long)n, base); -} - -void MarlinSerialUSB::print(long n, int base) { - if (base == 0) - write(n); - else if (base == 10) { - if (n < 0) { - print('-'); - n = -n; - } - printNumber(n, 10); - } - else - printNumber(n, base); -} - -void MarlinSerialUSB::print(unsigned long n, int base) { - if (base == 0) write(n); - else printNumber(n, base); -} - -void MarlinSerialUSB::print(double n, int digits) { - printFloat(n, digits); -} - -void MarlinSerialUSB::println() { - print('\r'); - print('\n'); -} - -void MarlinSerialUSB::println(const String& s) { - print(s); - println(); -} - -void MarlinSerialUSB::println(const char c[]) { - print(c); - println(); -} - -void MarlinSerialUSB::println(char c, int base) { - print(c, base); - println(); -} - -void MarlinSerialUSB::println(unsigned char b, int base) { - print(b, base); - println(); -} - -void MarlinSerialUSB::println(int n, int base) { - print(n, base); - println(); -} - -void MarlinSerialUSB::println(unsigned int n, int base) { - print(n, base); - println(); -} - -void MarlinSerialUSB::println(long n, int base) { - print(n, base); - println(); -} - -void MarlinSerialUSB::println(unsigned long n, int base) { - print(n, base); - println(); -} - -void MarlinSerialUSB::println(double n, int digits) { - print(n, digits); - println(); -} - -// Private Methods - -void MarlinSerialUSB::printNumber(unsigned long n, uint8_t base) { - if (n) { - unsigned char buf[8 * sizeof(long)]; // Enough space for base 2 - int8_t i = 0; - while (n) { - buf[i++] = n % base; - n /= base; - } - while (i--) - print((char)(buf[i] + (buf[i] < 10 ? '0' : 'A' - 10))); - } - else - print('0'); -} - -void MarlinSerialUSB::printFloat(double number, uint8_t digits) { - // Handle negative numbers - if (number < 0.0) { - print('-'); - number = -number; - } - - // Round correctly so that print(1.999, 2) prints as "2.00" - double rounding = 0.5; - LOOP_L_N(i, digits) - rounding *= 0.1; - - number += rounding; - - // Extract the integer part of the number and print it - unsigned long int_part = (unsigned long)number; - double remainder = number - (double)int_part; - print(int_part); - - // Print the decimal point, but only if there are digits beyond - if (digits) { - print('.'); - // Extract digits from the remainder one at a time - while (digits--) { - remainder *= 10.0; - int toPrint = int(remainder); - print(toPrint); - remainder -= toPrint; - } - } + return 1; } // Preinstantiate #if SERIAL_PORT == -1 - MarlinSerialUSB customizedSerial1; + MSerialT customizedSerial1(TERN0(EMERGENCY_PARSER, true)); #endif #if SERIAL_PORT_2 == -1 - MarlinSerialUSB customizedSerial2; + MSerialT customizedSerial2(TERN0(EMERGENCY_PARSER, true)); #endif #endif // HAS_USB_SERIAL diff --git a/Marlin/src/HAL/DUE/MarlinSerialUSB.h b/Marlin/src/HAL/DUE/MarlinSerialUSB.h index 2e3622e553..9643a8465a 100644 --- a/Marlin/src/HAL/DUE/MarlinSerialUSB.h +++ b/Marlin/src/HAL/DUE/MarlinSerialUSB.h @@ -27,20 +27,13 @@ */ #include "../../inc/MarlinConfig.h" - #if HAS_USB_SERIAL #include +#include "../../core/serial_hook.h" -#define DEC 10 -#define HEX 16 -#define OCT 8 -#define BIN 2 -class MarlinSerialUSB { - -public: - MarlinSerialUSB() {}; +struct MarlinSerialUSB { static void begin(const long); static void end(); static int peek(); @@ -48,7 +41,7 @@ public: static void flush(); static void flushTX(); static bool available(); - static void write(const uint8_t c); + static size_t write(const uint8_t c); #if ENABLED(SERIAL_STATS_DROPPED_RX) FORCE_INLINE static uint32_t dropped() { return 0; } @@ -57,43 +50,15 @@ public: #if ENABLED(SERIAL_STATS_MAX_RX_QUEUED) FORCE_INLINE static int rxMaxEnqueued() { return 0; } #endif - - FORCE_INLINE static void write(const char* str) { while (*str) write(*str++); } - FORCE_INLINE static void write(const uint8_t* buffer, size_t size) { while (size--) write(*buffer++); } - FORCE_INLINE static void print(const String& s) { for (int i = 0; i < (int)s.length(); i++) write(s[i]); } - FORCE_INLINE static void print(const char* str) { write(str); } - - static void print(char, int = 0); - static void print(unsigned char, int = 0); - static void print(int, int = DEC); - static void print(unsigned int, int = DEC); - static void print(long, int = DEC); - static void print(unsigned long, int = DEC); - static void print(double, int = 2); - - static void println(const String& s); - static void println(const char[]); - static void println(char, int = 0); - static void println(unsigned char, int = 0); - static void println(int, int = DEC); - static void println(unsigned int, int = DEC); - static void println(long, int = DEC); - static void println(unsigned long, int = DEC); - static void println(double, int = 2); - static void println(); - operator bool() { return true; } - -private: - static void printNumber(unsigned long, const uint8_t); - static void printFloat(double, uint8_t); }; +typedef Serial0Type MSerialT; #if SERIAL_PORT == -1 - extern MarlinSerialUSB customizedSerial1; + extern MSerialT customizedSerial1; #endif #if SERIAL_PORT_2 == -1 - extern MarlinSerialUSB customizedSerial2; + extern MSerialT customizedSerial2; #endif #endif // HAS_USB_SERIAL diff --git a/Marlin/src/HAL/DUE/usb/sd_mmc_spi_mem.cpp b/Marlin/src/HAL/DUE/usb/sd_mmc_spi_mem.cpp index db5e82ec55..d92d332c1e 100644 --- a/Marlin/src/HAL/DUE/usb/sd_mmc_spi_mem.cpp +++ b/Marlin/src/HAL/DUE/usb/sd_mmc_spi_mem.cpp @@ -68,7 +68,7 @@ Ctrl_status sd_mmc_spi_usb_read_10(uint32_t addr, uint16_t nb_sector) { { char buffer[80]; sprintf_P(buffer, PSTR("SDRD: %d @ 0x%08x\n"), nb_sector, addr); - PORT_REDIRECT(0); + PORT_REDIRECT(SERIAL_PORTMASK(0)); SERIAL_ECHO(buffer); } #endif @@ -108,7 +108,7 @@ Ctrl_status sd_mmc_spi_usb_write_10(uint32_t addr, uint16_t nb_sector) { { char buffer[80]; sprintf_P(buffer, PSTR("SDWR: %d @ 0x%08x\n"), nb_sector, addr); - PORT_REDIRECT(0); + PORT_REDIRECT(SERIAL_PORTMASK(0)); SERIAL_ECHO(buffer); } #endif diff --git a/Marlin/src/HAL/ESP32/FlushableHardwareSerial.cpp b/Marlin/src/HAL/ESP32/FlushableHardwareSerial.cpp index d4b2f42c53..cc5a4fc476 100644 --- a/Marlin/src/HAL/ESP32/FlushableHardwareSerial.cpp +++ b/Marlin/src/HAL/ESP32/FlushableHardwareSerial.cpp @@ -24,10 +24,7 @@ #ifdef ARDUINO_ARCH_ESP32 -FlushableHardwareSerial::FlushableHardwareSerial(int uart_nr) - : HardwareSerial(uart_nr) -{} -FlushableHardwareSerial flushableSerial(0); +Serial0Type flushableSerial(false, 0); #endif // ARDUINO_ARCH_ESP32 diff --git a/Marlin/src/HAL/ESP32/FlushableHardwareSerial.h b/Marlin/src/HAL/ESP32/FlushableHardwareSerial.h index b43caea13c..27df0be4b6 100644 --- a/Marlin/src/HAL/ESP32/FlushableHardwareSerial.h +++ b/Marlin/src/HAL/ESP32/FlushableHardwareSerial.h @@ -24,14 +24,13 @@ #ifdef ARDUINO_ARCH_ESP32 #include +#include "../../core/serial_hook.h" class FlushableHardwareSerial : public HardwareSerial { public: - FlushableHardwareSerial(int uart_nr); - - inline void flushTX() { /* No need to flush the hardware serial, but defined here for compatibility. */ } + FlushableHardwareSerial(int uart_nr) : HardwareSerial(uart_nr) {} }; -extern FlushableHardwareSerial flushableSerial; +extern Serial0Type flushableSerial; #endif // ARDUINO_ARCH_ESP32 diff --git a/Marlin/src/HAL/ESP32/HAL.cpp b/Marlin/src/HAL/ESP32/HAL.cpp index ead448d78d..6ff1446b1c 100644 --- a/Marlin/src/HAL/ESP32/HAL.cpp +++ b/Marlin/src/HAL/ESP32/HAL.cpp @@ -40,6 +40,10 @@ #endif #endif +#if ENABLED(ESP3D_WIFISUPPORT) + DefaultSerial MSerial(false, Serial2Socket); +#endif + // ------------------------ // Externs // ------------------------ diff --git a/Marlin/src/HAL/ESP32/HAL.h b/Marlin/src/HAL/ESP32/HAL.h index be87737b0f..3dc27c6493 100644 --- a/Marlin/src/HAL/ESP32/HAL.h +++ b/Marlin/src/HAL/ESP32/HAL.h @@ -55,7 +55,9 @@ extern portMUX_TYPE spinlock; #if EITHER(WIFISUPPORT, ESP3D_WIFISUPPORT) #if ENABLED(ESP3D_WIFISUPPORT) - #define MYSERIAL1 Serial2Socket + typedef ForwardSerial0Type< decltype(Serial2Socket) > DefaultSerial; + extern DefaultSerial MSerial; + #define MYSERIAL1 MSerial #else #define MYSERIAL1 webSocketSerial #endif @@ -67,10 +69,6 @@ extern portMUX_TYPE spinlock; #define ENABLE_ISRS() if (spinlock.owner != portMUX_FREE_VAL) portEXIT_CRITICAL(&spinlock) #define DISABLE_ISRS() portENTER_CRITICAL(&spinlock) -// Fix bug in pgm_read_ptr -#undef pgm_read_ptr -#define pgm_read_ptr(addr) (*(addr)) - // ------------------------ // Types // ------------------------ diff --git a/Marlin/src/HAL/ESP32/WebSocketSerial.cpp b/Marlin/src/HAL/ESP32/WebSocketSerial.cpp index ca7f47a1f8..8825742d38 100644 --- a/Marlin/src/HAL/ESP32/WebSocketSerial.cpp +++ b/Marlin/src/HAL/ESP32/WebSocketSerial.cpp @@ -29,7 +29,7 @@ #include "wifi.h" #include -WebSocketSerial webSocketSerial; +MSerialT webSocketSerial(false); AsyncWebSocket ws("/ws"); // TODO Move inside the class. // RingBuffer impl @@ -144,9 +144,5 @@ size_t WebSocketSerial::write(const uint8_t* buffer, size_t size) { return written; } -void WebSocketSerial::flushTX() { - // No need to do anything as there's no benefit to sending partial lines over the websocket connection. -} - #endif // WIFISUPPORT #endif // ARDUINO_ARCH_ESP32 diff --git a/Marlin/src/HAL/ESP32/WebSocketSerial.h b/Marlin/src/HAL/ESP32/WebSocketSerial.h index 7a25c6dc5e..c68792c8c1 100644 --- a/Marlin/src/HAL/ESP32/WebSocketSerial.h +++ b/Marlin/src/HAL/ESP32/WebSocketSerial.h @@ -22,6 +22,7 @@ #pragma once #include "../../inc/MarlinConfig.h" +#include "../../core/serial_hook.h" #include @@ -68,12 +69,9 @@ public: int peek(); int read(); void flush(); - void flushTX(); size_t write(const uint8_t c); size_t write(const uint8_t* buffer, size_t size); - operator bool() { return true; } - #if ENABLED(SERIAL_STATS_DROPPED_RX) FORCE_INLINE uint32_t dropped() { return 0; } #endif @@ -83,4 +81,5 @@ public: #endif }; -extern WebSocketSerial webSocketSerial; +typedef Serial0Type MSerialT; +extern MSerialT webSocketSerial; diff --git a/Marlin/src/HAL/LINUX/HAL.cpp b/Marlin/src/HAL/LINUX/HAL.cpp index ee9e31e140..771f1d2a08 100644 --- a/Marlin/src/HAL/LINUX/HAL.cpp +++ b/Marlin/src/HAL/LINUX/HAL.cpp @@ -24,7 +24,7 @@ #include "../../inc/MarlinConfig.h" #include "../shared/Delay.h" -HalSerial usb_serial; +MSerialT usb_serial(TERN0(EMERGENCY_PARSER, true)); // U8glib required functions extern "C" { diff --git a/Marlin/src/HAL/LINUX/HAL.h b/Marlin/src/HAL/LINUX/HAL.h index 729f6c856e..e4f4dd3fc3 100644 --- a/Marlin/src/HAL/LINUX/HAL.h +++ b/Marlin/src/HAL/LINUX/HAL.h @@ -60,7 +60,7 @@ uint8_t _getc(); #define SHARED_SERVOS HAS_SERVOS -extern HalSerial usb_serial; +extern MSerialT usb_serial; #define MYSERIAL0 usb_serial #define ST7920_DELAY_1 DELAY_NS(600) @@ -113,8 +113,3 @@ inline void HAL_reboot() {} // reboot the board or restart the bootloader FORCE_INLINE static void DELAY_CYCLES(uint64_t x) { Clock::delayCycles(x); } - -// Add strcmp_P if missing -#ifndef strcmp_P - #define strcmp_P(a, b) strcmp((a), (b)) -#endif diff --git a/Marlin/src/HAL/LINUX/include/Arduino.h b/Marlin/src/HAL/LINUX/include/Arduino.h index 6aeb0db583..d4086e259a 100644 --- a/Marlin/src/HAL/LINUX/include/Arduino.h +++ b/Marlin/src/HAL/LINUX/include/Arduino.h @@ -73,27 +73,6 @@ extern "C" { void GpioDisableInt(uint32_t port, uint32_t pin); } -// Program Memory -#define pgm_read_ptr(addr) (*((void**)(addr))) -#define pgm_read_byte_near(addr) (*((uint8_t*)(addr))) -#define pgm_read_float_near(addr) (*((float*)(addr))) -#define pgm_read_word_near(addr) (*((uint16_t*)(addr))) -#define pgm_read_dword_near(addr) (*((uint32_t*)(addr))) -#define pgm_read_byte(addr) pgm_read_byte_near(addr) -#define pgm_read_float(addr) pgm_read_float_near(addr) -#define pgm_read_word(addr) pgm_read_word_near(addr) -#define pgm_read_dword(addr) pgm_read_dword_near(addr) - -using std::memcpy; -#define memcpy_P memcpy -#define sprintf_P sprintf -#define strstr_P strstr -#define strncpy_P strncpy -#define vsnprintf_P vsnprintf -#define strcpy_P strcpy -#define snprintf_P snprintf -#define strlen_P strlen - // Time functions extern "C" void delay(const int milis); void _delay_ms(const int delay); diff --git a/Marlin/src/HAL/LINUX/include/serial.h b/Marlin/src/HAL/LINUX/include/serial.h index e916249389..2585be25bf 100644 --- a/Marlin/src/HAL/LINUX/include/serial.h +++ b/Marlin/src/HAL/LINUX/include/serial.h @@ -25,6 +25,7 @@ #if ENABLED(EMERGENCY_PARSER) #include "../../../feature/e_parser.h" #endif +#include "../../../core/serial_hook.h" #include #include @@ -73,19 +74,11 @@ private: volatile uint32_t index_read; }; -class HalSerial { -public: - - #if ENABLED(EMERGENCY_PARSER) - EmergencyParser::State emergency_state; - static inline bool emergency_parser_enabled() { return true; } - #endif - +struct HalSerial { HalSerial() { host_connected = true; } void begin(int32_t) {} - - void end() {} + void end() {} int peek() { uint8_t value; @@ -100,7 +93,7 @@ public: return transmit_buffer.write(c); } - operator bool() { return host_connected; } + bool connected() { return host_connected; } uint16_t available() { return (uint16_t)receive_buffer.available(); @@ -117,92 +110,9 @@ public: while (transmit_buffer.available()) { /* nada */ } } - void printf(const char *format, ...) { - static char buffer[256]; - va_list vArgs; - va_start(vArgs, format); - int length = vsnprintf((char *) buffer, 256, (char const *) format, vArgs); - va_end(vArgs); - if (length > 0 && length < 256) { - if (host_connected) { - for (int i = 0; i < length;) { - if (transmit_buffer.write(buffer[i])) { - ++i; - } - } - } - } - } - - #define DEC 10 - #define HEX 16 - #define OCT 8 - #define BIN 2 - - void print_bin(uint32_t value, uint8_t num_digits) { - uint32_t mask = 1 << (num_digits -1); - for (uint8_t i = 0; i < num_digits; i++) { - if (!(i % 4) && i) write(' '); - if (!(i % 16) && i) write(' '); - if (value & mask) write('1'); - else write('0'); - value <<= 1; - } - } - - void print(const char value[]) { printf("%s" , value); } - void print(char value, int nbase = 0) { - if (nbase == BIN) print_bin(value, 8); - else if (nbase == OCT) printf("%3o", value); - else if (nbase == HEX) printf("%2X", value); - else if (nbase == DEC ) printf("%d", value); - else printf("%c" , value); - } - void print(unsigned char value, int nbase = 0) { - if (nbase == BIN) print_bin(value, 8); - else if (nbase == OCT) printf("%3o", value); - else if (nbase == HEX) printf("%2X", value); - else printf("%u" , value); - } - void print(int value, int nbase = 0) { - if (nbase == BIN) print_bin(value, 16); - else if (nbase == OCT) printf("%6o", value); - else if (nbase == HEX) printf("%4X", value); - else printf("%d", value); - } - void print(unsigned int value, int nbase = 0) { - if (nbase == BIN) print_bin(value, 16); - else if (nbase == OCT) printf("%6o", value); - else if (nbase == HEX) printf("%4X", value); - else printf("%u" , value); - } - void print(long value, int nbase = 0) { - if (nbase == BIN) print_bin(value, 32); - else if (nbase == OCT) printf("%11o", value); - else if (nbase == HEX) printf("%8X", value); - else printf("%ld" , value); - } - void print(unsigned long value, int nbase = 0) { - if (nbase == BIN) print_bin(value, 32); - else if (nbase == OCT) printf("%11o", value); - else if (nbase == HEX) printf("%8X", value); - else printf("%lu" , value); - } - void print(float value, int round = 6) { printf("%f" , value); } - void print(double value, int round = 6) { printf("%f" , value); } - - void println(const char value[]) { printf("%s\n" , value); } - void println(char value, int nbase = 0) { print(value, nbase); println(); } - void println(unsigned char value, int nbase = 0) { print(value, nbase); println(); } - void println(int value, int nbase = 0) { print(value, nbase); println(); } - void println(unsigned int value, int nbase = 0) { print(value, nbase); println(); } - void println(long value, int nbase = 0) { print(value, nbase); println(); } - void println(unsigned long value, int nbase = 0) { print(value, nbase); println(); } - void println(float value, int round = 6) { printf("%f\n" , value); } - void println(double value, int round = 6) { printf("%f\n" , value); } - void println() { print('\n'); } - volatile RingBuffer receive_buffer; volatile RingBuffer transmit_buffer; volatile bool host_connected; }; + +typedef Serial0Type MSerialT; diff --git a/Marlin/src/HAL/LINUX/main.cpp b/Marlin/src/HAL/LINUX/main.cpp index eadc409324..c409a83e5d 100644 --- a/Marlin/src/HAL/LINUX/main.cpp +++ b/Marlin/src/HAL/LINUX/main.cpp @@ -1,6 +1,5 @@ /** * Marlin 3D Printer Firmware - * * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] * * This program is free software: you can redistribute it and/or modify diff --git a/Marlin/src/HAL/LPC1768/HAL.cpp b/Marlin/src/HAL/LPC1768/HAL.cpp index 3614e95385..27aa569fae 100644 --- a/Marlin/src/HAL/LPC1768/HAL.cpp +++ b/Marlin/src/HAL/LPC1768/HAL.cpp @@ -29,6 +29,8 @@ #include "watchdog.h" #endif +DefaultSerial USBSerial(false, UsbSerial); + uint32_t HAL_adc_reading = 0; // U8glib required functions diff --git a/Marlin/src/HAL/LPC1768/HAL.h b/Marlin/src/HAL/LPC1768/HAL.h index 44a4e88624..1dc4fe6ff9 100644 --- a/Marlin/src/HAL/LPC1768/HAL.h +++ b/Marlin/src/HAL/LPC1768/HAL.h @@ -60,12 +60,15 @@ extern "C" volatile uint32_t _millis; #define ST7920_DELAY_3 DELAY_NS(750) #endif +typedef ForwardSerial0Type< decltype(UsbSerial) > DefaultSerial; +extern DefaultSerial USBSerial; + #define _MSERIAL(X) MSerial##X #define MSERIAL(X) _MSERIAL(X) #define MSerial0 MSerial #if SERIAL_PORT == -1 - #define MYSERIAL0 UsbSerial + #define MYSERIAL0 USBSerial #elif WITHIN(SERIAL_PORT, 0, 3) #define MYSERIAL0 MSERIAL(SERIAL_PORT) #else @@ -74,7 +77,7 @@ extern "C" volatile uint32_t _millis; #ifdef SERIAL_PORT_2 #if SERIAL_PORT_2 == -1 - #define MYSERIAL1 UsbSerial + #define MYSERIAL1 USBSerial #elif WITHIN(SERIAL_PORT_2, 0, 3) #define MYSERIAL1 MSERIAL(SERIAL_PORT_2) #else @@ -84,7 +87,7 @@ extern "C" volatile uint32_t _millis; #ifdef MMU2_SERIAL_PORT #if MMU2_SERIAL_PORT == -1 - #define MMU2_SERIAL UsbSerial + #define MMU2_SERIAL USBSerial #elif WITHIN(MMU2_SERIAL_PORT, 0, 3) #define MMU2_SERIAL MSERIAL(MMU2_SERIAL_PORT) #else @@ -94,7 +97,7 @@ extern "C" volatile uint32_t _millis; #ifdef LCD_SERIAL_PORT #if LCD_SERIAL_PORT == -1 - #define LCD_SERIAL UsbSerial + #define LCD_SERIAL USBSerial #elif WITHIN(LCD_SERIAL_PORT, 0, 3) #define LCD_SERIAL MSERIAL(LCD_SERIAL_PORT) #else @@ -214,16 +217,3 @@ void HAL_clear_reset_source(void); uint8_t HAL_get_reset_source(void); inline void HAL_reboot() {} // reboot the board or restart the bootloader - -// Add strcmp_P if missing -#ifndef strcmp_P - #define strcmp_P(a, b) strcmp((a), (b)) -#endif - -#ifndef strcat_P - #define strcat_P(a, b) strcat((a), (b)) -#endif - -#ifndef strcpy_P - #define strcpy_P(a, b) strcpy((a), (b)) -#endif diff --git a/Marlin/src/HAL/LPC1768/MarlinSerial.cpp b/Marlin/src/HAL/LPC1768/MarlinSerial.cpp index baad3f8f26..454ace33b2 100644 --- a/Marlin/src/HAL/LPC1768/MarlinSerial.cpp +++ b/Marlin/src/HAL/LPC1768/MarlinSerial.cpp @@ -25,19 +25,19 @@ #include "MarlinSerial.h" #if USING_SERIAL_0 - MarlinSerial MSerial(LPC_UART0); + MSerialT MSerial(true, LPC_UART0); extern "C" void UART0_IRQHandler() { MSerial.IRQHandler(); } #endif #if USING_SERIAL_1 - MarlinSerial MSerial1((LPC_UART_TypeDef *) LPC_UART1); + MSerialT MSerial1(true, (LPC_UART_TypeDef *) LPC_UART1); extern "C" void UART1_IRQHandler() { MSerial1.IRQHandler(); } #endif #if USING_SERIAL_2 - MarlinSerial MSerial2(LPC_UART2); + MSerialT MSerial2(true, LPC_UART2); extern "C" void UART2_IRQHandler() { MSerial2.IRQHandler(); } #endif #if USING_SERIAL_3 - MarlinSerial MSerial3(LPC_UART3); + MSerialT MSerial3(true, LPC_UART3); extern "C" void UART3_IRQHandler() { MSerial3.IRQHandler(); } #endif diff --git a/Marlin/src/HAL/LPC1768/MarlinSerial.h b/Marlin/src/HAL/LPC1768/MarlinSerial.h index 8d6b64378a..de0f62f006 100644 --- a/Marlin/src/HAL/LPC1768/MarlinSerial.h +++ b/Marlin/src/HAL/LPC1768/MarlinSerial.h @@ -28,6 +28,7 @@ #if ENABLED(EMERGENCY_PARSER) #include "../../feature/e_parser.h" #endif +#include "../../core/serial_hook.h" #ifndef SERIAL_PORT #define SERIAL_PORT 0 @@ -41,27 +42,20 @@ class MarlinSerial : public HardwareSerial { public: - MarlinSerial(LPC_UART_TypeDef *UARTx) : - HardwareSerial(UARTx) - #if ENABLED(EMERGENCY_PARSER) - , emergency_state(EmergencyParser::State::EP_RESET) - #endif - { } + MarlinSerial(LPC_UART_TypeDef *UARTx) : HardwareSerial(UARTx) { } void end() {} #if ENABLED(EMERGENCY_PARSER) bool recv_callback(const char c) override { - emergency_parser.update(emergency_state, c); + emergency_parser.update(static_cast *>(this)->emergency_state, c); return true; // do not discard character } - - EmergencyParser::State emergency_state; - static inline bool emergency_parser_enabled() { return true; } #endif }; -extern MarlinSerial MSerial; -extern MarlinSerial MSerial1; -extern MarlinSerial MSerial2; -extern MarlinSerial MSerial3; +typedef Serial0Type MSerialT; +extern MSerialT MSerial; +extern MSerialT MSerial1; +extern MSerialT MSerial2; +extern MSerialT MSerial3; diff --git a/Marlin/src/HAL/LPC1768/inc/Conditionals_post.h b/Marlin/src/HAL/LPC1768/inc/Conditionals_post.h index ce6d3fdde2..94e4ce1341 100644 --- a/Marlin/src/HAL/LPC1768/inc/Conditionals_post.h +++ b/Marlin/src/HAL/LPC1768/inc/Conditionals_post.h @@ -26,3 +26,10 @@ #elif EITHER(I2C_EEPROM, SPI_EEPROM) #define USE_SHARED_EEPROM 1 #endif + +// LPC1768 boards seem to lose steps when saving to EEPROM during print (issue #20785) +// TODO: Which other boards are incompatible? +#if defined(MCU_LPC1768) && PRINTCOUNTER_SAVE_INTERVAL > 0 + #warning "To prevent step loss, motion will pause for PRINTCOUNTER auto-save." + #define PRINTCOUNTER_SYNC 1 +#endif diff --git a/Marlin/src/HAL/SAMD51/HAL.cpp b/Marlin/src/HAL/SAMD51/HAL.cpp index d985ef3787..a413c4cd80 100644 --- a/Marlin/src/HAL/SAMD51/HAL.cpp +++ b/Marlin/src/HAL/SAMD51/HAL.cpp @@ -24,6 +24,11 @@ #include #include +#ifdef ADAFRUIT_GRAND_CENTRAL_M4 + DefaultSerial MSerial(false, Serial); + DefaultSerial1 MSerial1(false, Serial1); +#endif + // ------------------------ // Local defines // ------------------------ diff --git a/Marlin/src/HAL/SAMD51/HAL.h b/Marlin/src/HAL/SAMD51/HAL.h index fd2eb59475..f28583c771 100644 --- a/Marlin/src/HAL/SAMD51/HAL.h +++ b/Marlin/src/HAL/SAMD51/HAL.h @@ -32,15 +32,19 @@ #include "MarlinSerial_AGCM4.h" // Serial ports + typedef ForwardSerial0Type< decltype(Serial) > DefaultSerial; + extern DefaultSerial MSerial; + typedef ForwardSerial0Type< decltype(Serial1) > DefaultSerial1; + extern DefaultSerial1 MSerial1; // MYSERIAL0 required before MarlinSerial includes! - #define __MSERIAL(X) Serial##X + #define __MSERIAL(X) MSerial##X #define _MSERIAL(X) __MSERIAL(X) #define MSERIAL(X) _MSERIAL(INCREMENT(X)) #if SERIAL_PORT == -1 - #define MYSERIAL0 Serial + #define MYSERIAL0 MSerial #elif WITHIN(SERIAL_PORT, 0, 3) #define MYSERIAL0 MSERIAL(SERIAL_PORT) #else @@ -49,7 +53,7 @@ #ifdef SERIAL_PORT_2 #if SERIAL_PORT_2 == -1 - #define MYSERIAL1 Serial + #define MYSERIAL1 MSerial #elif WITHIN(SERIAL_PORT_2, 0, 3) #define MYSERIAL1 MSERIAL(SERIAL_PORT_2) #else @@ -59,7 +63,7 @@ #ifdef MMU2_SERIAL_PORT #if MMU2_SERIAL_PORT == -1 - #define MMU2_SERIAL Serial + #define MMU2_SERIAL MSerial #elif WITHIN(MMU2_SERIAL_PORT, 0, 3) #define MMU2_SERIAL MSERIAL(MMU2_SERIAL_PORT) #else @@ -69,7 +73,7 @@ #ifdef LCD_SERIAL_PORT #if LCD_SERIAL_PORT == -1 - #define LCD_SERIAL Serial + #define LCD_SERIAL MSerial #elif WITHIN(LCD_SERIAL_PORT, 0, 3) #define LCD_SERIAL MSERIAL(LCD_SERIAL_PORT) #else diff --git a/Marlin/src/HAL/SAMD51/MarlinSerial_AGCM4.cpp b/Marlin/src/HAL/SAMD51/MarlinSerial_AGCM4.cpp index fac67cf5a3..ce32eafee5 100644 --- a/Marlin/src/HAL/SAMD51/MarlinSerial_AGCM4.cpp +++ b/Marlin/src/HAL/SAMD51/MarlinSerial_AGCM4.cpp @@ -28,7 +28,7 @@ #include "../../inc/MarlinConfig.h" #if USING_SERIAL_1 - Uart Serial2(&sercom4, PIN_SERIAL2_RX, PIN_SERIAL2_TX, PAD_SERIAL2_RX, PAD_SERIAL2_TX); + UartT Serial2(false, &sercom4, PIN_SERIAL2_RX, PIN_SERIAL2_TX, PAD_SERIAL2_RX, PAD_SERIAL2_TX); void SERCOM4_0_Handler() { Serial2.IrqHandler(); } void SERCOM4_1_Handler() { Serial2.IrqHandler(); } void SERCOM4_2_Handler() { Serial2.IrqHandler(); } @@ -36,7 +36,7 @@ #endif #if USING_SERIAL_2 - Uart Serial3(&sercom1, PIN_SERIAL3_RX, PIN_SERIAL3_TX, PAD_SERIAL3_RX, PAD_SERIAL3_TX); + UartT Serial3(false, &sercom1, PIN_SERIAL3_RX, PIN_SERIAL3_TX, PAD_SERIAL3_RX, PAD_SERIAL3_TX); void SERCOM1_0_Handler() { Serial3.IrqHandler(); } void SERCOM1_1_Handler() { Serial3.IrqHandler(); } void SERCOM1_2_Handler() { Serial3.IrqHandler(); } @@ -44,7 +44,7 @@ #endif #if USING_SERIAL_3 - Uart Serial4(&sercom5, PIN_SERIAL4_RX, PIN_SERIAL4_TX, PAD_SERIAL4_RX, PAD_SERIAL4_TX); + UartT Serial4(false, &sercom5, PIN_SERIAL4_RX, PIN_SERIAL4_TX, PAD_SERIAL4_RX, PAD_SERIAL4_TX); void SERCOM5_0_Handler() { Serial4.IrqHandler(); } void SERCOM5_1_Handler() { Serial4.IrqHandler(); } void SERCOM5_2_Handler() { Serial4.IrqHandler(); } diff --git a/Marlin/src/HAL/SAMD51/MarlinSerial_AGCM4.h b/Marlin/src/HAL/SAMD51/MarlinSerial_AGCM4.h index f3821d8d5a..b7293415d1 100644 --- a/Marlin/src/HAL/SAMD51/MarlinSerial_AGCM4.h +++ b/Marlin/src/HAL/SAMD51/MarlinSerial_AGCM4.h @@ -20,6 +20,10 @@ */ #pragma once -extern Uart Serial2; -extern Uart Serial3; -extern Uart Serial4; +#include "../../core/serial_hook.h" + +typedef Serial0Type UartT; + +extern UartT Serial2; +extern UartT Serial3; +extern UartT Serial4; diff --git a/Marlin/src/HAL/STM32/HAL.cpp b/Marlin/src/HAL/STM32/HAL.cpp index c886f9c0b9..b8db5b5e0b 100644 --- a/Marlin/src/HAL/STM32/HAL.cpp +++ b/Marlin/src/HAL/STM32/HAL.cpp @@ -28,6 +28,10 @@ #include "../../inc/MarlinConfig.h" #include "../shared/Delay.h" +#ifdef USBCON + DefaultSerial MSerial(false, SerialUSB); +#endif + #if ENABLED(SRAM_EEPROM_EMULATION) #if STM32F7xx #include diff --git a/Marlin/src/HAL/STM32/HAL.h b/Marlin/src/HAL/STM32/HAL.h index 1c6f7743b8..baac7aad3e 100644 --- a/Marlin/src/HAL/STM32/HAL.h +++ b/Marlin/src/HAL/STM32/HAL.h @@ -39,6 +39,9 @@ #ifdef USBCON #include + #include "../../core/serial_hook.h" + typedef ForwardSerial0Type< decltype(SerialUSB) > DefaultSerial; + extern DefaultSerial MSerial; #endif // ------------------------ @@ -48,7 +51,7 @@ #define MSERIAL(X) _MSERIAL(X) #if SERIAL_PORT == -1 - #define MYSERIAL0 SerialUSB + #define MYSERIAL0 MSerial #elif WITHIN(SERIAL_PORT, 1, 6) #define MYSERIAL0 MSERIAL(SERIAL_PORT) #else @@ -57,7 +60,7 @@ #ifdef SERIAL_PORT_2 #if SERIAL_PORT_2 == -1 - #define MYSERIAL1 SerialUSB + #define MYSERIAL1 MSerial #elif WITHIN(SERIAL_PORT_2, 1, 6) #define MYSERIAL1 MSERIAL(SERIAL_PORT_2) #else @@ -67,7 +70,7 @@ #ifdef MMU2_SERIAL_PORT #if MMU2_SERIAL_PORT == -1 - #define MMU2_SERIAL SerialUSB + #define MMU2_SERIAL MSerial #elif WITHIN(MMU2_SERIAL_PORT, 1, 6) #define MMU2_SERIAL MSERIAL(MMU2_SERIAL_PORT) #else @@ -77,7 +80,7 @@ #ifdef LCD_SERIAL_PORT #if LCD_SERIAL_PORT == -1 - #define LCD_SERIAL SerialUSB + #define LCD_SERIAL MSerial #elif WITHIN(LCD_SERIAL_PORT, 1, 6) #define LCD_SERIAL MSERIAL(LCD_SERIAL_PORT) #else @@ -106,14 +109,6 @@ // On AVR this is in math.h? #define square(x) ((x)*(x)) -#ifndef strncpy_P - #define strncpy_P(dest, src, num) strncpy((dest), (src), (num)) -#endif - -// Fix bug in pgm_read_ptr -#undef pgm_read_ptr -#define pgm_read_ptr(addr) (*(addr)) - // ------------------------ // Types // ------------------------ diff --git a/Marlin/src/HAL/STM32/MarlinSerial.cpp b/Marlin/src/HAL/STM32/MarlinSerial.cpp index 4d9177248a..c420ce40cf 100644 --- a/Marlin/src/HAL/STM32/MarlinSerial.cpp +++ b/Marlin/src/HAL/STM32/MarlinSerial.cpp @@ -35,7 +35,7 @@ #define DECLARE_SERIAL_PORT(ser_num) \ void _rx_complete_irq_ ## ser_num (serial_t * obj); \ - MarlinSerial MSerial ## ser_num (USART ## ser_num, &_rx_complete_irq_ ## ser_num); \ + MSerialT MSerial ## ser_num (true, USART ## ser_num, &_rx_complete_irq_ ## ser_num); \ void _rx_complete_irq_ ## ser_num (serial_t * obj) { MSerial ## ser_num ._rx_complete_irq(obj); } #define DECLARE_SERIAL_PORT_EXP(ser_num) DECLARE_SERIAL_PORT(ser_num) diff --git a/Marlin/src/HAL/STM32/MarlinSerial.h b/Marlin/src/HAL/STM32/MarlinSerial.h index 3611cc78d7..8cc4f0dd4c 100644 --- a/Marlin/src/HAL/STM32/MarlinSerial.h +++ b/Marlin/src/HAL/STM32/MarlinSerial.h @@ -24,21 +24,15 @@ #include "../../feature/e_parser.h" #endif +#include "../../core/serial_hook.h" + typedef void (*usart_rx_callback_t)(serial_t * obj); -class MarlinSerial : public HardwareSerial { -public: +struct MarlinSerial : public HardwareSerial { MarlinSerial(void* peripheral, usart_rx_callback_t rx_callback) : HardwareSerial(peripheral), _rx_callback(rx_callback) - #if ENABLED(EMERGENCY_PARSER) - , emergency_state(EmergencyParser::State::EP_RESET) - #endif { } - #if ENABLED(EMERGENCY_PARSER) - static inline bool emergency_parser_enabled() { return true; } - #endif - void begin(unsigned long baud, uint8_t config); inline void begin(unsigned long baud) { begin(baud, SERIAL_8N1); } @@ -46,19 +40,17 @@ public: protected: usart_rx_callback_t _rx_callback; - #if ENABLED(EMERGENCY_PARSER) - EmergencyParser::State emergency_state; - #endif }; -extern MarlinSerial MSerial1; -extern MarlinSerial MSerial2; -extern MarlinSerial MSerial3; -extern MarlinSerial MSerial4; -extern MarlinSerial MSerial5; -extern MarlinSerial MSerial6; -extern MarlinSerial MSerial7; -extern MarlinSerial MSerial8; -extern MarlinSerial MSerial9; -extern MarlinSerial MSerial10; -extern MarlinSerial MSerialLP1; +typedef Serial0Type MSerialT; +extern MSerialT MSerial1; +extern MSerialT MSerial2; +extern MSerialT MSerial3; +extern MSerialT MSerial4; +extern MSerialT MSerial5; +extern MSerialT MSerial6; +extern MSerialT MSerial7; +extern MSerialT MSerial8; +extern MSerialT MSerial9; +extern MSerialT MSerial10; +extern MSerialT MSerialLP1; diff --git a/Marlin/src/HAL/STM32/eeprom_flash.cpp b/Marlin/src/HAL/STM32/eeprom_flash.cpp index 8cd62879a5..633a286dc8 100644 --- a/Marlin/src/HAL/STM32/eeprom_flash.cpp +++ b/Marlin/src/HAL/STM32/eeprom_flash.cpp @@ -61,7 +61,9 @@ #define FLASH_UNIT_SIZE 0x20000 // 128kB #endif - #define FLASH_ADDRESS_START (FLASH_END - ((FLASH_SECTOR_TOTAL - (FLASH_SECTOR)) * (FLASH_UNIT_SIZE)) + 1) + #ifndef FLASH_ADDRESS_START + #define FLASH_ADDRESS_START (FLASH_END - ((FLASH_SECTOR_TOTAL - (FLASH_SECTOR)) * (FLASH_UNIT_SIZE)) + 1) + #endif #define FLASH_ADDRESS_END (FLASH_ADDRESS_START + FLASH_UNIT_SIZE - 1) #define EEPROM_SLOTS ((FLASH_UNIT_SIZE) / (MARLIN_EEPROM_SIZE)) diff --git a/Marlin/src/HAL/STM32F1/HAL.cpp b/Marlin/src/HAL/STM32F1/HAL.cpp index dfa99d83f4..c1e29a843c 100644 --- a/Marlin/src/HAL/STM32F1/HAL.cpp +++ b/Marlin/src/HAL/STM32F1/HAL.cpp @@ -84,6 +84,7 @@ #if defined(SERIAL_USB) && !HAS_SD_HOST_DRIVE USBSerial SerialUSB; + DefaultSerial MSerial(false, SerialUSB); #endif uint16_t HAL_adc_result; diff --git a/Marlin/src/HAL/STM32F1/HAL.h b/Marlin/src/HAL/STM32F1/HAL.h index 26f321bfed..162c428fad 100644 --- a/Marlin/src/HAL/STM32F1/HAL.h +++ b/Marlin/src/HAL/STM32F1/HAL.h @@ -61,8 +61,11 @@ #endif #ifdef SERIAL_USB + typedef ForwardSerial0Type< USBSerial > DefaultSerial; + extern DefaultSerial MSerial; + #if !HAS_SD_HOST_DRIVE - #define UsbSerial Serial + #define UsbSerial MSerial #else #define UsbSerial MarlinCompositeSerial #endif @@ -152,14 +155,6 @@ void HAL_idletask(); // On AVR this is in math.h? #define square(x) ((x)*(x)) -#ifndef strncpy_P - #define strncpy_P(dest, src, num) strncpy((dest), (src), (num)) -#endif - -// Fix bug in pgm_read_ptr -#undef pgm_read_ptr -#define pgm_read_ptr(addr) (*(addr)) - #define RST_POWER_ON 1 #define RST_EXTERNAL 2 #define RST_BROWN_OUT 4 diff --git a/Marlin/src/HAL/STM32F1/MarlinSerial.cpp b/Marlin/src/HAL/STM32F1/MarlinSerial.cpp index 7c9625d64c..c404e81b35 100644 --- a/Marlin/src/HAL/STM32F1/MarlinSerial.cpp +++ b/Marlin/src/HAL/STM32F1/MarlinSerial.cpp @@ -28,7 +28,7 @@ // Copied from ~/.platformio/packages/framework-arduinoststm32-maple/STM32F1/system/libmaple/usart_private.h // Changed to handle Emergency Parser -static inline __always_inline void my_usart_irq(ring_buffer *rb, ring_buffer *wb, usart_reg_map *regs, MarlinSerial &serial) { +static inline __always_inline void my_usart_irq(ring_buffer *rb, ring_buffer *wb, usart_reg_map *regs, MSerialT &serial) { /* Handle RXNEIE and TXEIE interrupts. * RXNE signifies availability of a byte in DR. * @@ -90,20 +90,20 @@ constexpr bool serial_handles_emergency(int port) { ; } -#define DEFINE_HWSERIAL_MARLIN(name, n) \ - MarlinSerial name(USART##n, \ - BOARD_USART##n##_TX_PIN, \ - BOARD_USART##n##_RX_PIN, \ - serial_handles_emergency(n)); \ - extern "C" void __irq_usart##n(void) { \ +#define DEFINE_HWSERIAL_MARLIN(name, n) \ + MSerialT name(serial_handles_emergency(n),\ + USART##n, \ + BOARD_USART##n##_TX_PIN, \ + BOARD_USART##n##_RX_PIN); \ + extern "C" void __irq_usart##n(void) { \ my_usart_irq(USART##n->rb, USART##n->wb, USART##n##_BASE, MSerial##n); \ } #define DEFINE_HWSERIAL_UART_MARLIN(name, n) \ - MarlinSerial name(UART##n, \ + MSerialT name(serial_handles_emergency(n), \ + UART##n, \ BOARD_USART##n##_TX_PIN, \ - BOARD_USART##n##_RX_PIN, \ - serial_handles_emergency(n)); \ + BOARD_USART##n##_RX_PIN); \ extern "C" void __irq_usart##n(void) { \ my_usart_irq(UART##n->rb, UART##n->wb, UART##n##_BASE, MSerial##n); \ } diff --git a/Marlin/src/HAL/STM32F1/MarlinSerial.h b/Marlin/src/HAL/STM32F1/MarlinSerial.h index 6aa94b64ff..692e97e618 100644 --- a/Marlin/src/HAL/STM32F1/MarlinSerial.h +++ b/Marlin/src/HAL/STM32F1/MarlinSerial.h @@ -26,28 +26,13 @@ #include #include "../../inc/MarlinConfigPre.h" -#if ENABLED(EMERGENCY_PARSER) - #include "../../feature/e_parser.h" -#endif +#include "../../core/serial_hook.h" // Increase priority of serial interrupts, to reduce overflow errors #define UART_IRQ_PRIO 1 -class MarlinSerial : public HardwareSerial { -public: - #if ENABLED(EMERGENCY_PARSER) - const bool ep_enabled; - EmergencyParser::State emergency_state; - inline bool emergency_parser_enabled() { return ep_enabled; } - #endif - - MarlinSerial(struct usart_dev *usart_device, uint8 tx_pin, uint8 rx_pin, bool TERN_(EMERGENCY_PARSER, ep_capable)) : - HardwareSerial(usart_device, tx_pin, rx_pin) - #if ENABLED(EMERGENCY_PARSER) - , ep_enabled(ep_capable) - , emergency_state(EmergencyParser::State::EP_RESET) - #endif - { } +struct MarlinSerial : public HardwareSerial { + MarlinSerial(struct usart_dev *usart_device, uint8 tx_pin, uint8 rx_pin) : HardwareSerial(usart_device, tx_pin, rx_pin) { } #ifdef UART_IRQ_PRIO // Shadow the parent methods to set IRQ priority after begin() @@ -62,10 +47,12 @@ public: #endif }; -extern MarlinSerial MSerial1; -extern MarlinSerial MSerial2; -extern MarlinSerial MSerial3; +typedef Serial0Type MSerialT; + +extern MSerialT MSerial1; +extern MSerialT MSerial2; +extern MSerialT MSerial3; #if EITHER(STM32_HIGH_DENSITY, STM32_XL_DENSITY) - extern MarlinSerial MSerial4; - extern MarlinSerial MSerial5; + extern MSerialT MSerial4; + extern MSerialT MSerial5; #endif diff --git a/Marlin/src/HAL/STM32F1/eeprom_wired.cpp b/Marlin/src/HAL/STM32F1/eeprom_wired.cpp index 6e992a22a3..16cfc24af6 100644 --- a/Marlin/src/HAL/STM32F1/eeprom_wired.cpp +++ b/Marlin/src/HAL/STM32F1/eeprom_wired.cpp @@ -1,6 +1,5 @@ /** * Marlin 3D Printer Firmware - * * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] * * This program is free software: you can redistribute it and/or modify diff --git a/Marlin/src/HAL/STM32F1/msc_sd.cpp b/Marlin/src/HAL/STM32F1/msc_sd.cpp index ba722b8aeb..548a6dbc57 100644 --- a/Marlin/src/HAL/STM32F1/msc_sd.cpp +++ b/Marlin/src/HAL/STM32F1/msc_sd.cpp @@ -23,7 +23,7 @@ #define PRODUCT_ID 0x29 USBMassStorage MarlinMSC; -MarlinUSBCompositeSerial MarlinCompositeSerial; +Serial0Type MarlinCompositeSerial(true); #include "../../inc/MarlinConfig.h" diff --git a/Marlin/src/HAL/STM32F1/msc_sd.h b/Marlin/src/HAL/STM32F1/msc_sd.h index 1e4e4c44b1..151287f7a7 100644 --- a/Marlin/src/HAL/STM32F1/msc_sd.h +++ b/Marlin/src/HAL/STM32F1/msc_sd.h @@ -18,25 +18,9 @@ #include #include "../../inc/MarlinConfigPre.h" -#if ENABLED(EMERGENCY_PARSER) - #include "../../feature/e_parser.h" -#endif - -class MarlinUSBCompositeSerial : public USBCompositeSerial { -public: - MarlinUSBCompositeSerial() : USBCompositeSerial() - #if ENABLED(EMERGENCY_PARSER) - , emergency_state(EmergencyParser::State::EP_RESET) - #endif - { } - - #if ENABLED(EMERGENCY_PARSER) - EmergencyParser::State emergency_state; - inline bool emergency_parser_enabled() { return true; } - #endif -}; +#include "../../core/serial_hook.h" extern USBMassStorage MarlinMSC; -extern MarlinUSBCompositeSerial MarlinCompositeSerial; +extern Serial0Type MarlinCompositeSerial; void MSC_SD_init(); diff --git a/Marlin/src/HAL/TEENSY31_32/HAL.cpp b/Marlin/src/HAL/TEENSY31_32/HAL.cpp index 8c3dd83377..51636d29bf 100644 --- a/Marlin/src/HAL/TEENSY31_32/HAL.cpp +++ b/Marlin/src/HAL/TEENSY31_32/HAL.cpp @@ -31,6 +31,9 @@ #include +DefaultSerial MSerial(false); +USBSerialType USBSerial(false, SerialUSB); + uint16_t HAL_adc_result; static const uint8_t pin2sc1a[] = { diff --git a/Marlin/src/HAL/TEENSY31_32/HAL.h b/Marlin/src/HAL/TEENSY31_32/HAL.h index 9156aadb4d..5273b38637 100644 --- a/Marlin/src/HAL/TEENSY31_32/HAL.h +++ b/Marlin/src/HAL/TEENSY31_32/HAL.h @@ -50,12 +50,18 @@ #define IS_TEENSY32 1 #endif -#define _MSERIAL(X) Serial##X +#include "../../core/serial_hook.h" +typedef Serial0Type DefaultSerial; +extern DefaultSerial MSerial; +typedef ForwardSerial0Type USBSerialType; +extern USBSerialType USBSerial; + +#define _MSERIAL(X) MSerial##X #define MSERIAL(X) _MSERIAL(X) -#define Serial0 Serial +#define MSerial0 MSerial #if SERIAL_PORT == -1 - #define MYSERIAL0 SerialUSB + #define MYSERIAL0 USBSerial #elif WITHIN(SERIAL_PORT, 0, 3) #define MYSERIAL0 MSERIAL(SERIAL_PORT) #endif @@ -74,17 +80,6 @@ typedef int8_t pin_t; #define ENABLE_ISRS() __enable_irq() #define DISABLE_ISRS() __disable_irq() -#ifndef strncpy_P - #define strncpy_P(dest, src, num) strncpy((dest), (src), (num)) -#endif - -// Fix bug in pgm_read_ptr -#undef pgm_read_ptr -#define pgm_read_ptr(addr) (*((void**)(addr))) -// Add type-checking to pgm_read_word -#undef pgm_read_word -#define pgm_read_word(addr) (*((uint16_t*)(addr))) - inline void HAL_init() {} // Clear the reset reason diff --git a/Marlin/src/HAL/TEENSY35_36/HAL.cpp b/Marlin/src/HAL/TEENSY35_36/HAL.cpp index 92907353b8..547681de5f 100644 --- a/Marlin/src/HAL/TEENSY35_36/HAL.cpp +++ b/Marlin/src/HAL/TEENSY35_36/HAL.cpp @@ -31,6 +31,9 @@ #include +DefaultSerial MSerial(false); +USBSerialType USBSerial(false, SerialUSB); + uint16_t HAL_adc_result, HAL_adc_select; static const uint8_t pin2sc1a[] = { diff --git a/Marlin/src/HAL/TEENSY35_36/HAL.h b/Marlin/src/HAL/TEENSY35_36/HAL.h index 04151e8378..94c514bf62 100644 --- a/Marlin/src/HAL/TEENSY35_36/HAL.h +++ b/Marlin/src/HAL/TEENSY35_36/HAL.h @@ -53,12 +53,18 @@ #define IS_TEENSY35 1 #endif -#define _MSERIAL(X) Serial##X +#include "../../core/serial_hook.h" +typedef Serial0Type DefaultSerial; +extern DefaultSerial MSerial; +typedef ForwardSerial0Type USBSerialType; +extern USBSerialType USBSerial; + +#define _MSERIAL(X) MSerial##X #define MSERIAL(X) _MSERIAL(X) -#define Serial0 Serial +#define MSerial0 MSerial #if SERIAL_PORT == -1 - #define MYSERIAL0 SerialUSB + #define MYSERIAL0 USBSerial #elif WITHIN(SERIAL_PORT, 0, 3) #define MYSERIAL0 MSERIAL(SERIAL_PORT) #endif @@ -80,17 +86,6 @@ typedef int8_t pin_t; #undef sq #define sq(x) ((x)*(x)) -#ifndef strncpy_P - #define strncpy_P(dest, src, num) strncpy((dest), (src), (num)) -#endif - -// Fix bug in pgm_read_ptr -#undef pgm_read_ptr -#define pgm_read_ptr(addr) (*((void**)(addr))) -// Add type-checking to pgm_read_word -#undef pgm_read_word -#define pgm_read_word(addr) (*((uint16_t*)(addr))) - inline void HAL_init() {} // Clear reset reason diff --git a/Marlin/src/HAL/TEENSY40_41/HAL.cpp b/Marlin/src/HAL/TEENSY40_41/HAL.cpp index 5b1b4272f5..26449d7eb2 100644 --- a/Marlin/src/HAL/TEENSY40_41/HAL.cpp +++ b/Marlin/src/HAL/TEENSY40_41/HAL.cpp @@ -32,6 +32,9 @@ #include +DefaultSerial MSerial(false); +USBSerialType USBSerial(false, SerialUSB); + uint16_t HAL_adc_result, HAL_adc_select; static const uint8_t pin2sc1a[] = { diff --git a/Marlin/src/HAL/TEENSY40_41/HAL.h b/Marlin/src/HAL/TEENSY40_41/HAL.h index 28f511631e..6aa1e521a4 100644 --- a/Marlin/src/HAL/TEENSY40_41/HAL.h +++ b/Marlin/src/HAL/TEENSY40_41/HAL.h @@ -37,6 +37,10 @@ #include #include +#if HAS_ETHERNET + #include "../../feature/ethernet.h" +#endif + //#define ST7920_DELAY_1 DELAY_NS(600) //#define ST7920_DELAY_2 DELAY_NS(750) //#define ST7920_DELAY_3 DELAY_NS(750) @@ -51,9 +55,15 @@ #define IS_TEENSY41 1 #endif -#define _MSERIAL(X) Serial##X +#include "../../core/serial_hook.h" +typedef Serial0Type DefaultSerial; +extern DefaultSerial MSerial; +typedef ForwardSerial0Type USBSerialType; +extern USBSerialType USBSerial; + +#define _MSERIAL(X) MSerial##X #define MSERIAL(X) _MSERIAL(X) -#define Serial0 Serial +#define MSerial0 MSerial #if SERIAL_PORT == -1 #define MYSERIAL0 SerialUSB @@ -92,21 +102,10 @@ typedef int8_t pin_t; #undef sq #define sq(x) ((x)*(x)) -#ifndef strncpy_P - #define strncpy_P(dest, src, num) strncpy((dest), (src), (num)) -#endif - // Don't place string constants in PROGMEM #undef PSTR #define PSTR(str) ({static const char *data = (str); &data[0];}) -// Fix bug in pgm_read_ptr -#undef pgm_read_ptr -#define pgm_read_ptr(addr) (*((void**)(addr))) -// Add type-checking to pgm_read_word -#undef pgm_read_word -#define pgm_read_word(addr) (*((uint16_t*)(addr))) - // Enable hooks into idle and setup for HAL #define HAL_IDLETASK 1 FORCE_INLINE void HAL_idletask() {} diff --git a/Marlin/src/HAL/shared/Marduino.h b/Marlin/src/HAL/shared/Marduino.h index 2580723511..d0ee6ecc9d 100644 --- a/Marlin/src/HAL/shared/Marduino.h +++ b/Marlin/src/HAL/shared/Marduino.h @@ -81,3 +81,5 @@ #ifndef UNUSED #define UNUSED(x) ((void)(x)) #endif + +#include "progmem.h" diff --git a/Marlin/src/HAL/shared/progmem.h b/Marlin/src/HAL/shared/progmem.h new file mode 100644 index 0000000000..539d02705e --- /dev/null +++ b/Marlin/src/HAL/shared/progmem.h @@ -0,0 +1,189 @@ +/** + * 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 + +#ifndef __AVR__ +#ifndef __PGMSPACE_H_ +// This define should prevent reading the system pgmspace.h if included elsewhere +// This is not normally needed. +#define __PGMSPACE_H_ 1 +#endif + +#ifndef PROGMEM +#define PROGMEM +#endif +#ifndef PGM_P +#define PGM_P const char * +#endif +#ifndef PSTR +#define PSTR(str) (str) +#endif +#ifndef F +#define F(str) (str) +#endif +#ifndef _SFR_BYTE +#define _SFR_BYTE(n) (n) +#endif +#ifndef memchr_P +#define memchr_P(str, c, len) memchr((str), (c), (len)) +#endif +#ifndef memcmp_P +#define memcmp_P(a, b, n) memcmp((a), (b), (n)) +#endif +#ifndef memcpy_P +#define memcpy_P(dest, src, num) memcpy((dest), (src), (num)) +#endif +#ifndef memmem_P +#define memmem_P(a, alen, b, blen) memmem((a), (alen), (b), (blen)) +#endif +#ifndef memrchr_P +#define memrchr_P(str, val, len) memrchr((str), (val), (len)) +#endif +#ifndef strcat_P +#define strcat_P(dest, src) strcat((dest), (src)) +#endif +#ifndef strchr_P +#define strchr_P(str, c) strchr((str), (c)) +#endif +#ifndef strchrnul_P +#define strchrnul_P(str, c) strchrnul((str), (c)) +#endif +#ifndef strcmp_P +#define strcmp_P(a, b) strcmp((a), (b)) +#endif +#ifndef strcpy_P +#define strcpy_P(dest, src) strcpy((dest), (src)) +#endif +#ifndef strcasecmp_P +#define strcasecmp_P(a, b) strcasecmp((a), (b)) +#endif +#ifndef strcasestr_P +#define strcasestr_P(a, b) strcasestr((a), (b)) +#endif +#ifndef strlcat_P +#define strlcat_P(dest, src, len) strlcat((dest), (src), (len)) +#endif +#ifndef strlcpy_P +#define strlcpy_P(dest, src, len) strlcpy((dest), (src), (len)) +#endif +#ifndef strlen_P +#define strlen_P(s) strlen((const char *)(s)) +#endif +#ifndef strnlen_P +#define strnlen_P(str, len) strnlen((str), (len)) +#endif +#ifndef strncmp_P +#define strncmp_P(a, b, n) strncmp((a), (b), (n)) +#endif +#ifndef strncasecmp_P +#define strncasecmp_P(a, b, n) strncasecmp((a), (b), (n)) +#endif +#ifndef strncat_P +#define strncat_P(a, b, n) strncat((a), (b), (n)) +#endif +#ifndef strncpy_P +#define strncpy_P(a, b, n) strncpy((a), (b), (n)) +#endif +#ifndef strpbrk_P +#define strpbrk_P(str, chrs) strpbrk((str), (chrs)) +#endif +#ifndef strrchr_P +#define strrchr_P(str, c) strrchr((str), (c)) +#endif +#ifndef strsep_P +#define strsep_P(strp, delim) strsep((strp), (delim)) +#endif +#ifndef strspn_P +#define strspn_P(str, chrs) strspn((str), (chrs)) +#endif +#ifndef strstr_P +#define strstr_P(a, b) strstr((a), (b)) +#endif +#ifndef sprintf_P +#define sprintf_P(s, ...) sprintf((s), __VA_ARGS__) +#endif +#ifndef vfprintf_P +#define vfprintf_P(s, ...) vfprintf((s), __VA_ARGS__) +#endif +#ifndef printf_P +#define printf_P(...) printf(__VA_ARGS__) +#endif +#ifndef snprintf_P +#define snprintf_P(s, n, ...) snprintf((s), (n), __VA_ARGS__) +#endif +#ifndef vsprintf_P +#define vsprintf_P(s, ...) vsprintf((s),__VA_ARGS__) +#endif +#ifndef vsnprintf_P +#define vsnprintf_P(s, n, ...) vsnprintf((s), (n),__VA_ARGS__) +#endif +#ifndef fprintf_P +#define fprintf_P(s, ...) fprintf((s), __VA_ARGS__) +#endif + +#ifndef pgm_read_byte +#define pgm_read_byte(addr) (*(const unsigned char *)(addr)) +#endif +#ifndef pgm_read_word +#define pgm_read_word(addr) (*(const unsigned short *)(addr)) +#endif +#ifndef pgm_read_dword +#define pgm_read_dword(addr) (*(const unsigned long *)(addr)) +#endif +#ifndef pgm_read_float +#define pgm_read_float(addr) (*(const float *)(addr)) +#endif + +#ifndef pgm_read_byte_near +#define pgm_read_byte_near(addr) pgm_read_byte(addr) +#endif +#ifndef pgm_read_word_near +#define pgm_read_word_near(addr) pgm_read_word(addr) +#endif +#ifndef pgm_read_dword_near +#define pgm_read_dword_near(addr) pgm_read_dword(addr) +#endif +#ifndef pgm_read_float_near +#define pgm_read_float_near(addr) pgm_read_float(addr) +#endif +#ifndef pgm_read_byte_far +#define pgm_read_byte_far(addr) pgm_read_byte(addr) +#endif +#ifndef pgm_read_word_far +#define pgm_read_word_far(addr) pgm_read_word(addr) +#endif +#ifndef pgm_read_dword_far +#define pgm_read_dword_far(addr) pgm_read_dword(addr) +#endif +#ifndef pgm_read_float_far +#define pgm_read_float_far(addr) pgm_read_float(addr) +#endif + +#ifndef pgm_read_pointer +#define pgm_read_pointer +#endif + +// Fix bug in pgm_read_ptr +#undef pgm_read_ptr +#define pgm_read_ptr(addr) (*((void**)(addr))) + +#endif // __AVR__ diff --git a/Marlin/src/MarlinCore.cpp b/Marlin/src/MarlinCore.cpp index f994e2e32c..51e0efafd6 100644 --- a/Marlin/src/MarlinCore.cpp +++ b/Marlin/src/MarlinCore.cpp @@ -43,6 +43,7 @@ #include #include "core/utility.h" + #include "module/motion.h" #include "module/planner.h" #include "module/endstops.h" @@ -57,6 +58,7 @@ #include "gcode/parser.h" #include "gcode/queue.h" +#include "feature/pause.h" #include "sd/cardreader.h" #include "lcd/marlinui.h" @@ -139,7 +141,6 @@ #if ENABLED(EXPERIMENTAL_I2CBUS) #include "feature/twibus.h" - TWIBus i2c; #endif #if ENABLED(I2C_POSITION_ENCODERS) @@ -173,10 +174,6 @@ #include "feature/bedlevel/bedlevel.h" #endif -#if BOTH(ADVANCED_PAUSE_FEATURE, PAUSE_PARK_NO_STEPPER_TIMEOUT) - #include "feature/pause.h" -#endif - #if ENABLED(GCODE_REPEAT_MARKERS) #include "feature/repeat.h" #endif @@ -233,18 +230,7 @@ #include "feature/password/password.h" #endif -PGMSTR(NUL_STR, ""); PGMSTR(M112_KILL_STR, "M112 Shutdown"); -PGMSTR(G28_STR, "G28"); -PGMSTR(M21_STR, "M21"); -PGMSTR(M23_STR, "M23 %s"); -PGMSTR(M24_STR, "M24"); -PGMSTR(SP_P_STR, " P"); PGMSTR(SP_T_STR, " T"); -PGMSTR(X_STR, "X"); PGMSTR(Y_STR, "Y"); PGMSTR(Z_STR, "Z"); PGMSTR(E_STR, "E"); -PGMSTR(X_LBL, "X:"); PGMSTR(Y_LBL, "Y:"); PGMSTR(Z_LBL, "Z:"); PGMSTR(E_LBL, "E:"); -PGMSTR(SP_A_STR, " A"); PGMSTR(SP_B_STR, " B"); PGMSTR(SP_C_STR, " C"); -PGMSTR(SP_X_STR, " X"); PGMSTR(SP_Y_STR, " Y"); PGMSTR(SP_Z_STR, " Z"); PGMSTR(SP_E_STR, " E"); -PGMSTR(SP_X_LBL, " X:"); PGMSTR(SP_Y_LBL, " Y:"); PGMSTR(SP_Z_LBL, " Z:"); PGMSTR(SP_E_LBL, " E:"); MarlinState marlin_state = MF_INITIALIZING; @@ -267,40 +253,12 @@ bool wait_for_heatup = true; #endif -#if PIN_EXISTS(CHDK) - extern millis_t chdk_timeout; -#endif - -#if ENABLED(I2C_POSITION_ENCODERS) - I2CPositionEncodersMgr I2CPEM; -#endif - /** * *************************************************************************** * ******************************** FUNCTIONS ******************************** * *************************************************************************** */ -void setup_killpin() { - #if HAS_KILL - #if KILL_PIN_STATE - SET_INPUT_PULLDOWN(KILL_PIN); - #else - SET_INPUT_PULLUP(KILL_PIN); - #endif - #endif -} - -void setup_powerhold() { - #if HAS_SUICIDE - OUT_WRITE(SUICIDE_PIN, !SUICIDE_PIN_INVERTING); - #endif - #if ENABLED(PSU_CONTROL) - powersupply_on = ENABLED(PSU_DEFAULT_OFF); - if (ENABLED(PSU_DEFAULT_OFF)) PSU_OFF(); else PSU_ON(); - #endif -} - /** * Stepper Reset (RigidBoard, et.al.) */ @@ -309,18 +267,6 @@ void setup_powerhold() { void enableStepperDrivers() { SET_INPUT(STEPPER_RESET_PIN); } // Set to input, allowing pullups to pull the pin high #endif -#if ENABLED(EXPERIMENTAL_I2CBUS) && I2C_SLAVE_ADDRESS > 0 - - void i2c_on_receive(int bytes) { // just echo all bytes received to serial - i2c.receive(bytes); - } - - void i2c_on_request() { // just send dummy data for now - i2c.reply("Hello World!\n"); - } - -#endif - /** * Sensitive pin test for M42, M226 */ @@ -342,17 +288,6 @@ bool pin_is_protected(const pin_t pin) { #pragma GCC diagnostic pop -void protected_pin_err() { - SERIAL_ERROR_MSG(STR_ERR_PROTECTED_PIN); -} - -void quickstop_stepper() { - planner.quick_stop(); - planner.synchronize(); - set_current_from_steppers_for_axis(ALL_AXES); - sync_plan_position(); -} - void enable_e_steppers() { #define _ENA_E(N) ENABLE_AXIS_E##N(); REPEAT(E_STEPPERS, _ENA_E) @@ -389,41 +324,6 @@ void disable_all_steppers() { TERN_(EXTENSIBLE_UI, ExtUI::onSteppersDisabled()); } -#if ENABLED(G29_RETRY_AND_RECOVER) - - void event_probe_failure() { - #ifdef ACTION_ON_G29_FAILURE - host_action(PSTR(ACTION_ON_G29_FAILURE)); - #endif - #ifdef G29_FAILURE_COMMANDS - gcode.process_subcommands_now_P(PSTR(G29_FAILURE_COMMANDS)); - #endif - #if ENABLED(G29_HALT_ON_FAILURE) - #ifdef ACTION_ON_CANCEL - host_action_cancel(); - #endif - kill(GET_TEXT(MSG_LCD_PROBING_FAILED)); - #endif - } - - void event_probe_recover() { - TERN_(HOST_PROMPT_SUPPORT, host_prompt_do(PROMPT_INFO, PSTR("G29 Retrying"), DISMISS_STR)); - #ifdef ACTION_ON_G29_RECOVER - host_action(PSTR(ACTION_ON_G29_RECOVER)); - #endif - #ifdef G29_RECOVER_COMMANDS - gcode.process_subcommands_now_P(PSTR(G29_RECOVER_COMMANDS)); - #endif - } - -#endif - -#if ENABLED(ADVANCED_PAUSE_FEATURE) - #include "feature/pause.h" -#else - constexpr bool did_pause_print = false; -#endif - /** * A Print Job exists when the timer is running or SD printing */ @@ -462,19 +362,20 @@ void startOrResumeJob() { inline void abortSDPrinting() { IF_DISABLED(NO_SD_AUTOSTART, card.autofile_cancel()); card.endFilePrint(TERN_(SD_RESORT, true)); + queue.clear(); quickstop_stepper(); - print_job_timer.stop(); - #if DISABLED(SD_ABORT_NO_COOLDOWN) - thermalManager.disable_all_heaters(); - #endif - #if !HAS_CUTTER - thermalManager.zero_fan_speeds(); - #else - cutter.kill(); // Full cutter shutdown including ISR control - #endif + + print_job_timer.abort(); + + IF_DISABLED(SD_ABORT_NO_COOLDOWN, thermalManager.disable_all_heaters()); + + TERN(HAS_CUTTER, cutter.kill(), thermalManager.zero_fan_speeds()); // Full cutter shutdown including ISR control + wait_for_heatup = false; + TERN_(POWER_LOSS_RECOVERY, recovery.purge()); + #ifdef EVENT_GCODE_SD_ABORT queue.inject_P(PSTR(EVENT_GCODE_SD_ABORT)); #endif @@ -511,8 +412,8 @@ inline void manage_inactivity(const bool ignore_stepper_queue=false) { // Prevent steppers timing-out in the middle of M600 // unless PAUSE_PARK_NO_STEPPER_TIMEOUT is disabled - const bool parked_or_ignoring = ignore_stepper_queue || - (BOTH(ADVANCED_PAUSE_FEATURE, PAUSE_PARK_NO_STEPPER_TIMEOUT) && did_pause_print); + const bool parked_or_ignoring = ignore_stepper_queue + || TERN0(PAUSE_PARK_NO_STEPPER_TIMEOUT, did_pause_print); // Reset both the M18/M84 activity timeout and the M85 max 'kill' timeout if (parked_or_ignoring) gcode.reset_stepper_timeout(ms); @@ -550,6 +451,7 @@ inline void manage_inactivity(const bool ignore_stepper_queue=false) { } #if PIN_EXISTS(CHDK) // Check if pin should be set to LOW (after M240 set it HIGH) + extern millis_t chdk_timeout; if (chdk_timeout && ELAPSED(ms, chdk_timeout)) { chdk_timeout = 0; WRITE(CHDK_PIN, LOW); @@ -785,8 +687,8 @@ void idle(TERN_(ADVANCED_PAUSE_FEATURE, bool no_stepper_sleep/*=false*/)) { // Auto-report Temperatures / SD Status #if HAS_AUTO_REPORTING if (!gcode.autoreport_paused) { - TERN_(AUTO_REPORT_TEMPERATURES, thermalManager.auto_report_temperatures()); - TERN_(AUTO_REPORT_SD_STATUS, card.auto_report_sd_status()); + TERN_(AUTO_REPORT_TEMPERATURES, thermalManager.auto_reporter.tick()); + TERN_(AUTO_REPORT_SD_STATUS, card.auto_reporter.tick()); } #endif @@ -882,6 +784,7 @@ void minkill(const bool steppers_off/*=false*/) { */ void stop() { thermalManager.disable_all_heaters(); // 'unpause' taken care of in here + print_job_timer.stop(); #if ENABLED(PROBING_FANS_OFF) @@ -983,6 +886,27 @@ void setup() { #endif #define SETUP_RUN(C) do{ SETUP_LOG(STRINGIFY(C)); C; }while(0) + // Set up these pins early to prevent suicide + #if HAS_KILL + SETUP_LOG("KILL_PIN"); + #if KILL_PIN_STATE + SET_INPUT_PULLDOWN(KILL_PIN); + #else + SET_INPUT_PULLUP(KILL_PIN); + #endif + #endif + + #if HAS_SUICIDE + SETUP_LOG("SUICIDE_PIN"); + OUT_WRITE(SUICIDE_PIN, !SUICIDE_PIN_INVERTING); + #endif + + #if ENABLED(PSU_CONTROL) + SETUP_LOG("PSU_CONTROL"); + powersupply_on = ENABLED(PSU_DEFAULT_OFF); + if (ENABLED(PSU_DEFAULT_OFF)) PSU_OFF(); else PSU_ON(); + #endif + #if EITHER(DISABLE_DEBUG, DISABLE_JTAG) // Disable any hardware debug to free up pins for IO #if ENABLED(DISABLE_DEBUG) && defined(JTAGSWD_DISABLE) @@ -996,12 +920,12 @@ void setup() { MYSERIAL0.begin(BAUDRATE); millis_t serial_connect_timeout = millis() + 1000UL; - while (!MYSERIAL0 && PENDING(millis(), serial_connect_timeout)) { /*nada*/ } + while (!MYSERIAL0.connected() && PENDING(millis(), serial_connect_timeout)) { /*nada*/ } #if HAS_MULTI_SERIAL && !HAS_ETHERNET MYSERIAL1.begin(BAUDRATE); serial_connect_timeout = millis() + 1000UL; - while (!MYSERIAL1 && PENDING(millis(), serial_connect_timeout)) { /*nada*/ } + while (!MYSERIAL1.connected() && PENDING(millis(), serial_connect_timeout)) { /*nada*/ } #endif SERIAL_ECHOLNPGM("start"); @@ -1038,14 +962,10 @@ void setup() { SETUP_RUN(recovery.setup()); #endif - SETUP_RUN(setup_killpin()); - #if HAS_TMC220x SETUP_RUN(tmc_serial_begin()); #endif - SETUP_RUN(setup_powerhold()); - #if HAS_STEPPER_RESET SETUP_RUN(disableStepperDrivers()); #endif diff --git a/Marlin/src/MarlinCore.h b/Marlin/src/MarlinCore.h index 908636e967..d43d46bbd8 100644 --- a/Marlin/src/MarlinCore.h +++ b/Marlin/src/MarlinCore.h @@ -37,11 +37,6 @@ void stop(); void idle(TERN_(ADVANCED_PAUSE_FEATURE, bool no_stepper_sleep=false)); inline void idle_no_sleep() { idle(TERN_(ADVANCED_PAUSE_FEATURE, true)); } -#if ENABLED(EXPERIMENTAL_I2CBUS) - #include "feature/twibus.h" - extern TWIBus i2c; -#endif - #if ENABLED(G38_PROBE_TARGET) extern uint8_t G38_move; // Flag to tell the ISR that G38 is in progress, and the type extern bool G38_did_trigger; // Flag from the ISR to indicate the endstop changed @@ -59,8 +54,6 @@ void disable_all_steppers(); void kill(PGM_P const lcd_error=nullptr, PGM_P const lcd_component=nullptr, const bool steppers_off=false); void minkill(const bool steppers_off=false); -void quickstop_stepper(); - // Global State of the firmware enum MarlinState : uint8_t { MF_INITIALIZING = 0, @@ -103,7 +96,6 @@ extern bool wait_for_heatup; #endif bool pin_is_protected(const pin_t pin); -void protected_pin_err(); #if HAS_SUICIDE inline void suicide() { OUT_WRITE(SUICIDE_PIN, SUICIDE_PIN_INVERTING); } @@ -116,12 +108,4 @@ void protected_pin_err(); inline bool kill_state() { return READ(KILL_PIN) == KILL_PIN_STATE; } #endif -#if ENABLED(G29_RETRY_AND_RECOVER) - void event_probe_recover(); - void event_probe_failure(); -#endif - -extern const char NUL_STR[], M112_KILL_STR[], G28_STR[], M21_STR[], M23_STR[], M24_STR[], - SP_A_STR[], SP_B_STR[], SP_C_STR[], - SP_P_STR[], SP_T_STR[], SP_X_STR[], SP_Y_STR[], SP_Z_STR[], SP_E_STR[], - X_LBL[], Y_LBL[], Z_LBL[], E_LBL[], SP_X_LBL[], SP_Y_LBL[], SP_Z_LBL[], SP_E_LBL[]; +extern const char M112_KILL_STR[]; diff --git a/Marlin/src/core/boards.h b/Marlin/src/core/boards.h index 13a202daed..afb6887766 100644 --- a/Marlin/src/core/boards.h +++ b/Marlin/src/core/boards.h @@ -338,6 +338,7 @@ #define BOARD_FLY_MINI 4045 // FLY MINI (STM32F103RCT6) #define BOARD_FLSUN_HISPEED 4046 // FLSUN HiSpeedV1 (STM32F103VET6) #define BOARD_BEAST 4047 // STM32F103RET6 Libmaple-based controller +#define BOARD_MINGDA_MPX_ARM_MINI 4048 // STM32F103ZET6 Mingda MD-16 // // ARM Cortex-M4F @@ -373,6 +374,7 @@ #define BOARD_MKS_ROBIN_NANO_V3 4220 // MKS Robin Nano V3 (STM32F407VG) #define BOARD_ANET_ET4 4221 // ANET ET4 V1.x (STM32F407VGT6) #define BOARD_ANET_ET4P 4222 // ANET ET4P V1.x (STM32F407VGT6) +#define BOARD_FYSETC_CHEETAH_V20 4223 // FYSETC Cheetah V2.0 // // ARM Cortex M7 diff --git a/Marlin/src/core/language.h b/Marlin/src/core/language.h index d6048d293c..923ad903cb 100644 --- a/Marlin/src/core/language.h +++ b/Marlin/src/core/language.h @@ -68,6 +68,7 @@ // ro Romanian // ru Russian // sk Slovak +// sv Swedish // tr Turkish // uk Ukrainian // vi Vietnamese diff --git a/Marlin/src/core/macros.h b/Marlin/src/core/macros.h index d5b3342437..dcc688ae29 100644 --- a/Marlin/src/core/macros.h +++ b/Marlin/src/core/macros.h @@ -53,6 +53,7 @@ #define _FORCE_INLINE_ __attribute__((__always_inline__)) __inline__ #define FORCE_INLINE __attribute__((always_inline)) inline +#define NO_INLINE __attribute__((noinline)) #define _UNUSED __attribute__((unused)) #define _O0 __attribute__((optimize("O0"))) #define _Os __attribute__((optimize("Os"))) @@ -162,6 +163,7 @@ #define _DO_12(W,C,A,V...) (_##W##_1(A) C _DO_11(W,C,V)) #define _DO_13(W,C,A,V...) (_##W##_1(A) C _DO_12(W,C,V)) #define _DO_14(W,C,A,V...) (_##W##_1(A) C _DO_13(W,C,V)) +#define _DO_15(W,C,A,V...) (_##W##_1(A) C _DO_14(W,C,V)) #define __DO_N(W,C,N,V...) _DO_##N(W,C,V) #define _DO_N(W,C,N,V...) __DO_N(W,C,N,V) #define DO(W,C,V...) (_DO_N(W,C,NUM_ARGS(V),V)) @@ -313,6 +315,32 @@ #endif + // C++11 solution that is standard compliant. is not available on all platform + namespace Private { + template struct enable_if { }; + template struct enable_if { typedef _Tp type; }; + } + // C++11 solution using SFINAE to detect the existance of a member in a class at compile time. + // It creates a HasMember structure containing 'value' set to true if the member exists + #define HAS_MEMBER_IMPL(Member) \ + namespace Private { \ + template struct HasMember_ ## Member { \ + template static Yes& test( decltype(&C::Member) ) ; \ + template static No& test(...); \ + enum { value = sizeof(test(0)) == sizeof(Yes) }; }; \ + } + + // Call the method if it exists, but do nothing if it does not. The method is detected at compile time. + // If the method exists, this is inlined and does not cost anything. Else, an "empty" wrapper is created, returning a default value + #define CALL_IF_EXISTS_IMPL(Return, Method, ...) \ + HAS_MEMBER_IMPL(Method) \ + namespace Private { \ + template FORCE_INLINE typename enable_if::value, Return>::type Call_ ## Method(T * t, Args... a) { return static_cast(t->Method(a...)); } \ + _UNUSED static Return Call_ ## Method(...) { return __VA_ARGS__; } \ + } + #define CALL_IF_EXISTS(Return, That, Method, ...) \ + static_cast(Private::Call_ ## Method(That, ##__VA_ARGS__)) + #else #define MIN_2(a,b) ((a)<(b)?(a):(b)) diff --git a/Marlin/src/core/multi_language.h b/Marlin/src/core/multi_language.h index 6af4af2f8d..5a26edf8d4 100644 --- a/Marlin/src/core/multi_language.h +++ b/Marlin/src/core/multi_language.h @@ -20,6 +20,8 @@ ****************************************************************************/ #pragma once +#include "../inc/MarlinConfigPre.h" + typedef const char Language_Str[]; #ifdef LCD_LANGUAGE_5 @@ -57,26 +59,27 @@ typedef const char Language_Str[]; #define GET_LANG(LANG) _GET_LANG(LANG) #if NUM_LANGUAGES > 1 - extern uint8_t lang; + #define HAS_MULTI_LANGUAGE 1 #define GET_TEXT(MSG) ( \ - lang == 0 ? GET_LANG(LCD_LANGUAGE)::MSG : \ - lang == 1 ? GET_LANG(LCD_LANGUAGE_2)::MSG : \ - lang == 2 ? GET_LANG(LCD_LANGUAGE_3)::MSG : \ - lang == 3 ? GET_LANG(LCD_LANGUAGE_4)::MSG : \ - GET_LANG(LCD_LANGUAGE_5)::MSG \ - ) - #define MAX_LANG_CHARSIZE _MAX(GET_LANG(LCD_LANGUAGE)::CHARSIZE, \ - GET_LANG(LCD_LANGUAGE_2)::CHARSIZE, \ - GET_LANG(LCD_LANGUAGE_3)::CHARSIZE, \ - GET_LANG(LCD_LANGUAGE_4)::CHARSIZE, \ - GET_LANG(LCD_LANGUAGE_5)::CHARSIZE) + ui.language == 0 ? GET_LANG(LCD_LANGUAGE )::MSG : \ + ui.language == 1 ? GET_LANG(LCD_LANGUAGE_2)::MSG : \ + ui.language == 2 ? GET_LANG(LCD_LANGUAGE_3)::MSG : \ + ui.language == 3 ? GET_LANG(LCD_LANGUAGE_4)::MSG : \ + GET_LANG(LCD_LANGUAGE_5)::MSG ) + #define MAX_LANG_CHARSIZE _MAX(GET_LANG(LCD_LANGUAGE )::CHARSIZE, \ + GET_LANG(LCD_LANGUAGE_2)::CHARSIZE, \ + GET_LANG(LCD_LANGUAGE_3)::CHARSIZE, \ + GET_LANG(LCD_LANGUAGE_4)::CHARSIZE, \ + GET_LANG(LCD_LANGUAGE_5)::CHARSIZE ) #else #define GET_TEXT(MSG) GET_LANG(LCD_LANGUAGE)::MSG - #define MAX_LANG_CHARSIZE GET_LANG(LCD_LANGUAGE)::CHARSIZE + #define MAX_LANG_CHARSIZE LANG_CHARSIZE #endif #define GET_TEXT_F(MSG) (const __FlashStringHelper*)GET_TEXT(MSG) #define GET_LANGUAGE_NAME(INDEX) GET_LANG(LCD_LANGUAGE_##INDEX)::LANGUAGE +#define LANG_CHARSIZE GET_TEXT(CHARSIZE) +#define USE_WIDE_GLYPH (LANG_CHARSIZE > 2) #define MSG_1_LINE(A) A "\0" "\0" #define MSG_2_LINE(A,B) A "\0" B "\0" diff --git a/Marlin/src/core/serial.cpp b/Marlin/src/core/serial.cpp index 0d22f7bfc0..365f28ba55 100644 --- a/Marlin/src/core/serial.cpp +++ b/Marlin/src/core/serial.cpp @@ -23,20 +23,41 @@ #include "serial.h" #include "../inc/MarlinConfig.h" +#if HAS_ETHERNET + #include "../feature/ethernet.h" +#endif + uint8_t marlin_debug_flags = MARLIN_DEBUG_NONE; -static PGMSTR(errormagic, "Error:"); -static PGMSTR(echomagic, "echo:"); +// Commonly-used strings in serial output +PGMSTR(NUL_STR, ""); PGMSTR(SP_P_STR, " P"); PGMSTR(SP_T_STR, " T"); +PGMSTR(X_STR, "X"); PGMSTR(Y_STR, "Y"); PGMSTR(Z_STR, "Z"); PGMSTR(E_STR, "E"); +PGMSTR(X_LBL, "X:"); PGMSTR(Y_LBL, "Y:"); PGMSTR(Z_LBL, "Z:"); PGMSTR(E_LBL, "E:"); +PGMSTR(SP_A_STR, " A"); PGMSTR(SP_B_STR, " B"); PGMSTR(SP_C_STR, " C"); +PGMSTR(SP_X_STR, " X"); PGMSTR(SP_Y_STR, " Y"); PGMSTR(SP_Z_STR, " Z"); PGMSTR(SP_E_STR, " E"); +PGMSTR(SP_X_LBL, " X:"); PGMSTR(SP_Y_LBL, " Y:"); PGMSTR(SP_Z_LBL, " Z:"); PGMSTR(SP_E_LBL, " E:"); #if HAS_MULTI_SERIAL - int8_t serial_port_index = 0; + #ifdef SERIAL_CATCHALL + SerialOutputT multiSerial(MYSERIAL, SERIAL_CATCHALL); + #else + #if HAS_ETHERNET + // Runtime checking of the condition variable + ConditionalSerial serialOut1(ethernet.have_telnet_client, MYSERIAL1, false); // Takes reference here + #else + // Don't pay for runtime checking a true variable, instead use the output directly + #define serialOut1 MYSERIAL1 + #endif + SerialOutputT multiSerial(MYSERIAL0, serialOut1); + #endif #endif void serialprintPGM(PGM_P str) { while (const char c = pgm_read_byte(str++)) SERIAL_CHAR(c); } -void serial_echo_start() { serialprintPGM(echomagic); } -void serial_error_start() { serialprintPGM(errormagic); } + +void serial_echo_start() { static PGMSTR(echomagic, "echo:"); serialprintPGM(echomagic); } +void serial_error_start() { static PGMSTR(errormagic, "Error:"); serialprintPGM(errormagic); } void serial_echopair_PGM(PGM_P const s_P, const char *v) { serialprintPGM(s_P); SERIAL_ECHO(v); } void serial_echopair_PGM(PGM_P const s_P, char v) { serialprintPGM(s_P); SERIAL_CHAR(v); } @@ -65,8 +86,6 @@ void print_bin(uint16_t val) { } } -extern const char SP_X_STR[], SP_Y_STR[], SP_Z_STR[]; - void print_xyz(const float &x, const float &y, const float &z, PGM_P const prefix/*=nullptr*/, PGM_P const suffix/*=nullptr*/) { if (prefix) serialprintPGM(prefix); SERIAL_ECHOPAIR_P(SP_X_STR, x, SP_Y_STR, y, SP_Z_STR, z); diff --git a/Marlin/src/core/serial.h b/Marlin/src/core/serial.h index 4824866aeb..4c0c32f7d8 100644 --- a/Marlin/src/core/serial.h +++ b/Marlin/src/core/serial.h @@ -22,14 +22,19 @@ #pragma once #include "../inc/MarlinConfig.h" +#include "serial_hook.h" -#if HAS_ETHERNET - #include "../feature/ethernet.h" -#endif +// Commonly-used strings in serial output +extern const char NUL_STR[], SP_P_STR[], SP_T_STR[], + X_STR[], Y_STR[], Z_STR[], E_STR[], + X_LBL[], Y_LBL[], Z_LBL[], E_LBL[], + SP_A_STR[], SP_B_STR[], SP_C_STR[], + SP_X_STR[], SP_Y_STR[], SP_Z_STR[], SP_E_STR[], + SP_X_LBL[], SP_Y_LBL[], SP_Z_LBL[], SP_E_LBL[]; -/** - * Define debug bit-masks - */ +// +// Debugging flags for use by M111 +// enum MarlinDebugFlags : uint8_t { MARLIN_DEBUG_NONE = 0, MARLIN_DEBUG_ECHO = _BV(0), ///< Echo commands in order as they are processed @@ -50,39 +55,37 @@ enum MarlinDebugFlags : uint8_t { extern uint8_t marlin_debug_flags; #define DEBUGGING(F) (marlin_debug_flags & (MARLIN_DEBUG_## F)) -#define SERIAL_BOTH 0x7F +// +// Serial redirection +// +typedef int8_t serial_index_t; +#define SERIAL_ALL 0x7F #if HAS_MULTI_SERIAL - extern int8_t serial_port_index; - #define _PORT_REDIRECT(n,p) REMEMBER(n,serial_port_index,p) - #define _PORT_RESTORE(n) RESTORE(n) - + #define _PORT_REDIRECT(n,p) REMEMBER(n,multiSerial.portMask,p) + #define SERIAL_ASSERT(P) if(multiSerial.portMask!=(P)){ debugger(); } #ifdef SERIAL_CATCHALL - #define SERIAL_OUT(WHAT, V...) (void)CAT(MYSERIAL,SERIAL_CATCHALL).WHAT(V) + typedef MultiSerial SerialOutputT; #else - #define SERIAL_OUT(WHAT, V...) do{ \ - const bool port2_open = TERN1(HAS_ETHERNET, ethernet.have_telnet_client); \ - if ( serial_port_index == 0 || serial_port_index == SERIAL_BOTH) (void)MYSERIAL0.WHAT(V); \ - if ((serial_port_index == 1 || serial_port_index == SERIAL_BOTH) && port2_open) (void)MYSERIAL1.WHAT(V); \ - }while(0) + typedef MultiSerial, decltype(MYSERIAL1)), 0> SerialOutputT; #endif - - #define SERIAL_ASSERT(P) if(serial_port_index!=(P)){ debugger(); } + extern SerialOutputT multiSerial; + #define SERIAL_IMPL multiSerial #else #define _PORT_REDIRECT(n,p) NOOP - #define _PORT_RESTORE(n) NOOP - #define SERIAL_OUT(WHAT, V...) (void)MYSERIAL0.WHAT(V) #define SERIAL_ASSERT(P) NOOP + #define SERIAL_IMPL MYSERIAL0 #endif +#define SERIAL_OUT(WHAT, V...) (void)SERIAL_IMPL.WHAT(V) + #define PORT_REDIRECT(p) _PORT_REDIRECT(1,p) -#define PORT_RESTORE() _PORT_RESTORE(1) +#define SERIAL_PORTMASK(P) _BV(P) #define SERIAL_ECHO(x) SERIAL_OUT(print, x) #define SERIAL_ECHO_F(V...) SERIAL_OUT(print, V) #define SERIAL_ECHOLN(x) SERIAL_OUT(println, x) #define SERIAL_PRINT(x,b) SERIAL_OUT(print, x, b) #define SERIAL_PRINTLN(x,b) SERIAL_OUT(println, x, b) -#define SERIAL_PRINTF(V...) SERIAL_OUT(printf, V) #define SERIAL_FLUSH() SERIAL_OUT(flush) #ifdef ARDUINO_ARCH_STM32 diff --git a/Marlin/src/core/serial_base.h b/Marlin/src/core/serial_base.h new file mode 100644 index 0000000000..220ccae831 --- /dev/null +++ b/Marlin/src/core/serial_base.h @@ -0,0 +1,146 @@ +/** + * 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 + +#include "../inc/MarlinConfigPre.h" + +#if ENABLED(EMERGENCY_PARSER) + #include "../feature/e_parser.h" +#endif + +#ifndef DEC + #define DEC 10 + #define HEX 16 + #define OCT 8 + #define BIN 2 +#endif + +// flushTX is not implemented in all HAL, so use SFINAE to call the method where it is. +CALL_IF_EXISTS_IMPL(void, flushTX ); +CALL_IF_EXISTS_IMPL(bool, connected, true); + +// Using Curiously Recurring Template Pattern here to avoid virtual table cost when compiling. +// Since the real serial class is known at compile time, this results in compiler writing a completely +// efficient code +template +struct SerialBase { + #if ENABLED(EMERGENCY_PARSER) + const bool ep_enabled; + EmergencyParser::State emergency_state; + inline bool emergency_parser_enabled() { return ep_enabled; } + SerialBase(bool ep_capable) : ep_enabled(ep_capable), emergency_state(EmergencyParser::State::EP_RESET) {} + #else + SerialBase(const bool) {} + #endif + + // Static dispatch methods below: + // The most important method here is where it all ends to: + size_t write(uint8_t c) { return static_cast(this)->write(c); } + // Called when the parser finished processing an instruction, usually build to nothing + void msgDone() { static_cast(this)->msgDone(); } + // Called upon initialization + void begin(const long baudRate) { static_cast(this)->begin(baudRate); } + // Called upon destruction + void end() { static_cast(this)->end(); } + /** Check for available data from the port + @param index The port index, usually 0 */ + bool available(uint8_t index = 0) { return static_cast(this)->available(index); } + /** Read a value from the port + @param index The port index, usually 0 */ + int read(uint8_t index = 0) { return static_cast(this)->read(index); } + // Check if the serial port is connected (usually bypassed) + bool connected() { return static_cast(this)->connected(); } + // Redirect flush + void flush() { static_cast(this)->flush(); } + // Not all implementation have a flushTX, so let's call them only if the child has the implementation + void flushTX() { CALL_IF_EXISTS(void, static_cast(this), flushTX); } + + // Glue code here + FORCE_INLINE void write(const char* str) { while (*str) write(*str++); } + FORCE_INLINE void write(const uint8_t* buffer, size_t size) { while (size--) write(*buffer++); } + FORCE_INLINE void print(const char* str) { write(str); } + NO_INLINE void print(char c, int base = 0) { print((long)c, base); } + NO_INLINE void print(unsigned char c, int base = 0) { print((unsigned long)c, base); } + NO_INLINE void print(int c, int base = DEC) { print((long)c, base); } + NO_INLINE void print(unsigned int c, int base = DEC) { print((unsigned long)c, base); } + void print(long c, int base = DEC) { if (!base) write(c); write((const uint8_t*)"-", c < 0); printNumber(c < 0 ? -c : c, base); } + void print(unsigned long c, int base = DEC) { printNumber(c, base); } + void print(double c, int digits = 2) { printFloat(c, digits); } + + NO_INLINE void println(const char s[]) { print(s); println(); } + NO_INLINE void println(char c, int base = 0) { print(c, base); println(); } + NO_INLINE void println(unsigned char c, int base = 0) { print(c, base); println(); } + NO_INLINE void println(int c, int base = DEC) { print(c, base); println(); } + NO_INLINE void println(unsigned int c, int base = DEC) { print(c, base); println(); } + NO_INLINE void println(long c, int base = DEC) { print(c, base); println(); } + NO_INLINE void println(unsigned long c, int base = DEC) { print(c, base); println(); } + NO_INLINE void println(double c, int digits = 2) { print(c, digits); println(); } + NO_INLINE void println() { write('\r'); write('\n'); } + + // Print a number with the given base + void printNumber(unsigned long n, const uint8_t base) { + if (n) { + unsigned char buf[8 * sizeof(long)]; // Enough space for base 2 + int8_t i = 0; + while (n) { + buf[i++] = n % base; + n /= base; + } + while (i--) write((char)(buf[i] + (buf[i] < 10 ? '0' : 'A' - 10))); + } + else write('0'); + } + + // Print a decimal number + void printFloat(double number, uint8_t digits) { + // Handle negative numbers + if (number < 0.0) { + write('-'); + number = -number; + } + + // Round correctly so that print(1.999, 2) prints as "2.00" + double rounding = 0.5; + LOOP_L_N(i, digits) rounding *= 0.1; + number += rounding; + + // Extract the integer part of the number and print it + unsigned long int_part = (unsigned long)number; + double remainder = number - (double)int_part; + printNumber(int_part, 10); + + // Print the decimal point, but only if there are digits beyond + if (digits) { + write('.'); + // Extract digits from the remainder one at a time + while (digits--) { + remainder *= 10.0; + int toPrint = int(remainder); + printNumber(toPrint, 10); + remainder -= toPrint; + } + } + } +}; + +// All serial instances will be built by chaining the features required for the function in a form of a template +// type definition diff --git a/Marlin/src/core/serial_hook.h b/Marlin/src/core/serial_hook.h new file mode 100644 index 0000000000..e14b821a9c --- /dev/null +++ b/Marlin/src/core/serial_hook.h @@ -0,0 +1,234 @@ +/** + * 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 + +#include "serial_base.h" + +// The most basic serial class: it dispatch to the base serial class with no hook whatsoever. This will compile to nothing but the base serial class +template +struct BaseSerial : public SerialBase< BaseSerial >, public SerialT { + typedef SerialBase< BaseSerial > BaseClassT; + + // It's required to implement a write method here to help compiler disambiguate what method to call + using SerialT::write; + using SerialT::flush; + + void msgDone() {} + + bool available(uint8_t index) { return index == 0 && SerialT::available(); } + int read(uint8_t index) { return index == 0 ? SerialT::read() : -1; } + bool connected() { return CALL_IF_EXISTS(bool, static_cast(this), connected);; } + // We have 2 implementation of the same method in both base class, let's say which one we want + using SerialT::available; + using SerialT::read; + using SerialT::begin; + using SerialT::end; + + using BaseClassT::print; + using BaseClassT::println; + + BaseSerial(const bool e) : BaseClassT(e) {} + + // Forward constructor + template + BaseSerial(const bool e, Args... args) : BaseClassT(e), SerialT(args...) {} +}; + +// A serial with a condition checked at runtime for its output +// A bit less efficient than static dispatching but since it's only used for ethernet's serial output right now, it's ok. +template +struct ConditionalSerial : public SerialBase< ConditionalSerial > { + typedef SerialBase< ConditionalSerial > BaseClassT; + + bool & condition; + SerialT & out; + NO_INLINE size_t write(uint8_t c) { if (condition) return out.write(c); return 0; } + void flush() { if (condition) out.flush(); } + void begin(long br) { out.begin(br); } + void end() { out.end(); } + + void msgDone() {} + bool connected() { return CALL_IF_EXISTS(bool, &out, connected); } + + bool available(uint8_t index) { return index == 0 && out.available(); } + int read(uint8_t index) { return index == 0 ? out.read() : -1; } + using BaseClassT::available; + using BaseClassT::read; + + ConditionalSerial(bool & conditionVariable, SerialT & out, const bool e) : BaseClassT(e), condition(conditionVariable), out(out) {} +}; + +// A simple foward class that taking a reference to an existing serial instance (likely created in their respective framework) +template +struct ForwardSerial : public SerialBase< ForwardSerial > { + typedef SerialBase< ForwardSerial > BaseClassT; + + SerialT & out; + NO_INLINE size_t write(uint8_t c) { return out.write(c); } + void flush() { out.flush(); } + void begin(long br) { out.begin(br); } + void end() { out.end(); } + + void msgDone() {} + // Existing instances implement Arduino's operator bool, so use that if it's available + bool connected() { return Private::HasMember_connected::value ? CALL_IF_EXISTS(bool, &out, connected) : (bool)out; } + + bool available(uint8_t index) { return index == 0 && out.available(); } + int read(uint8_t index) { return index == 0 ? out.read() : -1; } + bool available() { return out.available(); } + int read() { return out.read(); } + + ForwardSerial(const bool e, SerialT & out) : BaseClassT(e), out(out) {} +}; + +// A class that's can be hooked and unhooked at runtime, useful to capturing the output of the serial interface +template +struct RuntimeSerial : public SerialBase< RuntimeSerial >, public SerialT { + typedef SerialBase< RuntimeSerial > BaseClassT; + typedef void (*WriteHook)(void * userPointer, uint8_t c); + typedef void (*EndOfMessageHook)(void * userPointer); + + WriteHook writeHook; + EndOfMessageHook eofHook; + void * userPointer; + + NO_INLINE size_t write(uint8_t c) { + if (writeHook) writeHook(userPointer, c); + return SerialT::write(c); + } + + NO_INLINE void msgDone() { + if (eofHook) eofHook(userPointer); + } + + bool available(uint8_t index) { return index == 0 && SerialT::available(); } + int read(uint8_t index) { return index == 0 ? SerialT::read() : -1; } + using SerialT::available; + using SerialT::read; + using SerialT::flush; + using SerialT::begin; + using SerialT::end; + + using BaseClassT::print; + using BaseClassT::println; + + // Underlying implementation might use Arduino's bool operator + bool connected() { + return Private::HasMember_connected::value ? CALL_IF_EXISTS(bool, static_cast(this), connected) : static_cast(this)->operator bool(); + } + + void setHook(WriteHook writeHook = 0, EndOfMessageHook eofHook = 0, void * userPointer = 0) { + // Order is important here as serial code can be called inside interrupts + // When setting a hook, the user pointer must be set first so if writeHook is called as soon as it's set, it'll be valid + if (userPointer) this->userPointer = userPointer; + this->writeHook = writeHook; + this->eofHook = eofHook; + // Order is important here because of asynchronous access here + // When unsetting a hook, the user pointer must be unset last so that any pending writeHook is still using the old pointer + if (!userPointer) this->userPointer = 0; + } + + RuntimeSerial(const bool e) : BaseClassT(e), writeHook(0), eofHook(0), userPointer(0) {} + + // Forward constructor + template + RuntimeSerial(const bool e, Args... args) : BaseClassT(e), SerialT(args...) {} +}; + +// A class that's duplicating its output conditionally to 2 serial interface +template +struct MultiSerial : public SerialBase< MultiSerial > { + typedef SerialBase< MultiSerial > BaseClassT; + + uint8_t portMask; + Serial0T & serial0; + Serial1T & serial1; + + enum Masks { + FirstOutputMask = (1 << offset), + SecondOutputMask = (1 << (offset + 1)), + AllMask = FirstOutputMask | SecondOutputMask, + }; + + NO_INLINE size_t write(uint8_t c) { + size_t ret = 0; + if (portMask & FirstOutputMask) ret = serial0.write(c); + if (portMask & SecondOutputMask) ret = serial1.write(c) | ret; + return ret; + } + NO_INLINE void msgDone() { + if (portMask & FirstOutputMask) serial0.msgDone(); + if (portMask & SecondOutputMask) serial1.msgDone(); + } + bool available(uint8_t index) { + switch(index) { + case 0 + offset: return serial0.available(); + case 1 + offset: return serial1.available(); + default: return false; + } + } + NO_INLINE int read(uint8_t index) { + switch(index) { + case 0 + offset: return serial0.read(); + case 1 + offset: return serial1.read(); + default: return -1; + } + } + void begin(const long br) { + if (portMask & FirstOutputMask) serial0.begin(br); + if (portMask & SecondOutputMask) serial1.begin(br); + } + void end() { + if (portMask & FirstOutputMask) serial0.end(); + if (portMask & SecondOutputMask) serial1.end(); + } + bool connected() { + bool ret = true; + if (portMask & FirstOutputMask) ret = CALL_IF_EXISTS(bool, &serial0, connected); + if (portMask & SecondOutputMask) ret = ret && CALL_IF_EXISTS(bool, &serial1, connected); + return ret; + } + + using BaseClassT::available; + using BaseClassT::read; + + // Redirect flush + NO_INLINE void flush() { + if (portMask & FirstOutputMask) serial0.flush(); + if (portMask & SecondOutputMask) serial1.flush(); + } + NO_INLINE void flushTX() { + if (portMask & FirstOutputMask) CALL_IF_EXISTS(void, &serial0, flushTX); + if (portMask & SecondOutputMask) CALL_IF_EXISTS(void, &serial1, flushTX); + } + + MultiSerial(Serial0T & serial0, Serial1T & serial1, int8_t mask = AllMask, const bool e = false) : + BaseClassT(e), + portMask(mask), serial0(serial0), serial1(serial1) {} +}; + +// Build the actual serial object depending on current configuration +#define Serial0Type TERN(SERIAL_RUNTIME_HOOK, RuntimeSerial, BaseSerial) +#define ForwardSerial0Type TERN(SERIAL_RUNTIME_HOOK, RuntimeSerial, ForwardSerial) +#ifdef HAS_MULTI_SERIAL + #define Serial1Type ConditionalSerial +#endif diff --git a/Marlin/src/feature/binary_stream.h b/Marlin/src/feature/binary_stream.h index 32ebcce2f6..81d6e7184b 100644 --- a/Marlin/src/feature/binary_stream.h +++ b/Marlin/src/feature/binary_stream.h @@ -30,23 +30,11 @@ #endif inline bool bs_serial_data_available(const uint8_t index) { - switch (index) { - case 0: return MYSERIAL0.available(); - #if HAS_MULTI_SERIAL - case 1: return MYSERIAL1.available(); - #endif - } - return false; + return SERIAL_IMPL.available(index); } inline int bs_read_serial(const uint8_t index) { - switch (index) { - case 0: return MYSERIAL0.read(); - #if HAS_MULTI_SERIAL - case 1: return MYSERIAL1.read(); - #endif - } - return -1; + return SERIAL_IMPL.read(index); } #if ENABLED(BINARY_STREAM_COMPRESSION) @@ -297,7 +285,7 @@ public: millis_t transfer_window = millis() + RX_TIMESLICE; #if ENABLED(SDSUPPORT) - PORT_REDIRECT(card.transfer_port_index); + PORT_REDIRECT(SERIAL_PORTMASK(card.transfer_port_index)); #endif #pragma GCC diagnostic push diff --git a/Marlin/src/feature/e_parser.h b/Marlin/src/feature/e_parser.h index a4c07de465..659e516787 100644 --- a/Marlin/src/feature/e_parser.h +++ b/Marlin/src/feature/e_parser.h @@ -33,7 +33,6 @@ // External references extern bool wait_for_user, wait_for_heatup; -void quickstop_stepper(); class EmergencyParser { diff --git a/Marlin/src/feature/encoder_i2c.cpp b/Marlin/src/feature/encoder_i2c.cpp index dda165edf7..fa3cf1503f 100644 --- a/Marlin/src/feature/encoder_i2c.cpp +++ b/Marlin/src/feature/encoder_i2c.cpp @@ -41,6 +41,8 @@ #include +I2CPositionEncodersMgr I2CPEM; + void I2CPositionEncoder::init(const uint8_t address, const AxisEnum axis) { encoderAxis = axis; i2cAddress = address; diff --git a/Marlin/src/feature/host_actions.cpp b/Marlin/src/feature/host_actions.cpp index a8b2b51dfc..5ba3a3e3d2 100644 --- a/Marlin/src/feature/host_actions.cpp +++ b/Marlin/src/feature/host_actions.cpp @@ -38,7 +38,7 @@ #endif void host_action(PGM_P const pstr, const bool eol) { - PORT_REDIRECT(SERIAL_BOTH); + PORT_REDIRECT(SERIAL_ALL); SERIAL_ECHOPGM("//action:"); serialprintPGM(pstr); if (eol) SERIAL_EOL(); @@ -78,20 +78,20 @@ void host_action(PGM_P const pstr, const bool eol) { PromptReason host_prompt_reason = PROMPT_NOT_DEFINED; void host_action_notify(const char * const message) { - PORT_REDIRECT(SERIAL_BOTH); + PORT_REDIRECT(SERIAL_ALL); host_action(PSTR("notification "), false); SERIAL_ECHOLN(message); } void host_action_notify_P(PGM_P const message) { - PORT_REDIRECT(SERIAL_BOTH); + PORT_REDIRECT(SERIAL_ALL); host_action(PSTR("notification "), false); serialprintPGM(message); SERIAL_EOL(); } void host_action_prompt(PGM_P const ptype, const bool eol=true) { - PORT_REDIRECT(SERIAL_BOTH); + PORT_REDIRECT(SERIAL_ALL); host_action(PSTR("prompt_"), false); serialprintPGM(ptype); if (eol) SERIAL_EOL(); @@ -99,7 +99,7 @@ void host_action(PGM_P const pstr, const bool eol) { void host_action_prompt_plus(PGM_P const ptype, PGM_P const pstr, const char extra_char='\0') { host_action_prompt(ptype, false); - PORT_REDIRECT(SERIAL_BOTH); + PORT_REDIRECT(SERIAL_ALL); SERIAL_CHAR(' '); serialprintPGM(pstr); if (extra_char != '\0') SERIAL_CHAR(extra_char); diff --git a/Marlin/src/feature/meatpack.cpp b/Marlin/src/feature/meatpack.cpp new file mode 100644 index 0000000000..cd6d8ce6b9 --- /dev/null +++ b/Marlin/src/feature/meatpack.cpp @@ -0,0 +1,228 @@ +/** + * 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 . + * + */ + +/** + * MeatPack G-code Compression + * + * Algorithm & Implementation: Scott Mudge - mail@scottmudge.com + * Date: Dec. 2020 + * + * Character Frequencies from ~30 MB of comment-stripped gcode: + * '1' -> 4451136 '4' -> 1353273 '\n' -> 1087683 '-' -> 90242 + * '0' -> 4253577 '9' -> 1352147 'G' -> 1075806 'Z' -> 34109 + * ' ' -> 3053297 '3' -> 1262929 'X' -> 975742 'M' -> 11879 + * '.' -> 3035310 '5' -> 1189871 'E' -> 965275 'S' -> 9910 + * '2' -> 1523296 '6' -> 1127900 'Y' -> 965274 + * '8' -> 1366812 '7' -> 1112908 'F' -> 99416 + * + * When space is omitted the letter 'E' is used in its place + */ + +#include "../inc/MarlinConfig.h" + +#if ENABLED(MEATPACK) + +#include "meatpack.h" +MeatPack meatpack; + +#define MeatPack_ProtocolVersion "PV01" +//#define MP_DEBUG + +#define DEBUG_OUT ENABLED(MP_DEBUG) +#include "../core/debug_out.h" + +bool MeatPack::cmd_is_next = false; // A command is pending +uint8_t MeatPack::state = 0; // Configuration state OFF +uint8_t MeatPack::second_char = 0; // The unpacked 2nd character from an out-of-sequence packed pair +uint8_t MeatPack::cmd_count = 0, // Counts how many command bytes are received (need 2) + MeatPack::full_char_count = 0, // Counts how many full-width characters are to be received + MeatPack::char_out_count = 0; // Stores number of characters to be read out. +uint8_t MeatPack::char_out_buf[2]; // Output buffer for caching up to 2 characters + +// The 15 most-common characters used in G-code, ~90-95% of all G-code uses these characters +// Stored in SRAM for performance. +uint8_t meatPackLookupTable[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '.', ' ', '\n', 'G', 'X', + '\0' // Unused. 0b1111 indicates a literal character +}; + +TERN_(MP_DEBUG, uint8_t chars_decoded = 0); // Log the first 64 bytes after each reset + +void MeatPack::reset_state() { + state = 0; + cmd_is_next = false; + second_char = 0; + cmd_count = full_char_count = char_out_count = 0; + TERN_(MP_DEBUG, chars_decoded = 0); +} + +/** + * Unpack one or two characters from a packed byte into a buffer. + * Return flags indicating whether any literal bytes follow. + */ +uint8_t MeatPack::unpack_chars(const uint8_t pk, uint8_t* __restrict const chars_out) { + uint8_t out = 0; + + // If lower nybble is 1111, the higher nybble is unused, and next char is full. + if ((pk & kFirstNotPacked) == kFirstNotPacked) + out = kFirstCharIsLiteral; + else { + const uint8_t chr = pk & 0x0F; + chars_out[0] = meatPackLookupTable[chr]; // Set the first char + } + + // Check if upper nybble is 1111... if so, we don't need the second char. + if ((pk & kSecondNotPacked) == kSecondNotPacked) + out |= kSecondCharIsLiteral; + else { + const uint8_t chr = (pk >> 4) & 0x0F; + chars_out[1] = meatPackLookupTable[chr]; // Set the second char + } + + return out; +} + +/** + * Interpret a single (non-command) character + * according to the current MeatPack state. + */ +void MeatPack::handle_rx_char_inner(const uint8_t c) { + if (TEST(state, MPConfig_Bit_Active)) { // Is MeatPack active? + if (!full_char_count) { // No literal characters to fetch? + uint8_t buf[2] = { 0, 0 }; + register const uint8_t res = unpack_chars(c, buf); // Decode the byte into one or two characters. + if (res & kFirstCharIsLiteral) { // The 1st character couldn't be packed. + ++full_char_count; // So the next stream byte is a full character. + if (res & kSecondCharIsLiteral) ++full_char_count; // The 2nd character couldn't be packed. Another stream byte is a full character. + else second_char = buf[1]; // Retain the unpacked second character. + } + else { + handle_output_char(buf[0]); // Send the unpacked first character out. + if (buf[0] != '\n') { // After a newline the next char won't be set + if (res & kSecondCharIsLiteral) ++full_char_count; // The 2nd character couldn't be packed. The next stream byte is a full character. + else handle_output_char(buf[1]); // Send the unpacked second character out. + } + } + } + else { + handle_output_char(c); // Pass through the character that couldn't be packed... + if (second_char) { + handle_output_char(second_char); // ...and send an unpacked 2nd character, if set. + second_char = 0; + } + --full_char_count; // One literal character was consumed + } + } + else // Packing not enabled, just copy character to output + handle_output_char(c); +} + +/** + * Buffer a single output character which will be picked up in + * GCodeQueue::get_serial_commands via calls to get_result_char + */ +void MeatPack::handle_output_char(const uint8_t c) { + char_out_buf[char_out_count++] = c; + + #if ENABLED(MP_DEBUG) + if (chars_decoded < 1024) { + ++chars_decoded; + DEBUG_ECHOPGM("RB: "); + MYSERIAL.print((char)c); + DEBUG_EOL(); + } + #endif +} + +/** + * Process a MeatPack command byte to update the state. + * Report the new state to serial. + */ +void MeatPack::handle_command(const MeatPack_Command c) { + switch (c) { + case MPCommand_QueryConfig: break; + case MPCommand_EnablePacking: SBI(state, MPConfig_Bit_Active); DEBUG_ECHOLNPGM("[MPDBG] ENA REC"); break; + case MPCommand_DisablePacking: CBI(state, MPConfig_Bit_Active); DEBUG_ECHOLNPGM("[MPDBG] DIS REC"); break; + case MPCommand_ResetAll: reset_state(); DEBUG_ECHOLNPGM("[MPDBG] RESET REC"); break; + case MPCommand_EnableNoSpaces: + SBI(state, MPConfig_Bit_NoSpaces); + meatPackLookupTable[kSpaceCharIdx] = kSpaceCharReplace; DEBUG_ECHOLNPGM("[MPDBG] ENA NSP"); break; + case MPCommand_DisableNoSpaces: + CBI(state, MPConfig_Bit_NoSpaces); + meatPackLookupTable[kSpaceCharIdx] = ' '; DEBUG_ECHOLNPGM("[MPDBG] DIS NSP"); break; + default: DEBUG_ECHOLNPGM("[MPDBG] UNK CMD REC"); + } + report_state(); +} + +void MeatPack::report_state() { + // NOTE: if any configuration vars are added below, the outgoing sync text for host plugin + // should not contain the "PV' substring, as this is used to indicate protocol version + SERIAL_ECHOPGM("[MP] "); + SERIAL_ECHOPGM(MeatPack_ProtocolVersion " "); + serialprint_onoff(TEST(state, MPConfig_Bit_Active)); + serialprintPGM(TEST(state, MPConfig_Bit_NoSpaces) ? PSTR(" NSP\n") : PSTR(" ESP\n")); +} + +/** + * Interpret a single character received from serial + * according to the current meatpack state. + */ +void MeatPack::handle_rx_char(const uint8_t c, const serial_index_t serial_ind) { + if (c == kCommandByte) { // A command (0xFF) byte? + if (cmd_count) { // In fact, two in a row? + cmd_is_next = true; // Then a MeatPack command follows + cmd_count = 0; + } + else + ++cmd_count; // cmd_count = 1 // One command byte received so far... + return; + } + + if (cmd_is_next) { // Were two command bytes received? + PORT_REDIRECT(serial_ind); + handle_command((MeatPack_Command)c); // Then the byte is a MeatPack command + cmd_is_next = false; + return; + } + + if (cmd_count) { // Only a single 0xFF was received + handle_rx_char_inner(kCommandByte); // A single 0xFF is passed on literally so it can be interpreted as kFirstNotPacked|kSecondNotPacked + cmd_count = 0; + } + + handle_rx_char_inner(c); // Other characters are passed on for MeatPack decoding +} + +uint8_t MeatPack::get_result_char(char* const __restrict out) { + uint8_t res = 0; + if (char_out_count) { + res = char_out_count; + char_out_count = 0; + for (register uint8_t i = 0; i < res; ++i) + out[i] = (char)char_out_buf[i]; + } + return res; +} + +#endif // MEATPACK diff --git a/Marlin/src/feature/meatpack.h b/Marlin/src/feature/meatpack.h new file mode 100644 index 0000000000..2641130bd8 --- /dev/null +++ b/Marlin/src/feature/meatpack.h @@ -0,0 +1,123 @@ +/** + * 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 . + * + */ + +/* + * MeatPack G-code Compression + * + * Algorithm & Implementation: Scott Mudge - mail@scottmudge.com + * Date: Dec. 2020 + * + * Specifically optimized for 3D printing G-Code, this is a zero-cost data compression method + * which packs ~180-190% more data into the same amount of bytes going to the CNC controller. + * As a majority of G-Code can be represented by a restricted alphabet, I performed histogram + * analysis on a wide variety of 3D printing gcode samples, and found ~93% of all gcode could + * be represented by the same 15-character alphabet. + * + * This allowed me to design a system of packing 2 8-bit characters into a single byte, assuming + * they fall within this limited 15-character alphabet. Using a 4-bit lookup table, these 8-bit + * characters can be represented by a 4-bit index. + * + * Combined with some logic to allow commingling of full-width characters outside of this 15- + * character alphabet (at the cost of an extra 8-bits per full-width character), and by stripping + * out unnecessary comments, the end result is gcode which is roughly half the original size. + * + * Why did I do this? I noticed micro-stuttering and other data-bottleneck issues while printing + * objects with high curvature, especially at high speeds. There is also the issue of the limited + * baud rate provided by Prusa's Atmega2560-based boards, over the USB serial connection. So soft- + * ware like OctoPrint would also suffer this same micro-stuttering and poor print quality issue. + * + */ +#pragma once + +#include + +/** + * Commands sent to MeatPack to control its behavior. + * They are sent by first sending 2x MeatPack_CommandByte (0xFF) in sequence, + * followed by one of the command bytes below. + * Provided that 0xFF is an exceedingly rare character that is virtually never + * present in G-code naturally, it is safe to assume 2 in sequence should never + * happen naturally, and so it is used as a signal here. + * + * 0xFF *IS* used in "packed" G-code (used to denote that the next 2 characters are + * full-width), however 2 in a row will never occur, as the next 2 bytes will always + * some non-0xFF character. + */ +enum MeatPack_Command : uint8_t { + MPCommand_None = 0, + MPCommand_EnablePacking = 0xFB, + MPCommand_DisablePacking = 0xFA, + MPCommand_ResetAll = 0xF9, + MPCommand_QueryConfig = 0xF8, + MPCommand_EnableNoSpaces = 0xF7, + MPCommand_DisableNoSpaces = 0xF6 +}; + +enum MeatPack_ConfigStateBits : uint8_t { + MPConfig_Bit_Active = 0, + MPConfig_Bit_NoSpaces = 1 +}; + +class MeatPack { +private: + friend class GCodeQueue; + + // Utility definitions + static const uint8_t kCommandByte = 0b11111111, + kFirstNotPacked = 0b00001111, + kSecondNotPacked = 0b11110000, + kFirstCharIsLiteral = 0b00000001, + kSecondCharIsLiteral = 0b00000010; + + static const uint8_t kSpaceCharIdx = 11; + static const char kSpaceCharReplace = 'E'; + + static bool cmd_is_next; // A command is pending + static uint8_t state; // Configuration state + static uint8_t second_char; // Buffers a character if dealing with out-of-sequence pairs + static uint8_t cmd_count, // Counter of command bytes received (need 2) + full_char_count, // Counter for full-width characters to be received + char_out_count; // Stores number of characters to be read out. + static uint8_t char_out_buf[2]; // Output buffer for caching up to 2 characters + + // Pass in a character rx'd by SD card or serial. Automatically parses command/ctrl sequences, + // and will control state internally. + static void handle_rx_char(const uint8_t c, const serial_index_t serial_ind); + + /** + * After passing in rx'd char using above method, call this to get characters out. + * Can return from 0 to 2 characters at once. + * @param out [in] Output pointer for unpacked/processed data. + * @return Number of characters returned. Range from 0 to 2. + */ + static uint8_t get_result_char(char* const __restrict out); + + static void reset_state(); + static void report_state(); + static uint8_t unpacked_char(register const uint8_t in); + static uint8_t unpack_chars(const uint8_t pk, uint8_t* __restrict const chars_out); + static void handle_command(const MeatPack_Command c); + static void handle_output_char(const uint8_t c); + static void handle_rx_char_inner(const uint8_t c); +}; + +extern MeatPack meatpack; diff --git a/Marlin/src/feature/mmu/mmu2.cpp b/Marlin/src/feature/mmu/mmu2.cpp index a4b7f257a9..e3036947d5 100644 --- a/Marlin/src/feature/mmu/mmu2.cpp +++ b/Marlin/src/feature/mmu/mmu2.cpp @@ -167,6 +167,8 @@ void MMU2::mmu_loop() { case -1: if (rx_start()) { + prev_P0_request = millis(); // Initialize finda sensor timeout + DEBUG_ECHOLNPGM("MMU => 'start'"); DEBUG_ECHOLNPGM("MMU <= 'S1'"); @@ -311,7 +313,7 @@ void MMU2::mmu_loop() { // if (finda_runout_valid) DEBUG_ECHOLNPAIR_F("MMU <= 'P0'\nMMU => ", finda, 6); if (!finda && finda_runout_valid) filament_runout(); - if (cmd == 0) ready = true; + if (cmd == MMU_CMD_NONE) ready = true; state = 1; } else if (ELAPSED(millis(), prev_request + MMU_P0_TIMEOUT)) // Resend request after timeout (3s) @@ -333,18 +335,20 @@ void MMU2::mmu_loop() { #endif if (rx_ok()) { - // Response to C0 mmu command in MMU2S model - bool can_reset = true; #if HAS_PRUSA_MMU2S - if (!mmu2s_triggered && last_cmd == MMU_CMD_C0) { - can_reset = false; + // Respond to C0 MMU command in MMU2S model + const bool keep_trying = !mmu2s_triggered && last_cmd == MMU_CMD_C0; + if (keep_trying) { // MMU ok received but filament sensor not triggered, retrying... DEBUG_ECHOLNPGM("MMU => 'ok' (filament not present in gears)"); DEBUG_ECHOLNPGM("MMU <= 'C0' (keep trying)"); MMU2_COMMAND("C0"); } + #else + constexpr bool keep_trying = false; #endif - if (can_reset) { + + if (!keep_trying) { DEBUG_ECHOLNPGM("MMU => 'ok'"); ready = true; state = 1; @@ -370,11 +374,7 @@ void MMU2::mmu_loop() { */ bool MMU2::rx_start() { // check for start message - if (rx_str_P(PSTR("start\n"))) { - prev_P0_request = millis(); - return true; - } - return false; + return rx_str_P(PSTR("start\n")); } /** @@ -385,13 +385,13 @@ bool MMU2::rx_str_P(const char* str) { while (MMU2_SERIAL.available()) { rx_buffer[i++] = MMU2_SERIAL.read(); - rx_buffer[i] = '\0'; if (i == sizeof(rx_buffer) - 1) { DEBUG_ECHOLNPGM("rx buffer overrun"); break; } } + rx_buffer[i] = '\0'; uint8_t len = strlen_P(str); @@ -416,7 +416,6 @@ void MMU2::tx_str_P(const char* str) { clear_rx_buffer(); uint8_t len = strlen_P(str); LOOP_L_N(i, len) MMU2_SERIAL.write(pgm_read_byte(str++)); - rx_buffer[0] = '\0'; prev_request = millis(); } @@ -427,7 +426,6 @@ void MMU2::tx_printf_P(const char* format, int argument = -1) { clear_rx_buffer(); uint8_t len = sprintf_P(tx_buffer, format, argument); LOOP_L_N(i, len) MMU2_SERIAL.write(tx_buffer[i]); - rx_buffer[0] = '\0'; prev_request = millis(); } @@ -438,7 +436,6 @@ void MMU2::tx_printf_P(const char* format, int argument1, int argument2) { clear_rx_buffer(); uint8_t len = sprintf_P(tx_buffer, format, argument1, argument2); LOOP_L_N(i, len) MMU2_SERIAL.write(tx_buffer[i]); - rx_buffer[0] = '\0'; prev_request = millis(); } @@ -570,7 +567,7 @@ static void mmu2_not_responding() { case 'c': { while (!thermalManager.wait_for_hotend(active_extruder, false)) safe_delay(100); - execute_extruder_sequence((const E_Step *)load_to_nozzle_sequence, COUNT(load_to_nozzle_sequence)); + load_to_nozzle(); } break; } @@ -791,7 +788,7 @@ bool MMU2::get_response() { } /** - * Wait for response and deal with timeout if nexcessary + * Wait for response and deal with timeout if necessary */ void MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) { @@ -917,6 +914,7 @@ void MMU2::filament_runout() { // Load filament into MMU2 void MMU2::load_filament(const uint8_t index) { if (!enabled) return; + command(MMU_CMD_L0 + index); manage_response(false, false); BUZZ(200, 404); @@ -935,6 +933,7 @@ bool MMU2::load_filament_to_nozzle(const uint8_t index) { return false; } + DISABLE_AXIS_E0(); command(MMU_CMD_T0 + index); manage_response(true, true); @@ -957,7 +956,6 @@ bool MMU2::load_filament_to_nozzle(const uint8_t index) { * filament to nozzle. */ void MMU2::load_to_nozzle() { - if (!enabled) return; execute_extruder_sequence((const E_Step *)load_to_nozzle_sequence, COUNT(load_to_nozzle_sequence)); } @@ -1020,7 +1018,8 @@ bool MMU2::unload() { return false; } - filament_ramming(); + // Unload sequence to optimize shape of the tip of the unloaded filament + execute_extruder_sequence((const E_Step *)ramming_sequence, sizeof(ramming_sequence) / sizeof(E_Step)); command(MMU_CMD_U0); manage_response(false, true); @@ -1035,13 +1034,6 @@ bool MMU2::unload() { return true; } -/** - * Unload sequence to optimize shape of the tip of the unloaded filament - */ -void MMU2::filament_ramming() { - execute_extruder_sequence((const E_Step *)ramming_sequence, sizeof(ramming_sequence) / sizeof(E_Step)); -} - void MMU2::execute_extruder_sequence(const E_Step * sequence, int steps) { planner.synchronize(); diff --git a/Marlin/src/feature/mmu/mmu2.h b/Marlin/src/feature/mmu/mmu2.h index 09ff3b6683..4326989a74 100644 --- a/Marlin/src/feature/mmu/mmu2.h +++ b/Marlin/src/feature/mmu/mmu2.h @@ -71,7 +71,6 @@ private: static void manage_response(const bool move_axes, const bool turn_off_nozzle); static void load_to_nozzle(); - static void filament_ramming(); static void execute_extruder_sequence(const E_Step * sequence, int steps); static void filament_runout(); diff --git a/Marlin/src/feature/pause.cpp b/Marlin/src/feature/pause.cpp index c8265a154f..5ab4f2b146 100644 --- a/Marlin/src/feature/pause.cpp +++ b/Marlin/src/feature/pause.cpp @@ -137,10 +137,7 @@ static bool ensure_safe_temperature(const bool wait=true, const PauseMode mode=P thermalManager.setTargetHotend(thermalManager.extrude_min_temp, active_extruder); #endif - #if HAS_LCD_MENU - lcd_pause_show_message(PAUSE_MESSAGE_HEATING, mode); - #endif - UNUSED(mode); + ui.pause_show_message(PAUSE_MESSAGE_HEATING, mode); UNUSED(mode); if (wait) return thermalManager.wait_for_hotend(active_extruder); @@ -181,19 +178,13 @@ bool load_filament(const float &slow_load_length/*=0*/, const float &fast_load_l DEBUG_SECTION(lf, "load_filament", true); DEBUG_ECHOLNPAIR("... slowlen:", slow_load_length, " fastlen:", fast_load_length, " purgelen:", purge_length, " maxbeep:", int(max_beep_count), " showlcd:", int(show_lcd), " pauseforuser:", int(pause_for_user), " pausemode:", int(mode) DXC_SAY); - UNUSED(show_lcd); - if (!ensure_safe_temperature(false, mode)) { - #if HAS_LCD_MENU - if (show_lcd) lcd_pause_show_message(PAUSE_MESSAGE_STATUS, mode); - #endif + if (show_lcd) ui.pause_show_message(PAUSE_MESSAGE_STATUS, mode); return false; } if (pause_for_user) { - #if HAS_LCD_MENU - if (show_lcd) lcd_pause_show_message(PAUSE_MESSAGE_INSERT, mode); - #endif + if (show_lcd) ui.pause_show_message(PAUSE_MESSAGE_INSERT, mode); SERIAL_ECHO_MSG(_PMSG(STR_FILAMENT_CHANGE_INSERT)); first_impatient_beep(max_beep_count); @@ -217,9 +208,7 @@ bool load_filament(const float &slow_load_length/*=0*/, const float &fast_load_l } } - #if HAS_LCD_MENU - if (show_lcd) lcd_pause_show_message(PAUSE_MESSAGE_LOAD, mode); - #endif + if (show_lcd) ui.pause_show_message(PAUSE_MESSAGE_LOAD, mode); #if ENABLED(DUAL_X_CARRIAGE) const int8_t saved_ext = active_extruder; @@ -250,9 +239,7 @@ bool load_filament(const float &slow_load_length/*=0*/, const float &fast_load_l #if ENABLED(ADVANCED_PAUSE_CONTINUOUS_PURGE) - #if HAS_LCD_MENU - if (show_lcd) lcd_pause_show_message(PAUSE_MESSAGE_PURGE); - #endif + if (show_lcd) ui.pause_show_message(PAUSE_MESSAGE_PURGE); TERN_(HOST_PROMPT_SUPPORT, host_prompt_do(PROMPT_USER_CONTINUE, PSTR("Filament Purging..."), CONTINUE_STR)); TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired_P(PSTR("Filament Purging..."))); @@ -266,9 +253,7 @@ bool load_filament(const float &slow_load_length/*=0*/, const float &fast_load_l do { if (purge_length > 0) { // "Wait for filament purge" - #if HAS_LCD_MENU - if (show_lcd) lcd_pause_show_message(PAUSE_MESSAGE_PURGE); - #endif + if (show_lcd) ui.pause_show_message(PAUSE_MESSAGE_PURGE); // Extrude filament to get into hotend unscaled_e_move(purge_length, ADVANCED_PAUSE_PURGE_FEEDRATE); @@ -281,7 +266,7 @@ bool load_filament(const float &slow_load_length/*=0*/, const float &fast_load_l // 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); + ui.pause_show_message(PAUSE_MESSAGE_OPTION); while (pause_menu_response == PAUSE_RESPONSE_WAIT_FOR) idle_no_sleep(); } #endif @@ -330,22 +315,16 @@ bool unload_filament(const float &unload_length, const bool show_lcd/*=false*/, #endif ); - UNUSED(show_lcd); - #if !BOTH(FILAMENT_UNLOAD_ALL_EXTRUDERS, MIXING_EXTRUDER) constexpr float mix_multiplier = 1.0; #endif if (!ensure_safe_temperature(false, mode)) { - #if HAS_LCD_MENU - if (show_lcd) lcd_pause_show_message(PAUSE_MESSAGE_STATUS); - #endif + if (show_lcd) ui.pause_show_message(PAUSE_MESSAGE_STATUS); return false; } - #if HAS_LCD_MENU - if (show_lcd) lcd_pause_show_message(PAUSE_MESSAGE_UNLOAD, mode); - #endif + if (show_lcd) ui.pause_show_message(PAUSE_MESSAGE_UNLOAD, mode); // Retract filament unscaled_e_move(-(FILAMENT_UNLOAD_PURGE_RETRACT) * mix_multiplier, (PAUSE_PARK_RETRACT_FEEDRATE) * mix_multiplier); @@ -479,7 +458,7 @@ void show_continue_prompt(const bool is_reload) { DEBUG_SECTION(scp, "pause_print", true); DEBUG_ECHOLNPAIR("... is_reload:", int(is_reload)); - TERN_(HAS_LCD_MENU, lcd_pause_show_message(is_reload ? PAUSE_MESSAGE_INSERT : PAUSE_MESSAGE_WAITING)); + ui.pause_show_message(is_reload ? PAUSE_MESSAGE_INSERT : PAUSE_MESSAGE_WAITING); SERIAL_ECHO_START(); serialprintPGM(is_reload ? PSTR(_PMSG(STR_FILAMENT_CHANGE_INSERT) "\n") : PSTR(_PMSG(STR_FILAMENT_CHANGE_WAIT) "\n")); } @@ -520,7 +499,7 @@ void wait_for_confirmation(const bool is_reload/*=false*/, const int8_t max_beep // Wait for the user to press the button to re-heat the nozzle, then // re-heat the nozzle, re-show the continue prompt, restart idle timers, start over if (nozzle_timed_out) { - TERN_(HAS_LCD_MENU, lcd_pause_show_message(PAUSE_MESSAGE_HEAT)); + ui.pause_show_message(PAUSE_MESSAGE_HEAT); SERIAL_ECHO_MSG(_PMSG(STR_FILAMENT_CHANGE_HEAT)); TERN_(HOST_PROMPT_SUPPORT, host_prompt_do(PROMPT_USER_CONTINUE, GET_TEXT(MSG_HEATER_TIMEOUT), GET_TEXT(MSG_REHEAT))); @@ -614,7 +593,7 @@ void resume_print(const float &slow_load_length/*=0*/, const float &fast_load_le thermalManager.wait_for_hotend(active_extruder, false); } - TERN_(HAS_LCD_MENU, lcd_pause_show_message(PAUSE_MESSAGE_RESUME)); + ui.pause_show_message(PAUSE_MESSAGE_RESUME); // Check Temperature before moving hotend ensure_safe_temperature(); @@ -653,7 +632,7 @@ void resume_print(const float &slow_load_length/*=0*/, const float &fast_load_le // Write PLR now to update the z axis value TERN_(POWER_LOSS_RECOVERY, if (recovery.enabled) recovery.save(true)); - TERN_(HAS_LCD_MENU, lcd_pause_show_message(PAUSE_MESSAGE_STATUS)); + ui.pause_show_message(PAUSE_MESSAGE_STATUS); #ifdef ACTION_ON_RESUMED host_action_resumed(); diff --git a/Marlin/src/feature/pause.h b/Marlin/src/feature/pause.h index c69ed73546..7e58d4564e 100644 --- a/Marlin/src/feature/pause.h +++ b/Marlin/src/feature/pause.h @@ -101,4 +101,8 @@ bool unload_filament(const float &unload_length, const bool show_lcd=false, cons #endif ); -#endif // ADVANCED_PAUSE_FEATURE +#else // !ADVANCED_PAUSE_FEATURE + + constexpr uint8_t did_pause_print = 0; + +#endif // !ADVANCED_PAUSE_FEATURE diff --git a/Marlin/src/feature/powerloss.cpp b/Marlin/src/feature/powerloss.cpp index 0e669a74d4..be35ff8511 100644 --- a/Marlin/src/feature/powerloss.cpp +++ b/Marlin/src/feature/powerloss.cpp @@ -520,7 +520,6 @@ void PrintJobRecovery::resume() { // Resume the SD file from the last position char *fn = info.sd_filename; - extern const char M23_STR[]; sprintf_P(cmd, M23_STR, fn); gcode.process_subcommands_now(cmd); sprintf_P(cmd, PSTR("M24 S%ld T%ld"), resume_sdpos, info.print_job_elapsed); diff --git a/Marlin/src/feature/runout.cpp b/Marlin/src/feature/runout.cpp index 50e18e52ef..be769d2dc8 100644 --- a/Marlin/src/feature/runout.cpp +++ b/Marlin/src/feature/runout.cpp @@ -59,6 +59,7 @@ bool FilamentMonitorBase::enabled = true, // Filament Runout event handler // #include "../MarlinCore.h" +#include "../feature/pause.h" #include "../gcode/queue.h" #if ENABLED(HOST_ACTION_COMMANDS) @@ -71,7 +72,7 @@ bool FilamentMonitorBase::enabled = true, void event_filament_runout() { - if (TERN0(ADVANCED_PAUSE_FEATURE, did_pause_print)) return; // Action already in progress. Purge triggered repeated runout. + if (did_pause_print) return; // Action already in progress. Purge triggered repeated runout. #if ENABLED(TOOLCHANGE_MIGRATION_FEATURE) if (migration.in_progress) { diff --git a/Marlin/src/feature/runout.h b/Marlin/src/feature/runout.h index 09443e6e2b..60154c5e43 100644 --- a/Marlin/src/feature/runout.h +++ b/Marlin/src/feature/runout.h @@ -30,6 +30,7 @@ #include "../module/planner.h" #include "../module/stepper.h" // for block_t #include "../gcode/queue.h" +#include "../feature/pause.h" #include "../inc/MarlinConfig.h" @@ -37,10 +38,6 @@ #include "../lcd/extui/ui_api.h" #endif -#if ENABLED(ADVANCED_PAUSE_FEATURE) - #include "pause.h" -#endif - //#define FILAMENT_RUNOUT_SENSOR_DEBUG #ifndef FILAMENT_RUNOUT_THRESHOLD #define FILAMENT_RUNOUT_THRESHOLD 5 @@ -118,9 +115,7 @@ class TFilamentMonitor : public FilamentMonitorBase { // Give the response a chance to update its counter. static inline void run() { - if ( enabled && !filament_ran_out - && (printingIsActive() || TERN0(ADVANCED_PAUSE_FEATURE, did_pause_print)) - ) { + if (enabled && !filament_ran_out && (printingIsActive() || did_pause_print)) { TERN_(HAS_FILAMENT_RUNOUT_DISTANCE, cli()); // Prevent RunoutResponseDelayed::block_completed from accumulating here response.run(); sensor.run(); @@ -343,9 +338,7 @@ class FilamentSensorBase { } static inline void block_completed(const block_t* const b) { - if (b->steps.x || b->steps.y || b->steps.z - || TERN0(ADVANCED_PAUSE_FEATURE, did_pause_print) // Allow pause purge move to re-trigger runout state - ) { + if (b->steps.x || b->steps.y || b->steps.z || did_pause_print) { // Allow pause purge move to re-trigger runout state // Only trigger on extrusion with XYZ movement to allow filament change and retract/recover. const uint8_t e = b->extruder; const int32_t steps = b->steps.e; diff --git a/Marlin/src/feature/spindle_laser.h b/Marlin/src/feature/spindle_laser.h index 57fc136c8c..d50bc7eb42 100644 --- a/Marlin/src/feature/spindle_laser.h +++ b/Marlin/src/feature/spindle_laser.h @@ -157,7 +157,7 @@ public: #elif CUTTER_UNIT_IS(RPM) 2 #else - #error "CUTTER_UNIT_IS(???)" + #error "CUTTER_UNIT_IS(unknown)" #endif )); } diff --git a/Marlin/src/feature/tmc_util.cpp b/Marlin/src/feature/tmc_util.cpp index 29bb249cea..8d0156883b 100644 --- a/Marlin/src/feature/tmc_util.cpp +++ b/Marlin/src/feature/tmc_util.cpp @@ -604,8 +604,6 @@ case TMC_PWM_OFS_AUTO: SERIAL_PRINT(st.pwm_ofs_auto(), DEC); break; case TMC_PWM_GRAD_AUTO: SERIAL_PRINT(st.pwm_grad_auto(), DEC); break; case TMC_STEALTHCHOP: serialprint_truefalse(st.stealth()); break; - case TMC_S2VSA: if (st.s2vsa()) SERIAL_CHAR('*'); break; - case TMC_S2VSB: if (st.s2vsb()) SERIAL_CHAR('*'); break; case TMC_INTERPOLATE: serialprint_truefalse(st.intpol()); break; default: break; } @@ -631,6 +629,8 @@ case TMC_T150: if (st.t150()) SERIAL_CHAR('*'); break; case TMC_T143: if (st.t143()) SERIAL_CHAR('*'); break; case TMC_T120: if (st.t120()) SERIAL_CHAR('*'); break; + case TMC_S2VSA: if (st.s2vsa()) SERIAL_CHAR('*'); break; + case TMC_S2VSB: if (st.s2vsb()) SERIAL_CHAR('*'); break; case TMC_DRV_CS_ACTUAL: SERIAL_PRINT(st.cs_actual(), DEC); break; default: break; } diff --git a/Marlin/src/feature/twibus.cpp b/Marlin/src/feature/twibus.cpp index 3cc20579ac..855a3188d1 100644 --- a/Marlin/src/feature/twibus.cpp +++ b/Marlin/src/feature/twibus.cpp @@ -28,6 +28,8 @@ #include +TWIBus i2c; + TWIBus::TWIBus() { #if I2C_SLAVE_ADDRESS == 0 Wire.begin(); // No address joins the BUS as the master @@ -155,6 +157,14 @@ void TWIBus::flush() { reset(); } + void i2c_on_receive(int bytes) { // just echo all bytes received to serial + i2c.receive(bytes); + } + + void i2c_on_request() { // just send dummy data for now + i2c.reply("Hello World!\n"); + } + #endif #if ENABLED(DEBUG_TWIBUS) diff --git a/Marlin/src/feature/twibus.h b/Marlin/src/feature/twibus.h index 82aa9aa16a..5939153482 100644 --- a/Marlin/src/feature/twibus.h +++ b/Marlin/src/feature/twibus.h @@ -31,6 +31,17 @@ typedef void (*twiReceiveFunc_t)(int bytes); typedef void (*twiRequestFunc_t)(); +/** + * For a light i2c protocol that runs on two boards running Marlin see: + * See https://github.com/MarlinFirmware/Marlin/issues/4776#issuecomment-246262879 + */ +#if I2C_SLAVE_ADDRESS > 0 + + void i2c_on_receive(int bytes); // Demo i2c onReceive handler + void i2c_on_request(); // Demo i2c onRequest handler + +#endif + #define TWIBUS_BUFFER_SIZE 32 /** @@ -238,3 +249,5 @@ class TWIBus { static inline void debug(const char[], uint8_t) {} #endif }; + +extern TWIBus i2c; diff --git a/Marlin/src/gcode/bedlevel/G26.cpp b/Marlin/src/gcode/bedlevel/G26.cpp index 650b039b55..5a79aaac7b 100644 --- a/Marlin/src/gcode/bedlevel/G26.cpp +++ b/Marlin/src/gcode/bedlevel/G26.cpp @@ -128,6 +128,10 @@ #define G26_XY_FEEDRATE (PLANNER_XY_FEEDRATE() / 3.0) #endif +#ifndef G26_XY_FEEDRATE_TRAVEL + #define G26_XY_FEEDRATE_TRAVEL (PLANNER_XY_FEEDRATE() / 1.5) +#endif + #if CROSSHAIRS_SIZE >= INTERSECTION_CIRCLE_RADIUS #error "CROSSHAIRS_SIZE must be less than INTERSECTION_CIRCLE_RADIUS." #endif @@ -214,22 +218,25 @@ void move_to(const float &rx, const float &ry, const float &z, const float &e_de const xy_pos_t dest = { rx, ry }; const bool has_xy_component = dest != current_position; // Check if X or Y is involved in the movement. + const bool has_e_component = e_delta != 0.0; destination = current_position; if (z != last_z) { last_z = destination.z = z; - const feedRate_t feed_value = planner.settings.max_feedrate_mm_s[Z_AXIS] * 0.5f; // Use half of the Z_AXIS max feed rate - prepare_internal_move_to_destination(feed_value); - destination = current_position; + const feedRate_t fr_mm_s = planner.settings.max_feedrate_mm_s[Z_AXIS] * 0.5f; // Use half of the Z_AXIS max feed rate + prepare_internal_move_to_destination(fr_mm_s); } - // If X or Y is involved do a 'normal' move. Otherwise retract/recover/hop. + // If X or Y in combination with E is involved do a 'normal' move. + // If X or Y with no E is involved do a 'fast' move + // Otherwise retract/recover/hop. destination = dest; destination.e += e_delta; - const feedRate_t feed_value = has_xy_component ? feedRate_t(G26_XY_FEEDRATE) : planner.settings.max_feedrate_mm_s[E_AXIS] * 0.666f; - prepare_internal_move_to_destination(feed_value); - destination = current_position; + const feedRate_t fr_mm_s = has_xy_component + ? (has_e_component ? feedRate_t(G26_XY_FEEDRATE) : feedRate_t(G26_XY_FEEDRATE_TRAVEL)) + : planner.settings.max_feedrate_mm_s[E_AXIS] * 0.666f; + prepare_internal_move_to_destination(fr_mm_s); } FORCE_INLINE void move_to(const xyz_pos_t &where, const float &de) { move_to(where.x, where.y, where.z, de); } diff --git a/Marlin/src/gcode/bedlevel/abl/G29.cpp b/Marlin/src/gcode/bedlevel/abl/G29.cpp index 3c3bb18deb..b8194e0c21 100644 --- a/Marlin/src/gcode/bedlevel/abl/G29.cpp +++ b/Marlin/src/gcode/bedlevel/abl/G29.cpp @@ -194,7 +194,7 @@ G29_TYPE GcodeSuite::G29() { // Send 'N' to force homing before G29 (internal only) if (parser.seen('N')) - gcode.process_subcommands_now_P(TERN(G28_L0_ENSURES_LEVELING_OFF, PSTR("G28L0"), G28_STR)); + process_subcommands_now_P(TERN(G28_L0_ENSURES_LEVELING_OFF, PSTR("G28L0"), G28_STR)); // Don't allow auto-leveling without homing first if (homing_needed_error()) G29_RETURN(false); diff --git a/Marlin/src/gcode/calibrate/G76_M192_M871.cpp b/Marlin/src/gcode/calibrate/G76_M192_M871.cpp index 7438b0e83d..5d0bb0dc1e 100644 --- a/Marlin/src/gcode/calibrate/G76_M192_M871.cpp +++ b/Marlin/src/gcode/calibrate/G76_M192_M871.cpp @@ -38,7 +38,7 @@ #include "../../feature/probe_temp_comp.h" #include "../../lcd/marlinui.h" -#include "../../MarlinCore.h" // for wait_for_heatup, idle(), G28_STR +#include "../../MarlinCore.h" // for wait_for_heatup, idle() #if ENABLED(PRINTJOB_TIMER_AUTOSTART) #include "../../module/printcounter.h" @@ -267,7 +267,7 @@ void GcodeSuite::G76() { say_waiting_for_probe_heating(); SERIAL_ECHOLNPAIR(" Bed:", target_bed, " Probe:", target_probe); - const millis_t probe_timeout_ms = millis() + 900UL * 1000UL; + const millis_t probe_timeout_ms = millis() + SEC_TO_MS(900UL); while (thermalManager.degProbe() < target_probe) { if (report_temps(next_temp_report, probe_timeout_ms)) { SERIAL_ECHOLNPGM("!Probe heating timed out."); diff --git a/Marlin/src/gcode/calibrate/M48.cpp b/Marlin/src/gcode/calibrate/M48.cpp index 46367df10d..529d5c75d9 100644 --- a/Marlin/src/gcode/calibrate/M48.cpp +++ b/Marlin/src/gcode/calibrate/M48.cpp @@ -51,8 +51,6 @@ * This function requires the machine to be homed before invocation. */ -extern const char SP_Y_STR[]; - void GcodeSuite::M48() { if (homing_needed_error()) return; diff --git a/Marlin/src/gcode/config/M217.cpp b/Marlin/src/gcode/config/M217.cpp index b57dec31f3..f2fefb5756 100644 --- a/Marlin/src/gcode/config/M217.cpp +++ b/Marlin/src/gcode/config/M217.cpp @@ -33,8 +33,6 @@ #include "../../MarlinCore.h" // for SP_X_STR, etc. -extern const char SP_X_STR[], SP_Y_STR[], SP_Z_STR[]; - void M217_report(const bool eeprom=false) { #if ENABLED(TOOLCHANGE_FILAMENT_SWAP) diff --git a/Marlin/src/gcode/control/M108_M112_M410.cpp b/Marlin/src/gcode/control/M108_M112_M410.cpp index df145d5d11..309c806c8f 100644 --- a/Marlin/src/gcode/control/M108_M112_M410.cpp +++ b/Marlin/src/gcode/control/M108_M112_M410.cpp @@ -25,7 +25,8 @@ #if DISABLED(EMERGENCY_PARSER) #include "../gcode.h" -#include "../../MarlinCore.h" // for wait_for_heatup, kill, quickstop_stepper +#include "../../MarlinCore.h" // for wait_for_heatup, kill, M112_KILL_STR +#include "../../module/motion.h" // for quickstop_stepper /** * M108: Stop the waiting for heaters in M109, M190, M303. Does not affect the target temperature. diff --git a/Marlin/src/gcode/control/M226.cpp b/Marlin/src/gcode/control/M226.cpp index ad717e614d..63f022e82b 100644 --- a/Marlin/src/gcode/control/M226.cpp +++ b/Marlin/src/gcode/control/M226.cpp @@ -28,6 +28,8 @@ #include "../../MarlinCore.h" // for pin_is_protected and idle() #include "../../module/stepper.h" +void protected_pin_err(); + /** * M226: Wait until the specified pin reaches the state required (M226 P S) */ diff --git a/Marlin/src/gcode/control/M42.cpp b/Marlin/src/gcode/control/M42.cpp index c635c06ec6..6ef8455e0b 100644 --- a/Marlin/src/gcode/control/M42.cpp +++ b/Marlin/src/gcode/control/M42.cpp @@ -31,6 +31,10 @@ #include "../../module/temperature.h" #endif +void protected_pin_err() { + SERIAL_ERROR_MSG(STR_ERR_PROTECTED_PIN); +} + /** * M42: Change pin status via GCode * diff --git a/Marlin/src/gcode/control/M80_M81.cpp b/Marlin/src/gcode/control/M80_M81.cpp index ea0f9c2b13..394b06d8ac 100644 --- a/Marlin/src/gcode/control/M80_M81.cpp +++ b/Marlin/src/gcode/control/M80_M81.cpp @@ -89,9 +89,10 @@ */ void GcodeSuite::M81() { thermalManager.disable_all_heaters(); - print_job_timer.stop(); planner.finish_and_disable(); + print_job_timer.stop(); + #if HAS_FAN thermalManager.zero_fan_speeds(); #if ENABLED(PROBING_FANS_OFF) diff --git a/Marlin/src/gcode/feature/L6470/M916-918.cpp b/Marlin/src/gcode/feature/L6470/M916-918.cpp index 2672f91239..8a1ea48306 100644 --- a/Marlin/src/gcode/feature/L6470/M916-918.cpp +++ b/Marlin/src/gcode/feature/L6470/M916-918.cpp @@ -119,7 +119,7 @@ void GcodeSuite::M916() { M91x_counter_max = 256; // KVAL_HOLD is 8 bits uint8_t M91x_delay_s = parser.byteval('D'); // get delay in seconds - millis_t M91x_delay_ms = M91x_delay_s * 60 * 1000; + millis_t M91x_delay_ms = SEC_TO_MS(M91x_delay_s * 60); millis_t M91x_delay_end; DEBUG_ECHOLNPGM(".\n."); diff --git a/Marlin/src/gcode/feature/i2c/M260_M261.cpp b/Marlin/src/gcode/feature/i2c/M260_M261.cpp index 526d9101e1..438d1527f5 100644 --- a/Marlin/src/gcode/feature/i2c/M260_M261.cpp +++ b/Marlin/src/gcode/feature/i2c/M260_M261.cpp @@ -26,7 +26,7 @@ #include "../../gcode.h" -#include "../../../MarlinCore.h" // for i2c +#include "../../../feature/twibus.h" /** * M260: Send data to a I2C slave device diff --git a/Marlin/src/gcode/feature/network/M552-M554.cpp b/Marlin/src/gcode/feature/network/M552-M554.cpp index d88c38cb5a..6ea15fefbf 100644 --- a/Marlin/src/gcode/feature/network/M552-M554.cpp +++ b/Marlin/src/gcode/feature/network/M552-M554.cpp @@ -47,7 +47,8 @@ void MAC_report() { Ethernet.MACAddress(mac); SERIAL_ECHOPGM(" MAC: "); LOOP_L_N(i, 6) { - SERIAL_PRINTF("%02X", mac[i]); + if (mac[i] < 16) SERIAL_CHAR('0'); + SERIAL_PRINT(mac[i], HEX); if (i < 5) SERIAL_CHAR(':'); } } diff --git a/Marlin/src/gcode/feature/pause/M125.cpp b/Marlin/src/gcode/feature/pause/M125.cpp index b1d76e83ae..9391b8661b 100644 --- a/Marlin/src/gcode/feature/pause/M125.cpp +++ b/Marlin/src/gcode/feature/pause/M125.cpp @@ -27,13 +27,10 @@ #include "../../gcode.h" #include "../../parser.h" #include "../../../feature/pause.h" +#include "../../../lcd/marlinui.h" #include "../../../module/motion.h" -#include "../../../sd/cardreader.h" #include "../../../module/printcounter.h" - -#if HAS_LCD_MENU - #include "../../../lcd/marlinui.h" -#endif +#include "../../../sd/cardreader.h" #if ENABLED(POWER_LOSS_RECOVERY) #include "../../../feature/powerloss.h" @@ -76,7 +73,7 @@ void GcodeSuite::M125() { const bool sd_printing = TERN0(SDSUPPORT, IS_SD_PRINTING()); - TERN_(HAS_LCD_MENU, lcd_pause_show_message(PAUSE_MESSAGE_PARKING, PAUSE_MODE_PAUSE_PRINT)); + ui.pause_show_message(PAUSE_MESSAGE_PARKING, PAUSE_MODE_PAUSE_PRINT); // If possible, show an LCD prompt with the 'P' flag const bool show_lcd = TERN0(HAS_LCD_MENU, parser.boolval('P')); diff --git a/Marlin/src/gcode/feature/pause/M600.cpp b/Marlin/src/gcode/feature/pause/M600.cpp index db8bc93a9f..1c282f2052 100644 --- a/Marlin/src/gcode/feature/pause/M600.cpp +++ b/Marlin/src/gcode/feature/pause/M600.cpp @@ -28,15 +28,12 @@ #include "../../../feature/pause.h" #include "../../../module/motion.h" #include "../../../module/printcounter.h" +#include "../../../lcd/marlinui.h" #if HAS_MULTI_EXTRUDER #include "../../../module/tool_change.h" #endif -#if HAS_LCD_MENU - #include "../../../lcd/marlinui.h" -#endif - #if ENABLED(MMU2_MENUS) #include "../../../lcd/menu/menu_mmu2.h" #endif @@ -96,8 +93,8 @@ void GcodeSuite::M600() { #endif // Show initial "wait for start" message - #if HAS_LCD_MENU && DISABLED(MMU2_MENUS) - lcd_pause_show_message(PAUSE_MESSAGE_CHANGING, PAUSE_MODE_PAUSE_PRINT, target_extruder); + #if DISABLED(MMU2_MENUS) + ui.pause_show_message(PAUSE_MESSAGE_CHANGING, PAUSE_MODE_PAUSE_PRINT, target_extruder); #endif #if ENABLED(HOME_BEFORE_FILAMENT_CHANGE) diff --git a/Marlin/src/gcode/feature/pause/M701_M702.cpp b/Marlin/src/gcode/feature/pause/M701_M702.cpp index a889da8aea..9a2b774936 100644 --- a/Marlin/src/gcode/feature/pause/M701_M702.cpp +++ b/Marlin/src/gcode/feature/pause/M701_M702.cpp @@ -29,15 +29,12 @@ #include "../../../module/motion.h" #include "../../../module/temperature.h" #include "../../../feature/pause.h" +#include "../../../lcd/marlinui.h" #if HAS_MULTI_EXTRUDER #include "../../../module/tool_change.h" #endif -#if HAS_LCD_MENU - #include "../../../lcd/marlinui.h" -#endif - #if HAS_PRUSA_MMU2 #include "../../../feature/mmu/mmu2.h" #endif @@ -82,7 +79,7 @@ void GcodeSuite::M701() { if (parser.seenval('Z')) park_point.z = parser.linearval('Z'); // Show initial "wait for load" message - TERN_(HAS_LCD_MENU, lcd_pause_show_message(PAUSE_MESSAGE_LOAD, PAUSE_MODE_LOAD_FILAMENT, target_extruder)); + ui.pause_show_message(PAUSE_MESSAGE_LOAD, PAUSE_MODE_LOAD_FILAMENT, target_extruder); #if HAS_MULTI_EXTRUDER && (HAS_PRUSA_MMU1 || !HAS_MMU) // Change toolhead if specified @@ -128,7 +125,7 @@ void GcodeSuite::M701() { TERN_(MIXING_EXTRUDER, mixer.T(old_mixing_tool)); // Restore original mixing tool // Show status screen - TERN_(HAS_LCD_MENU, lcd_pause_show_message(PAUSE_MESSAGE_STATUS)); + ui.pause_show_message(PAUSE_MESSAGE_STATUS); } /** @@ -180,7 +177,7 @@ void GcodeSuite::M702() { if (parser.seenval('Z')) park_point.z = parser.linearval('Z'); // Show initial "wait for unload" message - TERN_(HAS_LCD_MENU, lcd_pause_show_message(PAUSE_MESSAGE_UNLOAD, PAUSE_MODE_UNLOAD_FILAMENT, target_extruder)); + ui.pause_show_message(PAUSE_MESSAGE_UNLOAD, PAUSE_MODE_UNLOAD_FILAMENT, target_extruder); #if HAS_MULTI_EXTRUDER && (HAS_PRUSA_MMU1 || !HAS_MMU) // Change toolhead if specified @@ -232,7 +229,7 @@ void GcodeSuite::M702() { TERN_(MIXING_EXTRUDER, mixer.T(old_mixing_tool)); // Restore original mixing tool // Show status screen - TERN_(HAS_LCD_MENU, lcd_pause_show_message(PAUSE_MESSAGE_STATUS)); + ui.pause_show_message(PAUSE_MESSAGE_STATUS); } #endif // ADVANCED_PAUSE_FEATURE diff --git a/Marlin/src/gcode/gcode.cpp b/Marlin/src/gcode/gcode.cpp index 89bc0dc7af..f9173188dc 100644 --- a/Marlin/src/gcode/gcode.cpp +++ b/Marlin/src/gcode/gcode.cpp @@ -40,7 +40,7 @@ GcodeSuite gcode; #include "../module/printcounter.h" #endif -#if ENABLED(HOST_PROMPT_SUPPORT) +#if ENABLED(HOST_ACTION_COMMANDS) #include "../feature/host_actions.h" #endif @@ -61,7 +61,7 @@ GcodeSuite gcode; #include "../feature/password/password.h" #endif -#include "../MarlinCore.h" // for idle() +#include "../MarlinCore.h" // for idle, kill // Inactivity shutdown millis_t GcodeSuite::previous_move_ms = 0, @@ -209,6 +209,31 @@ void GcodeSuite::dwell(millis_t time) { */ #if BOTH(HAS_LEVELING, G29_RETRY_AND_RECOVER) + void GcodeSuite::event_probe_recover() { + TERN_(HOST_PROMPT_SUPPORT, host_prompt_do(PROMPT_INFO, PSTR("G29 Retrying"), DISMISS_STR)); + #ifdef ACTION_ON_G29_RECOVER + host_action(PSTR(ACTION_ON_G29_RECOVER)); + #endif + #ifdef G29_RECOVER_COMMANDS + process_subcommands_now_P(PSTR(G29_RECOVER_COMMANDS)); + #endif + } + + void GcodeSuite::event_probe_failure() { + #ifdef ACTION_ON_G29_FAILURE + host_action(PSTR(ACTION_ON_G29_FAILURE)); + #endif + #ifdef G29_FAILURE_COMMANDS + process_subcommands_now_P(PSTR(G29_FAILURE_COMMANDS)); + #endif + #if ENABLED(G29_HALT_ON_FAILURE) + #ifdef ACTION_ON_CANCEL + host_action_cancel(); + #endif + kill(GET_TEXT(MSG_LCD_PROBING_FAILED)); + #endif + } + #ifndef G29_MAX_RETRIES #define G29_MAX_RETRIES 0 #endif @@ -216,7 +241,10 @@ void GcodeSuite::dwell(millis_t time) { void GcodeSuite::G29_with_retry() { uint8_t retries = G29_MAX_RETRIES; while (G29()) { // G29 should return true for failed probes ONLY - if (retries--) event_probe_recover(); + if (retries) { + event_probe_recover(); + --retries; + } else { event_probe_failure(); return; @@ -718,6 +746,10 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) { case 412: M412(); break; // M412: Enable/Disable filament runout detection #endif + #if HAS_MULTI_LANGUAGE + case 414: M414(); break; // M414: Select multi language menu + #endif + #if HAS_LEVELING case 420: M420(); break; // M420: Enable/Disable Bed Leveling #endif @@ -954,6 +986,8 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) { } if (!no_ok) queue.ok_to_send(); + + SERIAL_OUT(msgDone); // Call the msgDone serial hook to signal command processing done } /** @@ -963,7 +997,7 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) { void GcodeSuite::process_next_command() { char * const current_command = queue.command_buffer[queue.index_r]; - PORT_REDIRECT(queue.port[queue.index_r]); + PORT_REDIRECT(SERIAL_PORTMASK(queue.port[queue.index_r])); #if ENABLED(POWER_LOSS_RECOVERY) recovery.queue_index_r = queue.index_r; diff --git a/Marlin/src/gcode/gcode.h b/Marlin/src/gcode/gcode.h index 765cd8e591..7fd8d6904a 100644 --- a/Marlin/src/gcode/gcode.h +++ b/Marlin/src/gcode/gcode.h @@ -213,6 +213,7 @@ * M410 - Quickstop. Abort all planned moves. * M412 - Enable / Disable Filament Runout Detection. (Requires FILAMENT_RUNOUT_SENSOR) * M413 - Enable / Disable Power-Loss Recovery. (Requires POWER_LOSS_RECOVERY) + * M414 - Set language by index. (Requires LCD_LANGUAGE_2...) * M420 - Enable/Disable Leveling (with current values) S1=enable S0=disable (Requires MESH_BED_LEVELING or ABL) * M421 - Set a single Z coordinate in the Mesh Leveling grid. X Y Z (Requires MESH_BED_LEVELING, AUTO_BED_LEVELING_BILINEAR, or AUTO_BED_LEVELING_UBL) * M422 - Set Z Stepper automatic alignment position using probe. X Y A (Requires Z_STEPPER_AUTO_ALIGN) @@ -309,6 +310,8 @@ enum AxisRelative : uint8_t { REL_X, REL_Y, REL_Z, REL_E, E_MODE_ABS, E_MODE_REL }; +extern const char G28_STR[]; + class GcodeSuite { public: @@ -370,7 +373,6 @@ public: static void process_subcommands_now(char * gcode); static inline void home_all_axes(const bool keep_leveling=false) { - extern const char G28_STR[]; process_subcommands_now_P(keep_leveling ? G28_STR : TERN(G28_L0_ENSURES_LEVELING_OFF, PSTR("G28L0"), G28_STR)); } @@ -451,6 +453,8 @@ private: #if HAS_LEVELING #if ENABLED(G29_RETRY_AND_RECOVER) + static void event_probe_failure(); + static void event_probe_recover(); static void G29_with_retry(); #define G29_TYPE bool #else @@ -747,6 +751,8 @@ private: TERN_(HAS_FILAMENT_SENSOR, static void M412()); + TERN_(HAS_MULTI_LANGUAGE, static void M414()); + #if HAS_LEVELING static void M420(); static void M421(); diff --git a/Marlin/src/gcode/geometry/M206_M428.cpp b/Marlin/src/gcode/geometry/M206_M428.cpp index efb89fbcf2..2a2cdb16ff 100644 --- a/Marlin/src/gcode/geometry/M206_M428.cpp +++ b/Marlin/src/gcode/geometry/M206_M428.cpp @@ -30,8 +30,6 @@ #include "../../libs/buzzer.h" #include "../../MarlinCore.h" -extern const char SP_Y_STR[], SP_Z_STR[]; - void m206_report() { SERIAL_ECHOLNPAIR_P(PSTR("M206 X"), home_offset.x, SP_Y_STR, home_offset.y, SP_Z_STR, home_offset.z); } diff --git a/Marlin/src/gcode/host/M115.cpp b/Marlin/src/gcode/host/M115.cpp index 63511b606d..1b088e7d34 100644 --- a/Marlin/src/gcode/host/M115.cpp +++ b/Marlin/src/gcode/host/M115.cpp @@ -141,6 +141,9 @@ void GcodeSuite::M115() { // CHAMBER_TEMPERATURE (M141, M191) cap_line(PSTR("CHAMBER_TEMPERATURE"), ENABLED(HAS_HEATED_CHAMBER)); + // MEATPACK Compresson + cap_line(PSTR("MEATPACK"), ENABLED(MEATPACK)); + // Machine Geometry #if ENABLED(M115_GEOMETRY_REPORT) const xyz_pos_t dmin = { X_MIN_POS, Y_MIN_POS, Z_MIN_POS }, diff --git a/Marlin/src/gcode/host/M118.cpp b/Marlin/src/gcode/host/M118.cpp index 27207b7172..73115d5c0a 100644 --- a/Marlin/src/gcode/host/M118.cpp +++ b/Marlin/src/gcode/host/M118.cpp @@ -53,21 +53,14 @@ void GcodeSuite::M118() { } #if HAS_MULTI_SERIAL - const int8_t old_serial = serial_port_index; + const int8_t old_serial = multiSerial.portMask; if (WITHIN(port, 0, NUM_SERIAL)) - serial_port_index = ( - port == 0 ? SERIAL_BOTH - : port == 1 ? 0 - #if HAS_MULTI_SERIAL - : port == 2 ? 1 - #endif - : SERIAL_PORT - ); + multiSerial.portMask = port ? _BV(port - 1) : SERIAL_ALL; #endif if (hasE) SERIAL_ECHO_START(); if (hasA) SERIAL_ECHOPGM("//"); SERIAL_ECHOLN(p); - TERN_(HAS_MULTI_SERIAL, serial_port_index = old_serial); + TERN_(HAS_MULTI_SERIAL, multiSerial.portMask = old_serial); } diff --git a/Marlin/src/gcode/lcd/M414.cpp b/Marlin/src/gcode/lcd/M414.cpp new file mode 100644 index 0000000000..760028a899 --- /dev/null +++ b/Marlin/src/gcode/lcd/M414.cpp @@ -0,0 +1,44 @@ +/** + * 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 . + * + */ + +#include "../../inc/MarlinConfig.h" + +#if HAS_MULTI_LANGUAGE + +#include "../gcode.h" +#include "../../MarlinCore.h" +#include "../../lcd/marlinui.h" + +/** + * M414: Set the language for the UI + * + * Parameters + * S : The language to select + */ +void GcodeSuite::M414() { + + if (parser.seenval('S')) + ui.set_language(parser.value_byte()); + +} + +#endif // HAS_MULTI_LANGUAGE diff --git a/Marlin/src/gcode/parser.h b/Marlin/src/gcode/parser.h index 8633d2b1e9..cf531c4e47 100644 --- a/Marlin/src/gcode/parser.h +++ b/Marlin/src/gcode/parser.h @@ -282,7 +282,7 @@ public: // Code value for use as time static inline millis_t value_millis() { return value_ulong(); } - static inline millis_t value_millis_from_seconds() { return (millis_t)(value_float() * 1000); } + static inline millis_t value_millis_from_seconds() { return (millis_t)SEC_TO_MS(value_float()); } // Reduce to fewer bits static inline int16_t value_int() { return (int16_t)value_long(); } diff --git a/Marlin/src/gcode/probe/M851.cpp b/Marlin/src/gcode/probe/M851.cpp index ee60e9ebc0..04b293de31 100644 --- a/Marlin/src/gcode/probe/M851.cpp +++ b/Marlin/src/gcode/probe/M851.cpp @@ -28,8 +28,6 @@ #include "../../feature/bedlevel/bedlevel.h" #include "../../module/probe.h" -extern const char SP_Y_STR[], SP_Z_STR[]; - /** * M851: Set the nozzle-to-probe offsets in current units */ diff --git a/Marlin/src/gcode/queue.cpp b/Marlin/src/gcode/queue.cpp index 98fe91db40..4c42f7e353 100644 --- a/Marlin/src/gcode/queue.cpp +++ b/Marlin/src/gcode/queue.cpp @@ -31,6 +31,7 @@ GCodeQueue queue; #include "../lcd/marlinui.h" #include "../sd/cardreader.h" +#include "../module/motion.h" #include "../module/planner.h" #include "../module/temperature.h" #include "../MarlinCore.h" @@ -47,6 +48,10 @@ GCodeQueue queue; #include "../feature/binary_stream.h" #endif +#if ENABLED(MEATPACK) + #include "../feature/meatpack.h" +#endif + #if ENABLED(POWER_LOSS_RECOVERY) #include "../feature/powerloss.h" #endif @@ -55,6 +60,9 @@ GCodeQueue queue; #include "../feature/repeat.h" #endif +// Frequently used G-code strings +PGMSTR(G28_STR, "G28"); + /** * GCode line number handling. Hosts may opt to include line numbers when * sending commands to Marlin, and lines will be checked for sequentiality. @@ -81,7 +89,7 @@ char GCodeQueue::command_buffer[BUFSIZE][MAX_CMD_SIZE]; * The port that the command was received on */ #if HAS_MULTI_SERIAL - int16_t GCodeQueue::port[BUFSIZE]; + serial_index_t GCodeQueue::port[BUFSIZE]; #endif /** @@ -128,11 +136,11 @@ void GCodeQueue::clear() { */ void GCodeQueue::_commit_command(bool say_ok #if HAS_MULTI_SERIAL - , int16_t p/*=-1*/ + , serial_index_t serial_ind/*=-1*/ #endif ) { send_ok[index_w] = say_ok; - TERN_(HAS_MULTI_SERIAL, port[index_w] = p); + TERN_(HAS_MULTI_SERIAL, port[index_w] = serial_ind); TERN_(POWER_LOSS_RECOVERY, recovery.commit_sdpos(index_w)); if (++index_w >= BUFSIZE) index_w = 0; length++; @@ -145,14 +153,14 @@ void GCodeQueue::_commit_command(bool say_ok */ bool GCodeQueue::_enqueue(const char* cmd, bool say_ok/*=false*/ #if HAS_MULTI_SERIAL - , int16_t pn/*=-1*/ + , serial_index_t serial_ind/*=-1*/ #endif ) { if (*cmd == ';' || length >= BUFSIZE) return false; strcpy(command_buffer[index_w], cmd); _commit_command(say_ok #if HAS_MULTI_SERIAL - , pn + , serial_ind #endif ); return true; @@ -281,9 +289,9 @@ void GCodeQueue::enqueue_now_P(PGM_P const pgcode) { */ void GCodeQueue::ok_to_send() { #if HAS_MULTI_SERIAL - const int16_t pn = command_port(); - if (pn < 0) return; - PORT_REDIRECT(pn); // Reply to the serial port that sent the command + const serial_index_t serial_ind = command_port(); + if (serial_ind < 0) return; + PORT_REDIRECT(SERIAL_PORTMASK(serial_ind)); // Reply to the serial port that sent the command #endif if (!send_ok[index_r]) return; SERIAL_ECHOPGM(STR_OK); @@ -306,14 +314,14 @@ void GCodeQueue::ok_to_send() { * indicate that a command needs to be re-sent. */ void GCodeQueue::flush_and_request_resend() { - const int16_t pn = command_port(); + const serial_index_t serial_ind = command_port(); #if HAS_MULTI_SERIAL - if (pn < 0) return; - PORT_REDIRECT(pn); // Reply to the serial port that sent the command + if (serial_ind < 0) return; // Never mind. Command came from SD or Flash Drive + PORT_REDIRECT(SERIAL_PORTMASK(serial_ind)); // Reply to the serial port that sent the command #endif SERIAL_FLUSH(); SERIAL_ECHOPGM(STR_RESEND); - SERIAL_ECHOLN(last_N[pn] + 1); + SERIAL_ECHOLN(last_N[serial_ind] + 1); ok_to_send(); } @@ -340,14 +348,14 @@ inline int read_serial(const uint8_t index) { } } -void GCodeQueue::gcode_line_error(PGM_P const err, const int8_t pn) { - PORT_REDIRECT(pn); // Reply to the serial port that sent the command +void GCodeQueue::gcode_line_error(PGM_P const err, const serial_index_t serial_ind) { + PORT_REDIRECT(SERIAL_PORTMASK(serial_ind)); // Reply to the serial port that sent the command SERIAL_ERROR_START(); serialprintPGM(err); - SERIAL_ECHOLN(last_N[pn]); - while (read_serial(pn) != -1); // Clear out the RX buffer + SERIAL_ECHOLN(last_N[serial_ind]); + while (read_serial(serial_ind) != -1); // Clear out the RX buffer flush_and_request_resend(); - serial_count[pn] = 0; + serial_count[serial_ind] = 0; } FORCE_INLINE bool is_M29(const char * const cmd) { // matches "M29" & "M29 ", but not "M290", etc @@ -465,103 +473,114 @@ void GCodeQueue::get_serial_commands() { * Loop while serial characters are incoming and the queue is not full */ while (length < BUFSIZE && serial_data_available()) { - LOOP_L_N(i, NUM_SERIAL) { + LOOP_L_N(p, NUM_SERIAL) { - const int c = read_serial(i); + const int c = read_serial(p); if (c < 0) continue; - const char serial_char = c; + #if ENABLED(MEATPACK) + meatpack.handle_rx_char(uint8_t(c), p); + char c_res[2] = { 0, 0 }; + const uint8_t char_count = meatpack.get_result_char(c_res); + #else + constexpr uint8_t char_count = 1; + #endif - if (ISEOL(serial_char)) { + LOOP_L_N(char_index, char_count) { + const char serial_char = TERN(MEATPACK, c_res[char_index], c); - // Reset our state, continue if the line was empty - if (process_line_done(serial_input_state[i], serial_line_buffer[i], serial_count[i])) - continue; + if (ISEOL(serial_char)) { - char* command = serial_line_buffer[i]; + // Reset our state, continue if the line was empty + if (process_line_done(serial_input_state[p], serial_line_buffer[p], serial_count[p])) + continue; - while (*command == ' ') command++; // Skip leading spaces - char *npos = (*command == 'N') ? command : nullptr; // Require the N parameter to start the line + char* command = serial_line_buffer[p]; - if (npos) { + while (*command == ' ') command++; // Skip leading spaces + char *npos = (*command == 'N') ? command : nullptr; // Require the N parameter to start the line - const bool M110 = !!strstr_P(command, PSTR("M110")); + if (npos) { - if (M110) { - char* n2pos = strchr(command + 4, 'N'); - if (n2pos) npos = n2pos; + const bool M110 = !!strstr_P(command, PSTR("M110")); + + if (M110) { + char* n2pos = strchr(command + 4, 'N'); + if (n2pos) npos = n2pos; + } + + const long gcode_N = strtol(npos + 1, nullptr, 10); + + if (gcode_N != last_N[p] + 1 && !M110) + return gcode_line_error(PSTR(STR_ERR_LINE_NO), p); + + char *apos = strrchr(command, '*'); + if (apos) { + uint8_t checksum = 0, count = uint8_t(apos - command); + while (count) checksum ^= command[--count]; + if (strtol(apos + 1, nullptr, 10) != checksum) + return gcode_line_error(PSTR(STR_ERR_CHECKSUM_MISMATCH), p); + } + else + return gcode_line_error(PSTR(STR_ERR_NO_CHECKSUM), p); + + last_N[p] = gcode_N; } + #if ENABLED(SDSUPPORT) + // Pronterface "M29" and "M29 " has no line number + else if (card.flag.saving && !is_M29(command)) + return gcode_line_error(PSTR(STR_ERR_NO_CHECKSUM), p); + #endif - const long gcode_N = strtol(npos + 1, nullptr, 10); + // + // Movement commands give an alert when the machine is stopped + // - if (gcode_N != last_N[i] + 1 && !M110) - return gcode_line_error(PSTR(STR_ERR_LINE_NO), i); - - char *apos = strrchr(command, '*'); - if (apos) { - uint8_t checksum = 0, count = uint8_t(apos - command); - while (count) checksum ^= command[--count]; - if (strtol(apos + 1, nullptr, 10) != checksum) - return gcode_line_error(PSTR(STR_ERR_CHECKSUM_MISMATCH), i); - } - else - return gcode_line_error(PSTR(STR_ERR_NO_CHECKSUM), i); - - last_N[i] = gcode_N; - } - #if ENABLED(SDSUPPORT) - // Pronterface "M29" and "M29 " has no line number - else if (card.flag.saving && !is_M29(command)) - return gcode_line_error(PSTR(STR_ERR_NO_CHECKSUM), i); - #endif - - // - // Movement commands give an alert when the machine is stopped - // - - if (IsStopped()) { - char* gpos = strchr(command, 'G'); - if (gpos) { - switch (strtol(gpos + 1, nullptr, 10)) { - case 0: case 1: - #if ENABLED(ARC_SUPPORT) - case 2: case 3: - #endif - #if ENABLED(BEZIER_CURVE_SUPPORT) - case 5: - #endif - PORT_REDIRECT(i); // Reply to the serial port that sent the command - SERIAL_ECHOLNPGM(STR_ERR_STOPPED); - LCD_MESSAGEPGM(MSG_STOPPED); - break; + if (IsStopped()) { + char* gpos = strchr(command, 'G'); + if (gpos) { + switch (strtol(gpos + 1, nullptr, 10)) { + case 0: case 1: + #if ENABLED(ARC_SUPPORT) + case 2: case 3: + #endif + #if ENABLED(BEZIER_CURVE_SUPPORT) + case 5: + #endif + PORT_REDIRECT(SERIAL_PORTMASK(p)); // Reply to the serial port that sent the command + SERIAL_ECHOLNPGM(STR_ERR_STOPPED); + LCD_MESSAGEPGM(MSG_STOPPED); + break; + } } } - } - #if DISABLED(EMERGENCY_PARSER) - // Process critical commands early - if (command[0] == 'M') switch (command[3]) { - case '8': if (command[2] == '0' && command[1] == '1') { wait_for_heatup = false; TERN_(HAS_LCD_MENU, wait_for_user = false); } break; - case '2': if (command[2] == '1' && command[1] == '1') kill(M112_KILL_STR, nullptr, true); break; - case '0': if (command[1] == '4' && command[2] == '1') quickstop_stepper(); break; - } - #endif - - #if defined(NO_TIMEOUTS) && NO_TIMEOUTS > 0 - last_command_time = ms; - #endif - - // Add the command to the queue - _enqueue(serial_line_buffer[i], true - #if HAS_MULTI_SERIAL - , i + #if DISABLED(EMERGENCY_PARSER) + // Process critical commands early + if (command[0] == 'M') switch (command[3]) { + case '8': if (command[2] == '0' && command[1] == '1') { wait_for_heatup = false; TERN_(HAS_LCD_MENU, wait_for_user = false); } break; + case '2': if (command[2] == '1' && command[1] == '1') kill(M112_KILL_STR, nullptr, true); break; + case '0': if (command[1] == '4' && command[2] == '1') quickstop_stepper(); break; + } #endif - ); - } - else - process_stream_char(serial_char, serial_input_state[i], serial_line_buffer[i], serial_count[i]); - } // for NUM_SERIAL + #if defined(NO_TIMEOUTS) && NO_TIMEOUTS > 0 + last_command_time = ms; + #endif + + // Add the command to the queue + _enqueue(serial_line_buffer[p], true + #if HAS_MULTI_SERIAL + , p + #endif + ); + } + else + process_stream_char(serial_char, serial_input_state[p], serial_line_buffer[p], serial_count[p]); + + } // char_count loop + + } // NUM_SERIAL loop } // queue has space, serial has data } diff --git a/Marlin/src/gcode/queue.h b/Marlin/src/gcode/queue.h index 966af2871f..d677146a7d 100644 --- a/Marlin/src/gcode/queue.h +++ b/Marlin/src/gcode/queue.h @@ -56,12 +56,9 @@ public: * The port that the command was received on */ #if HAS_MULTI_SERIAL - static int16_t port[BUFSIZE]; + static serial_index_t port[BUFSIZE]; #endif - - static int16_t command_port() { - return TERN0(HAS_MULTI_SERIAL, port[index_r]); - } + static inline serial_index_t command_port() { return TERN0(HAS_MULTI_SERIAL, port[index_r]); } GCodeQueue(); @@ -159,13 +156,13 @@ private: static void _commit_command(bool say_ok #if HAS_MULTI_SERIAL - , int16_t p=-1 + , serial_index_t serial_ind=-1 #endif ); static bool _enqueue(const char* cmd, bool say_ok=false #if HAS_MULTI_SERIAL - , int16_t p=-1 + , serial_index_t serial_ind=-1 #endif ); @@ -181,8 +178,10 @@ private: */ static bool enqueue_one(const char* cmd); - static void gcode_line_error(PGM_P const err, const int8_t pn); + static void gcode_line_error(PGM_P const err, const serial_index_t serial_ind); }; extern GCodeQueue queue; + +extern const char G28_STR[]; diff --git a/Marlin/src/gcode/sd/M1001.cpp b/Marlin/src/gcode/sd/M1001.cpp index 406cd074c3..1cf700ae26 100644 --- a/Marlin/src/gcode/sd/M1001.cpp +++ b/Marlin/src/gcode/sd/M1001.cpp @@ -44,7 +44,7 @@ #endif #if HAS_LEDS_OFF_FLAG - #include "../../MarlinCore.h" // for wait_for_user_response + #include "../../MarlinCore.h" // for wait_for_user_response() #include "../../feature/leds/printer_event_leds.h" #endif @@ -82,7 +82,7 @@ void GcodeSuite::M1001() { // Announce SD file completion { - PORT_REDIRECT(SERIAL_BOTH); + PORT_REDIRECT(SERIAL_ALL); SERIAL_ECHOLNPGM(STR_FILE_PRINTED); } @@ -92,7 +92,7 @@ void GcodeSuite::M1001() { printerEventLEDs.onPrintCompleted(); TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired_P(GET_TEXT(MSG_PRINT_DONE))); TERN_(HOST_PROMPT_SUPPORT, host_prompt_do(PROMPT_USER_CONTINUE, GET_TEXT(MSG_PRINT_DONE), CONTINUE_STR)); - wait_for_user_response(1000UL * TERN(HAS_LCD_MENU, PE_LEDS_COMPLETED_TIME, 30)); + wait_for_user_response(SEC_TO_MS(TERN(HAS_LCD_MENU, PE_LEDS_COMPLETED_TIME, 30))); printerEventLEDs.onResumeAfterWait(); } #endif diff --git a/Marlin/src/gcode/sd/M27.cpp b/Marlin/src/gcode/sd/M27.cpp index 8592b8af25..a76070fda8 100644 --- a/Marlin/src/gcode/sd/M27.cpp +++ b/Marlin/src/gcode/sd/M27.cpp @@ -36,15 +36,17 @@ void GcodeSuite::M27() { if (parser.seen('C')) { SERIAL_ECHOPGM("Current file: "); card.printFilename(); + return; } #if ENABLED(AUTO_REPORT_SD_STATUS) - else if (parser.seenval('S')) - card.set_auto_report_interval(parser.value_byte()); + if (parser.seenval('S')) { + card.auto_reporter.set_interval(parser.value_byte()); + return; + } #endif - else - card.report_status(); + card.report_status(); } #endif // SDSUPPORT diff --git a/Marlin/src/gcode/temp/M104_M109.cpp b/Marlin/src/gcode/temp/M104_M109.cpp index 90e1b601e4..07e46e1775 100644 --- a/Marlin/src/gcode/temp/M104_M109.cpp +++ b/Marlin/src/gcode/temp/M104_M109.cpp @@ -45,7 +45,7 @@ #endif #endif -#if ENABLED(SINGLENOZZLE) +#if ENABLED(SINGLENOZZLE_STANDBY_TEMP) #include "../../module/tool_change.h" #endif @@ -88,7 +88,7 @@ void GcodeSuite::M104() { if (got_temp) { #if ENABLED(SINGLENOZZLE_STANDBY_TEMP) - singlenozzle_temp[target_extruder] = temp; + thermalManager.singlenozzle_temp[target_extruder] = temp; if (target_extruder != active_extruder) return; #endif thermalManager.setTargetHotend(temp, target_extruder); @@ -166,7 +166,7 @@ void GcodeSuite::M109() { if (got_temp) { #if ENABLED(SINGLENOZZLE_STANDBY_TEMP) - singlenozzle_temp[target_extruder] = temp; + thermalManager.singlenozzle_temp[target_extruder] = temp; if (target_extruder != active_extruder) return; #endif thermalManager.setTargetHotend(temp, target_extruder); diff --git a/Marlin/src/gcode/temp/M155.cpp b/Marlin/src/gcode/temp/M155.cpp index 30129a0e6f..48c23986ae 100644 --- a/Marlin/src/gcode/temp/M155.cpp +++ b/Marlin/src/gcode/temp/M155.cpp @@ -33,7 +33,7 @@ void GcodeSuite::M155() { if (parser.seenval('S')) - thermalManager.set_auto_report_interval(parser.value_byte()); + thermalManager.auto_reporter.set_interval(parser.value_byte()); } diff --git a/Marlin/src/inc/Conditionals_LCD.h b/Marlin/src/inc/Conditionals_LCD.h index c95262fced..976b8aaf8e 100644 --- a/Marlin/src/inc/Conditionals_LCD.h +++ b/Marlin/src/inc/Conditionals_LCD.h @@ -320,6 +320,7 @@ // FSMC/SPI TFT Panels (LVGL) #if ENABLED(TFT_LVGL_UI) #define HAS_TFT_LVGL_UI 1 + #define SERIAL_RUNTIME_HOOK 1 #endif // FSMC/SPI TFT Panels @@ -1155,36 +1156,37 @@ #endif #endif -#if ENABLED(TFT_COLOR_UI) && TFT_HEIGHT == 240 - #if ENABLED(TFT_INTERFACE_SPI) - #define TFT_320x240_SPI - #elif ENABLED(TFT_INTERFACE_FSMC) - #define TFT_320x240 - #endif -#elif ENABLED(TFT_COLOR_UI) && TFT_HEIGHT == 320 - #if ENABLED(TFT_INTERFACE_SPI) - #define TFT_480x320_SPI - #elif ENABLED(TFT_INTERFACE_FSMC) - #define TFT_480x320 - #endif -#elif ENABLED(TFT_COLOR_UI) && TFT_HEIGHT == 272 - #if ENABLED(TFT_INTERFACE_SPI) - #define TFT_480x272_SPI - #elif ENABLED(TFT_INTERFACE_FSMC) - #define TFT_480x272 +#if ENABLED(TFT_COLOR_UI) + #if TFT_HEIGHT == 240 + #if ENABLED(TFT_INTERFACE_SPI) + #define TFT_320x240_SPI + #elif ENABLED(TFT_INTERFACE_FSMC) + #define TFT_320x240 + #endif + #elif TFT_HEIGHT == 320 + #if ENABLED(TFT_INTERFACE_SPI) + #define TFT_480x320_SPI + #elif ENABLED(TFT_INTERFACE_FSMC) + #define TFT_480x320 + #endif + #elif TFT_HEIGHT == 272 + #if ENABLED(TFT_INTERFACE_SPI) + #define TFT_480x272_SPI + #elif ENABLED(TFT_INTERFACE_FSMC) + #define TFT_480x272 + #endif #endif #endif -// Fewer lines with touch buttons on-screen #if EITHER(TFT_320x240, TFT_320x240_SPI) #define HAS_UI_320x240 1 - #define LCD_HEIGHT TERN(TOUCH_SCREEN, 6, 7) #elif EITHER(TFT_480x320, TFT_480x320_SPI) #define HAS_UI_480x320 1 - #define LCD_HEIGHT TERN(TOUCH_SCREEN, 6, 7) #elif EITHER(TFT_480x272, TFT_480x272_SPI) #define HAS_UI_480x272 1 - #define LCD_HEIGHT TERN(TOUCH_SCREEN, 6, 7) +#endif +#if ANY(HAS_UI_320x240, HAS_UI_480x320, HAS_UI_480x272) + #define LCD_HEIGHT TERN(TOUCH_SCREEN, 6, 7) // Fewer lines with touch buttons onscreen #endif // This emulated DOGM has 'touch/xpt2046', not 'tft/xpt2046' diff --git a/Marlin/src/inc/MarlinConfig.h b/Marlin/src/inc/MarlinConfig.h index 2eafa2b417..8fdb4b9bae 100644 --- a/Marlin/src/inc/MarlinConfig.h +++ b/Marlin/src/inc/MarlinConfig.h @@ -55,3 +55,5 @@ #include "../core/serial.h" #endif + +#include "../core/multi_language.h" diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h index e68a2482f4..c10c4de540 100644 --- a/Marlin/src/inc/SanityCheck.h +++ b/Marlin/src/inc/SanityCheck.h @@ -357,10 +357,6 @@ #error "FILAMENT_CHANGE_LOAD_LENGTH is now FILAMENT_CHANGE_FAST_LOAD_LENGTH." #elif defined(LEVEL_CORNERS_INSET) #error "LEVEL_CORNERS_INSET is now LEVEL_CORNERS_INSET_LFRB." -#elif ENABLED(LEVEL_BED_CORNERS) && !defined(LEVEL_CORNERS_INSET_LFRB) - #error "LEVEL_BED_CORNERS requires LEVEL_CORNERS_INSET_LFRB values." -#elif BOTH(LEVEL_CORNERS_USE_PROBE, SENSORLESS_PROBING) - #error "LEVEL_CORNERS_USE_PROBE is incompatible with SENSORLESS_PROBING." #elif defined(BEZIER_JERK_CONTROL) #error "BEZIER_JERK_CONTROL is now S_CURVE_ACCELERATION." #elif HAS_JUNCTION_DEVIATION && defined(JUNCTION_DEVIATION_FACTOR) @@ -709,6 +705,10 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #endif #endif +#if ENABLED(USE_M73_REMAINING_TIME) && DISABLED(LCD_SET_PROGRESS_MANUALLY) + #error "USE_M73_REMAINING_TIME requires LCD_SET_PROGRESS_MANUALLY" +#endif + #if !HAS_LCD_MENU && ENABLED(SD_REPRINT_LAST_SELECTED_FILE) #error "SD_REPRINT_LAST_SELECTED_FILE currently requires a Marlin-native LCD menu." #endif @@ -802,8 +802,6 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #if ENABLED(BABYSTEP_XY) static_assert(BABYSTEP_MULTIPLICATOR_XY <= 0.25f, "BABYSTEP_MULTIPLICATOR_XY must be less than or equal to 0.25mm."); #endif - #elif ENABLED(BABYSTEP_DISPLAY_TOTAL) && ANY(TFT_320x240, TFT_320x240_SPI, TFT_480x320, TFT_480x320_SPI) - #error "New Color UI (TFT_320x240, TFT_320x240_SPI, TFT_480x320, TFT_480x320_SPI) does not support BABYSTEP_DISPLAY_TOTAL yet." #endif #endif @@ -1429,6 +1427,18 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #endif +#if ENABLED(LEVEL_BED_CORNERS) + #ifndef LEVEL_CORNERS_INSET_LFRB + #error "LEVEL_BED_CORNERS requires LEVEL_CORNERS_INSET_LFRB values." + #elif ENABLED(LEVEL_CORNERS_USE_PROBE) + #if !HAS_BED_PROBE + #error "LEVEL_CORNERS_USE_PROBE requires a real probe." + #elif ENABLED(SENSORLESS_PROBING) + #error "LEVEL_CORNERS_USE_PROBE is incompatible with SENSORLESS_PROBING." + #endif + #endif +#endif + /** * Allow only one bed leveling option to be defined */ @@ -1931,16 +1941,16 @@ static_assert(hbm[Z_AXIS] >= 0, "HOMING_BUMP_MM.Z must be greater than or equal * Basic multi hotend duplication mode */ #if ENABLED(MULTI_NOZZLE_DUPLICATION) - #if HOTENDS < 2 - #error "MULTI_NOZZLE_DUPLICATION requires 2 or more hotends." + #if ENABLED(SINGLENOZZLE) + #error "MULTI_NOZZLE_DUPLICATION is incompatible with SINGLENOZZLE." #elif ENABLED(DUAL_X_CARRIAGE) #error "MULTI_NOZZLE_DUPLICATION is incompatible with DUAL_X_CARRIAGE." - #elif ENABLED(SINGLENOZZLE) - #error "MULTI_NOZZLE_DUPLICATION is incompatible with SINGLENOZZLE." #elif ENABLED(MIXING_EXTRUDER) #error "MULTI_NOZZLE_DUPLICATION is incompatible with MIXING_EXTRUDER." #elif ENABLED(SWITCHING_EXTRUDER) #error "MULTI_NOZZLE_DUPLICATION is incompatible with SWITCHING_EXTRUDER." + #elif HOTENDS < 2 + #error "MULTI_NOZZLE_DUPLICATION requires 2 or more hotends." #endif #endif @@ -3291,6 +3301,14 @@ static_assert( _ARR_TEST(3,0) && _ARR_TEST(3,1) && _ARR_TEST(3,2) #endif #endif + +/** + * Sanity Check for MEATPACK and BINARY_FILE_TRANSFER Features + */ +#if BOTH(MEATPACK, BINARY_FILE_TRANSFER) + #error "Either enable MEATPACK or enable BINARY_FILE_TRANSFER." +#endif + /** * Sanity check for valid stepper driver types */ diff --git a/Marlin/src/inc/Version.h b/Marlin/src/inc/Version.h index af69c47b24..3ec1f3c1c0 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 "2021-01-17" + #define STRING_DISTRIBUTION_DATE "2021-01-30" #endif /** diff --git a/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp b/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp index 84c477fbde..635751b3f5 100644 --- a/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp +++ b/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp @@ -471,7 +471,6 @@ void MarlinUI::clear_lcd() { lcd.clear(); } // Show the Marlin logo and short build version // After a delay show the website URL // - extern const char NUL_STR[]; logo_lines(NUL_STR); CENTER_OR_SCROLL(SHORT_BUILD_VERSION, 1500); CENTER_OR_SCROLL(MARLIN_WEBSITE_URL, 1500); diff --git a/Marlin/src/lcd/dogm/dogm_Statusscreen.h b/Marlin/src/lcd/dogm/dogm_Statusscreen.h index 15578e21d9..61fee3e048 100644 --- a/Marlin/src/lcd/dogm/dogm_Statusscreen.h +++ b/Marlin/src/lcd/dogm/dogm_Statusscreen.h @@ -193,7 +193,7 @@ #define STATUS_LOGO_HEIGHT (sizeof(status_logo_bmp) / (STATUS_LOGO_BYTEWIDTH)) #endif #ifndef STATUS_LOGO_Y - #define STATUS_LOGO_Y _MAX(0L, (28L - _MIN(28L, STATUS_LOGO_HEIGHT)) / 2L) + #define STATUS_LOGO_Y _MAX(0U, (28U - _MIN(28U, STATUS_LOGO_HEIGHT)) / 2U) #endif static_assert( sizeof(status_logo_bmp) == (STATUS_LOGO_BYTEWIDTH) * (STATUS_LOGO_HEIGHT), diff --git a/Marlin/src/lcd/dogm/marlinui_DOGM.cpp b/Marlin/src/lcd/dogm/marlinui_DOGM.cpp index c326b89aa8..c7c5908b36 100644 --- a/Marlin/src/lcd/dogm/marlinui_DOGM.cpp +++ b/Marlin/src/lcd/dogm/marlinui_DOGM.cpp @@ -54,6 +54,7 @@ #include "../../sd/cardreader.h" #include "../../module/temperature.h" #include "../../module/printcounter.h" +#include "../../MarlinCore.h" #if ENABLED(SDSUPPORT) #include "../../libs/duration_t.h" @@ -455,20 +456,22 @@ void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop inline void draw_boxed_string(const u8g_uint_t x, const u8g_uint_t y, PGM_P const pstr, const bool inv) { const u8g_uint_t len = utf8_strlen_P(pstr), by = (y + 1) * (MENU_FONT_HEIGHT); - const pixel_len_t bw = len * (MENU_FONT_WIDTH), bx = x * (MENU_FONT_WIDTH); + const u8g_uint_t prop = USE_WIDE_GLYPH ? 2 : 1; + const pixel_len_t bw = len * prop * (MENU_FONT_WIDTH), bx = x * prop * (MENU_FONT_WIDTH); if (inv) { u8g.setColorIndex(1); - u8g.drawBox(bx - 1, by - (MENU_FONT_ASCENT) + 1, bw + 2, MENU_FONT_HEIGHT - 1); + u8g.drawBox(bx / prop - 1, by - (MENU_FONT_ASCENT) + 1, bw / prop + 2, MENU_FONT_HEIGHT - 1); u8g.setColorIndex(0); } - lcd_put_u8str_P(bx, by, pstr); + lcd_put_u8str_P(bx / prop, by, pstr); if (inv) u8g.setColorIndex(1); } void MenuItem_confirm::draw_select_screen(PGM_P const yes, PGM_P const no, const bool yesno, PGM_P const pref, const char * const string/*=nullptr*/, PGM_P const suff/*=nullptr*/) { ui.draw_select_screen_prompt(pref, string, suff); draw_boxed_string(1, LCD_HEIGHT - 1, no, !yesno); - draw_boxed_string(LCD_WIDTH - (utf8_strlen_P(yes) + 1), LCD_HEIGHT - 1, yes, yesno); + const u8g_uint_t xpos = (LCD_WIDTH) / (USE_WIDE_GLYPH ? 2 : 1); + draw_boxed_string(xpos - (utf8_strlen_P(yes) + 1), LCD_HEIGHT - 1, yes, yesno); } #if ENABLED(SDSUPPORT) diff --git a/Marlin/src/lcd/dogm/status_screen_DOGM.cpp b/Marlin/src/lcd/dogm/status_screen_DOGM.cpp index 985041ede5..8ae6ab6627 100644 --- a/Marlin/src/lcd/dogm/status_screen_DOGM.cpp +++ b/Marlin/src/lcd/dogm/status_screen_DOGM.cpp @@ -40,6 +40,10 @@ #include "../../gcode/parser.h" // for units (and volumetric) +#if ENABLED(LCD_SHOW_E_TOTAL) + #include "../../MarlinCore.h" // for printingIsActive(), marlin_state and MF_SD_COMPLETE +#endif + #if ENABLED(FILAMENT_LCD_DISPLAY) #include "../../feature/filwidth.h" #include "../../module/planner.h" diff --git a/Marlin/src/lcd/dwin/e3v2/dwin.cpp b/Marlin/src/lcd/dwin/e3v2/dwin.cpp index e1655d0ed9..39f161f5ad 100644 --- a/Marlin/src/lcd/dwin/e3v2/dwin.cpp +++ b/Marlin/src/lcd/dwin/e3v2/dwin.cpp @@ -132,8 +132,9 @@ #define FEEDRATE_E (60) -// Mininum unit (0.1) : multiple (10) -#define MINUNITMULT 10 +// Minimum unit (0.1) : multiple (10) +#define UNITFDIGITS 1 +#define MINUNITMULT pow(10, UNITFDIGITS) #define ENCODER_WAIT 20 #define DWIN_SCROLL_UPDATE_INTERVAL 2000 @@ -1171,8 +1172,8 @@ void HMI_Move_X() { } NOLESS(HMI_ValueStruct.Move_X_scale, (X_MIN_POS) * MINUNITMULT); NOMORE(HMI_ValueStruct.Move_X_scale, (X_MAX_POS) * MINUNITMULT); - current_position.x = HMI_ValueStruct.Move_X_scale / 10; - DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Select_Color, 3, 1, 216, MBASE(1), HMI_ValueStruct.Move_X_scale); + current_position.x = HMI_ValueStruct.Move_X_scale / MINUNITMULT; + DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Select_Color, 3, UNITFDIGITS, 216, MBASE(1), HMI_ValueStruct.Move_X_scale); DWIN_UpdateLCD(); } } @@ -1194,8 +1195,8 @@ void HMI_Move_Y() { } NOLESS(HMI_ValueStruct.Move_Y_scale, (Y_MIN_POS) * MINUNITMULT); NOMORE(HMI_ValueStruct.Move_Y_scale, (Y_MAX_POS) * MINUNITMULT); - current_position.y = HMI_ValueStruct.Move_Y_scale / 10; - DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Select_Color, 3, 1, 216, MBASE(2), HMI_ValueStruct.Move_Y_scale); + current_position.y = HMI_ValueStruct.Move_Y_scale / MINUNITMULT; + DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Select_Color, 3, UNITFDIGITS, 216, MBASE(2), HMI_ValueStruct.Move_Y_scale); DWIN_UpdateLCD(); } } @@ -1206,7 +1207,7 @@ void HMI_Move_Z() { if (Apply_Encoder(encoder_diffState, HMI_ValueStruct.Move_Z_scale)) { checkkey = AxisMove; EncoderRate.enabled = false; - DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Color_Bg_Black, 3, 1, 216, MBASE(3), HMI_ValueStruct.Move_Z_scale); + DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Color_Bg_Black, 3, UNITFDIGITS, 216, MBASE(3), HMI_ValueStruct.Move_Z_scale); if (!planner.is_full()) { // Wait for planner moves to finish! planner.synchronize(); @@ -1217,8 +1218,8 @@ void HMI_Move_Z() { } NOLESS(HMI_ValueStruct.Move_Z_scale, Z_MIN_POS * MINUNITMULT); NOMORE(HMI_ValueStruct.Move_Z_scale, Z_MAX_POS * MINUNITMULT); - current_position.z = HMI_ValueStruct.Move_Z_scale / 10; - DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Select_Color, 3, 1, 216, MBASE(3), HMI_ValueStruct.Move_Z_scale); + current_position.z = HMI_ValueStruct.Move_Z_scale / MINUNITMULT; + DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Select_Color, 3, UNITFDIGITS, 216, MBASE(3), HMI_ValueStruct.Move_Z_scale); DWIN_UpdateLCD(); } } @@ -1233,7 +1234,7 @@ void HMI_Move_Z() { checkkey = AxisMove; EncoderRate.enabled = false; last_E_scale = HMI_ValueStruct.Move_E_scale; - DWIN_Draw_Signed_Float(font8x16, Color_Bg_Black, 3, 1, 216, MBASE(4), HMI_ValueStruct.Move_E_scale); + DWIN_Draw_Signed_Float(font8x16, Color_Bg_Black, 3, UNITFDIGITS, 216, MBASE(4), HMI_ValueStruct.Move_E_scale); if (!planner.is_full()) { planner.synchronize(); // Wait for planner moves to finish! planner.buffer_line(current_position, MMM_TO_MMS(FEEDRATE_E), active_extruder); @@ -1245,8 +1246,8 @@ void HMI_Move_Z() { HMI_ValueStruct.Move_E_scale = last_E_scale + (EXTRUDE_MAXLENGTH) * MINUNITMULT; else if ((last_E_scale - HMI_ValueStruct.Move_E_scale) > (EXTRUDE_MAXLENGTH) * MINUNITMULT) HMI_ValueStruct.Move_E_scale = last_E_scale - (EXTRUDE_MAXLENGTH) * MINUNITMULT; - current_position.e = HMI_ValueStruct.Move_E_scale / 10; - DWIN_Draw_Signed_Float(font8x16, Select_Color, 3, 1, 216, MBASE(4), HMI_ValueStruct.Move_E_scale); + current_position.e = HMI_ValueStruct.Move_E_scale / MINUNITMULT; + DWIN_Draw_Signed_Float(font8x16, Select_Color, 3, UNITFDIGITS, 216, MBASE(4), HMI_ValueStruct.Move_E_scale); DWIN_UpdateLCD(); } } @@ -1503,7 +1504,7 @@ void HMI_MaxAccelerationXYZE() { NOMORE(HMI_ValueStruct.Max_Jerk, default_max_jerk[HMI_flag.jerk_axis] * 2 * MINUNITMULT); NOLESS(HMI_ValueStruct.Max_Jerk, (MIN_MAXJERK) * MINUNITMULT); // MaxJerk value - DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Select_Color, 3, 1, 210, MBASE(select_jerk.now), HMI_ValueStruct.Max_Jerk); + DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Select_Color, 3, UNITFDIGITS, 210, MBASE(select_jerk.now), HMI_ValueStruct.Max_Jerk); } } @@ -1525,7 +1526,7 @@ void HMI_StepXYZE() { NOMORE(HMI_ValueStruct.Max_Step, 999.9 * MINUNITMULT); NOLESS(HMI_ValueStruct.Max_Step, MIN_STEP); // Step value - DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Select_Color, 3, 1, 210, MBASE(select_step.now), HMI_ValueStruct.Max_Step); + DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Select_Color, 3, UNITFDIGITS, 210, MBASE(select_step.now), HMI_ValueStruct.Max_Step); } } @@ -2317,13 +2318,12 @@ void HMI_Prepare() { select_axis.reset(); Draw_Move_Menu(); - DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Color_Bg_Black, 3, 1, 216, MBASE(1), current_position.x * MINUNITMULT); - DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Color_Bg_Black, 3, 1, 216, MBASE(2), current_position.y * MINUNITMULT); - DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Color_Bg_Black, 3, 1, 216, MBASE(3), current_position.z * MINUNITMULT); + DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Color_Bg_Black, 3, UNITFDIGITS, 216, MBASE(1), current_position.x * MINUNITMULT); + DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Color_Bg_Black, 3, UNITFDIGITS, 216, MBASE(2), current_position.y * MINUNITMULT); + DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Color_Bg_Black, 3, UNITFDIGITS, 216, MBASE(3), current_position.z * MINUNITMULT); #if HAS_HOTEND - queue.inject_P(PSTR("G92 E0")); - current_position.e = HMI_ValueStruct.Move_E_scale = 0; - DWIN_Draw_Signed_Float(font8x16, Color_Bg_Black, 3, 1, 216, MBASE(4), 0); + HMI_ValueStruct.Move_E_scale = current_position.e * MINUNITMULT; + DWIN_Draw_Signed_Float(font8x16, Color_Bg_Black, 3, 1, 216, MBASE(4), HMI_ValueStruct.Move_E_scale); #endif break; case PREPARE_CASE_DISA: // Disable steppers @@ -2573,7 +2573,7 @@ void HMI_AxisMove() { if (HMI_flag.ETempTooLow_flag) { if (encoder_diffState == ENCODER_DIFF_ENTER) { HMI_flag.ETempTooLow_flag = false; - current_position.e = HMI_ValueStruct.Move_E_scale = 0; + HMI_ValueStruct.Move_E_scale = current_position.e * MINUNITMULT; Draw_Move_Menu(); DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Color_Bg_Black, 3, 1, 216, MBASE(1), HMI_ValueStruct.Move_X_scale); DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Color_Bg_Black, 3, 1, 216, MBASE(2), HMI_ValueStruct.Move_Y_scale); @@ -3019,11 +3019,11 @@ inline void Draw_Max_Accel_Menu() { Draw_Back_First(); LOOP_L_N(i, 3 + ENABLED(HAS_HOTEND)) Draw_Menu_Line(i + 1, ICON_MaxSpeedJerkX + i); - DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Color_Bg_Black, 3, 1, 210, MBASE(1), planner.max_jerk[X_AXIS] * MINUNITMULT); - DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Color_Bg_Black, 3, 1, 210, MBASE(2), planner.max_jerk[Y_AXIS] * MINUNITMULT); - DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Color_Bg_Black, 3, 1, 210, MBASE(3), planner.max_jerk[Z_AXIS] * MINUNITMULT); + DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Color_Bg_Black, 3, UNITFDIGITS, 210, MBASE(1), planner.max_jerk[X_AXIS] * MINUNITMULT); + DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Color_Bg_Black, 3, UNITFDIGITS, 210, MBASE(2), planner.max_jerk[Y_AXIS] * MINUNITMULT); + DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Color_Bg_Black, 3, UNITFDIGITS, 210, MBASE(3), planner.max_jerk[Z_AXIS] * MINUNITMULT); #if HAS_HOTEND - DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Color_Bg_Black, 3, 1, 210, MBASE(4), planner.max_jerk[E_AXIS] * MINUNITMULT); + DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Color_Bg_Black, 3, UNITFDIGITS, 210, MBASE(4), planner.max_jerk[E_AXIS] * MINUNITMULT); #endif } #endif @@ -3067,11 +3067,11 @@ inline void Draw_Steps_Menu() { Draw_Back_First(); LOOP_L_N(i, 3 + ENABLED(HAS_HOTEND)) Draw_Menu_Line(i + 1, ICON_StepX + i); - DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Color_Bg_Black, 3, 1, 210, MBASE(1), planner.settings.axis_steps_per_mm[X_AXIS] * MINUNITMULT); - DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Color_Bg_Black, 3, 1, 210, MBASE(2), planner.settings.axis_steps_per_mm[Y_AXIS] * MINUNITMULT); - DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Color_Bg_Black, 3, 1, 210, MBASE(3), planner.settings.axis_steps_per_mm[Z_AXIS] * MINUNITMULT); + DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Color_Bg_Black, 3, UNITFDIGITS, 210, MBASE(1), planner.settings.axis_steps_per_mm[X_AXIS] * MINUNITMULT); + DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Color_Bg_Black, 3, UNITFDIGITS, 210, MBASE(2), planner.settings.axis_steps_per_mm[Y_AXIS] * MINUNITMULT); + DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Color_Bg_Black, 3, UNITFDIGITS, 210, MBASE(3), planner.settings.axis_steps_per_mm[Z_AXIS] * MINUNITMULT); #if HAS_HOTEND - DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Color_Bg_Black, 3, 1, 210, MBASE(4), planner.settings.axis_steps_per_mm[E_AXIS] * MINUNITMULT); + DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Color_Bg_Black, 3, UNITFDIGITS, 210, MBASE(4), planner.settings.axis_steps_per_mm[E_AXIS] * MINUNITMULT); #endif } @@ -3418,7 +3418,7 @@ void HMI_MaxAcceleration() { checkkey = MaxJerk_value; HMI_flag.jerk_axis = AxisEnum(select_jerk.now - 1); HMI_ValueStruct.Max_Jerk = planner.max_jerk[HMI_flag.jerk_axis] * MINUNITMULT; - DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Select_Color, 3, 1, 210, MBASE(select_jerk.now), HMI_ValueStruct.Max_Jerk); + DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Select_Color, 3, UNITFDIGITS, 210, MBASE(select_jerk.now), HMI_ValueStruct.Max_Jerk); EncoderRate.enabled = true; } else { // Back @@ -3448,7 +3448,7 @@ void HMI_Step() { checkkey = Step_value; HMI_flag.step_axis = AxisEnum(select_step.now - 1); HMI_ValueStruct.Max_Step = planner.settings.axis_steps_per_mm[HMI_flag.step_axis] * MINUNITMULT; - DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Select_Color, 3, 1, 210, MBASE(select_step.now), HMI_ValueStruct.Max_Step); + DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Select_Color, 3, UNITFDIGITS, 210, MBASE(select_step.now), HMI_ValueStruct.Max_Step); EncoderRate.enabled = true; } else { // Back @@ -3553,7 +3553,7 @@ void EachMomentUpdate() { static millis_t next_remain_time_update = 0; if (Percentrecord > 1 && ELAPSED(ms, next_remain_time_update) && !HMI_flag.heat_flag) { remain_time = (elapsed.value - dwin_heat_time) / (Percentrecord * 0.01f) - (elapsed.value - dwin_heat_time); - next_remain_time_update += 20 * 1000UL; + next_remain_time_update += SEC_TO_MS(20); Draw_Print_ProgressRemain(); } } diff --git a/Marlin/src/lcd/dwin/e3v2/rotary_encoder.h b/Marlin/src/lcd/dwin/e3v2/rotary_encoder.h index bbba753a0b..7de80dfe01 100644 --- a/Marlin/src/lcd/dwin/e3v2/rotary_encoder.h +++ b/Marlin/src/lcd/dwin/e3v2/rotary_encoder.h @@ -30,7 +30,6 @@ ****************************************************************************/ #include "../../../inc/MarlinConfig.h" -#include "../../../MarlinCore.h" /*********************** Encoder Set ***********************/ diff --git a/Marlin/src/lcd/extui/dgus_lcd.cpp b/Marlin/src/lcd/extui/dgus_lcd.cpp index 33d8bd4d89..9fcb6c8d13 100644 --- a/Marlin/src/lcd/extui/dgus_lcd.cpp +++ b/Marlin/src/lcd/extui/dgus_lcd.cpp @@ -35,8 +35,6 @@ #include "lib/dgus/DGUSDisplayDef.h" #include "lib/dgus/DGUSScreenHandler.h" -extern const char NUL_STR[]; - namespace ExtUI { void onStartup() { diff --git a/Marlin/src/lcd/extui/lib/anycubic_chiron/FileNavigator.cpp b/Marlin/src/lcd/extui/lib/anycubic_chiron/FileNavigator.cpp index fb4c84abb4..19f8ec81bc 100644 --- a/Marlin/src/lcd/extui/lib/anycubic_chiron/FileNavigator.cpp +++ b/Marlin/src/lcd/extui/lib/anycubic_chiron/FileNavigator.cpp @@ -44,6 +44,8 @@ using namespace ExtUI; namespace Anycubic { + FileNavigator filenavigator; + FileList FileNavigator::filelist; // Instance of the Marlin file API char FileNavigator::currentfoldername[MAX_PATH_LEN]; // Current folder path uint16_t FileNavigator::lastindex; diff --git a/Marlin/src/lcd/extui/lib/anycubic_chiron/chiron_tft.cpp b/Marlin/src/lcd/extui/lib/anycubic_chiron/chiron_tft.cpp index b0053895a7..61057b5b10 100644 --- a/Marlin/src/lcd/extui/lib/anycubic_chiron/chiron_tft.cpp +++ b/Marlin/src/lcd/extui/lib/anycubic_chiron/chiron_tft.cpp @@ -54,6 +54,8 @@ namespace Anycubic { float ChironTFT::live_Zoffset; file_menu_t ChironTFT::file_menu; + ChironTFT Chiron; + ChironTFT::ChironTFT(){} void ChironTFT::Startup() { @@ -574,10 +576,11 @@ namespace Anycubic { } break; case 15: // A15 Resuming from outage - if (printer_state == AC_printer_resuming_from_power_outage) + if (printer_state == AC_printer_resuming_from_power_outage) { // Need to home here to restore the Z position - injectCommands_P(AC_cmnd_power_loss_recovery); - injectCommands_P(PSTR("M1000")); // home and start recovery + injectCommands(AC_cmnd_power_loss_recovery); + injectCommands("M1000"); // home and start recovery + } break; case 16: { // A16 Set HotEnd temp A17 S170 diff --git a/Marlin/src/lcd/extui/lib/anycubic_i3mega/anycubic_i3mega_lcd.cpp b/Marlin/src/lcd/extui/lib/anycubic_i3mega/anycubic_i3mega_lcd.cpp index a3f7c42a5c..1508dc0d27 100644 --- a/Marlin/src/lcd/extui/lib/anycubic_i3mega/anycubic_i3mega_lcd.cpp +++ b/Marlin/src/lcd/extui/lib/anycubic_i3mega/anycubic_i3mega_lcd.cpp @@ -27,8 +27,8 @@ #include "../../ui_api.h" #include "../../../../libs/numtostr.h" -#include "../../../../module/motion.h" // for A20 read printing speed feedrate_percentage -#include "../../../../MarlinCore.h" // for quickstop_stepper, disable_steppers, G28_STR +#include "../../../../module/motion.h" // for quickstop_stepper, A20 read printing speed, feedrate_percentage +#include "../../../../MarlinCore.h" // for disable_steppers #include "../../../../inc/MarlinConfig.h" // command sending macro's with debugging capability diff --git a/Marlin/src/lcd/extui/lib/anycubic_i3mega/anycubic_i3mega_lcd.h b/Marlin/src/lcd/extui/lib/anycubic_i3mega/anycubic_i3mega_lcd.h index a4ecf5604f..59050acccb 100644 --- a/Marlin/src/lcd/extui/lib/anycubic_i3mega/anycubic_i3mega_lcd.h +++ b/Marlin/src/lcd/extui/lib/anycubic_i3mega/anycubic_i3mega_lcd.h @@ -94,3 +94,4 @@ private: }; extern AnycubicTFTClass AnycubicTFT; +extern const char G28_STR[]; diff --git a/Marlin/src/lcd/extui/lib/dgus/DGUSDisplay.h b/Marlin/src/lcd/extui/lib/dgus/DGUSDisplay.h index ee536ea219..88c119566c 100644 --- a/Marlin/src/lcd/extui/lib/dgus/DGUSDisplay.h +++ b/Marlin/src/lcd/extui/lib/dgus/DGUSDisplay.h @@ -25,7 +25,8 @@ #include "../../../../inc/MarlinConfigPre.h" -#include "../../../../MarlinCore.h" +#include // size_t + #if HAS_BED_PROBE #include "../../../../module/probe.h" #endif @@ -96,7 +97,7 @@ private: static void WritePGM(const char str[], uint8_t len); static void ProcessRx(); - static inline uint16_t swap16(const uint16_t value) { return (value & 0xffU) << 8U | (value >> 8U); } + static inline uint16_t swap16(const uint16_t value) { return (value & 0xFFU) << 8U | (value >> 8U); } static rx_datagram_state_t rx_datagram_state; static uint8_t rx_datagram_len; static bool Initialized, no_reentrance; diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/compat.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/compat.h index 741b7076d1..c01d45ed7c 100644 --- a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/compat.h +++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/compat.h @@ -43,10 +43,11 @@ #define min(a,b) ((a)<(b)?(a):(b)) #else namespace UI { - static inline uint32_t safe_millis() {return millis();}; - static inline void yield() {}; + static inline uint32_t safe_millis() { return millis(); } + static inline void yield() {} }; #endif class __FlashStringHelper; typedef const __FlashStringHelper *progmem_str; +extern const char G28_STR[]; diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/filament_runout_screen.cpp b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/filament_runout_screen.cpp index c281ccb050..41e3be22ef 100644 --- a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/filament_runout_screen.cpp +++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/filament_runout_screen.cpp @@ -36,7 +36,6 @@ void FilamentRunoutScreen::onRedraw(draw_mode_t what) { w.toggle( 2, GET_TEXT_F(MSG_RUNOUT_SENSOR), getFilamentRunoutEnabled()); #if HAS_FILAMENT_RUNOUT_DISTANCE - extern const char NUL_STR[]; w.heading(GET_TEXT_F(MSG_RUNOUT_DISTANCE_MM)); w.units(GET_TEXT_F(MSG_UNITS_MM)); w.precision(0); diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/stress_test_screen.cpp b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/stress_test_screen.cpp index 0aed1b7c53..6c4aab6d31 100644 --- a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/stress_test_screen.cpp +++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/stress_test_screen.cpp @@ -120,7 +120,6 @@ void StressTestScreen::onIdle() { if (!commandsInQueue()) { if (!isPositionKnown()) { - extern const char G28_STR[]; injectCommands_P(G28_STR); } else { diff --git a/Marlin/src/lcd/extui/lib/mks_ui/draw_dialog.cpp b/Marlin/src/lcd/extui/lib/mks_ui/draw_dialog.cpp index 95077d09f2..6130e92224 100644 --- a/Marlin/src/lcd/extui/lib/mks_ui/draw_dialog.cpp +++ b/Marlin/src/lcd/extui/lib/mks_ui/draw_dialog.cpp @@ -257,7 +257,7 @@ void lv_draw_dialog(uint8_t type) { lv_label_set_text(labelOk, print_file_dialog_menu.confirm); } } - else if (DIALOG_IS(TYPE_UPDATE_ESP_FIRMARE)) { + else if (DIALOG_IS(TYPE_UPDATE_ESP_FIRMWARE)) { // nothing to do } #endif @@ -426,7 +426,7 @@ void lv_draw_dialog(uint8_t type) { lv_obj_align(labelDialog, nullptr, LV_ALIGN_CENTER, 0, -20); } } - else if (DIALOG_IS(TYPE_UPDATE_ESP_FIRMARE)) { + else if (DIALOG_IS(TYPE_UPDATE_ESP_FIRMWARE)) { lv_label_set_text(labelDialog, DIALOG_UPDATE_WIFI_FIRMWARE_EN); lv_obj_align(labelDialog, NULL, LV_ALIGN_CENTER, 0, -20); } diff --git a/Marlin/src/lcd/extui/lib/mks_ui/draw_home.cpp b/Marlin/src/lcd/extui/lib/mks_ui/draw_home.cpp index 5b65f990c1..588b940bb6 100644 --- a/Marlin/src/lcd/extui/lib/mks_ui/draw_home.cpp +++ b/Marlin/src/lcd/extui/lib/mks_ui/draw_home.cpp @@ -31,8 +31,6 @@ #include "../../../../gcode/queue.h" #include "../../../../inc/MarlinConfig.h" -extern const char G28_STR[]; - extern lv_group_t *g; static lv_obj_t *scr; diff --git a/Marlin/src/lcd/extui/lib/mks_ui/draw_manuaLevel.cpp b/Marlin/src/lcd/extui/lib/mks_ui/draw_manuaLevel.cpp index 0b09ae391d..495acda06b 100644 --- a/Marlin/src/lcd/extui/lib/mks_ui/draw_manuaLevel.cpp +++ b/Marlin/src/lcd/extui/lib/mks_ui/draw_manuaLevel.cpp @@ -29,8 +29,6 @@ #include "../../../../gcode/queue.h" #include "../../../../inc/MarlinConfig.h" -extern const char G28_STR[]; - extern lv_group_t *g; static lv_obj_t *scr; diff --git a/Marlin/src/lcd/extui/lib/mks_ui/draw_move_motor.cpp b/Marlin/src/lcd/extui/lib/mks_ui/draw_move_motor.cpp index 6db1810fcf..d10175344d 100644 --- a/Marlin/src/lcd/extui/lib/mks_ui/draw_move_motor.cpp +++ b/Marlin/src/lcd/extui/lib/mks_ui/draw_move_motor.cpp @@ -54,14 +54,18 @@ enum { static void event_handler(lv_obj_t *obj, lv_event_t event) { if (event != LV_EVENT_RELEASED) return; if (queue.length <= (BUFSIZE - 3)) { + bool do_inject = true; float dist = uiCfg.move_dist; switch (obj->mks_obj_id) { case ID_M_X_N: dist *= -1; case ID_M_X_P: cur_label = 'X'; break; case ID_M_Y_N: dist *= -1; case ID_M_Y_P: cur_label = 'Y'; break; case ID_M_Z_N: dist *= -1; case ID_M_Z_P: cur_label = 'Z'; break; + default: do_inject = false; + } + if (do_inject) { + sprintf_P(public_buf_l, PSTR("G91\nG1 %c%3.1f F%d\nG90"), cur_label, dist, uiCfg.moveSpeed); + queue.inject(public_buf_l); } - sprintf_P(public_buf_l, PSTR("G91\nG1 %c%3.1f F%d\nG90"), cur_label, dist, uiCfg.moveSpeed); - queue.inject(public_buf_l); } switch (obj->mks_obj_id) { diff --git a/Marlin/src/lcd/extui/lib/mks_ui/draw_ui.cpp b/Marlin/src/lcd/extui/lib/mks_ui/draw_ui.cpp index 88e6fab07c..84049d51ab 100644 --- a/Marlin/src/lcd/extui/lib/mks_ui/draw_ui.cpp +++ b/Marlin/src/lcd/extui/lib/mks_ui/draw_ui.cpp @@ -889,7 +889,7 @@ void GUI_RefreshPage() { lv_draw_wifi_tips(); } - if (tips_disp.timer_count >= 30 * 1000) { + if (tips_disp.timer_count >= SEC_TO_MS(30)) { tips_disp.timer = TIPS_TIMER_STOP; tips_disp.timer_count = 0; lv_clear_wifi_tips(); @@ -898,7 +898,7 @@ void GUI_RefreshPage() { } break; case TIPS_TYPE_TAILED_JOIN: - if (tips_disp.timer_count >= 3 * 1000) { + if (tips_disp.timer_count >= SEC_TO_MS(3)) { tips_disp.timer = TIPS_TIMER_STOP; tips_disp.timer_count = 0; @@ -908,7 +908,7 @@ void GUI_RefreshPage() { } break; case TIPS_TYPE_WIFI_CONECTED: - if (tips_disp.timer_count >= 3 * 1000) { + if (tips_disp.timer_count >= SEC_TO_MS(3)) { tips_disp.timer = TIPS_TIMER_STOP; tips_disp.timer_count = 0; diff --git a/Marlin/src/lcd/extui/lib/mks_ui/draw_ui.h b/Marlin/src/lcd/extui/lib/mks_ui/draw_ui.h index ded6bc7825..f02a58ad43 100644 --- a/Marlin/src/lcd/extui/lib/mks_ui/draw_ui.h +++ b/Marlin/src/lcd/extui/lib/mks_ui/draw_ui.h @@ -77,7 +77,7 @@ #include "draw_keyboard.h" #include "draw_encoder_settings.h" -#include "../../inc/MarlinConfigPre.h" +#include "../../../../inc/MarlinConfigPre.h" #if ENABLED(MKS_WIFI_MODULE) #include "wifiSerial.h" diff --git a/Marlin/src/lcd/extui/lib/mks_ui/mks_hardware_test.cpp b/Marlin/src/lcd/extui/lib/mks_ui/mks_hardware_test.cpp index d2d1c19063..8cbe319d14 100644 --- a/Marlin/src/lcd/extui/lib/mks_ui/mks_hardware_test.cpp +++ b/Marlin/src/lcd/extui/lib/mks_ui/mks_hardware_test.cpp @@ -157,7 +157,7 @@ void mks_gpio_test() { && (READ(PE6) == 0) && (READ(PE7) == 0) #endif - ) + ) disp_det_ok(); else disp_det_error(); diff --git a/Marlin/src/lcd/extui/lib/mks_ui/pic_manager.cpp b/Marlin/src/lcd/extui/lib/mks_ui/pic_manager.cpp index 1cb7ed185e..8b96587fea 100644 --- a/Marlin/src/lcd/extui/lib/mks_ui/pic_manager.cpp +++ b/Marlin/src/lcd/extui/lib/mks_ui/pic_manager.cpp @@ -64,7 +64,6 @@ static const char assets[][LONG_FILENAME_LENGTH] = { "bmp_speed255.bin", "bmp_speed127.bin", "bmp_speed0.bin", - "bmp_speed0.bin", "bmp_bed.bin", "bmp_step1_degree.bin", diff --git a/Marlin/src/lcd/extui/lib/mks_ui/tft_lvgl_configuration.cpp b/Marlin/src/lcd/extui/lib/mks_ui/tft_lvgl_configuration.cpp index 65b7538b71..b7441f71f4 100644 --- a/Marlin/src/lcd/extui/lib/mks_ui/tft_lvgl_configuration.cpp +++ b/Marlin/src/lcd/extui/lib/mks_ui/tft_lvgl_configuration.cpp @@ -89,8 +89,8 @@ void SysTick_Callback() { #endif if (uiCfg.filament_loading_time_flg) { uiCfg.filament_loading_time_cnt++; - uiCfg.filament_rate = (uint32_t)(((uiCfg.filament_loading_time_cnt / (uiCfg.filament_loading_time * 1000.0)) * 100.0) + 0.5); - if (uiCfg.filament_loading_time_cnt >= (uiCfg.filament_loading_time * 1000)) { + uiCfg.filament_rate = uint32_t(100.0f * uiCfg.filament_loading_time_cnt / SEC_TO_MS(uiCfg.filament_loading_time) + 0.5f); + if (uiCfg.filament_loading_time_cnt >= SEC_TO_MS(uiCfg.filament_loading_time)) { uiCfg.filament_loading_time_cnt = 0; uiCfg.filament_loading_time_flg = false; uiCfg.filament_loading_completed = true; @@ -98,8 +98,8 @@ void SysTick_Callback() { } if (uiCfg.filament_unloading_time_flg) { uiCfg.filament_unloading_time_cnt++; - uiCfg.filament_rate = (uint32_t)(((uiCfg.filament_unloading_time_cnt / (uiCfg.filament_unloading_time * 1000.0)) * 100.0) + 0.5); - if (uiCfg.filament_unloading_time_cnt >= (uiCfg.filament_unloading_time * 1000)) { + uiCfg.filament_rate = uint32_t(100.0f * uiCfg.filament_unloading_time_cnt / SEC_TO_MS(uiCfg.filament_unloading_time) + 0.5f); + if (uiCfg.filament_unloading_time_cnt >= SEC_TO_MS(uiCfg.filament_unloading_time)) { uiCfg.filament_unloading_time_cnt = 0; uiCfg.filament_unloading_time_flg = false; uiCfg.filament_unloading_completed = true; diff --git a/Marlin/src/lcd/extui/lib/mks_ui/tft_multi_language.cpp b/Marlin/src/lcd/extui/lib/mks_ui/tft_multi_language.cpp index 7db5e80561..28c90486d0 100644 --- a/Marlin/src/lcd/extui/lib/mks_ui/tft_multi_language.cpp +++ b/Marlin/src/lcd/extui/lib/mks_ui/tft_multi_language.cpp @@ -23,8 +23,6 @@ #if HAS_TFT_LVGL_UI -#include "../../../../MarlinCore.h" - #include "draw_ui.h" #include "tft_multi_language.h" diff --git a/Marlin/src/lcd/extui/lib/mks_ui/wifi_module.cpp b/Marlin/src/lcd/extui/lib/mks_ui/wifi_module.cpp index bf4f75017f..785e854c52 100644 --- a/Marlin/src/lcd/extui/lib/mks_ui/wifi_module.cpp +++ b/Marlin/src/lcd/extui/lib/mks_ui/wifi_module.cpp @@ -21,15 +21,13 @@ */ #include "../../../../inc/MarlinConfigPre.h" -#if HAS_TFT_LVGL_UI +#if BOTH(HAS_TFT_LVGL_UI, MKS_WIFI_MODULE) #include "draw_ui.h" #include "wifi_module.h" #include "wifi_upload.h" #include "SPI_TFT.h" -#if ENABLED(MKS_WIFI_MODULE) - #include "../../../../MarlinCore.h" #include "../../../../module/temperature.h" #include "../../../../gcode/queue.h" @@ -39,6 +37,10 @@ #include "../../../../module/planner.h" #include "../../../../module/servo.h" #include "../../../../module/probe.h" + +#if DISABLED(EMERGENCY_PARSER) + #include "../../../../module/motion.h" +#endif #if ENABLED(POWER_LOSS_RECOVERY) #include "../../../../feature/powerloss.h" #endif @@ -455,7 +457,6 @@ int package_to_wifi(WIFI_RET_TYPE type, uint8_t *buf, int len) { return 1; } - #define SEND_OK_TO_WIFI send_to_wifi((uint8_t *)"ok\r\n", strlen("ok\r\n")) int send_to_wifi(uint8_t *buf, int len) { return package_to_wifi(WIFI_TRANS_INF, buf, len); } @@ -549,7 +550,6 @@ typedef struct { uint8_t tail; } ESP_PROTOC_FRAME; - static int cut_msg_head(uint8_t *msg, uint16_t msgLen, uint16_t cutLen) { if (msgLen < cutLen) return 0; @@ -1663,7 +1663,7 @@ void mks_esp_wifi_init() { clear_cur_ui(); - draw_dialog(DIALOG_TYPE_UPDATE_ESP_FIRMARE); + draw_dialog(DIALOG_TYPE_UPDATE_ESP_FIRMWARE); if (wifi_upload(1) >= 0) { f_unlink("1:/MKS_WIFI_CUR"); @@ -1703,7 +1703,6 @@ void mks_esp_wifi_init() { wifi_link_state = WIFI_NOT_CONFIG; } - void mks_wifi_firmware_update() { card.openFileRead((char *)ESP_FIRMWARE_FILE); @@ -1717,7 +1716,7 @@ void mks_wifi_firmware_update() { clear_cur_ui(); - lv_draw_dialog(DIALOG_TYPE_UPDATE_ESP_FIRMARE); + lv_draw_dialog(DIALOG_TYPE_UPDATE_ESP_FIRMWARE); lv_task_handler(); watchdog_refresh(); @@ -1822,5 +1821,4 @@ int readWifiBuf(int8_t *buf, int32_t len) { return i; } -#endif // MKS_WIFI_MODULE -#endif // HAS_TFT_LVGL_UI +#endif // HAS_TFT_LVGL_UI && MKS_WIFI_MODULE diff --git a/Marlin/src/lcd/extui/lib/mks_ui/wifi_upload.cpp b/Marlin/src/lcd/extui/lib/mks_ui/wifi_upload.cpp index f4412f3830..378de6d584 100644 --- a/Marlin/src/lcd/extui/lib/mks_ui/wifi_upload.cpp +++ b/Marlin/src/lcd/extui/lib/mks_ui/wifi_upload.cpp @@ -152,7 +152,7 @@ uint32_t getData(unsigned byteCnt, const uint8_t *buf, int ofst) { uint32_t val = 0; if (buf && byteCnt) { unsigned int shiftCnt = 0; - NOMORE(byteCnt, 4); + NOMORE(byteCnt, 4U); do { val |= (uint32_t)buf[ofst++] << shiftCnt; shiftCnt += 8; @@ -164,7 +164,7 @@ uint32_t getData(unsigned byteCnt, const uint8_t *buf, int ofst) { // Put 1-4 bytes of a value in little-endian order into a buffer beginning at a specified offset. void putData(uint32_t val, unsigned byteCnt, uint8_t *buf, int ofst) { if (buf && byteCnt) { - NOMORE(byteCnt, 4); + NOMORE(byteCnt, 4U); do { buf[ofst++] = (uint8_t)(val & 0xFF); val >>= 8; diff --git a/Marlin/src/lcd/extui/malyan_lcd.cpp b/Marlin/src/lcd/extui/malyan_lcd.cpp index bdbf3802ab..6c55eea16d 100644 --- a/Marlin/src/lcd/extui/malyan_lcd.cpp +++ b/Marlin/src/lcd/extui/malyan_lcd.cpp @@ -414,8 +414,8 @@ void update_usb_status(const bool forceUpdate) { // This is mildly different than stock, which // appears to use the usb discovery status. // This is more logical. - if (last_usb_connected_status != MYSERIAL0 || forceUpdate) { - last_usb_connected_status = MYSERIAL0; + if (last_usb_connected_status != MYSERIAL0.connected() || forceUpdate) { + last_usb_connected_status = MYSERIAL0.connected(); write_to_lcd_P(last_usb_connected_status ? PSTR("{R:UC}\r\n") : PSTR("{R:UD}\r\n")); } } diff --git a/Marlin/src/lcd/extui/ui_api.cpp b/Marlin/src/lcd/extui/ui_api.cpp index 0ff222a3ce..741be04bb2 100644 --- a/Marlin/src/lcd/extui/ui_api.cpp +++ b/Marlin/src/lcd/extui/ui_api.cpp @@ -123,7 +123,7 @@ namespace ExtUI { // Machine was killed, reinit SysTick so we are able to compute time without ISRs if (currTimeHI == 0) { // Get the last time the Arduino time computed (from CMSIS) and convert it to SysTick - currTimeHI = (uint32_t)((GetTickCount() * (uint64_t)(F_CPU / 8000)) >> 24); + currTimeHI = uint32_t((GetTickCount() * uint64_t(F_CPU / 8000)) >> 24); // Reinit the SysTick timer to maximize its period SysTick->LOAD = SysTick_LOAD_RELOAD_Msk; // get the full range for the systick timer @@ -148,9 +148,9 @@ namespace ExtUI { } #endif // __SAM3X8E__ - void delay_us(unsigned long us) { DELAY_US(us); } + void delay_us(uint32_t us) { DELAY_US(us); } - void delay_ms(unsigned long ms) { + void delay_ms(uint32_t ms) { if (flags.printer_killed) DELAY_US(ms * 1000); else diff --git a/Marlin/src/lcd/extui/ui_api.h b/Marlin/src/lcd/extui/ui_api.h index edaaff0f1a..30bf06a963 100644 --- a/Marlin/src/lcd/extui/ui_api.h +++ b/Marlin/src/lcd/extui/ui_api.h @@ -155,7 +155,7 @@ namespace ExtUI { void onMeshUpdate(const int8_t xpos, const int8_t ypos, const float zval); inline void onMeshUpdate(const xy_int8_t &pos, const float zval) { onMeshUpdate(pos.x, pos.y, zval); } - typedef enum : unsigned char { + typedef enum : uint8_t { MESH_START, // Prior to start of probe MESH_FINISH, // Following probe of all points PROBE_START, // Beginning probe of grid location @@ -303,8 +303,8 @@ namespace ExtUI { FORCE_INLINE uint32_t safe_millis() { return millis(); } // TODO: Implement for AVR #endif - void delay_us(unsigned long us); - void delay_ms(unsigned long ms); + void delay_us(uint32_t us); + void delay_ms(uint32_t ms); void yield(); /** diff --git a/Marlin/src/lcd/language/language_sv.h b/Marlin/src/lcd/language/language_sv.h new file mode 100644 index 0000000000..722443fb21 --- /dev/null +++ b/Marlin/src/lcd/language/language_sv.h @@ -0,0 +1,681 @@ +/** + * 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 för more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#pragma once + +/** + * Swedish + * + * LCD Menu Messages + * See also https://marlinfw.org/docs/development/lcd_language.html + */ + +#define DISPLAY_CHARSET_ISO10646_1 + +namespace Language_sv { + using namespace Language_en; // Inherit undefined strings from English + + constexpr uint8_t CHARSIZE = 2; + PROGMEM Language_Str LANGUAGE = _UxGT("Swedish"); + + PROGMEM Language_Str WELCOME_MSG = MACHINE_NAME _UxGT(" Redo."); + PROGMEM Language_Str MSG_MARLIN = _UxGT("Marlin"); + PROGMEM Language_Str MSG_YES = _UxGT("JA"); + PROGMEM Language_Str MSG_NO = _UxGT("NEJ"); + PROGMEM Language_Str MSG_BACK = _UxGT("Bakåt"); + PROGMEM Language_Str MSG_MEDIA_ABORTING = _UxGT("Avbryter..."); + PROGMEM Language_Str MSG_MEDIA_INSERTED = _UxGT("Media Instatt"); + PROGMEM Language_Str MSG_MEDIA_REMOVED = _UxGT("Media Borttaget"); + PROGMEM Language_Str MSG_MEDIA_WAITING = _UxGT("Väntar på media"); + PROGMEM Language_Str MSG_SD_INIT_FAIL = _UxGT("SD init misslyckades"); + PROGMEM Language_Str MSG_MEDIA_READ_ERROR = _UxGT("Media läsningsfel"); + PROGMEM Language_Str MSG_MEDIA_USB_REMOVED = _UxGT("USB enhet borttagen"); + PROGMEM Language_Str MSG_MEDIA_USB_FAILED = _UxGT("USB start misslyckad"); + PROGMEM Language_Str MSG_KILL_SUBCALL_OVERFLOW = _UxGT("Underanrop överskriden"); + PROGMEM Language_Str MSG_LCD_ENDSTOPS = _UxGT("Slutstop"); // Max length 8 characters + PROGMEM Language_Str MSG_LCD_SOFT_ENDSTOPS = _UxGT("Mjuk slutstopp"); + PROGMEM Language_Str MSG_MAIN = _UxGT("Huvud"); + PROGMEM Language_Str MSG_ADVANCED_SETTINGS = _UxGT("Advancerade inställningar"); + PROGMEM Language_Str MSG_CONFIGURATION = _UxGT("Konfiguration"); + PROGMEM Language_Str MSG_RUN_AUTO_FILES = _UxGT("Autostarta Filer"); + PROGMEM Language_Str MSG_DISABLE_STEPPERS = _UxGT("Inaktivera Stegare"); + PROGMEM Language_Str MSG_DEBUG_MENU = _UxGT("Debug Meny"); + PROGMEM Language_Str MSG_PROGRESS_BAR_TEST = _UxGT("Framstegsindikator Test"); + PROGMEM Language_Str MSG_AUTO_HOME = _UxGT("Auto Hem"); + PROGMEM Language_Str MSG_AUTO_HOME_X = _UxGT("Hem X"); + PROGMEM Language_Str MSG_AUTO_HOME_Y = _UxGT("Hem Y"); + PROGMEM Language_Str MSG_AUTO_HOME_Z = _UxGT("Hem Z"); + PROGMEM Language_Str MSG_AUTO_Z_ALIGN = _UxGT("Auto Z-Justering"); + PROGMEM Language_Str MSG_ITERATION = _UxGT("G34 Iteration: %i"); + PROGMEM Language_Str MSG_DECREASING_ACCURACY = _UxGT("Noggrannhet Minskar!"); + PROGMEM Language_Str MSG_ACCURACY_ACHIEVED = _UxGT("Noggrannhet uppnådd"); + PROGMEM Language_Str MSG_LEVEL_BED_HOMING = _UxGT("Hemning XYZ"); + PROGMEM Language_Str MSG_LEVEL_BED_WAITING = _UxGT("Klicka för att börja"); + PROGMEM Language_Str MSG_LEVEL_BED_NEXT_POINT = _UxGT("Nästa Punkt"); + PROGMEM Language_Str MSG_LEVEL_BED_DONE = _UxGT("Nivellering Färdig!"); + PROGMEM Language_Str MSG_Z_FADE_HEIGHT = _UxGT("Falna Höjd"); + PROGMEM Language_Str MSG_SET_HOME_OFFSETS = _UxGT("Sätt Hem Offset"); + PROGMEM Language_Str MSG_HOME_OFFSETS_APPLIED = _UxGT("Offset Tillämpad"); + PROGMEM Language_Str MSG_SET_ORIGIN = _UxGT("Sätt Origo"); + PROGMEM Language_Str MSG_ASSISTED_TRAMMING = _UxGT("Assisterad justering"); + PROGMEM Language_Str MSG_TRAMMING_WIZARD = _UxGT("Justerings Wizard"); + PROGMEM Language_Str MSG_SELECT_ORIGIN = _UxGT("Välj Origo"); + PROGMEM Language_Str MSG_LAST_VALUE_SP = _UxGT("Senaste värde "); + + #if PREHEAT_COUNT + PROGMEM Language_Str MSG_PREHEAT_1 = _UxGT("Förvärmning ") PREHEAT_1_LABEL; + PROGMEM Language_Str MSG_PREHEAT_1_H = _UxGT("Förvärmning ") PREHEAT_1_LABEL " ~"; + PROGMEM Language_Str MSG_PREHEAT_1_END = _UxGT("Förvärmning ") PREHEAT_1_LABEL _UxGT(" Stoppa"); + PROGMEM Language_Str MSG_PREHEAT_1_END_E = _UxGT("Förvärmning ") PREHEAT_1_LABEL _UxGT(" Stoppa ~"); + PROGMEM Language_Str MSG_PREHEAT_1_ALL = _UxGT("Förvärmning ") PREHEAT_1_LABEL _UxGT(" Alla"); + PROGMEM Language_Str MSG_PREHEAT_1_BEDONLY = _UxGT("Förvärmning ") PREHEAT_1_LABEL _UxGT(" Bädd"); + PROGMEM Language_Str MSG_PREHEAT_1_SETTINGS = _UxGT("Förvärmning ") PREHEAT_1_LABEL _UxGT(" Konf"); + + PROGMEM Language_Str MSG_PREHEAT_M = _UxGT("Förvärmning $"); + PROGMEM Language_Str MSG_PREHEAT_M_H = _UxGT("Förvärmning $ ~"); + PROGMEM Language_Str MSG_PREHEAT_M_END = _UxGT("Förvärmning $ Stoppa"); + PROGMEM Language_Str MSG_PREHEAT_M_END_E = _UxGT("Förvärmning $ Stoppa ~"); + PROGMEM Language_Str MSG_PREHEAT_M_ALL = _UxGT("Förvärmning $ Alla"); + PROGMEM Language_Str MSG_PREHEAT_M_BEDONLY = _UxGT("Förvärmning $ Bädd"); + PROGMEM Language_Str MSG_PREHEAT_M_SETTINGS = _UxGT("Förvärmning $ Donf"); + #endif + + PROGMEM Language_Str MSG_PREHEAT_CUSTOM = _UxGT("Förvärmning Anpassad"); + PROGMEM Language_Str MSG_COOLDOWN = _UxGT("Nedkylning"); + PROGMEM Language_Str MSG_CUTTER_FREQUENCY = _UxGT("Frekvens"); + PROGMEM Language_Str MSG_LASER_MENU = _UxGT("Laser kontroll"); + PROGMEM Language_Str MSG_SPINDLE_MENU = _UxGT("Spindel Kontroll"); + PROGMEM Language_Str MSG_LASER_POWER = _UxGT("Laser Styrka"); + PROGMEM Language_Str MSG_SPINDLE_POWER = _UxGT("Spindel Styrka"); + PROGMEM Language_Str MSG_LASER_TOGGLE = _UxGT("Växla Laser"); + PROGMEM Language_Str MSG_LASER_PULSE_MS = _UxGT("Test Puls ms"); + PROGMEM Language_Str MSG_LASER_FIRE_PULSE = _UxGT("Avfyra Puls"); + PROGMEM Language_Str MSG_SPINDLE_TOGGLE = _UxGT("Växla Spindel"); + PROGMEM Language_Str MSG_SPINDLE_FORWARD = _UxGT("Spindel Framåt"); + PROGMEM Language_Str MSG_SPINDLE_REVERSE = _UxGT("Spindel Bakåt"); + PROGMEM Language_Str MSG_LASER_OFF = _UxGT("Laser Av"); + PROGMEM Language_Str MSG_LASER_ON = _UxGT("Laser På"); + PROGMEM Language_Str MSG_SPINDLE_OFF = _UxGT("Spindel Av"); + PROGMEM Language_Str MSG_SPINDLE_ON = _UxGT("Spindel På"); + PROGMEM Language_Str MSG_SWITCH_PS_ON = _UxGT("Sätt på ström"); + PROGMEM Language_Str MSG_SWITCH_PS_OFF = _UxGT("Stäng av ström"); + PROGMEM Language_Str MSG_EXTRUDE = _UxGT("Extrudera"); + PROGMEM Language_Str MSG_RETRACT = _UxGT("Dra tillbaka"); + PROGMEM Language_Str MSG_MOVE_AXIS = _UxGT("Flytta Axel"); + PROGMEM Language_Str MSG_BED_LEVELING = _UxGT("Bädd Nivellering"); + PROGMEM Language_Str MSG_LEVEL_BED = _UxGT("Nivellera Bädd"); + PROGMEM Language_Str MSG_LEVEL_CORNERS = _UxGT("Nivellera Hörn"); + PROGMEM Language_Str MSG_LEVEL_CORNERS_RAISE = _UxGT("Höj Bädd tills nästa Sond Triggad"); + PROGMEM Language_Str MSG_LEVEL_CORNERS_IN_RANGE = _UxGT("Alla Hörn inom Tolerans. Nivellering Bädd"); + PROGMEM Language_Str MSG_LEVEL_CORNERS_GOOD_POINTS = _UxGT("Bra Punkter: "); + PROGMEM Language_Str MSG_LEVEL_CORNERS_LAST_Z = _UxGT("Senaste Z: "); + PROGMEM Language_Str MSG_NEXT_CORNER = _UxGT("Nästa Hörn"); + PROGMEM Language_Str MSG_MESH_EDITOR = _UxGT("Nät Redigerare"); + PROGMEM Language_Str MSG_EDIT_MESH = _UxGT("Redigera Nät"); + PROGMEM Language_Str MSG_EDITING_STOPPED = _UxGT("Nätredigering Stoppad"); + PROGMEM Language_Str MSG_PROBING_MESH = _UxGT("Sonderingspunkt"); + PROGMEM Language_Str MSG_MESH_X = _UxGT("Index X"); + PROGMEM Language_Str MSG_MESH_Y = _UxGT("Index Y"); + PROGMEM Language_Str MSG_MESH_EDIT_Z = _UxGT("Z Värde"); + PROGMEM Language_Str MSG_USER_MENU = _UxGT("Anpassade Kommandon"); + PROGMEM Language_Str MSG_M48_TEST = _UxGT("M48 Sond Test"); + PROGMEM Language_Str MSG_M48_POINT = _UxGT("M48 Punkt"); + PROGMEM Language_Str MSG_M48_OUT_OF_BOUNDS = _UxGT("Sond utan för gränser"); + PROGMEM Language_Str MSG_M48_DEVIATION = _UxGT("Avvikelse"); + PROGMEM Language_Str MSG_IDEX_MENU = _UxGT("IDEX Läge"); + PROGMEM Language_Str MSG_OFFSETS_MENU = _UxGT("Verktygsoffset"); + PROGMEM Language_Str MSG_IDEX_MODE_AUTOPARK = _UxGT("Auto-Parkera"); + PROGMEM Language_Str MSG_IDEX_MODE_DUPLICATE = _UxGT("Duplicering"); + PROGMEM Language_Str MSG_IDEX_MODE_MIRRORED_COPY = _UxGT("Speglad Kopia"); + PROGMEM Language_Str MSG_IDEX_MODE_FULL_CTRL = _UxGT("Full Kontroll"); + PROGMEM Language_Str MSG_IDEX_DUPE_GAP = _UxGT("Duplicera X-Avstånd"); + PROGMEM Language_Str MSG_HOTEND_OFFSET_X = _UxGT("2:a Munstycke X"); + PROGMEM Language_Str MSG_HOTEND_OFFSET_Y = _UxGT("2:a Munstycke Y"); + PROGMEM Language_Str MSG_HOTEND_OFFSET_Z = _UxGT("2:a Munstycke Z"); + PROGMEM Language_Str MSG_UBL_DOING_G29 = _UxGT("Utför G29"); + PROGMEM Language_Str MSG_UBL_TOOLS = _UxGT("UBL Verktyg"); + PROGMEM Language_Str MSG_UBL_LEVEL_BED = _UxGT("Enad Bädd Nivellering (UBL)"); + PROGMEM Language_Str MSG_LCD_TILTING_MESH = _UxGT("Lutningspunkt"); + PROGMEM Language_Str MSG_UBL_MANUAL_MESH = _UxGT("Manuellt skapa nät"); + PROGMEM Language_Str MSG_UBL_BC_INSERT = _UxGT("Placera Shim & Mät"); + PROGMEM Language_Str MSG_UBL_BC_INSERT2 = _UxGT("Mät"); + PROGMEM Language_Str MSG_UBL_BC_REMOVE = _UxGT("Ta bort & Mät bädd"); + PROGMEM Language_Str MSG_UBL_MOVING_TO_NEXT = _UxGT("Flyttar till nästa"); + PROGMEM Language_Str MSG_UBL_ACTIVATE_MESH = _UxGT("Aktivera UBL"); + PROGMEM Language_Str MSG_UBL_DEACTIVATE_MESH = _UxGT("Avaktivera UBL"); + PROGMEM Language_Str MSG_UBL_SET_TEMP_BED = _UxGT("Bädd Temp"); + PROGMEM Language_Str MSG_UBL_BED_TEMP_CUSTOM = _UxGT("Bädd Temp"); + PROGMEM Language_Str MSG_UBL_SET_TEMP_HOTEND = _UxGT("Hetände Temp"); + PROGMEM Language_Str MSG_UBL_HOTEND_TEMP_CUSTOM = _UxGT("Hetände Temp"); + PROGMEM Language_Str MSG_UBL_MESH_EDIT = _UxGT("Nät Redigera"); + PROGMEM Language_Str MSG_UBL_EDIT_CUSTOM_MESH = _UxGT("Redigera Anpassat Nät"); + PROGMEM Language_Str MSG_UBL_FINE_TUNE_MESH = _UxGT("Finjustera Nät"); + PROGMEM Language_Str MSG_UBL_DONE_EDITING_MESH = _UxGT("Färdig Redigera Nät"); + PROGMEM Language_Str MSG_UBL_BUILD_CUSTOM_MESH = _UxGT("Bygg Anpassat Nät"); + PROGMEM Language_Str MSG_UBL_BUILD_MESH_MENU = _UxGT("Bygg Nät"); + PROGMEM Language_Str MSG_UBL_BUILD_MESH_M = _UxGT("Bygg Nät ($)"); + PROGMEM Language_Str MSG_UBL_BUILD_COLD_MESH = _UxGT("Bygg Kallt Nät"); + PROGMEM Language_Str MSG_UBL_MESH_HEIGHT_ADJUST = _UxGT("Justera Nät Höjd"); + PROGMEM Language_Str MSG_UBL_MESH_HEIGHT_AMOUNT = _UxGT("Höjd Antal"); + PROGMEM Language_Str MSG_UBL_VALIDATE_MESH_MENU = _UxGT("Validera Nät"); + PROGMEM Language_Str MSG_UBL_VALIDATE_MESH_M = _UxGT("Validera Nät ($)"); + PROGMEM Language_Str MSG_UBL_VALIDATE_CUSTOM_MESH = _UxGT("Validera Anpassat Nät"); + PROGMEM Language_Str MSG_G26_HEATING_BED = _UxGT("G26 Värma Bädd"); + PROGMEM Language_Str MSG_G26_HEATING_NOZZLE = _UxGT("G26 Värma Munstycke"); + PROGMEM Language_Str MSG_G26_MANUAL_PRIME = _UxGT("Manuel grundning..."); + PROGMEM Language_Str MSG_G26_FIXED_LENGTH = _UxGT("Fastlängd Grundning"); + PROGMEM Language_Str MSG_G26_PRIME_DONE = _UxGT("Färdig Grundning"); + PROGMEM Language_Str MSG_G26_CANCELED = _UxGT("G26 Avbruten"); + PROGMEM Language_Str MSG_G26_LEAVING = _UxGT("Nivellera G26"); + PROGMEM Language_Str MSG_UBL_CONTINUE_MESH = _UxGT("Fortsätt Bädd Nät"); + PROGMEM Language_Str MSG_UBL_MESH_LEVELING = _UxGT("Nät Nivellering"); + PROGMEM Language_Str MSG_UBL_3POINT_MESH_LEVELING = _UxGT("3-Punkts Nivellering"); + PROGMEM Language_Str MSG_UBL_GRID_MESH_LEVELING = _UxGT("Rutnät Nivellering"); + PROGMEM Language_Str MSG_UBL_MESH_LEVEL = _UxGT("Nivellera Nät"); + PROGMEM Language_Str MSG_UBL_SIDE_POINTS = _UxGT("Sidopunkter"); + PROGMEM Language_Str MSG_UBL_MAP_TYPE = _UxGT("Kart Typ"); + PROGMEM Language_Str MSG_UBL_OUTPUT_MAP = _UxGT("Utmatning Nät Map"); + PROGMEM Language_Str MSG_UBL_OUTPUT_MAP_HOST = _UxGT("Utmatning för Värd"); + PROGMEM Language_Str MSG_UBL_OUTPUT_MAP_CSV = _UxGT("Utmatning för CSV"); + PROGMEM Language_Str MSG_UBL_OUTPUT_MAP_BACKUP = _UxGT("Utanför skrivare Backup"); + PROGMEM Language_Str MSG_UBL_INFO_UBL = _UxGT("Utmatning UBL Info"); + PROGMEM Language_Str MSG_UBL_FILLIN_AMOUNT = _UxGT("Ifyllnad Mängd"); + PROGMEM Language_Str MSG_UBL_MANUAL_FILLIN = _UxGT("Manuell Ifyllnad"); + PROGMEM Language_Str MSG_UBL_SMART_FILLIN = _UxGT("Smart Ifyllnad"); + PROGMEM Language_Str MSG_UBL_FILLIN_MESH = _UxGT("Ifyllnad Nät"); + PROGMEM Language_Str MSG_UBL_INVALIDATE_ALL = _UxGT("Ogiltigförklara Alla"); + PROGMEM Language_Str MSG_UBL_INVALIDATE_CLOSEST = _UxGT("Ogiltigförklara Närmast"); + PROGMEM Language_Str MSG_UBL_FINE_TUNE_ALL = _UxGT("Finjustera Alla"); + PROGMEM Language_Str MSG_UBL_FINE_TUNE_CLOSEST = _UxGT("Finjustera Närmast"); + PROGMEM Language_Str MSG_UBL_STORAGE_MESH_MENU = _UxGT("Nät Lagra"); + PROGMEM Language_Str MSG_UBL_STORAGE_SLOT = _UxGT("Minnesöppning"); + PROGMEM Language_Str MSG_UBL_LOAD_MESH = _UxGT("Ladda Bädd Nät"); + PROGMEM Language_Str MSG_UBL_SAVE_MESH = _UxGT("Spara Bädd Nät"); + PROGMEM Language_Str MSG_MESH_LOADED = _UxGT("Nät %i Ladda"); + PROGMEM Language_Str MSG_MESH_SAVED = _UxGT("Nät %i Sparad"); + PROGMEM Language_Str MSG_UBL_NO_STORAGE = _UxGT("Ingen Lagring"); + PROGMEM Language_Str MSG_UBL_SAVE_ERROR = _UxGT("Fel: UBL Sparad"); + PROGMEM Language_Str MSG_UBL_RESTORE_ERROR = _UxGT("Fel: UBL Återställd"); + PROGMEM Language_Str MSG_UBL_Z_OFFSET = _UxGT("Z-Offset: "); + PROGMEM Language_Str MSG_UBL_Z_OFFSET_STOPPED = _UxGT("Z-Offset Stoppad"); + PROGMEM Language_Str MSG_UBL_STEP_BY_STEP_MENU = _UxGT("Steg-för-Steg UBL"); + PROGMEM Language_Str MSG_UBL_1_BUILD_COLD_MESH = _UxGT("1. Bygg Kallt Nät"); + PROGMEM Language_Str MSG_UBL_2_SMART_FILLIN = _UxGT("2. Smart Ifyllnad"); + PROGMEM Language_Str MSG_UBL_3_VALIDATE_MESH_MENU = _UxGT("3. Validera Nät"); + PROGMEM Language_Str MSG_UBL_4_FINE_TUNE_ALL = _UxGT("4. Finjustera Alla"); + PROGMEM Language_Str MSG_UBL_5_VALIDATE_MESH_MENU = _UxGT("5. Validera Nät"); + PROGMEM Language_Str MSG_UBL_6_FINE_TUNE_ALL = _UxGT("6. Finjustera Alla"); + PROGMEM Language_Str MSG_UBL_7_SAVE_MESH = _UxGT("7. Spara Bädd Nät"); + + PROGMEM Language_Str MSG_LED_CONTROL = _UxGT("LED Kontroll"); + PROGMEM Language_Str MSG_LEDS = _UxGT("Ljus"); + PROGMEM Language_Str MSG_LED_PRESETS = _UxGT("Ljus Förinställd"); + PROGMEM Language_Str MSG_SET_LEDS_RED = _UxGT("Röd"); + PROGMEM Language_Str MSG_SET_LEDS_ORANGE = _UxGT("Orange"); + PROGMEM Language_Str MSG_SET_LEDS_YELLOW = _UxGT("Gul"); + PROGMEM Language_Str MSG_SET_LEDS_GREEN = _UxGT("Grön"); + PROGMEM Language_Str MSG_SET_LEDS_BLUE = _UxGT("Blå"); + PROGMEM Language_Str MSG_SET_LEDS_INDIGO = _UxGT("Indigo"); + PROGMEM Language_Str MSG_SET_LEDS_VIOLET = _UxGT("Violet"); + PROGMEM Language_Str MSG_SET_LEDS_WHITE = _UxGT("Vitt"); + PROGMEM Language_Str MSG_SET_LEDS_DEFAULT = _UxGT("Standard"); + PROGMEM Language_Str MSG_LED_CHANNEL_N = _UxGT("Kanal ="); + PROGMEM Language_Str MSG_LEDS2 = _UxGT("Ljus #2"); + PROGMEM Language_Str MSG_NEO2_PRESETS = _UxGT("Ljus #2 Förinställd"); + PROGMEM Language_Str MSG_NEO2_BRIGHTNESS = _UxGT("Ljusstyrka"); + PROGMEM Language_Str MSG_CUSTOM_LEDS = _UxGT("Anpassat Ljus"); + PROGMEM Language_Str MSG_INTENSITY_R = _UxGT("Rör Intensitet"); + PROGMEM Language_Str MSG_INTENSITY_G = _UxGT("Grön Intensitet"); + PROGMEM Language_Str MSG_INTENSITY_B = _UxGT("Blå Intensitet"); + PROGMEM Language_Str MSG_INTENSITY_W = _UxGT("Vit Intensitet"); + PROGMEM Language_Str MSG_LED_BRIGHTNESS = _UxGT("Brightness"); + + PROGMEM Language_Str MSG_MOVING = _UxGT("Flyttar..."); + PROGMEM Language_Str MSG_FREE_XY = _UxGT("Fri XY"); + PROGMEM Language_Str MSG_MOVE_X = _UxGT("Flytta X"); + PROGMEM Language_Str MSG_MOVE_Y = _UxGT("Flytta Y"); + PROGMEM Language_Str MSG_MOVE_Z = _UxGT("Flytta Z"); + PROGMEM Language_Str MSG_MOVE_E = _UxGT("Extruder"); + PROGMEM Language_Str MSG_MOVE_EN = _UxGT("Extruder *"); + PROGMEM Language_Str MSG_HOTEND_TOO_COLD = _UxGT("Hetände för kall"); + PROGMEM Language_Str MSG_MOVE_N_MM = _UxGT("Flytta %smm"); + PROGMEM Language_Str MSG_MOVE_01MM = _UxGT("Flytta 0.1mm"); + PROGMEM Language_Str MSG_MOVE_1MM = _UxGT("Flytta 1mm"); + PROGMEM Language_Str MSG_MOVE_10MM = _UxGT("Flytta 10mm"); + PROGMEM Language_Str MSG_MOVE_0001IN = _UxGT("Flytta 0.001tum"); + PROGMEM Language_Str MSG_MOVE_001IN = _UxGT("Flytta 0.01tum"); + PROGMEM Language_Str MSG_MOVE_01IN = _UxGT("Flytta 0.1tum"); + PROGMEM Language_Str MSG_SPEED = _UxGT("Hastighet"); + PROGMEM Language_Str MSG_BED_Z = _UxGT("Bädd Z"); + PROGMEM Language_Str MSG_NOZZLE = _UxGT("Munstycke"); + PROGMEM Language_Str MSG_NOZZLE_N = _UxGT("Munstycke ~"); + PROGMEM Language_Str MSG_NOZZLE_PARKED = _UxGT("Munstycke Parkerad"); + PROGMEM Language_Str MSG_NOZZLE_STANDBY = _UxGT("Munstycke Standby"); + PROGMEM Language_Str MSG_BED = _UxGT("Bädd"); + PROGMEM Language_Str MSG_CHAMBER = _UxGT("Inkapsling"); + PROGMEM Language_Str MSG_FAN_SPEED = _UxGT("Fläkt Hastighet"); + PROGMEM Language_Str MSG_FAN_SPEED_N = _UxGT("Fläkt Hastighet ~"); + PROGMEM Language_Str MSG_STORED_FAN_N = _UxGT("Lagrad Fläkt ~"); + PROGMEM Language_Str MSG_EXTRA_FAN_SPEED = _UxGT("Extra Fläkt Hastighet"); + PROGMEM Language_Str MSG_EXTRA_FAN_SPEED_N = _UxGT("Extra Fläkt Hastighet ~"); + PROGMEM Language_Str MSG_CONTROLLER_FAN = _UxGT("Kontroller Fläkt"); + PROGMEM Language_Str MSG_CONTROLLER_FAN_IDLE_SPEED = _UxGT("Overksam Hastighet"); + PROGMEM Language_Str MSG_CONTROLLER_FAN_AUTO_ON = _UxGT("Auto läga"); + PROGMEM Language_Str MSG_CONTROLLER_FAN_SPEED = _UxGT("Aktive Hastighet"); + PROGMEM Language_Str MSG_CONTROLLER_FAN_DURATION = _UxGT("Overksam Period"); + PROGMEM Language_Str MSG_FLOW = _UxGT("Flöde"); + PROGMEM Language_Str MSG_FLOW_N = _UxGT("Flöde ~"); + PROGMEM Language_Str MSG_CONTROL = _UxGT("Kontroll"); + PROGMEM Language_Str MSG_MIN = " " LCD_STR_THERMOMETER _UxGT(" Min"); + PROGMEM Language_Str MSG_MAX = " " LCD_STR_THERMOMETER _UxGT(" Max"); + PROGMEM Language_Str MSG_FACTOR = " " LCD_STR_THERMOMETER _UxGT(" Fakt"); + PROGMEM Language_Str MSG_AUTOTEMP = _UxGT("Autotemp"); + PROGMEM Language_Str MSG_LCD_ON = _UxGT("På"); + PROGMEM Language_Str MSG_LCD_OFF = _UxGT("Av"); + PROGMEM Language_Str MSG_PID_AUTOTUNE = _UxGT("PID Autojustera"); + PROGMEM Language_Str MSG_PID_AUTOTUNE_E = _UxGT("PID Autojustera *"); + PROGMEM Language_Str MSG_PID_AUTOTUNE_DONE = _UxGT("PID tuning done"); + PROGMEM Language_Str MSG_PID_BAD_EXTRUDER_NUM = _UxGT("Autojustera misslyckad. Dålig extruder."); + PROGMEM Language_Str MSG_PID_TEMP_TOO_HIGH = _UxGT("Autojustera misslyckad. Temperatur för hög."); + PROGMEM Language_Str MSG_PID_TIMEOUT = _UxGT("Autojustera misslyckad! Tidsgräns."); + PROGMEM Language_Str MSG_SELECT = _UxGT("Välj"); + PROGMEM Language_Str MSG_SELECT_E = _UxGT("Välj *"); + PROGMEM Language_Str MSG_ACC = _UxGT("Accel"); + PROGMEM Language_Str MSG_JERK = _UxGT("Ryck"); + PROGMEM Language_Str MSG_VA_JERK = _UxGT("V") LCD_STR_A _UxGT("-Ryck"); + PROGMEM Language_Str MSG_VB_JERK = _UxGT("V") LCD_STR_B _UxGT("-Ryck"); + PROGMEM Language_Str MSG_VC_JERK = _UxGT("V") LCD_STR_C _UxGT("-Ryck"); + PROGMEM Language_Str MSG_VE_JERK = _UxGT("Ve-Ryck"); + PROGMEM Language_Str MSG_JUNCTION_DEVIATION = _UxGT("Knutpunkt Avv"); + PROGMEM Language_Str MSG_VELOCITY = _UxGT("Hastighet"); + PROGMEM Language_Str MSG_VMAX_A = _UxGT("Vmax ") LCD_STR_A; + PROGMEM Language_Str MSG_VMAX_B = _UxGT("Vmax ") LCD_STR_B; + PROGMEM Language_Str MSG_VMAX_C = _UxGT("Vmax ") LCD_STR_C; + PROGMEM Language_Str MSG_VMAX_E = _UxGT("Vmax ") LCD_STR_E; + PROGMEM Language_Str MSG_VMAX_EN = _UxGT("Vmax *"); + PROGMEM Language_Str MSG_VMIN = _UxGT("Vmin"); + PROGMEM Language_Str MSG_VTRAV_MIN = _UxGT("VTrav Min"); + PROGMEM Language_Str MSG_ACCELERATION = _UxGT("Acceleration"); + PROGMEM Language_Str MSG_AMAX_A = _UxGT("Amax ") LCD_STR_A; + PROGMEM Language_Str MSG_AMAX_B = _UxGT("Amax ") LCD_STR_B; + PROGMEM Language_Str MSG_AMAX_C = _UxGT("Amax ") LCD_STR_C; + PROGMEM Language_Str MSG_AMAX_E = _UxGT("Amax ") LCD_STR_E; + PROGMEM Language_Str MSG_AMAX_EN = _UxGT("Amax *"); + PROGMEM Language_Str MSG_A_RETRACT = _UxGT("A-Dra tillbaka"); + PROGMEM Language_Str MSG_A_TRAVEL = _UxGT("A-Färdas"); + PROGMEM Language_Str MSG_XY_FREQUENCY_LIMIT = _UxGT("Frekvens max"); + PROGMEM Language_Str MSG_XY_FREQUENCY_FEEDRATE = _UxGT("Flöde min"); + PROGMEM Language_Str MSG_STEPS_PER_MM = _UxGT("Steg/mm"); + PROGMEM Language_Str MSG_A_STEPS = LCD_STR_A _UxGT(" Steg/mm"); + PROGMEM Language_Str MSG_B_STEPS = LCD_STR_B _UxGT(" Steg/mm"); + PROGMEM Language_Str MSG_C_STEPS = LCD_STR_C _UxGT(" Steg/mm"); + PROGMEM Language_Str MSG_E_STEPS = _UxGT("E Steg/mm"); + PROGMEM Language_Str MSG_EN_STEPS = _UxGT("* Steg/mm"); + PROGMEM Language_Str MSG_TEMPERATURE = _UxGT("Temperatur"); + PROGMEM Language_Str MSG_MOTION = _UxGT("Rörelse"); + PROGMEM Language_Str MSG_FILAMENT = _UxGT("Tråd"); + PROGMEM Language_Str MSG_VOLUMETRIC_ENABLED = _UxGT("E i mm³"); + PROGMEM Language_Str MSG_VOLUMETRIC_LIMIT = _UxGT("E Gräns i mm³"); + PROGMEM Language_Str MSG_VOLUMETRIC_LIMIT_E = _UxGT("E Gräns *"); + PROGMEM Language_Str MSG_FILAMENT_DIAM = _UxGT("Tråd Dia."); + PROGMEM Language_Str MSG_FILAMENT_DIAM_E = _UxGT("Tråd Dia. *"); + PROGMEM Language_Str MSG_FILAMENT_UNLOAD = _UxGT("Lossa mm"); + PROGMEM Language_Str MSG_FILAMENT_LOAD = _UxGT("Ladda mm"); + PROGMEM Language_Str MSG_ADVANCE_K = _UxGT("Advancera K"); + PROGMEM Language_Str MSG_ADVANCE_K_E = _UxGT("Advancera K *"); + PROGMEM Language_Str MSG_CONTRAST = _UxGT("LCD Kontrast"); + PROGMEM Language_Str MSG_STORE_EEPROM = _UxGT("Spara Inställningar"); + PROGMEM Language_Str MSG_LOAD_EEPROM = _UxGT("Ladda Inställningar"); + PROGMEM Language_Str MSG_RESTORE_DEFAULTS = _UxGT("Återställ Standard"); + PROGMEM Language_Str MSG_INIT_EEPROM = _UxGT("Initiera EEPROM"); + PROGMEM Language_Str MSG_ERR_EEPROM_CRC = _UxGT("EEPROM CRC Fel"); + PROGMEM Language_Str MSG_ERR_EEPROM_INDEX = _UxGT("EEPROM Index Fel"); + PROGMEM Language_Str MSG_ERR_EEPROM_VERSION = _UxGT("EEPROM Version Fel"); + PROGMEM Language_Str MSG_SETTINGS_STORED = _UxGT("Inställningar Lagrad"); + PROGMEM Language_Str MSG_MEDIA_UPDATE = _UxGT("Media Uppdatera"); + PROGMEM Language_Str MSG_RESET_PRINTER = _UxGT("Återställ Skrivare"); + PROGMEM Language_Str MSG_REFRESH = LCD_STR_REFRESH _UxGT("Uppdatera"); + PROGMEM Language_Str MSG_INFO_SCREEN = _UxGT("Info Skärm"); + PROGMEM Language_Str MSG_PREPARE = _UxGT("Förbered"); + PROGMEM Language_Str MSG_TUNE = _UxGT("Justera"); + PROGMEM Language_Str MSG_POWER_MONITOR = _UxGT("Ström övervakning"); + PROGMEM Language_Str MSG_CURRENT = _UxGT("Ström"); + PROGMEM Language_Str MSG_VOLTAGE = _UxGT("Spänning"); + PROGMEM Language_Str MSG_POWER = _UxGT("Ström"); + PROGMEM Language_Str MSG_START_PRINT = _UxGT("Start Utskrift"); + PROGMEM Language_Str MSG_BUTTON_NEXT = _UxGT("Nästa"); + PROGMEM Language_Str MSG_BUTTON_INIT = _UxGT("Initiera"); + PROGMEM Language_Str MSG_BUTTON_STOP = _UxGT("Stoppa"); + PROGMEM Language_Str MSG_BUTTON_PRINT = _UxGT("Skriv"); + PROGMEM Language_Str MSG_BUTTON_RESET = _UxGT("Återställa"); + PROGMEM Language_Str MSG_BUTTON_IGNORE = _UxGT("Ignorera"); + PROGMEM Language_Str MSG_BUTTON_CANCEL = _UxGT("Avbryt"); + PROGMEM Language_Str MSG_BUTTON_DONE = _UxGT("Färdig"); + PROGMEM Language_Str MSG_BUTTON_BACK = _UxGT("Bakåt"); + PROGMEM Language_Str MSG_BUTTON_PROCEED = _UxGT("Fortsätt"); + PROGMEM Language_Str MSG_BUTTON_SKIP = _UxGT("Hoppa över"); + PROGMEM Language_Str MSG_PAUSING = _UxGT("Paus.."); + PROGMEM Language_Str MSG_PAUSE_PRINT = _UxGT("Pausera Utskrift"); + PROGMEM Language_Str MSG_RESUME_PRINT = _UxGT("Återuppta Utskrift"); + PROGMEM Language_Str MSG_HOST_START_PRINT = _UxGT("Värd Start"); + PROGMEM Language_Str MSG_STOP_PRINT = _UxGT("Stoppa Utskrift"); + PROGMEM Language_Str MSG_END_LOOPS = _UxGT("Slut Upprepningsloop"); + PROGMEM Language_Str MSG_PRINTING_OBJECT = _UxGT("Skriver Objekt"); + PROGMEM Language_Str MSG_CANCEL_OBJECT = _UxGT("Avbryt Objekt"); + PROGMEM Language_Str MSG_CANCEL_OBJECT_N = _UxGT("Avbryt Objekt ="); + PROGMEM Language_Str MSG_OUTAGE_RECOVERY = _UxGT("Ström Avbrott"); + PROGMEM Language_Str MSG_MEDIA_MENU = _UxGT("Skriv fråm Media"); + PROGMEM Language_Str MSG_NO_MEDIA = _UxGT("Inget Media"); + PROGMEM Language_Str MSG_DWELL = _UxGT("Sov..."); + PROGMEM Language_Str MSG_USERWAIT = _UxGT("Klick för att återuppta..."); + PROGMEM Language_Str MSG_PRINT_PAUSED = _UxGT("Utskrift Pausad"); + PROGMEM Language_Str MSG_PRINTING = _UxGT("Skriver..."); + PROGMEM Language_Str MSG_PRINT_ABORTED = _UxGT("Utskrift Avbruten"); + PROGMEM Language_Str MSG_PRINT_DONE = _UxGT("Utskrift Färdig"); + PROGMEM Language_Str MSG_NO_MOVE = _UxGT("Ingen Flytt."); + PROGMEM Language_Str MSG_KILLED = _UxGT("DÖDAD. "); + PROGMEM Language_Str MSG_STOPPED = _UxGT("STOPPAD. "); + PROGMEM Language_Str MSG_CONTROL_RETRACT = _UxGT("Dra tillbaka mm"); + PROGMEM Language_Str MSG_CONTROL_RETRACT_SWAP = _UxGT("Byt Dra.mm"); + PROGMEM Language_Str MSG_CONTROL_RETRACTF = _UxGT("Dra tillbaka V"); + PROGMEM Language_Str MSG_CONTROL_RETRACT_ZHOP = _UxGT("Hoppa mm"); + PROGMEM Language_Str MSG_CONTROL_RETRACT_RECOVER = _UxGT("Åter dra tillbaka. mm"); + PROGMEM Language_Str MSG_CONTROL_RETRACT_RECOVER_SWAP = _UxGT("Byt åter dra t. mm"); + PROGMEM Language_Str MSG_CONTROL_RETRACT_RECOVERF = _UxGT("Återdrat. V"); + PROGMEM Language_Str MSG_CONTROL_RETRACT_RECOVER_SWAPF = _UxGT("Byt åter dra. V"); + PROGMEM Language_Str MSG_AUTORETRACT = _UxGT("Auto-Dra-tillbka"); + PROGMEM Language_Str MSG_FILAMENT_SWAP_LENGTH = _UxGT("Byt Längd"); + PROGMEM Language_Str MSG_FILAMENT_SWAP_EXTRA = _UxGT("Byt Extra"); + PROGMEM Language_Str MSG_FILAMENT_PURGE_LENGTH = _UxGT("Rensa Längd"); + PROGMEM Language_Str MSG_TOOL_CHANGE = _UxGT("Byt verktyg"); + PROGMEM Language_Str MSG_TOOL_CHANGE_ZLIFT = _UxGT("Z Höj"); + PROGMEM Language_Str MSG_SINGLENOZZLE_PRIME_SPEED = _UxGT("Grund Hastighet"); + PROGMEM Language_Str MSG_SINGLENOZZLE_RETRACT_SPEED = _UxGT("Återgå Hastighet"); + PROGMEM Language_Str MSG_FILAMENT_PARK_ENABLED = _UxGT("Parkera Huvud"); + PROGMEM Language_Str MSG_SINGLENOZZLE_UNRETRACT_SPEED = _UxGT("Återgår Hastighet"); + PROGMEM Language_Str MSG_SINGLENOZZLE_FAN_SPEED = _UxGT("Fläkt Hastighet"); + PROGMEM Language_Str MSG_SINGLENOZZLE_FAN_TIME = _UxGT("Fläkt Tid"); + PROGMEM Language_Str MSG_TOOL_MIGRATION_ON = _UxGT("Auto PÅ"); + PROGMEM Language_Str MSG_TOOL_MIGRATION_OFF = _UxGT("Auto AV"); + PROGMEM Language_Str MSG_TOOL_MIGRATION = _UxGT("Verktyg Migration"); + PROGMEM Language_Str MSG_TOOL_MIGRATION_AUTO = _UxGT("Auto-migration"); + PROGMEM Language_Str MSG_TOOL_MIGRATION_END = _UxGT("Senast Extruder"); + PROGMEM Language_Str MSG_TOOL_MIGRATION_SWAP = _UxGT("Migrera till *"); + PROGMEM Language_Str MSG_FILAMENTCHANGE = _UxGT("Byt Tråd"); + PROGMEM Language_Str MSG_FILAMENTCHANGE_E = _UxGT("Byt Tråd *"); + PROGMEM Language_Str MSG_FILAMENTLOAD = _UxGT("Ladda Tråd"); + PROGMEM Language_Str MSG_FILAMENTLOAD_E = _UxGT("Ladda *"); + PROGMEM Language_Str MSG_FILAMENTUNLOAD = _UxGT("Lossa Tråd"); + PROGMEM Language_Str MSG_FILAMENTUNLOAD_E = _UxGT("Lossa *"); + PROGMEM Language_Str MSG_FILAMENTUNLOAD_ALL = _UxGT("Lossa All"); + PROGMEM Language_Str MSG_ATTACH_MEDIA = _UxGT("Bifoga Media"); + PROGMEM Language_Str MSG_CHANGE_MEDIA = _UxGT("Byt Media"); + PROGMEM Language_Str MSG_RELEASE_MEDIA = _UxGT("Släpp Media"); + PROGMEM Language_Str MSG_ZPROBE_OUT = _UxGT("Z Sond Utanför Bädd"); + PROGMEM Language_Str MSG_SKEW_FACTOR = _UxGT("Skev Faktor"); + PROGMEM Language_Str MSG_BLTOUCH = _UxGT("BLTouch"); + PROGMEM Language_Str MSG_BLTOUCH_SELFTEST = _UxGT("Själv-Test"); + PROGMEM Language_Str MSG_BLTOUCH_RESET = _UxGT("Återställ"); + PROGMEM Language_Str MSG_BLTOUCH_STOW = _UxGT("Stuva undan"); + PROGMEM Language_Str MSG_BLTOUCH_DEPLOY = _UxGT("Fällut"); + PROGMEM Language_Str MSG_BLTOUCH_SW_MODE = _UxGT("SW-Läge"); + PROGMEM Language_Str MSG_BLTOUCH_5V_MODE = _UxGT("5V-Läge"); + PROGMEM Language_Str MSG_BLTOUCH_OD_MODE = _UxGT("OD-Läge"); + PROGMEM Language_Str MSG_BLTOUCH_MODE_STORE = _UxGT("Läge-Lägring"); + PROGMEM Language_Str MSG_BLTOUCH_MODE_STORE_5V = _UxGT("Sätt BLTouch to 5V"); + PROGMEM Language_Str MSG_BLTOUCH_MODE_STORE_OD = _UxGT("Sätt BLTouch to OD"); + PROGMEM Language_Str MSG_BLTOUCH_MODE_ECHO = _UxGT("Reportera Dränering"); + PROGMEM Language_Str MSG_BLTOUCH_MODE_CHANGE = _UxGT("FARA: Dålig inställningar kan orsaka skada! Fortsätt ändå?"); + PROGMEM Language_Str MSG_TOUCHMI_PROBE = _UxGT("TouchMI"); + PROGMEM Language_Str MSG_TOUCHMI_INIT = _UxGT("Initiera TouchMI"); + PROGMEM Language_Str MSG_TOUCHMI_ZTEST = _UxGT("Z Offset Test"); + PROGMEM Language_Str MSG_TOUCHMI_SAVE = _UxGT("Spara"); + PROGMEM Language_Str MSG_MANUAL_DEPLOY_TOUCHMI = _UxGT("Fällut TouchMI"); + PROGMEM Language_Str MSG_MANUAL_DEPLOY = _UxGT("Fällut Z-Sond"); + PROGMEM Language_Str MSG_MANUAL_STOW = _UxGT("Stuva undan Z-Sond"); + PROGMEM Language_Str MSG_HOME_FIRST = _UxGT("Hem %s%s%s Först"); + PROGMEM Language_Str MSG_ZPROBE_OFFSETS = _UxGT("Sond Offsets"); + PROGMEM Language_Str MSG_ZPROBE_XOFFSET = _UxGT("Sond X Offset"); + PROGMEM Language_Str MSG_ZPROBE_YOFFSET = _UxGT("Sond Y Offset"); + PROGMEM Language_Str MSG_ZPROBE_ZOFFSET = _UxGT("Sond Z Offset"); + PROGMEM Language_Str MSG_MOVE_NOZZLE_TO_BED = _UxGT("Flytta Munstycke till Bädd"); + PROGMEM Language_Str MSG_BABYSTEP_X = _UxGT("Småsteg X"); + PROGMEM Language_Str MSG_BABYSTEP_Y = _UxGT("Småsteg Y"); + PROGMEM Language_Str MSG_BABYSTEP_Z = _UxGT("Småsteg Z"); + PROGMEM Language_Str MSG_BABYSTEP_TOTAL = _UxGT("Total"); + PROGMEM Language_Str MSG_ENDSTOP_ABORT = _UxGT("Slutstopp Avbrott"); + PROGMEM Language_Str MSG_HEATING_FAILED_LCD = _UxGT("Värma Misslyckad"); + PROGMEM Language_Str MSG_ERR_REDUNDANT_TEMP = _UxGT("Fel: REDUNDANT TEMP"); + PROGMEM Language_Str MSG_THERMAL_RUNAWAY = _UxGT("TERMISK ÖVERDRIFT"); + PROGMEM Language_Str MSG_THERMAL_RUNAWAY_BED = _UxGT("BÄDD TERMISK ÖVERDRIFT"); + PROGMEM Language_Str MSG_THERMAL_RUNAWAY_CHAMBER = _UxGT("KAMMARE T. ÖVERDRIFT"); + PROGMEM Language_Str MSG_ERR_MAXTEMP = _UxGT("Fel: MAXTEMP"); + PROGMEM Language_Str MSG_ERR_MINTEMP = _UxGT("Fel: MINTEMP"); + PROGMEM Language_Str MSG_HALTED = _UxGT("Utskrift stoppad"); + PROGMEM Language_Str MSG_PLEASE_RESET = _UxGT("Snälla Återställ"); + PROGMEM Language_Str MSG_SHORT_DAY = _UxGT("d"); // One character only + PROGMEM Language_Str MSG_SHORT_HOUR = _UxGT("t"); // One character only + PROGMEM Language_Str MSG_SHORT_MINUTE = _UxGT("m"); // One character only + PROGMEM Language_Str MSG_HEATING = _UxGT("Värmer..."); + PROGMEM Language_Str MSG_COOLING = _UxGT("Kyler..."); + PROGMEM Language_Str MSG_BED_HEATING = _UxGT("Bädd Värmer..."); + PROGMEM Language_Str MSG_BED_COOLING = _UxGT("Bädd Kyler..."); + PROGMEM Language_Str MSG_PROBE_HEATING = _UxGT("Sond Värmer..."); + PROGMEM Language_Str MSG_PROBE_COOLING = _UxGT("Sond Kyler..."); + PROGMEM Language_Str MSG_CHAMBER_HEATING = _UxGT("Kammare Värmer..."); + PROGMEM Language_Str MSG_CHAMBER_COOLING = _UxGT("Kammare Kyler..."); + PROGMEM Language_Str MSG_DELTA_CALIBRATE = _UxGT("Delta Kalibrering"); + PROGMEM Language_Str MSG_DELTA_CALIBRATE_X = _UxGT("Kalibrera X"); + PROGMEM Language_Str MSG_DELTA_CALIBRATE_Y = _UxGT("Kalibrera Y"); + PROGMEM Language_Str MSG_DELTA_CALIBRATE_Z = _UxGT("Kalibrera Z"); + PROGMEM Language_Str MSG_DELTA_CALIBRATE_CENTER = _UxGT("Kalibrera Center"); + PROGMEM Language_Str MSG_DELTA_SETTINGS = _UxGT("Delta Inställningar"); + PROGMEM Language_Str MSG_DELTA_AUTO_CALIBRATE = _UxGT("Auto Kalibrering"); + PROGMEM Language_Str MSG_DELTA_HEIGHT_CALIBRATE = _UxGT("Sätt Delta Höjd"); + PROGMEM Language_Str MSG_DELTA_Z_OFFSET_CALIBRATE = _UxGT("Sond Z-offset"); + PROGMEM Language_Str MSG_DELTA_DIAG_ROD = _UxGT("Diag Rod"); + PROGMEM Language_Str MSG_DELTA_HEIGHT = _UxGT("Höjd"); + PROGMEM Language_Str MSG_DELTA_RADIUS = _UxGT("Radius"); + PROGMEM Language_Str MSG_INFO_MENU = _UxGT("Om Skrivaren"); + PROGMEM Language_Str MSG_INFO_PRINTER_MENU = _UxGT("Skrivare Info"); + PROGMEM Language_Str MSG_3POINT_LEVELING = _UxGT("3-Punkt Nivellering"); + PROGMEM Language_Str MSG_LINEAR_LEVELING = _UxGT("Linjär Nivellering"); + PROGMEM Language_Str MSG_BILINEAR_LEVELING = _UxGT("Bilinjär Nivellering"); + PROGMEM Language_Str MSG_UBL_LEVELING = _UxGT("Enhetlig Bädd Nivellering (UBL)"); + PROGMEM Language_Str MSG_MESH_LEVELING = _UxGT("Nät Nivellering"); + PROGMEM Language_Str MSG_INFO_STATS_MENU = _UxGT("Skrivar Stats"); + PROGMEM Language_Str MSG_INFO_BOARD_MENU = _UxGT("Kort Info"); + PROGMEM Language_Str MSG_INFO_THERMISTOR_MENU = _UxGT("Termistor"); + PROGMEM Language_Str MSG_INFO_EXTRUDERS = _UxGT("Extruderare"); + PROGMEM Language_Str MSG_INFO_BAUDRATE = _UxGT("Baud"); + PROGMEM Language_Str MSG_INFO_PROTOCOL = _UxGT("Protokoll"); + PROGMEM Language_Str MSG_INFO_RUNAWAY_OFF = _UxGT("Överdrift Övervakning: AV"); + PROGMEM Language_Str MSG_INFO_RUNAWAY_ON = _UxGT("Överdrift Övervakning: PÅ"); + PROGMEM Language_Str MSG_HOTEND_IDLE_TIMEOUT = _UxGT("Hetände Overksam Tidsgräns"); + + PROGMEM Language_Str MSG_CASE_LIGHT = _UxGT("Lådljus"); + PROGMEM Language_Str MSG_CASE_LIGHT_BRIGHTNESS = _UxGT("Ljus ljusstyrka"); + PROGMEM Language_Str MSG_KILL_EXPECTED_PRINTER = _UxGT("INKORREKT SKRIVARE"); + + #if LCD_WIDTH >= 20 + PROGMEM Language_Str MSG_INFO_PRINT_COUNT = _UxGT("Utskriftsantal"); + PROGMEM Language_Str MSG_INFO_COMPLETED_PRINTS = _UxGT("Färdiga"); + PROGMEM Language_Str MSG_INFO_PRINT_TIME = _UxGT("Total Utskriftstid"); + PROGMEM Language_Str MSG_INFO_PRINT_LONGEST = _UxGT("Längsta Jobbtid"); + PROGMEM Language_Str MSG_INFO_PRINT_FILAMENT = _UxGT("Extruderade Totalt"); + #else + PROGMEM Language_Str MSG_INFO_PRINT_COUNT = _UxGT("Utskrift"); + PROGMEM Language_Str MSG_INFO_COMPLETED_PRINTS = _UxGT("Färdig"); + PROGMEM Language_Str MSG_INFO_PRINT_TIME = _UxGT("Total"); + PROGMEM Language_Str MSG_INFO_PRINT_LONGEST = _UxGT("Längsta"); + PROGMEM Language_Str MSG_INFO_PRINT_FILAMENT = _UxGT("Extruderad"); + #endif + + PROGMEM Language_Str MSG_INFO_MIN_TEMP = _UxGT("Min Temp"); + PROGMEM Language_Str MSG_INFO_MAX_TEMP = _UxGT("Max Temp"); + PROGMEM Language_Str MSG_INFO_PSU = _UxGT("PSU"); + PROGMEM Language_Str MSG_DRIVE_STRENGTH = _UxGT("Driv Styrka"); + PROGMEM Language_Str MSG_DAC_PERCENT_X = _UxGT("X Driver %"); + PROGMEM Language_Str MSG_DAC_PERCENT_Y = _UxGT("Y Driver %"); + PROGMEM Language_Str MSG_DAC_PERCENT_Z = _UxGT("Z Driver %"); + PROGMEM Language_Str MSG_DAC_PERCENT_E = _UxGT("E Driver %"); + PROGMEM Language_Str MSG_ERROR_TMC = _UxGT("TMC KOPPLNINGSFEL"); + PROGMEM Language_Str MSG_DAC_EEPROM_WRITE = _UxGT("DAC EEPROM Skriv"); + PROGMEM Language_Str MSG_FILAMENT_CHANGE_HEADER = _UxGT("TRÅDBYTE"); + PROGMEM Language_Str MSG_FILAMENT_CHANGE_HEADER_PAUSE = _UxGT("UTSKRIFTSPAUSERAD"); + PROGMEM Language_Str MSG_FILAMENT_CHANGE_HEADER_LOAD = _UxGT("LADDA TRÅD"); + PROGMEM Language_Str MSG_FILAMENT_CHANGE_HEADER_UNLOAD = _UxGT("LOSSA TRÅD"); + PROGMEM Language_Str MSG_FILAMENT_CHANGE_OPTION_HEADER = _UxGT("ÅTERGÅ VAÖ:"); + PROGMEM Language_Str MSG_FILAMENT_CHANGE_OPTION_PURGE = _UxGT("Rensa mer"); + PROGMEM Language_Str MSG_FILAMENT_CHANGE_OPTION_RESUME = _UxGT("Fortsätt"); + PROGMEM Language_Str MSG_FILAMENT_CHANGE_NOZZLE = _UxGT(" Munstycke: "); + PROGMEM Language_Str MSG_RUNOUT_SENSOR = _UxGT("Utskjut Sensor"); + PROGMEM Language_Str MSG_RUNOUT_DISTANCE_MM = _UxGT("Utskjut Dist mm"); + PROGMEM Language_Str MSG_KILL_HOMING_FAILED = _UxGT("Hemning Misslyckad"); + PROGMEM Language_Str MSG_LCD_PROBING_FAILED = _UxGT("Sondering Misslyckad"); + + PROGMEM Language_Str MSG_MMU2_CHOOSE_FILAMENT_HEADER = _UxGT("VÄLJ TRÅD"); + PROGMEM Language_Str MSG_MMU2_MENU = _UxGT("MMU"); + PROGMEM Language_Str MSG_KILL_MMU2_FIRMWARE = _UxGT("Uppdatera MMU Firmware!"); + PROGMEM Language_Str MSG_MMU2_NOT_RESPONDING = _UxGT("MMU Behöver uppmärksamhet."); + PROGMEM Language_Str MSG_MMU2_RESUME = _UxGT("MMU Återuppta"); + PROGMEM Language_Str MSG_MMU2_RESUMING = _UxGT("MMU Återupptas..."); + PROGMEM Language_Str MSG_MMU2_LOAD_FILAMENT = _UxGT("MMU Ladda"); + PROGMEM Language_Str MSG_MMU2_LOAD_ALL = _UxGT("MMU Ladda Alla"); + PROGMEM Language_Str MSG_MMU2_LOAD_TO_NOZZLE = _UxGT("MMU Ladda till Munstycke"); + PROGMEM Language_Str MSG_MMU2_EJECT_FILAMENT = _UxGT("MMU Mata ut"); + PROGMEM Language_Str MSG_MMU2_EJECT_FILAMENT_N = _UxGT("MMU Mata ut ~"); + PROGMEM Language_Str MSG_MMU2_UNLOAD_FILAMENT = _UxGT("MMU Lossa"); + PROGMEM Language_Str MSG_MMU2_LOADING_FILAMENT = _UxGT("Ladda Tråd %i..."); + PROGMEM Language_Str MSG_MMU2_EJECTING_FILAMENT = _UxGT("Mata ut Tråd ..."); + PROGMEM Language_Str MSG_MMU2_UNLOADING_FILAMENT = _UxGT("Lossa Tråd..."); + PROGMEM Language_Str MSG_MMU2_ALL = _UxGT("Alla"); + PROGMEM Language_Str MSG_MMU2_FILAMENT_N = _UxGT("Tråd ~"); + PROGMEM Language_Str MSG_MMU2_RESET = _UxGT("Återställ MMU"); + PROGMEM Language_Str MSG_MMU2_RESETTING = _UxGT("MMU Återställer..."); + PROGMEM Language_Str MSG_MMU2_EJECT_RECOVER = _UxGT("Ta bort, Klicka"); + + PROGMEM Language_Str MSG_MIX = _UxGT("Mixa"); + PROGMEM Language_Str MSG_MIX_COMPONENT_N = _UxGT("Komponent ="); + PROGMEM Language_Str MSG_MIXER = _UxGT("Mixer"); + PROGMEM Language_Str MSG_GRADIENT = _UxGT("Gradient"); + PROGMEM Language_Str MSG_FULL_GRADIENT = _UxGT("Full Gradient"); + PROGMEM Language_Str MSG_TOGGLE_MIX = _UxGT("Växla Mix"); + PROGMEM Language_Str MSG_CYCLE_MIX = _UxGT("Totera Mix"); + PROGMEM Language_Str MSG_GRADIENT_MIX = _UxGT("Gradient Mix"); + PROGMEM Language_Str MSG_REVERSE_GRADIENT = _UxGT("Omvänd Gradient"); + PROGMEM Language_Str MSG_ACTIVE_VTOOL = _UxGT("Aktive V-verktyg"); + PROGMEM Language_Str MSG_START_VTOOL = _UxGT("Start V-verktyg"); + PROGMEM Language_Str MSG_END_VTOOL = _UxGT(" Slut V-verktyg"); + PROGMEM Language_Str MSG_GRADIENT_ALIAS = _UxGT("Alias V-verktyg"); + PROGMEM Language_Str MSG_RESET_VTOOLS = _UxGT("Återställ V-verktyg"); + PROGMEM Language_Str MSG_COMMIT_VTOOL = _UxGT("Kommitta V-verktyg Mix"); + PROGMEM Language_Str MSG_VTOOLS_RESET = _UxGT("V-verktyg blev Återställda"); + PROGMEM Language_Str MSG_START_Z = _UxGT("Start Z:"); + PROGMEM Language_Str MSG_END_Z = _UxGT(" Slut Z:"); + + PROGMEM Language_Str MSG_GAMES = _UxGT("Spel"); + PROGMEM Language_Str MSG_BRICKOUT = _UxGT("Brickout"); + PROGMEM Language_Str MSG_INVADERS = _UxGT("Invaders"); + PROGMEM Language_Str MSG_SNAKE = _UxGT("Sn4k3"); + PROGMEM Language_Str MSG_MAZE = _UxGT("Labyrint"); + + PROGMEM Language_Str MSG_BAD_PAGE = _UxGT("Dålig sida index"); + PROGMEM Language_Str MSG_BAD_PAGE_SPEED = _UxGT("Dålig sida hastighet"); + + PROGMEM Language_Str MSG_EDIT_PASSWORD = _UxGT("Redigera Lösenord"); + PROGMEM Language_Str MSG_LOGIN_REQUIRED = _UxGT("Login Krävs"); + PROGMEM Language_Str MSG_PASSWORD_SETTINGS = _UxGT("Lösenordsinställningar"); + PROGMEM Language_Str MSG_ENTER_DIGIT = _UxGT("Ange Siffra"); + PROGMEM Language_Str MSG_CHANGE_PASSWORD = _UxGT("Sätt/Redigera Lösenord"); + PROGMEM Language_Str MSG_REMOVE_PASSWORD = _UxGT("Ta bort Lösenord"); + PROGMEM Language_Str MSG_PASSWORD_SET = _UxGT("Lösenord är "); + PROGMEM Language_Str MSG_START_OVER = _UxGT("Börja om"); + PROGMEM Language_Str MSG_REMINDER_SAVE_SETTINGS = _UxGT("Kom ihåg att Spara!"); + PROGMEM Language_Str MSG_PASSWORD_REMOVED = _UxGT("Lösenord Bort taget"); + + // + // Filament Change screens show up to 3 lines on a 4-line display + // ...or up to 2 lines on a 3-line display + // + #if LCD_HEIGHT >= 4 + PROGMEM Language_Str MSG_ADVANCED_PAUSE_WAITING = _UxGT(MSG_2_LINE("Tryck på knappen", "för att fortsätta utskrift")); + PROGMEM Language_Str MSG_PAUSE_PRINT_PARKING = _UxGT(MSG_1_LINE("Parkera...")); + PROGMEM Language_Str MSG_FILAMENT_CHANGE_INIT = _UxGT(MSG_3_LINE("Vänta på", "trådbyte", "att börja")); + PROGMEM Language_Str MSG_FILAMENT_CHANGE_INSERT = _UxGT(MSG_3_LINE("Sätt in tråd", "och tryck på knappen", "för att fortsätta")); + PROGMEM Language_Str MSG_FILAMENT_CHANGE_HEAT = _UxGT(MSG_2_LINE("Tryck på knappen", "för att värma munstycke")); + PROGMEM Language_Str MSG_FILAMENT_CHANGE_HEATING = _UxGT(MSG_2_LINE("Munstycke värms", "Var snäll och vänta...")); + PROGMEM Language_Str MSG_FILAMENT_CHANGE_UNLOAD = _UxGT(MSG_2_LINE("Väntar på", "trådlossning")); + PROGMEM Language_Str MSG_FILAMENT_CHANGE_LOAD = _UxGT(MSG_2_LINE("Väntar på", "trådladdning")); + PROGMEM Language_Str MSG_FILAMENT_CHANGE_PURGE = _UxGT(MSG_2_LINE("Väntar på", "tråd utrensning")); + PROGMEM Language_Str MSG_FILAMENT_CHANGE_CONT_PURGE = _UxGT(MSG_2_LINE("Klicka för att slutföra", "tråd utrensning")); + PROGMEM Language_Str MSG_FILAMENT_CHANGE_RESUME = _UxGT(MSG_2_LINE("Väntar på utskrift", "att återstarta...")); + #else + PROGMEM Language_Str MSG_ADVANCED_PAUSE_WAITING = _UxGT(MSG_1_LINE("Klick för att fortsätta")); + PROGMEM Language_Str MSG_PAUSE_PRINT_PARKING = _UxGT(MSG_1_LINE("Parkera...")); + PROGMEM Language_Str MSG_FILAMENT_CHANGE_INIT = _UxGT(MSG_1_LINE("Vänta...")); + PROGMEM Language_Str MSG_FILAMENT_CHANGE_INSERT = _UxGT(MSG_1_LINE("Sätt in och klicka")); + PROGMEM Language_Str MSG_FILAMENT_CHANGE_HEAT = _UxGT(MSG_1_LINE("Klicka för att värma")); + PROGMEM Language_Str MSG_FILAMENT_CHANGE_HEATING = _UxGT(MSG_1_LINE("Värmer...")); + PROGMEM Language_Str MSG_FILAMENT_CHANGE_UNLOAD = _UxGT(MSG_1_LINE("Lossar...")); + PROGMEM Language_Str MSG_FILAMENT_CHANGE_LOAD = _UxGT(MSG_1_LINE("Laddar...")); + PROGMEM Language_Str MSG_FILAMENT_CHANGE_PURGE = _UxGT(MSG_1_LINE("Rensar...")); + PROGMEM Language_Str MSG_FILAMENT_CHANGE_CONT_PURGE = _UxGT(MSG_1_LINE("Klicka för att slutföra")); + PROGMEM Language_Str MSG_FILAMENT_CHANGE_RESUME = _UxGT(MSG_1_LINE("Återgår...")); + #endif + PROGMEM Language_Str MSG_TMC_DRIVERS = _UxGT("TMC Drivers"); + PROGMEM Language_Str MSG_TMC_CURRENT = _UxGT("Driver Ström"); + PROGMEM Language_Str MSG_TMC_HYBRID_THRS = _UxGT("Hybrid Tröskelvärde"); + PROGMEM Language_Str MSG_TMC_HOMING_THRS = _UxGT("Sensorlös Hemning"); + PROGMEM Language_Str MSG_TMC_STEPPING_MODE = _UxGT("Stegningsläge"); + PROGMEM Language_Str MSG_TMC_STEALTH_ENABLED = _UxGT("Smyghack Aktiverad"); + PROGMEM Language_Str MSG_SERVICE_RESET = _UxGT("Återställ"); + PROGMEM Language_Str MSG_SERVICE_IN = _UxGT(" in:"); + PROGMEM Language_Str MSG_BACKLASH = _UxGT("Backlash"); + PROGMEM Language_Str MSG_BACKLASH_A = LCD_STR_A; + PROGMEM Language_Str MSG_BACKLASH_B = LCD_STR_B; + PROGMEM Language_Str MSG_BACKLASH_C = LCD_STR_C; + PROGMEM Language_Str MSG_BACKLASH_CORRECTION = _UxGT("Korrigering"); + PROGMEM Language_Str MSG_BACKLASH_SMOOTHING = _UxGT("Glättning"); + + PROGMEM Language_Str MSG_LEVEL_X_AXIS = _UxGT("Nivå X Axel"); + PROGMEM Language_Str MSG_AUTO_CALIBRATE = _UxGT("Auto Kalibrera"); + #if ENABLED(TOUCH_UI_FTDI_EVE) + PROGMEM Language_Str MSG_HEATER_TIMEOUT = _UxGT("Overksam tidsgräns, temperatur minskning. Tryck ok för att återvärma och igen för att fortsätta."); + #else + PROGMEM Language_Str MSG_HEATER_TIMEOUT = _UxGT("Värmare Tidsgräns"); + #endif + PROGMEM Language_Str MSG_REHEAT = _UxGT("Återvärm"); + PROGMEM Language_Str MSG_REHEATING = _UxGT("Återvärmning..."); + + PROGMEM Language_Str MSG_PROBE_WIZARD = _UxGT("Z Sond Wizard"); + PROGMEM Language_Str MSG_PROBE_WIZARD_PROBING = _UxGT("Sondering Z Referens"); + PROGMEM Language_Str MSG_PROBE_WIZARD_MOVING = _UxGT("Flyttar till Sonderings Pos"); + + PROGMEM Language_Str MSG_SOUND = _UxGT("Ljud"); + + PROGMEM Language_Str MSG_TOP_LEFT = _UxGT("Uppe Vänster"); + PROGMEM Language_Str MSG_BOTTOM_LEFT = _UxGT("Nere Vänster"); + PROGMEM Language_Str MSG_TOP_RIGHT = _UxGT("Uppe Höger"); + PROGMEM Language_Str MSG_BOTTOM_RIGHT = _UxGT("Nere Höger"); + PROGMEM Language_Str MSG_CALIBRATION_COMPLETED = _UxGT("Kalibrering Färdig"); + PROGMEM Language_Str MSG_CALIBRATION_FAILED = _UxGT("Kalibrering Misslyckad"); +} diff --git a/Marlin/src/lcd/language/language_uk.h b/Marlin/src/lcd/language/language_uk.h index eb69bc1b74..069ad7066d 100644 --- a/Marlin/src/lcd/language/language_uk.h +++ b/Marlin/src/lcd/language/language_uk.h @@ -215,7 +215,7 @@ namespace Language_uk { PROGMEM Language_Str MSG_UBL_MESH_HEIGHT_AMOUNT = _UxGT("Висота"); PROGMEM Language_Str MSG_UBL_VALIDATE_MESH_MENU = _UxGT("Підтвердити сітку"); PROGMEM Language_Str MSG_UBL_VALIDATE_CUSTOM_MESH = _UxGT("Підтвердити свою"); - + PROGMEM Language_Str MSG_G26_HEATING_BED = _UxGT("G26 нагрів столу"); PROGMEM Language_Str MSG_G26_HEATING_NOZZLE = _UxGT("G26 нагрів сопла"); PROGMEM Language_Str MSG_G26_MANUAL_PRIME = _UxGT("Ручне грунтування"); @@ -714,7 +714,7 @@ namespace Language_uk { PROGMEM Language_Str MSG_CYCLE_MIX = _UxGT("Циклічне змішування"); PROGMEM Language_Str MSG_GRADIENT_MIX = _UxGT("Градієнт змішування"); PROGMEM Language_Str MSG_REVERSE_GRADIENT = _UxGT("Змінити градієнт"); - + #if LCD_WIDTH > 21 PROGMEM Language_Str MSG_ACTIVE_VTOOL = _UxGT("Активація В-інструменту"); PROGMEM Language_Str MSG_GRADIENT_ALIAS = _UxGT("Псевдонім В-інструменту"); @@ -728,7 +728,7 @@ namespace Language_uk { PROGMEM Language_Str MSG_END_VTOOL = _UxGT("Кінець В-інструменту"); PROGMEM Language_Str MSG_COMMIT_VTOOL = _UxGT("Змішати В-інструменти"); PROGMEM Language_Str MSG_VTOOLS_RESET = _UxGT("В-інструменти зкинуті"); - + PROGMEM Language_Str MSG_START_Z = _UxGT("Початок Z:"); PROGMEM Language_Str MSG_END_Z = _UxGT(" Кінець Z:"); diff --git a/Marlin/src/lcd/lcdprint.cpp b/Marlin/src/lcd/lcdprint.cpp index 2c78b14834..32f425168f 100644 --- a/Marlin/src/lcd/lcdprint.cpp +++ b/Marlin/src/lcd/lcdprint.cpp @@ -28,6 +28,7 @@ #if HAS_WIRED_LCD && !HAS_GRAPHICAL_TFT +#include "marlinui.h" #include "lcdprint.h" /** diff --git a/Marlin/src/lcd/marlinui.cpp b/Marlin/src/lcd/marlinui.cpp index d4e1357e86..46db571936 100644 --- a/Marlin/src/lcd/marlinui.cpp +++ b/Marlin/src/lcd/marlinui.cpp @@ -78,6 +78,10 @@ constexpr uint8_t epps = ENCODER_PULSES_PER_STEP; #endif #endif +#if HAS_MULTI_LANGUAGE + uint8_t MarlinUI::language; // Initialized by settings.load() +#endif + #if ENABLED(SOUND_MENU_ITEM) bool MarlinUI::buzzer_enabled = true; #endif @@ -1491,8 +1495,8 @@ void MarlinUI::update() { #ifdef ACTION_ON_CANCEL host_action_cancel(); #endif + IF_DISABLED(SDSUPPORT, print_job_timer.stop()); TERN_(HOST_PROMPT_SUPPORT, host_prompt_open(PROMPT_INFO, PSTR("UI Aborted"), DISMISS_STR)); - print_job_timer.stop(); LCD_MESSAGEPGM(MSG_PRINT_ABORTED); TERN_(HAS_LCD_MENU, return_to_status()); } @@ -1512,7 +1516,7 @@ void MarlinUI::update() { LCD_MESSAGEPGM(MSG_PRINT_PAUSED); #if ENABLED(PARK_HEAD_ON_PAUSE) - TERN_(HAS_WIRED_LCD, lcd_pause_show_message(PAUSE_MESSAGE_PARKING, PAUSE_MODE_PAUSE_PRINT)); // Show message immediately to let user know about pause in progress + pause_show_message(PAUSE_MESSAGE_PARKING, PAUSE_MODE_PAUSE_PRINT); // Show message immediately to let user know about pause in progress queue.inject_P(PSTR("M25 P\nM24")); #elif ENABLED(SDSUPPORT) queue.inject_P(PSTR("M25")); @@ -1524,7 +1528,7 @@ void MarlinUI::update() { void MarlinUI::resume_print() { reset_status(); TERN_(PARK_HEAD_ON_PAUSE, wait_for_heatup = wait_for_user = false); - if (IS_SD_PAUSED()) queue.inject_P(M24_STR); + TERN_(SDSUPPORT, if (IS_SD_PAUSED()) queue.inject_P(M24_STR)); #ifdef ACTION_ON_RESUME host_action_resume(); #endif diff --git a/Marlin/src/lcd/marlinui.h b/Marlin/src/lcd/marlinui.h index a64483fcb0..2e55c9ad1d 100644 --- a/Marlin/src/lcd/marlinui.h +++ b/Marlin/src/lcd/marlinui.h @@ -51,15 +51,13 @@ #include "../module/printcounter.h" #endif +#if BOTH(HAS_LCD_MENU, ADVANCED_PAUSE_FEATURE) + #include "../feature/pause.h" + #include "../module/motion.h" // for active_extruder +#endif + #if HAS_WIRED_LCD - #include "../MarlinCore.h" - - #if ENABLED(ADVANCED_PAUSE_FEATURE) - #include "../feature/pause.h" - #include "../module/motion.h" // for active_extruder - #endif - enum LCDViewAction : uint8_t { LCDVIEW_NONE, LCDVIEW_REDRAW_NOW, @@ -87,12 +85,6 @@ typedef void (*screenFunc_t)(); typedef void (*menuAction_t)(); - #if ENABLED(ADVANCED_PAUSE_FEATURE) - void lcd_pause_show_message(const PauseMessage message, - const PauseMode mode=PAUSE_MODE_SAME, - const uint8_t extruder=active_extruder); - #endif - #if ENABLED(AUTO_BED_LEVELING_UBL) void lcd_mesh_edit_setup(const float &initial); float lcd_mesh_edit(); @@ -178,6 +170,17 @@ public: TERN_(HAS_LCD_MENU, currentScreen = status_screen); } + #if HAS_MULTI_LANGUAGE + static uint8_t language; + static inline void set_language(const uint8_t lang) { + if (lang < NUM_LANGUAGES) { + language = lang; + return_to_status(); + refresh(); + } + } + #endif + #if ENABLED(SOUND_MENU_ITEM) static bool buzzer_enabled; // Initialized by settings.load() #else @@ -495,6 +498,13 @@ public: #endif + #if BOTH(HAS_LCD_MENU, ADVANCED_PAUSE_FEATURE) + static void pause_show_message(const PauseMessage message, const PauseMode mode=PAUSE_MODE_SAME, const uint8_t extruder=active_extruder); + #else + static inline void _pause_show_message() {} + #define pause_show_message(...) _pause_show_message() + #endif + // // EEPROM: Reset / Init / Load / Store // diff --git a/Marlin/src/lcd/menu/menu_advanced.cpp b/Marlin/src/lcd/menu/menu_advanced.cpp index b5f8d1d5de..cb7827168b 100644 --- a/Marlin/src/lcd/menu/menu_advanced.cpp +++ b/Marlin/src/lcd/menu/menu_advanced.cpp @@ -155,7 +155,7 @@ void menu_backlash(); #if HAS_FILAMENT_RUNOUT_DISTANCE editable.decimal = runout.runout_distance(); - EDIT_ITEM(float3, MSG_RUNOUT_DISTANCE_MM, &editable.decimal, 1, float(FILAMENT_RUNOUT_DISTANCE_MM) * 1.5f, + EDIT_ITEM_FAST(float3, MSG_RUNOUT_DISTANCE_MM, &editable.decimal, 1, 999, []{ runout.set_runout_distance(editable.decimal); }, true ); #endif diff --git a/Marlin/src/lcd/menu/menu_bed_corners.cpp b/Marlin/src/lcd/menu/menu_bed_corners.cpp index bcf5aea8d7..751be18600 100644 --- a/Marlin/src/lcd/menu/menu_bed_corners.cpp +++ b/Marlin/src/lcd/menu/menu_bed_corners.cpp @@ -39,7 +39,6 @@ #ifndef LEVEL_CORNERS_Z_HOP #define LEVEL_CORNERS_Z_HOP 4.0 #endif - #ifndef LEVEL_CORNERS_HEIGHT #define LEVEL_CORNERS_HEIGHT 0.0 #endif @@ -67,8 +66,6 @@ static_assert(LEVEL_CORNERS_Z_HOP >= 0, "LEVEL_CORNERS_Z_HOP must be >= 0. Please update your configuration."); -extern const char G28_STR[]; - #if HAS_LEVELING static bool leveling_was_active = false; #endif @@ -177,12 +174,13 @@ static inline void _lcd_level_bed_corners_get_next_position() { MenuItem_static::draw(0, GET_TEXT(MSG_PROBING_MESH), SS_INVERT); // "Probing Mesh" heading - uint8_t cy = LCD_HEIGHT - 1, y = LCD_ROW_Y(cy); + uint8_t cy = TERN(TFT_COLOR_UI, 3, LCD_HEIGHT - 1), y = LCD_ROW_Y(cy); // Display # of good points found vs total needed if (PAGE_CONTAINS(y - (MENU_FONT_HEIGHT), y)) { - SETCURSOR(0, cy); + SETCURSOR(TERN(TFT_COLOR_UI, 2, 0), cy); lcd_put_u8str_P(GET_TEXT(MSG_LEVEL_CORNERS_GOOD_POINTS)); + IF_ENABLED(TFT_COLOR_UI, lcd_moveto(12, cy)); lcd_put_u8str(GOOD_POINTS_TO_STR(good_points)); lcd_put_wchar('/'); lcd_put_u8str(GOOD_POINTS_TO_STR(nr_edge_points)); @@ -193,8 +191,9 @@ static inline void _lcd_level_bed_corners_get_next_position() { // Display the Last Z value if (PAGE_CONTAINS(y - (MENU_FONT_HEIGHT), y)) { - SETCURSOR(0, cy); + SETCURSOR(TERN(TFT_COLOR_UI, 2, 0), cy); lcd_put_u8str_P(GET_TEXT(MSG_LEVEL_CORNERS_LAST_Z)); + IF_ENABLED(TFT_COLOR_UI, lcd_moveto(12, 2)); lcd_put_u8str(LAST_Z_TO_STR(last_z)); } } @@ -206,7 +205,7 @@ static inline void _lcd_level_bed_corners_get_next_position() { , []{ corner_probing_done = true; wait_for_probe = false; } , []{ wait_for_probe = false; } , GET_TEXT(MSG_LEVEL_CORNERS_RAISE) - , (const char*)nullptr, PSTR("") + , (const char*)nullptr, NUL_STR ); } @@ -248,7 +247,7 @@ static inline void _lcd_level_bed_corners_get_next_position() { wait_for_probe = true; ui.goto_screen(_lcd_draw_raise); // show raise screen ui.set_selection(true); - while (wait_for_probe && !probe_triggered) { //loop while waiting to bed raise and probe trigger + while (wait_for_probe && !probe_triggered) { // loop while waiting to bed raise and probe trigger probe_triggered = PROBE_TRIGGERED(); if (probe_triggered) { endstops.hit_on_purpose(); @@ -269,7 +268,7 @@ static inline void _lcd_level_bed_corners_get_next_position() { ui.goto_screen(_lcd_draw_probing); do { ui.refresh(LCDVIEW_REDRAW_NOW); - _lcd_draw_probing(); //update screen with # of good points + _lcd_draw_probing(); // update screen with # of good points do_blocking_move_to_z(current_position.z + LEVEL_CORNERS_Z_HOP); // clearance _lcd_level_bed_corners_get_next_position(); // Select next corner coordinates @@ -330,6 +329,7 @@ static inline void _lcd_level_bed_corners_homing() { GET_TEXT(MSG_BUTTON_NEXT), GET_TEXT(MSG_BUTTON_DONE) , _lcd_goto_next_corner , []{ + line_to_z(LEVEL_CORNERS_Z_HOP); // Raise Z off the bed when done TERN_(HAS_LEVELING, set_bed_leveling_enabled(leveling_was_active)); ui.goto_previous_screen_no_defer(); } diff --git a/Marlin/src/lcd/menu/menu_delta_calibrate.cpp b/Marlin/src/lcd/menu/menu_delta_calibrate.cpp index 4efcb7c8ed..a86ae74fce 100644 --- a/Marlin/src/lcd/menu/menu_delta_calibrate.cpp +++ b/Marlin/src/lcd/menu/menu_delta_calibrate.cpp @@ -53,6 +53,7 @@ void _man_probe_pt(const xy_pos_t &xy) { #if ENABLED(DELTA_AUTO_CALIBRATION) + #include "../../MarlinCore.h" // for wait_for_user_response() #include "../../gcode/gcode.h" #if ENABLED(HOST_PROMPT_SUPPORT) diff --git a/Marlin/src/lcd/menu/menu_filament.cpp b/Marlin/src/lcd/menu/menu_filament.cpp index 7bd12bde17..19601d678e 100644 --- a/Marlin/src/lcd/menu/menu_filament.cpp +++ b/Marlin/src/lcd/menu/menu_filament.cpp @@ -107,6 +107,8 @@ void _menu_temp_filament_op(const PauseMode mode, const int8_t extruder) { */ #if E_STEPPERS > 1 || ENABLED(FILAMENT_LOAD_UNLOAD_GCODES) + bool printingIsPaused(); + void menu_change_filament() { // Say "filament change" when no print is active editable.int8 = printingIsPaused() ? PAUSE_MODE_PAUSE_PRINT : PAUSE_MODE_CHANGE_FILAMENT; @@ -315,7 +317,7 @@ FORCE_INLINE screenFunc_t ap_message_screen(const PauseMessage message) { return nullptr; } -void lcd_pause_show_message( +void MarlinUI::pause_show_message( const PauseMessage message, const PauseMode mode/*=PAUSE_MODE_SAME*/, const uint8_t extruder/*=active_extruder*/ diff --git a/Marlin/src/lcd/menu/menu_item.h b/Marlin/src/lcd/menu/menu_item.h index 1d9a2f6b2c..6873f209b4 100644 --- a/Marlin/src/lcd/menu/menu_item.h +++ b/Marlin/src/lcd/menu/menu_item.h @@ -485,7 +485,7 @@ class MenuItem_bool : public MenuEditItemBase { #if SNFAN(1) || SNFAN(2) || SNFAN(3) || SNFAN(4) || SNFAN(5) || SNFAN(6) || SNFAN(7) #define DEFINE_SINGLENOZZLE_ITEM() \ auto singlenozzle_item = [&](const uint8_t f) { \ - editable.uint8 = singlenozzle_fan_speed[f]; \ + editable.uint8 = thermalManager.singlenozzle_fan_speed[f]; \ EDIT_ITEM_FAST_N(percent, f, MSG_STORED_FAN_N, &editable.uint8, 0, 255, on_fan_update); \ } #else diff --git a/Marlin/src/lcd/menu/menu_language.cpp b/Marlin/src/lcd/menu/menu_language.cpp new file mode 100644 index 0000000000..4c4b7880f2 --- /dev/null +++ b/Marlin/src/lcd/menu/menu_language.cpp @@ -0,0 +1,59 @@ +/** + * 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 . + * + */ + +// +// Language Selection Menu +// + +#include "../../inc/MarlinConfig.h" + +#if HAS_MULTI_LANGUAGE + +#include "menu_item.h" +#include "../../MarlinCore.h" +#include "../../module/settings.h" + +static void set_lcd_language(const uint8_t inlang) { + ui.set_language(inlang); + TERN_(LCD_LANGUAGE_AUTO_SAVE, (void)settings.save()); +} + +void menu_language() { + START_MENU(); + BACK_ITEM(MSG_MAIN); + + MENU_ITEM_P(function, GET_LANG(LCD_LANGUAGE )::LANGUAGE, []{ set_lcd_language(0); }); + MENU_ITEM_P(function, GET_LANG(LCD_LANGUAGE_2)::LANGUAGE, []{ set_lcd_language(1); }); + #if NUM_LANGUAGES > 2 + MENU_ITEM_P(function, GET_LANG(LCD_LANGUAGE_3)::LANGUAGE, []{ set_lcd_language(2); }); + #if NUM_LANGUAGES > 3 + MENU_ITEM_P(function, GET_LANG(LCD_LANGUAGE_4)::LANGUAGE, []{ set_lcd_language(3); }); + #if NUM_LANGUAGES > 4 + MENU_ITEM_P(function, GET_LANG(LCD_LANGUAGE_5)::LANGUAGE, []{ set_lcd_language(4); }); + #endif + #endif + #endif + + END_MENU(); +} + +#endif // HAS_MULTI_LANGUAGE diff --git a/Marlin/src/lcd/menu/menu_led.cpp b/Marlin/src/lcd/menu/menu_led.cpp index d9540592d0..552c03a69f 100644 --- a/Marlin/src/lcd/menu/menu_led.cpp +++ b/Marlin/src/lcd/menu/menu_led.cpp @@ -123,11 +123,15 @@ void menu_led() { #if ENABLED(LED_CONTROL_MENU) editable.state = leds.lights_on; EDIT_ITEM(bool, MSG_LEDS, &editable.state, leds.toggle); - ACTION_ITEM(MSG_SET_LEDS_DEFAULT, leds.set_default); + #if ENABLED(LED_COLOR_PRESETS) + ACTION_ITEM(MSG_SET_LEDS_DEFAULT, leds.set_default); + #endif #if ENABLED(NEOPIXEL2_SEPARATE) editable.state = leds2.lights_on; EDIT_ITEM(bool, MSG_LEDS2, &editable.state, leds2.toggle); - ACTION_ITEM(MSG_SET_LEDS_DEFAULT, leds2.set_default); + #if ENABLED(NEO2_COLOR_PRESETS) + ACTION_ITEM(MSG_SET_LEDS_DEFAULT, leds2.set_default); + #endif #endif #if ENABLED(LED_COLOR_PRESETS) SUBMENU(MSG_LED_PRESETS, menu_led_presets); diff --git a/Marlin/src/lcd/menu/menu_main.cpp b/Marlin/src/lcd/menu/menu_main.cpp index b7cd549e6b..878ac83a5a 100644 --- a/Marlin/src/lcd/menu/menu_main.cpp +++ b/Marlin/src/lcd/menu/menu_main.cpp @@ -97,7 +97,9 @@ void menu_configuration(); void menu_spindle_laser(); #endif -extern const char M21_STR[]; +#if HAS_MULTI_LANGUAGE + void menu_language(); +#endif void menu_main() { const bool busy = printingIsActive() @@ -152,7 +154,7 @@ void menu_main() { if (!card_open) { SUBMENU(MSG_MEDIA_MENU, MEDIA_MENU_GATEWAY); #if PIN_EXISTS(SD_DETECT) - GCODES_ITEM(MSG_CHANGE_MEDIA, M21_STR); + GCODES_ITEM(MSG_CHANGE_MEDIA, PSTR("M21")); #else GCODES_ITEM(MSG_RELEASE_MEDIA, PSTR("M22")); #endif @@ -162,7 +164,7 @@ void menu_main() { #if PIN_EXISTS(SD_DETECT) ACTION_ITEM(MSG_NO_MEDIA, nullptr); #else - GCODES_ITEM(MSG_ATTACH_MEDIA, M21_STR); + GCODES_ITEM(MSG_ATTACH_MEDIA, PSTR("M21")); #endif } @@ -253,7 +255,7 @@ void menu_main() { if (card_detected) { if (!card_open) { #if PIN_EXISTS(SD_DETECT) - GCODES_ITEM(MSG_CHANGE_MEDIA, M21_STR); + GCODES_ITEM(MSG_CHANGE_MEDIA, PSTR("M21")); #else GCODES_ITEM(MSG_RELEASE_MEDIA, PSTR("M22")); #endif @@ -264,7 +266,7 @@ void menu_main() { #if PIN_EXISTS(SD_DETECT) ACTION_ITEM(MSG_NO_MEDIA, nullptr); #else - GCODES_ITEM(MSG_ATTACH_MEDIA, M21_STR); + GCODES_ITEM(MSG_ATTACH_MEDIA, PSTR("M21")); #endif } } @@ -325,6 +327,10 @@ void menu_main() { } #endif + #if HAS_MULTI_LANGUAGE + SUBMENU(LANGUAGE, menu_language); + #endif + END_MENU(); } diff --git a/Marlin/src/lcd/menu/menu_mmu2.cpp b/Marlin/src/lcd/menu/menu_mmu2.cpp index 8a34e7d296..7e71f00d25 100644 --- a/Marlin/src/lcd/menu/menu_mmu2.cpp +++ b/Marlin/src/lcd/menu/menu_mmu2.cpp @@ -32,15 +32,12 @@ // Load Filament // -void _mmu2_load_filamentToNozzle(uint8_t index) { +inline void action_mmu2_load_filament_to_nozzle(const uint8_t tool) { ui.reset_status(); ui.return_to_status(); - ui.status_printf_P(0, GET_TEXT(MSG_MMU2_LOADING_FILAMENT), int(index + 1)); - if (mmu2.load_filament_to_nozzle(index)) ui.reset_status(); -} - -inline void action_mmu2_load_filament_to_nozzle(const uint8_t tool) { - _mmu2_load_filamentToNozzle(tool); + ui.status_printf_P(0, GET_TEXT(MSG_MMU2_LOADING_FILAMENT), int(tool + 1)); + if (mmu2.load_filament_to_nozzle(tool)) + ui.reset_status(); ui.return_to_status(); } @@ -59,14 +56,14 @@ void menu_mmu2_load_filament() { START_MENU(); BACK_ITEM(MSG_MMU2_MENU); ACTION_ITEM(MSG_MMU2_ALL, action_mmu2_load_all); - LOOP_L_N(i, 5) ACTION_ITEM_N(i, MSG_MMU2_FILAMENT_N, []{ _mmu2_load_filament(MenuItemBase::itemIndex); }); + LOOP_L_N(i, EXTRUDERS) ACTION_ITEM_N(i, MSG_MMU2_FILAMENT_N, []{ _mmu2_load_filament(MenuItemBase::itemIndex); }); END_MENU(); } void menu_mmu2_load_to_nozzle() { START_MENU(); BACK_ITEM(MSG_MMU2_MENU); - LOOP_L_N(i, 5) ACTION_ITEM_N(i, MSG_MMU2_FILAMENT_N, []{ action_mmu2_load_filament_to_nozzle(MenuItemBase::itemIndex); }); + LOOP_L_N(i, EXTRUDERS) ACTION_ITEM_N(i, MSG_MMU2_FILAMENT_N, []{ action_mmu2_load_filament_to_nozzle(MenuItemBase::itemIndex); }); END_MENU(); } @@ -92,7 +89,7 @@ void action_mmu2_unload_filament() { void menu_mmu2_eject_filament() { START_MENU(); BACK_ITEM(MSG_MMU2_MENU); - LOOP_L_N(i, 5) ACTION_ITEM_N(i, MSG_MMU2_FILAMENT_N, []{ _mmu2_eject_filament(MenuItemBase::itemIndex); }); + LOOP_L_N(i, EXTRUDERS) ACTION_ITEM_N(i, MSG_MMU2_FILAMENT_N, []{ _mmu2_eject_filament(MenuItemBase::itemIndex); }); END_MENU(); } @@ -133,7 +130,7 @@ void menu_mmu2_choose_filament() { #if LCD_HEIGHT > 2 STATIC_ITEM(MSG_MMU2_CHOOSE_FILAMENT_HEADER, SS_DEFAULT|SS_INVERT); #endif - LOOP_L_N(i, 5) ACTION_ITEM_N(i, MSG_MMU2_FILAMENT_N, []{ action_mmu2_chosen(MenuItemBase::itemIndex); }); + LOOP_L_N(i, EXTRUDERS) ACTION_ITEM_N(i, MSG_MMU2_FILAMENT_N, []{ action_mmu2_chosen(MenuItemBase::itemIndex); }); END_MENU(); } diff --git a/Marlin/src/lcd/menu/menu_motion.cpp b/Marlin/src/lcd/menu/menu_motion.cpp index ecc378b607..71fc4246c7 100644 --- a/Marlin/src/lcd/menu/menu_motion.cpp +++ b/Marlin/src/lcd/menu/menu_motion.cpp @@ -189,7 +189,6 @@ void _menu_move_distance(const AxisEnum axis, const screenFunc_t func, const int sprintf_P(tmp, label, dtostrf(FINE_MANUAL_MOVE, 1, digs, numstr)); #if DISABLED(HAS_GRAPHICAL_TFT) - extern const char NUL_STR[]; SUBMENU_P(NUL_STR, []{ _goto_manual_move(float(FINE_MANUAL_MOVE)); }); MENU_ITEM_ADDON_START(0 + ENABLED(HAS_MARLINUI_HD44780)); lcd_put_u8str(tmp); diff --git a/Marlin/src/lcd/menu/menu_password.cpp b/Marlin/src/lcd/menu/menu_password.cpp index c58931cf2e..80c5c3dc66 100644 --- a/Marlin/src/lcd/menu/menu_password.cpp +++ b/Marlin/src/lcd/menu/menu_password.cpp @@ -49,7 +49,7 @@ void Password::menu_password_entry() { // "Login" or "New Code" STATIC_ITEM_P(authenticating ? GET_TEXT(MSG_LOGIN_REQUIRED) : GET_TEXT(MSG_EDIT_PASSWORD), SS_CENTER|SS_INVERT); - STATIC_ITEM_P(PSTR(""), SS_CENTER|SS_INVERT, string); + STATIC_ITEM_P(NUL_STR, SS_CENTER|SS_INVERT, string); // Make the digit edit item look like a sub-menu PGM_P const label = GET_TEXT(MSG_ENTER_DIGIT); diff --git a/Marlin/src/lcd/menu/menu_probe_offset.cpp b/Marlin/src/lcd/menu/menu_probe_offset.cpp index 5b88c8e805..2f0c37b433 100644 --- a/Marlin/src/lcd/menu/menu_probe_offset.cpp +++ b/Marlin/src/lcd/menu/menu_probe_offset.cpp @@ -88,7 +88,6 @@ void probe_offset_wizard_menu() { !UNEAR_ZERO((FINE_MANUAL_MOVE) * 100 - int((FINE_MANUAL_MOVE) * 100)) ? 3 : 2; sprintf_P(tmp, GET_TEXT(MSG_MOVE_N_MM), dtostrf(FINE_MANUAL_MOVE, 1, digs, numstr)); #if DISABLED(HAS_GRAPHICAL_TFT) - extern const char NUL_STR[]; SUBMENU_P(NUL_STR, []{ _goto_manual_move_z(float(FINE_MANUAL_MOVE)); }); MENU_ITEM_ADDON_START(0 + ENABLED(HAS_MARLINUI_HD44780)); lcd_put_u8str(tmp); diff --git a/Marlin/src/lcd/menu/menu_temperature.cpp b/Marlin/src/lcd/menu/menu_temperature.cpp index 2e5aff1006..01c1f8f547 100644 --- a/Marlin/src/lcd/menu/menu_temperature.cpp +++ b/Marlin/src/lcd/menu/menu_temperature.cpp @@ -35,6 +35,10 @@ #include "../../module/motion.h" #endif +#if ENABLED(SINGLENOZZLE_STANDBY_TEMP) + #include "../../module/tool_change.h" +#endif + // // "Temperature" submenu items // @@ -155,7 +159,7 @@ void menu_temperature() { #if ENABLED(SINGLENOZZLE_STANDBY_TEMP) LOOP_S_L_N(e, 1, EXTRUDERS) - EDIT_ITEM_FAST_N(uint16_3, e, MSG_NOZZLE_STANDBY, &singlenozzle_temp[e], 0, thermalManager.heater_maxtemp[0] - (HOTEND_OVERSHOOT)); + EDIT_ITEM_FAST_N(uint16_3, e, MSG_NOZZLE_STANDBY, &thermalManager.singlenozzle_temp[e], 0, thermalManager.heater_maxtemp[0] - (HOTEND_OVERSHOOT)); #endif // diff --git a/Marlin/src/lcd/menu/menu_tune.cpp b/Marlin/src/lcd/menu/menu_tune.cpp index 5da25ce59a..0fbb57f2ac 100644 --- a/Marlin/src/lcd/menu/menu_tune.cpp +++ b/Marlin/src/lcd/menu/menu_tune.cpp @@ -34,6 +34,10 @@ #include "../../module/temperature.h" #include "../../MarlinCore.h" +#if ENABLED(SINGLENOZZLE_STANDBY_TEMP) + #include "../../module/tool_change.h" +#endif + #if HAS_LEVELING #include "../../feature/bedlevel/bedlevel.h" #endif @@ -67,9 +71,16 @@ const bool in_view = TERN1(HAS_MARLINUI_U8GLIB, PAGE_CONTAINS(LCD_PIXEL_HEIGHT - MENU_FONT_HEIGHT, LCD_PIXEL_HEIGHT - 1)); if (in_view) { TERN_(HAS_MARLINUI_U8GLIB, ui.set_font(FONT_MENU)); - lcd_moveto(0, TERN(HAS_MARLINUI_U8GLIB, LCD_PIXEL_HEIGHT - MENU_FONT_DESCENT, LCD_HEIGHT - 1)); - lcd_put_u8str_P(GET_TEXT(MSG_BABYSTEP_TOTAL)); - lcd_put_wchar(':'); + #if ENABLED(TFT_COLOR_UI) + lcd_moveto(4, 3); + lcd_put_u8str_P(GET_TEXT(MSG_BABYSTEP_TOTAL)); + lcd_put_wchar(':'); + lcd_moveto(10, 3); + #else + lcd_moveto(0, TERN(HAS_MARLINUI_U8GLIB, LCD_PIXEL_HEIGHT - MENU_FONT_DESCENT, LCD_HEIGHT - 1)); + lcd_put_u8str_P(GET_TEXT(MSG_BABYSTEP_TOTAL)); + lcd_put_wchar(':'); + #endif lcd_put_u8str(BABYSTEP_TO_STR(spm * babystep.axis_total[BS_TOTAL_IND(axis)])); } #endif @@ -123,7 +134,7 @@ void menu_tune() { #if ENABLED(SINGLENOZZLE_STANDBY_TEMP) LOOP_S_L_N(e, 1, EXTRUDERS) - EDIT_ITEM_FAST_N(uint16_3, e, MSG_NOZZLE_STANDBY, &singlenozzle_temp[e], 0, thermalManager.heater_maxtemp[0] - HOTEND_OVERSHOOT); + EDIT_ITEM_FAST_N(uint16_3, e, MSG_NOZZLE_STANDBY, &thermalManager.singlenozzle_temp[e], 0, thermalManager.heater_maxtemp[0] - HOTEND_OVERSHOOT); #endif // diff --git a/Marlin/src/lcd/tft/tft_image.cpp b/Marlin/src/lcd/tft/tft_image.cpp index 9cc6fb15e4..851410b2e0 100644 --- a/Marlin/src/lcd/tft/tft_image.cpp +++ b/Marlin/src/lcd/tft/tft_image.cpp @@ -20,8 +20,11 @@ * */ +#include "../../inc/MarlinConfigPre.h" + +#if HAS_GRAPHICAL_TFT + #include "tft_image.h" -#include const tImage NoLogo = { nullptr, 0, 0, NOCOLORS }; @@ -70,4 +73,38 @@ const tImage Leveling_32x32x4 = { (void *)leveling_32x32x4, 32, 32, GREYSC const tImage Slider8x16x4 = { (void *)slider_8x16x4, 8, 16, GREYSCALE4 }; -extern const tImage Images[imgCount]; +const tImage Images[imgCount] = { + TERN(SHOW_BOOTSCREEN, TERN(BOOT_MARLIN_LOGO_SMALL, MarlinLogo195x59x16, MARLIN_LOGO_FULL_SIZE), NoLogo), + HotEnd_64x64x4, + Bed_64x64x4, + Bed_Heated_64x64x4, + Chamber_64x64x4, + Chamber_Heated_64x64x4, + Fan0_64x64x4, + Fan_Slow0_64x64x4, + Fan_Slow1_64x64x4, + Fan_Fast0_64x64x4, + Fan_Fast1_64x64x4, + Feedrate_32x32x4, + Flowrate_32x32x4, + SD_64x64x4, + Menu_64x64x4, + Settings_64x64x4, + Directory_32x32x4, + Confirm_64x64x4, + Cancel_64x64x4, + Increase_64x64x4, + Decrease_64x64x4, + Back_32x32x4, + Up_32x32x4, + Down_32x32x4, + Left_32x32x4, + Right_32x32x4, + Refresh_32x32x4, + Leveling_32x32x4, + Slider8x16x4, + Home_64x64x4, + BtnRounded_64x52x4, +}; + +#endif // HAS_GRAPHICAL_TFT diff --git a/Marlin/src/lcd/tft/tft_image.h b/Marlin/src/lcd/tft/tft_image.h index 21bd2d665f..960a4e4356 100644 --- a/Marlin/src/lcd/tft/tft_image.h +++ b/Marlin/src/lcd/tft/tft_image.h @@ -21,9 +21,10 @@ */ #pragma once -#include "stdint.h" #include "../../inc/MarlinConfigPre.h" +#include + extern const uint8_t marlin_logo_112x38x1[]; extern const uint8_t marlin_logo_228x255x2[]; extern const uint8_t marlin_logo_228x255x4[]; diff --git a/Marlin/src/lcd/tft/tft_string.cpp b/Marlin/src/lcd/tft/tft_string.cpp index eb805ac423..31ac14cf92 100644 --- a/Marlin/src/lcd/tft/tft_string.cpp +++ b/Marlin/src/lcd/tft/tft_string.cpp @@ -36,7 +36,7 @@ font_t *TFT_String::font_header; uint8_t TFT_String::data[]; uint16_t TFT_String::span; -uint16_t TFT_String::length; +uint8_t TFT_String::length; void TFT_String::set_font(const uint8_t *font) { font_header = (font_t *)font; @@ -122,13 +122,14 @@ void TFT_String::add(uint8_t *string, int8_t index, uint8_t *itemString) { eol(); } -void TFT_String::add(uint8_t *string) { +void TFT_String::add(uint8_t *string, uint8_t max_len) { wchar_t wchar; - while (*string) { + while (*string && max_len) { string = get_utf8_value_cb(string, read_byte, &wchar); if (wchar > 255) wchar |= 0x0080; uint8_t ch = uint8_t(wchar & 0x00FF); add_character(ch); + max_len--; } eol(); } diff --git a/Marlin/src/lcd/tft/tft_string.h b/Marlin/src/lcd/tft/tft_string.h index e800b1ded9..133889d9ae 100644 --- a/Marlin/src/lcd/tft/tft_string.h +++ b/Marlin/src/lcd/tft/tft_string.h @@ -69,7 +69,7 @@ class TFT_String { static uint8_t data[MAX_STRING_LENGTH + 1]; static uint16_t span; // in pixels - static uint16_t length; // in characters + static uint8_t length; // in characters static void add_character(uint8_t character); static void eol() { data[length] = 0x00; } @@ -85,7 +85,7 @@ class TFT_String { static void set(); static void add(uint8_t character) { add_character(character); eol(); } - static void add(uint8_t *string); + static void add(uint8_t *string, uint8_t max_len=MAX_STRING_LENGTH); static void add(uint8_t *string, int8_t index, uint8_t *itemString=nullptr); static void set(uint8_t *string) { set(); add(string); }; static void set(uint8_t *string, int8_t index, const char *itemString=nullptr) { set(); add(string, index, (uint8_t *)itemString); }; @@ -96,6 +96,9 @@ class TFT_String { static void trim(uint8_t character=0x20); static void rtrim(uint8_t character=0x20); static void ltrim(uint8_t character=0x20); + + static void truncate(uint8_t maxlen) { if (length > maxlen) { length = maxlen; eol(); } } + static uint16_t width() { return span; } static uint8_t *string() { return data; } static uint16_t center(uint16_t width) { return span > width ? 0 : (width - span) / 2; } diff --git a/Marlin/src/lcd/tft/ui_320x240.cpp b/Marlin/src/lcd/tft/ui_320x240.cpp index 4c09d9803e..eadd09ef27 100644 --- a/Marlin/src/lcd/tft/ui_320x240.cpp +++ b/Marlin/src/lcd/tft/ui_320x240.cpp @@ -24,7 +24,7 @@ #if HAS_UI_320x240 -#include "ui_320x240.h" +#include "ui_common.h" #include "../marlinui.h" #include "../menu/menu.h" @@ -45,12 +45,6 @@ #include "../../feature/bedlevel/bedlevel.h" #endif -#if !HAS_LCD_MENU - #error "Seriously? High resolution TFT screen without menu?" -#endif - -static bool draw_menu_navigation = false; - void MarlinUI::tft_idle() { #if ENABLED(TOUCH_SCREEN) if (draw_menu_navigation) { @@ -65,28 +59,6 @@ void MarlinUI::tft_idle() { TERN_(TOUCH_SCREEN, touch.idle()); } -void MarlinUI::init_lcd() { - tft.init(); - tft.set_font(MENU_FONT_NAME); - #ifdef SYMBOLS_FONT_NAME - tft.add_glyphs(SYMBOLS_FONT_NAME); - #endif - TERN_(TOUCH_SCREEN, touch.init()); - clear_lcd(); -} - -bool MarlinUI::detected() { return true; } - -void MarlinUI::clear_lcd() { - #if ENABLED(TOUCH_SCREEN) - touch.reset(); - draw_menu_navigation = false; - #endif - - tft.queue.reset(); - tft.fill(0, 0, TFT_WIDTH, TFT_HEIGHT, COLOR_BACKGROUND); -} - #if ENABLED(SHOW_BOOTSCREEN) void MarlinUI::show_bootscreen() { tft.queue.reset(); @@ -98,8 +70,8 @@ void MarlinUI::clear_lcd() { #define SITE_URL_Y (TFT_HEIGHT - 46) tft.set_background(COLOR_BACKGROUND); #else - #define BOOT_LOGO_W 320 // MarlinLogo320x240x16 - #define BOOT_LOGO_H 240 + #define BOOT_LOGO_W TFT_WIDTH // MarlinLogo320x240x16 + #define BOOT_LOGO_H TFT_HEIGHT #define SITE_URL_Y (TFT_HEIGHT - 52) #endif tft.add_image((TFT_WIDTH - BOOT_LOGO_W) / 2, (TFT_HEIGHT - BOOT_LOGO_H) / 2, imgBootScreen); @@ -148,22 +120,22 @@ void draw_heater_status(uint16_t x, uint16_t y, const int8_t Heater) { currentTemperature = thermalManager.degHotend(Heater); targetTemperature = thermalManager.degTargetHotend(Heater); } -#if HAS_HEATED_BED - else if (Heater == H_BED) { - currentTemperature = thermalManager.degBed(); - targetTemperature = thermalManager.degTargetBed(); - } -#endif // HAS_HEATED_BED -#if HAS_TEMP_CHAMBER - else if (Heater == H_CHAMBER) { - currentTemperature = thermalManager.degChamber(); - #if HAS_HEATED_CHAMBER - targetTemperature = thermalManager.degTargetChamber(); - #else - targetTemperature = ABSOLUTE_ZERO; - #endif - } -#endif // HAS_TEMP_CHAMBER + #if HAS_HEATED_BED + else if (Heater == H_BED) { + currentTemperature = thermalManager.degBed(); + targetTemperature = thermalManager.degTargetBed(); + } + #endif + #if HAS_TEMP_CHAMBER + else if (Heater == H_CHAMBER) { + currentTemperature = thermalManager.degChamber(); + #if HAS_HEATED_CHAMBER + targetTemperature = thermalManager.degTargetChamber(); + #else + targetTemperature = ABSOLUTE_ZERO; + #endif + } + #endif else return; TERN_(TOUCH_SCREEN, if (targetTemperature >= 0) touch.add_control(HEATER, x, y, 64, 100, Heater)); @@ -176,17 +148,17 @@ void draw_heater_status(uint16_t x, uint16_t y, const int8_t Heater) { if (currentTemperature >= 50) Color = COLOR_HOTEND; } #if HAS_HEATED_BED - else if (Heater == H_BED) { - if (currentTemperature >= 50) Color = COLOR_HEATED_BED; - image = targetTemperature > 0 ? imgBedHeated : imgBed; - } - #endif // HAS_HEATED_BED + else if (Heater == H_BED) { + if (currentTemperature >= 50) Color = COLOR_HEATED_BED; + image = targetTemperature > 0 ? imgBedHeated : imgBed; + } + #endif #if HAS_TEMP_CHAMBER - else if (Heater == H_CHAMBER) { - if (currentTemperature >= 50) Color = COLOR_CHAMBER; - image = targetTemperature > 0 ? imgChamberHeated : imgChamber; - } - #endif // HAS_TEMP_CHAMBER + else if (Heater == H_CHAMBER) { + if (currentTemperature >= 50) Color = COLOR_CHAMBER; + image = targetTemperature > 0 ? imgChamberHeated : imgChamber; + } + #endif tft.add_image(0, 18, image, Color); @@ -200,7 +172,6 @@ void draw_heater_status(uint16_t x, uint16_t y, const int8_t Heater) { tft_string.add(LCD_STR_DEGREE); tft_string.trim(); tft.add_text(tft_string.center(64) + 2, 8, Color, tft_string); - } } @@ -232,7 +203,7 @@ void MarlinUI::draw_status_screen() { TERN_(TOUCH_SCREEN, touch.clear()); // heaters and fan - uint16_t i, x, y = POS_Y; + uint16_t i, x, y = TFT_STATUS_TOP_Y; for (i = 0 ; i < ITEMS_COUNT; i++) { x = (320 / ITEMS_COUNT - 64) / 2 + (320 * i / ITEMS_COUNT); @@ -341,49 +312,6 @@ void MarlinUI::draw_status_screen() { #endif } -// Draw a static item with no left-right margin required. Centered by default. -void MenuItem_static::draw(const uint8_t row, PGM_P const pstr, const uint8_t style/*=SS_DEFAULT*/, const char * const vstr/*=nullptr*/) { - menu_item(row); - tft_string.set(pstr, itemIndex, itemString); - if (vstr) - tft_string.add(vstr); - tft.add_text(tft_string.center(TFT_WIDTH), MENU_TEXT_Y_OFFSET, COLOR_YELLOW, tft_string); -} - -// Draw a generic menu item with pre_char (if selected) and post_char -void MenuItemBase::_draw(const bool sel, const uint8_t row, PGM_P const pstr, const char pre_char, const char post_char) { - menu_item(row, sel); - - uint8_t *string = (uint8_t *)pstr; - MarlinImage image = noImage; - switch (*string) { - case 0x01: image = imgRefresh; break; // LCD_STR_REFRESH - case 0x02: image = imgDirectory; break; // LCD_STR_FOLDER - } - - uint8_t offset = MENU_TEXT_X_OFFSET; - if (image != noImage) { - string++; - offset = 32; - tft.add_image(0, 0, image, COLOR_MENU_TEXT, sel ? COLOR_SELECTION_BG : COLOR_BACKGROUND); - } - - tft_string.set(string, itemIndex, itemString); - tft.add_text(offset, MENU_TEXT_Y_OFFSET, COLOR_MENU_TEXT, tft_string); -} - -// Draw a menu item with a (potentially) editable value -void MenuEditItemBase::draw(const bool sel, const uint8_t row, PGM_P const pstr, const char* const data, const bool pgm) { - menu_item(row, sel); - - tft_string.set(pstr, itemIndex, itemString); - tft.add_text(MENU_TEXT_X_OFFSET, MENU_TEXT_Y_OFFSET, COLOR_MENU_TEXT, tft_string); - if (data) { - tft_string.set(data); - tft.add_text(TFT_WIDTH - MENU_TEXT_X_OFFSET - tft_string.width(), MENU_TEXT_Y_OFFSET, COLOR_MENU_VALUE, tft_string); - } -} - // Low-level draw_edit_screen can be used to draw an edit screen from anyplace void MenuEditItemBase::draw_edit_screen(PGM_P const pstr, const char* const value/*=nullptr*/) { ui.encoder_direction_normal(); @@ -483,16 +411,8 @@ void MenuItem_confirm::draw_select_screen(PGM_P const yes, PGM_P const no, const #endif } -#if ENABLED(SDSUPPORT) - void MenuItem_sdbase::draw(const bool sel, const uint8_t row, PGM_P const, CardReader &theCard, const bool isDir) { - menu_item(row, sel); - if (isDir) - tft.add_image(0, 0, imgDirectory, COLOR_MENU_TEXT, sel ? COLOR_SELECTION_BG : COLOR_BACKGROUND); - tft.add_text(32, MENU_TEXT_Y_OFFSET, COLOR_MENU_TEXT, theCard.longest_filename()); - } -#endif - #if ENABLED(ADVANCED_PAUSE_FEATURE) + void MarlinUI::draw_hotend_status(const uint8_t row, const uint8_t extruder) { #if ENABLED(TOUCH_SCREEN) touch.clear(); @@ -513,6 +433,7 @@ void MenuItem_confirm::draw_select_screen(PGM_P const yes, PGM_P const no, const tft_string.trim(); tft.add_text(tft_string.center(TFT_WIDTH), MENU_TEXT_Y_OFFSET, COLOR_MENU_TEXT, tft_string); } + #endif // ADVANCED_PAUSE_FEATURE #if ENABLED(AUTO_BED_LEVELING_UBL) @@ -562,18 +483,18 @@ void MenuItem_confirm::draw_select_screen(PGM_P const yes, PGM_P const no, const tft_string.trim(); tft.add_text(96 - tft_string.width(), MENU_TEXT_Y_OFFSET, COLOR_MENU_VALUE, tft_string); - - tft.canvas(GRID_OFFSET_X + (GRID_WIDTH - 32) / 2, GRID_OFFSET_Y + GRID_HEIGHT + CONTROL_OFFSET - 1, 32, 32); + constexpr uint8_t w = (TFT_WIDTH) / 10; + tft.canvas(GRID_OFFSET_X + (GRID_WIDTH - w) / 2, GRID_OFFSET_Y + GRID_HEIGHT + CONTROL_OFFSET - 1, w, 32); tft.set_background(COLOR_BACKGROUND); tft_string.set(ui8tostr3rj(x_plot)); tft_string.trim(); - tft.add_text(tft_string.center(32), MENU_TEXT_Y_OFFSET, COLOR_MENU_VALUE, tft_string); + tft.add_text(tft_string.center(w), MENU_TEXT_Y_OFFSET, COLOR_MENU_VALUE, tft_string); - tft.canvas(GRID_OFFSET_X + GRID_WIDTH + CONTROL_OFFSET, GRID_OFFSET_Y + (GRID_HEIGHT - 27) / 2, 32, 32); + tft.canvas(GRID_OFFSET_X + GRID_WIDTH + CONTROL_OFFSET, GRID_OFFSET_Y + (GRID_HEIGHT - 27) / 2, w, 32); tft.set_background(COLOR_BACKGROUND); tft_string.set(ui8tostr3rj(y_plot)); tft_string.trim(); - tft.add_text(tft_string.center(32), MENU_TEXT_Y_OFFSET, COLOR_MENU_VALUE, tft_string); + tft.add_text(tft_string.center(w), MENU_TEXT_Y_OFFSET, COLOR_MENU_VALUE, tft_string); #if ENABLED(TOUCH_SCREEN) touch.clear(); @@ -588,97 +509,6 @@ void MenuItem_confirm::draw_select_screen(PGM_P const yes, PGM_P const no, const } #endif // AUTO_BED_LEVELING_UBL -#if ENABLED(TOUCH_SCREEN_CALIBRATION) - void MarlinUI::touch_calibration_screen() { - uint16_t x, y; - - calibrationState calibration_stage = touch_calibration.get_calibration_state(); - - if (calibration_stage == CALIBRATION_NONE) { - defer_status_screen(true); - clear_lcd(); - calibration_stage = touch_calibration.calibration_start(); - } - else { - x = touch_calibration.calibration_points[_MIN(calibration_stage - 1, CALIBRATION_BOTTOM_RIGHT)].x; - y = touch_calibration.calibration_points[_MIN(calibration_stage - 1, CALIBRATION_BOTTOM_RIGHT)].y; - tft.canvas(x - 15, y - 15, 31, 31); - tft.set_background(COLOR_BACKGROUND); - } - - touch.clear(); - - if (calibration_stage < CALIBRATION_SUCCESS) { - switch (calibration_stage) { - case CALIBRATION_TOP_LEFT: tft_string.set(GET_TEXT(MSG_TOP_LEFT)); break; - case CALIBRATION_BOTTOM_LEFT: tft_string.set(GET_TEXT(MSG_BOTTOM_LEFT)); break; - case CALIBRATION_TOP_RIGHT: tft_string.set(GET_TEXT(MSG_TOP_RIGHT)); break; - case CALIBRATION_BOTTOM_RIGHT: tft_string.set(GET_TEXT(MSG_BOTTOM_RIGHT)); break; - default: break; - } - - x = touch_calibration.calibration_points[calibration_stage].x; - y = touch_calibration.calibration_points[calibration_stage].y; - - tft.canvas(x - 15, y - 15, 31, 31); - tft.set_background(COLOR_BACKGROUND); - tft.add_bar(0, 15, 31, 1, COLOR_TOUCH_CALIBRATION); - tft.add_bar(15, 0, 1, 31, COLOR_TOUCH_CALIBRATION); - - touch.add_control(CALIBRATE, 0, 0, TFT_WIDTH, TFT_HEIGHT, uint32_t(x) << 16 | uint32_t(y)); - } - else { - tft_string.set(calibration_stage == CALIBRATION_SUCCESS ? GET_TEXT(MSG_CALIBRATION_COMPLETED) : GET_TEXT(MSG_CALIBRATION_FAILED)); - defer_status_screen(false); - touch_calibration.calibration_end(); - touch.add_control(BACK, 0, 0, TFT_WIDTH, TFT_HEIGHT); - } - - tft.canvas(0, (TFT_HEIGHT - tft_string.font_height()) >> 1, TFT_WIDTH, tft_string.font_height()); - tft.set_background(COLOR_BACKGROUND); - tft.add_text(tft_string.center(TFT_WIDTH), 0, COLOR_MENU_TEXT, tft_string); - } -#endif // TOUCH_SCREEN_CALIBRATION - -void menu_line(const uint8_t row, uint16_t color) { - tft.canvas(0, 2 + 34 * row, TFT_WIDTH, 32); - tft.set_background(color); -} - -void menu_pause_option(); - -void menu_item(const uint8_t row, bool sel ) { - #if ENABLED(TOUCH_SCREEN) - if (row == 0) { - touch.clear(); - draw_menu_navigation = TERN(ADVANCED_PAUSE_FEATURE, ui.currentScreen != menu_pause_option, true); - } - #endif - - menu_line(row, sel ? COLOR_SELECTION_BG : COLOR_BACKGROUND); - #if ENABLED(TOUCH_SCREEN) - const TouchControlType tct = TERN(SINGLE_TOUCH_NAVIGATION, true, sel) ? MENU_CLICK : MENU_ITEM; - touch.add_control(tct, 0, 2 + 34 * row, TFT_WIDTH, 32, encoderTopLine + row); - #endif -} - -void lcd_moveto(const lcd_uint_t col, const lcd_uint_t row) { - #define TFT_COL_WIDTH ((TFT_WIDTH) / (LCD_WIDTH)) - tft.canvas(col * TFT_COL_WIDTH, 4 + 45 * row, TFT_WIDTH - (col * TFT_COL_WIDTH), 43); - tft.set_background(COLOR_BACKGROUND); -} - -int lcd_put_u8str_max_P(PGM_P utf8_str_P, pixel_len_t max_length) { - tft_string.set(utf8_str_P); - tft_string.trim(); - tft.add_text(MENU_TEXT_X_OFFSET, MENU_TEXT_Y_OFFSET, COLOR_MENU_TEXT, tft_string); - return tft_string.width(); -} - -int lcd_put_u8str_max(const char * utf8_str, pixel_len_t max_length) { - return lcd_put_u8str_max_P(utf8_str, max_length); -} - void MarlinUI::move_axis_screen() { } diff --git a/Marlin/src/lcd/tft/ui_320x240.h b/Marlin/src/lcd/tft/ui_320x240.h index 249a21c4f1..40b2185577 100644 --- a/Marlin/src/lcd/tft/ui_320x240.h +++ b/Marlin/src/lcd/tft/ui_320x240.h @@ -21,88 +21,22 @@ */ #pragma once -#include "../../inc/MarlinConfigPre.h" +#define MARLIN_LOGO_FULL_SIZE MarlinLogo320x240x16 -#include "tft.h" -#include "tft_image.h" +#define TFT_STATUS_TOP_Y 0 +#define TFT_TOP_LINE_Y 2 -#if ENABLED(TOUCH_SCREEN) - #include "touch.h" -#endif +#define MENU_TEXT_X_OFFSET 10 +#define MENU_TEXT_Y_OFFSET 7 -void draw_heater_status(uint16_t x, uint16_t y, const int8_t Heater); -void draw_fan_status(uint16_t x, uint16_t y, const bool blink); +#define MENU_ITEM_ICON_X 0 +#define MENU_ITEM_ICON_Y 0 +#define MENU_ITEM_ICON_SPACE 32 -#define MENU_TEXT_X_OFFSET 10 -#define MENU_TEXT_Y_OFFSET 7 -void menu_line(const uint8_t row, uint16_t color = COLOR_BACKGROUND); -void menu_item(const uint8_t row, bool sel = false); +#define MENU_ITEM_HEIGHT 32 +#define MENU_LINE_HEIGHT (MENU_ITEM_HEIGHT + 2) -#define MENU_FONT_NAME Helvetica14 -#define SYMBOLS_FONT_NAME Helvetica14_symbols +#define MENU_FONT_NAME Helvetica14 +#define SYMBOLS_FONT_NAME Helvetica14_symbols -#define ABSOLUTE_ZERO -273.15 - -const tImage Images[imgCount] = { - TERN(SHOW_BOOTSCREEN, TERN(BOOT_MARLIN_LOGO_SMALL, MarlinLogo195x59x16, MarlinLogo320x240x16), NoLogo), - HotEnd_64x64x4, - Bed_64x64x4, - Bed_Heated_64x64x4, - Chamber_64x64x4, - Chamber_Heated_64x64x4, - Fan0_64x64x4, - Fan_Slow0_64x64x4, - Fan_Slow1_64x64x4, - Fan_Fast0_64x64x4, - Fan_Fast1_64x64x4, - Feedrate_32x32x4, - Flowrate_32x32x4, - SD_64x64x4, - Menu_64x64x4, - Settings_64x64x4, - Directory_32x32x4, - Confirm_64x64x4, - Cancel_64x64x4, - Increase_64x64x4, - Decrease_64x64x4, - Back_32x32x4, - Up_32x32x4, - Down_32x32x4, - Left_32x32x4, - Right_32x32x4, - Refresh_32x32x4, - Leveling_32x32x4, - Slider8x16x4, - Home_64x64x4, - BtnRounded_64x52x4, -}; - -#if HAS_TEMP_CHAMBER && HOTENDS > 1 - #define ITEM_E0 0 - #define ITEM_E1 1 - #define ITEM_BED 2 - #define ITEM_CHAMBER 3 - #define ITEM_FAN 4 - #define ITEMS_COUNT 5 - #define POS_Y 0 -#elif HAS_TEMP_CHAMBER - #define ITEM_E0 0 - #define ITEM_BED 1 - #define ITEM_CHAMBER 2 - #define ITEM_FAN 3 - #define ITEMS_COUNT 4 - #define POS_Y 0 -#elif HOTENDS > 1 - #define ITEM_E0 0 - #define ITEM_E1 1 - #define ITEM_BED 2 - #define ITEM_FAN 3 - #define ITEMS_COUNT 4 - #define POS_Y 0 -#else - #define ITEM_E0 0 - #define ITEM_BED 1 - #define ITEM_FAN 2 - #define ITEMS_COUNT 3 - #define POS_Y 0 -#endif +#include "ui_common.h" diff --git a/Marlin/src/lcd/tft/ui_480x320.cpp b/Marlin/src/lcd/tft/ui_480x320.cpp index b6ffb4592f..5000aedc39 100644 --- a/Marlin/src/lcd/tft/ui_480x320.cpp +++ b/Marlin/src/lcd/tft/ui_480x320.cpp @@ -24,7 +24,7 @@ #if HAS_UI_480x320 || HAS_UI_480x272 -#include "ui_480x320.h" +#include "ui_common.h" #include "../marlinui.h" #include "../menu/menu.h" @@ -45,14 +45,6 @@ #include "../../feature/bedlevel/bedlevel.h" #endif -#if !HAS_LCD_MENU - #error "Seriously? High resolution TFT screen without menu?" -#endif - -#if ENABLED(TOUCH_SCREEN) - static bool draw_menu_navigation = false; -#endif - void MarlinUI::tft_idle() { #if ENABLED(TOUCH_SCREEN) if (draw_menu_navigation) { @@ -67,28 +59,6 @@ void MarlinUI::tft_idle() { TERN_(TOUCH_SCREEN, touch.idle()); } -void MarlinUI::init_lcd() { - tft.init(); - tft.set_font(MENU_FONT_NAME); - #ifdef SYMBOLS_FONT_NAME - tft.add_glyphs(SYMBOLS_FONT_NAME); - #endif - TERN_(TOUCH_SCREEN, touch.init()); - clear_lcd(); -} - -bool MarlinUI::detected() { return true; } - -void MarlinUI::clear_lcd() { - #if ENABLED(TOUCH_SCREEN) - touch.reset(); - draw_menu_navigation = false; - #endif - - tft.queue.reset(); - tft.fill(0, 0, TFT_WIDTH, TFT_HEIGHT, COLOR_BACKGROUND); -} - #if ENABLED(SHOW_BOOTSCREEN) void MarlinUI::show_bootscreen() { tft.queue.reset(); @@ -100,8 +70,8 @@ void MarlinUI::clear_lcd() { #define SITE_URL_Y (TFT_HEIGHT - 70) tft.set_background(COLOR_BACKGROUND); #else - #define BOOT_LOGO_W 480 // MarlinLogo480x320x16 - #define BOOT_LOGO_H 320 + #define BOOT_LOGO_W TFT_WIDTH // MarlinLogo480x320x16 + #define BOOT_LOGO_H TFT_HEIGHT #define SITE_URL_Y (TFT_HEIGHT - 90) #endif tft.add_image((TFT_WIDTH - BOOT_LOGO_W) / 2, (TFT_HEIGHT - BOOT_LOGO_H) / 2, imgBootScreen); @@ -150,22 +120,22 @@ void draw_heater_status(uint16_t x, uint16_t y, const int8_t Heater) { currentTemperature = thermalManager.degHotend(Heater); targetTemperature = thermalManager.degTargetHotend(Heater); } -#if HAS_HEATED_BED - else if (Heater == H_BED) { - currentTemperature = thermalManager.degBed(); - targetTemperature = thermalManager.degTargetBed(); - } -#endif // HAS_HEATED_BED -#if HAS_TEMP_CHAMBER - else if (Heater == H_CHAMBER) { - currentTemperature = thermalManager.degChamber(); - #if HAS_HEATED_CHAMBER - targetTemperature = thermalManager.degTargetChamber(); - #else - targetTemperature = ABSOLUTE_ZERO; - #endif - } -#endif // HAS_TEMP_CHAMBER + #if HAS_HEATED_BED + else if (Heater == H_BED) { + currentTemperature = thermalManager.degBed(); + targetTemperature = thermalManager.degTargetBed(); + } + #endif + #if HAS_TEMP_CHAMBER + else if (Heater == H_CHAMBER) { + currentTemperature = thermalManager.degChamber(); + #if HAS_HEATED_CHAMBER + targetTemperature = thermalManager.degTargetChamber(); + #else + targetTemperature = ABSOLUTE_ZERO; + #endif + } + #endif else return; TERN_(TOUCH_SCREEN, if (targetTemperature >= 0) touch.add_control(HEATER, x, y, 80, 120, Heater)); @@ -178,17 +148,17 @@ void draw_heater_status(uint16_t x, uint16_t y, const int8_t Heater) { if (currentTemperature >= 50) Color = COLOR_HOTEND; } #if HAS_HEATED_BED - else if (Heater == H_BED) { - if (currentTemperature >= 50) Color = COLOR_HEATED_BED; - image = targetTemperature > 0 ? imgBedHeated : imgBed; - } - #endif // HAS_HEATED_BED + else if (Heater == H_BED) { + if (currentTemperature >= 50) Color = COLOR_HEATED_BED; + image = targetTemperature > 0 ? imgBedHeated : imgBed; + } + #endif #if HAS_TEMP_CHAMBER - else if (Heater == H_CHAMBER) { - if (currentTemperature >= 50) Color = COLOR_CHAMBER; - image = targetTemperature > 0 ? imgChamberHeated : imgChamber; - } - #endif // HAS_TEMP_CHAMBER + else if (Heater == H_CHAMBER) { + if (currentTemperature >= 50) Color = COLOR_CHAMBER; + image = targetTemperature > 0 ? imgChamberHeated : imgChamber; + } + #endif tft.add_image(8, 28, image, Color); @@ -233,7 +203,7 @@ void MarlinUI::draw_status_screen() { TERN_(TOUCH_SCREEN, touch.clear()); // heaters and fan - uint16_t i, x, y = POS_Y; + uint16_t i, x, y = TFT_STATUS_TOP_Y; for (i = 0 ; i < ITEMS_COUNT; i++) { x = (TFT_WIDTH / ITEMS_COUNT - 80) / 2 + (TFT_WIDTH * i / ITEMS_COUNT); @@ -349,49 +319,6 @@ void MarlinUI::draw_status_screen() { tft.add_text(tft_string.center(TFT_WIDTH), 0, COLOR_STATUS_MESSAGE, tft_string); } -// Draw a static item with no left-right margin required. Centered by default. -void MenuItem_static::draw(const uint8_t row, PGM_P const pstr, const uint8_t style/*=SS_DEFAULT*/, const char * const vstr/*=nullptr*/) { - menu_item(row); - tft_string.set(pstr, itemIndex, itemString); - if (vstr) - tft_string.add(vstr); - tft.add_text(tft_string.center(TFT_WIDTH), MENU_TEXT_Y_OFFSET, COLOR_YELLOW, tft_string); -} - -// Draw a generic menu item with pre_char (if selected) and post_char -void MenuItemBase::_draw(const bool sel, const uint8_t row, PGM_P const pstr, const char pre_char, const char post_char) { - menu_item(row, sel); - - uint8_t *string = (uint8_t *)pstr; - MarlinImage image = noImage; - switch (*string) { - case 0x01: image = imgRefresh; break; // LCD_STR_REFRESH - case 0x02: image = imgDirectory; break; // LCD_STR_FOLDER - } - - uint8_t offset = MENU_TEXT_X_OFFSET; - if (image != noImage) { - string++; - offset = 42; - tft.add_image(5, 5, image, COLOR_MENU_TEXT, sel ? COLOR_SELECTION_BG : COLOR_BACKGROUND); - } - - tft_string.set(string, itemIndex, itemString); - tft.add_text(offset, MENU_TEXT_Y_OFFSET, COLOR_MENU_TEXT, tft_string); -} - -// Draw a menu item with a (potentially) editable value -void MenuEditItemBase::draw(const bool sel, const uint8_t row, PGM_P const pstr, const char* const data, const bool pgm) { - menu_item(row, sel); - - tft_string.set(pstr, itemIndex, itemString); - tft.add_text(MENU_TEXT_X_OFFSET, MENU_TEXT_Y_OFFSET, COLOR_MENU_TEXT, tft_string); - if (data) { - tft_string.set(data); - tft.add_text(TFT_WIDTH - MENU_TEXT_X_OFFSET - tft_string.width(), MENU_TEXT_Y_OFFSET, COLOR_MENU_VALUE, tft_string); - } -} - // Low-level draw_edit_screen can be used to draw an edit screen from anyplace void MenuEditItemBase::draw_edit_screen(PGM_P const pstr, const char* const value/*=nullptr*/) { ui.encoder_direction_normal(); @@ -491,16 +418,8 @@ void MenuItem_confirm::draw_select_screen(PGM_P const yes, PGM_P const no, const #endif } -#if ENABLED(SDSUPPORT) - void MenuItem_sdbase::draw(const bool sel, const uint8_t row, PGM_P const, CardReader &theCard, const bool isDir) { - menu_item(row, sel); - if (isDir) - tft.add_image(5, 5, imgDirectory, COLOR_MENU_TEXT, sel ? COLOR_SELECTION_BG : COLOR_BACKGROUND); - tft.add_text(42, MENU_TEXT_Y_OFFSET, COLOR_MENU_TEXT, theCard.longest_filename()); - } -#endif - #if ENABLED(ADVANCED_PAUSE_FEATURE) + void MarlinUI::draw_hotend_status(const uint8_t row, const uint8_t extruder) { #if ENABLED(TOUCH_SCREEN) touch.clear(); @@ -521,6 +440,7 @@ void MenuItem_confirm::draw_select_screen(PGM_P const yes, PGM_P const no, const tft_string.trim(); tft.add_text(tft_string.center(TFT_WIDTH), 0, COLOR_MENU_TEXT, tft_string); } + #endif // ADVANCED_PAUSE_FEATURE #if ENABLED(AUTO_BED_LEVELING_UBL) @@ -570,18 +490,18 @@ void MenuItem_confirm::draw_select_screen(PGM_P const yes, PGM_P const no, const tft_string.trim(); tft.add_text(120 - tft_string.width(), MENU_TEXT_Y_OFFSET, COLOR_MENU_VALUE, tft_string); - - tft.canvas(GRID_OFFSET_X + (GRID_WIDTH - 48) / 2, GRID_OFFSET_Y + GRID_HEIGHT + CONTROL_OFFSET - 5, 48, MENU_ITEM_HEIGHT); + constexpr uint8_t w = (TFT_WIDTH) / 10; + tft.canvas(GRID_OFFSET_X + (GRID_WIDTH - w) / 2, GRID_OFFSET_Y + GRID_HEIGHT + CONTROL_OFFSET - 5, w, MENU_ITEM_HEIGHT); tft.set_background(COLOR_BACKGROUND); tft_string.set(ui8tostr3rj(x_plot)); tft_string.trim(); - tft.add_text(tft_string.center(48), MENU_TEXT_Y_OFFSET, COLOR_MENU_VALUE, tft_string); + tft.add_text(tft_string.center(w), MENU_TEXT_Y_OFFSET, COLOR_MENU_VALUE, tft_string); - tft.canvas(GRID_OFFSET_X + GRID_WIDTH + CONTROL_OFFSET + 16 - 24, GRID_OFFSET_Y + (GRID_HEIGHT - MENU_ITEM_HEIGHT) / 2, 48, MENU_ITEM_HEIGHT); + tft.canvas(GRID_OFFSET_X + GRID_WIDTH + CONTROL_OFFSET + 16 - 24, GRID_OFFSET_Y + (GRID_HEIGHT - MENU_ITEM_HEIGHT) / 2, w, MENU_ITEM_HEIGHT); tft.set_background(COLOR_BACKGROUND); tft_string.set(ui8tostr3rj(y_plot)); tft_string.trim(); - tft.add_text(tft_string.center(48), MENU_TEXT_Y_OFFSET, COLOR_MENU_VALUE, tft_string); + tft.add_text(tft_string.center(w), MENU_TEXT_Y_OFFSET, COLOR_MENU_VALUE, tft_string); #if ENABLED(TOUCH_SCREEN) touch.clear(); @@ -596,97 +516,6 @@ void MenuItem_confirm::draw_select_screen(PGM_P const yes, PGM_P const no, const } #endif // AUTO_BED_LEVELING_UBL -#if ENABLED(TOUCH_SCREEN_CALIBRATION) - void MarlinUI::touch_calibration_screen() { - uint16_t x, y; - - calibrationState calibration_stage = touch_calibration.get_calibration_state(); - - if (calibration_stage == CALIBRATION_NONE) { - defer_status_screen(true); - clear_lcd(); - calibration_stage = touch_calibration.calibration_start(); - } - else { - x = touch_calibration.calibration_points[_MIN(calibration_stage - 1, CALIBRATION_BOTTOM_RIGHT)].x; - y = touch_calibration.calibration_points[_MIN(calibration_stage - 1, CALIBRATION_BOTTOM_RIGHT)].y; - tft.canvas(x - 15, y - 15, 31, 31); - tft.set_background(COLOR_BACKGROUND); - } - - touch.clear(); - - if (calibration_stage < CALIBRATION_SUCCESS) { - switch (calibration_stage) { - case CALIBRATION_TOP_LEFT: tft_string.set(GET_TEXT(MSG_TOP_LEFT)); break; - case CALIBRATION_BOTTOM_LEFT: tft_string.set(GET_TEXT(MSG_BOTTOM_LEFT)); break; - case CALIBRATION_TOP_RIGHT: tft_string.set(GET_TEXT(MSG_TOP_RIGHT)); break; - case CALIBRATION_BOTTOM_RIGHT: tft_string.set(GET_TEXT(MSG_BOTTOM_RIGHT)); break; - default: break; - } - - x = touch_calibration.calibration_points[calibration_stage].x; - y = touch_calibration.calibration_points[calibration_stage].y; - - tft.canvas(x - 15, y - 15, 31, 31); - tft.set_background(COLOR_BACKGROUND); - tft.add_bar(0, 15, 31, 1, COLOR_TOUCH_CALIBRATION); - tft.add_bar(15, 0, 1, 31, COLOR_TOUCH_CALIBRATION); - - touch.add_control(CALIBRATE, 0, 0, TFT_WIDTH, TFT_HEIGHT, uint32_t(x) << 16 | uint32_t(y)); - } - else { - tft_string.set(calibration_stage == CALIBRATION_SUCCESS ? GET_TEXT(MSG_CALIBRATION_COMPLETED) : GET_TEXT(MSG_CALIBRATION_FAILED)); - defer_status_screen(false); - touch_calibration.calibration_end(); - touch.add_control(BACK, 0, 0, TFT_WIDTH, TFT_HEIGHT); - } - - tft.canvas(0, (TFT_HEIGHT - tft_string.font_height()) >> 1, TFT_WIDTH, tft_string.font_height()); - tft.set_background(COLOR_BACKGROUND); - tft.add_text(tft_string.center(TFT_WIDTH), 0, COLOR_MENU_TEXT, tft_string); - } -#endif // TOUCH_SCREEN_CALIBRATION - -void menu_line(const uint8_t row, uint16_t color) { - tft.canvas(0, 4 + (MENU_ITEM_HEIGHT + 2) * row, TFT_WIDTH, MENU_ITEM_HEIGHT); - tft.set_background(color); -} - -void menu_pause_option(); - -void menu_item(const uint8_t row, bool sel ) { - #if ENABLED(TOUCH_SCREEN) - if (row == 0) { - touch.clear(); - draw_menu_navigation = TERN(ADVANCED_PAUSE_FEATURE, ui.currentScreen != menu_pause_option, true); - } - #endif - - menu_line(row, sel ? COLOR_SELECTION_BG : COLOR_BACKGROUND); - #if ENABLED(TOUCH_SCREEN) - const TouchControlType tct = TERN(SINGLE_TOUCH_NAVIGATION, true, sel) ? MENU_CLICK : MENU_ITEM; - touch.add_control(tct, 0, 4 + (MENU_ITEM_HEIGHT + 2) * row, TFT_WIDTH, MENU_ITEM_HEIGHT, encoderTopLine + row); - #endif -} - -void lcd_moveto(const lcd_uint_t col, const lcd_uint_t row) { - #define TFT_COL_WIDTH ((TFT_WIDTH) / (LCD_WIDTH)) - tft.canvas(col * TFT_COL_WIDTH, 4 + 45 * row, TFT_WIDTH - (col * TFT_COL_WIDTH), 43); - tft.set_background(COLOR_BACKGROUND); -} - -int lcd_put_u8str_max_P(PGM_P utf8_str_P, pixel_len_t max_length) { - tft_string.set(utf8_str_P); - tft_string.trim(); - tft.add_text(MENU_TEXT_X_OFFSET, MENU_TEXT_Y_OFFSET, COLOR_MENU_TEXT, tft_string); - return tft_string.width(); -} - -int lcd_put_u8str_max(const char * utf8_str, pixel_len_t max_length) { - return lcd_put_u8str_max_P(utf8_str, max_length); -} - #if ENABLED(BABYSTEP_ZPROBE_OFFSET) #include "../../feature/babystep.h" #endif @@ -867,7 +696,7 @@ static void moveAxis(AxisEnum axis, const int8_t direction) { NOMORE(ui.manual_move.offset, max - current_position[axis]); #else current_position[axis] += diff; - const char *msg = PSTR(""); // clear the error + const char *msg = NUL_STR; // clear the error if (direction < 0 && current_position[axis] < min) { current_position[axis] = min; msg = GET_TEXT(MSG_LCD_SOFT_ENDSTOPS); @@ -889,37 +718,14 @@ static void moveAxis(AxisEnum axis, const int8_t direction) { drawAxisValue(axis); } -static void e_plus() { - moveAxis(E_AXIS, 1); -} - -static void e_minus() { - moveAxis(E_AXIS, -1); -} - -static void x_minus() { - moveAxis(X_AXIS, -1); -} - -static void x_plus() { - moveAxis(X_AXIS, 1); -} - -static void y_plus() { - moveAxis(Y_AXIS, 1); -} - -static void y_minus() { - moveAxis(Y_AXIS, -1); -} - -static void z_plus() { - moveAxis(Z_AXIS, 1); -} - -static void z_minus() { - moveAxis(Z_AXIS, -1); -} +static void e_plus() { moveAxis(E_AXIS, 1); } +static void e_minus() { moveAxis(E_AXIS, -1); } +static void x_minus() { moveAxis(X_AXIS, -1); } +static void x_plus() { moveAxis(X_AXIS, 1); } +static void y_plus() { moveAxis(Y_AXIS, 1); } +static void y_minus() { moveAxis(Y_AXIS, -1); } +static void z_plus() { moveAxis(Z_AXIS, 1); } +static void z_minus() { moveAxis(Z_AXIS, -1); } #if ENABLED(TOUCH_SCREEN) static void e_select() { @@ -1002,8 +808,9 @@ void MarlinUI::move_axis_screen() { const bool busy = printingIsActive(); - // if we have baby step and we are printing, select baby step - if (busy && ENABLED(BABYSTEP_ZPROBE_OFFSET)) motionAxisState.z_selection = Z_SELECTION_Z_PROBE; + // Babysteps during printing? Select babystep for Z probe offset + if (busy && ENABLED(BABYSTEP_ZPROBE_OFFSET)) + motionAxisState.z_selection = Z_SELECTION_Z_PROBE; // ROW 1 -> E- Y- CurY Z+ int x = X_MARGIN, y = Y_MARGIN, spacing = 0; @@ -1089,7 +896,7 @@ void MarlinUI::move_axis_screen() { TERN_(HAS_TFT_XPT2046, touch.add_control(BUTTON, motionAxisState.stepValuePos.x, motionAxisState.stepValuePos.y, CUR_STEP_VALUE_WIDTH, BTN_HEIGHT, (intptr_t)step_size)); } - // alinged with x+ + // aligned with x+ drawBtn(xplus_x, TFT_HEIGHT - Y_MARGIN - BTN_HEIGHT, "off", (intptr_t)disable_steppers, imgCancel, COLOR_WHITE, !busy); TERN_(HAS_TFT_XPT2046, add_control(TFT_WIDTH - X_MARGIN - BTN_WIDTH, y, BACK, imgBack)); diff --git a/Marlin/src/lcd/tft/ui_480x320.h b/Marlin/src/lcd/tft/ui_480x320.h index e3a688f112..fca9ed9c2a 100644 --- a/Marlin/src/lcd/tft/ui_480x320.h +++ b/Marlin/src/lcd/tft/ui_480x320.h @@ -21,97 +21,29 @@ */ #pragma once -#include "../../inc/MarlinConfigPre.h" +#define MARLIN_LOGO_FULL_SIZE MarlinLogo480x320x16 -#include "tft.h" -#include "tft_image.h" +#include "ui_common.h" -#if ENABLED(TOUCH_SCREEN) - #include "touch.h" -#endif +#define TFT_STATUS_TOP_Y 4 +#define TFT_TOP_LINE_Y 4 -void draw_heater_status(uint16_t x, uint16_t y, const int8_t Heater); -void draw_fan_status(uint16_t x, uint16_t y, const bool blink); +#define MENU_TEXT_X_OFFSET 16 +#define MENU_TEXT_Y_OFFSET 7 -#define MENU_TEXT_X_OFFSET 16 -#define MENU_TEXT_Y_OFFSET 7 -void menu_line(const uint8_t row, uint16_t color = COLOR_BACKGROUND); -void menu_item(const uint8_t row, bool sel = false); +#define MENU_ITEM_ICON_X 5 +#define MENU_ITEM_ICON_Y 5 +#define MENU_ITEM_ICON_SPACE 42 #if HAS_UI_480x320 - #define MENU_FONT_NAME Helvetica18 - #define SYMBOLS_FONT_NAME Helvetica18_symbols - #define MENU_ITEM_HEIGHT 43 - #define FONT_LINE_HEIGHT 34 + #define MENU_FONT_NAME Helvetica18 + #define SYMBOLS_FONT_NAME Helvetica18_symbols + #define MENU_ITEM_HEIGHT 43 + #define FONT_LINE_HEIGHT 34 #elif HAS_UI_480x272 - #define MENU_FONT_NAME Helvetica14 - #define SYMBOLS_FONT_NAME Helvetica14_symbols - #define MENU_ITEM_HEIGHT 36 - #define FONT_LINE_HEIGHT 24 -#endif - -#define ABSOLUTE_ZERO -273.15 - -const tImage Images[imgCount] = { - TERN(SHOW_BOOTSCREEN, TERN(BOOT_MARLIN_LOGO_SMALL, MarlinLogo195x59x16, MarlinLogo480x320x16), NoLogo), - HotEnd_64x64x4, - Bed_64x64x4, - Bed_Heated_64x64x4, - Chamber_64x64x4, - Chamber_Heated_64x64x4, - Fan0_64x64x4, - Fan_Slow0_64x64x4, - Fan_Slow1_64x64x4, - Fan_Fast0_64x64x4, - Fan_Fast1_64x64x4, - Feedrate_32x32x4, - Flowrate_32x32x4, - SD_64x64x4, - Menu_64x64x4, - Settings_64x64x4, - Directory_32x32x4, - Confirm_64x64x4, - Cancel_64x64x4, - Increase_64x64x4, - Decrease_64x64x4, - Back_32x32x4, - Up_32x32x4, - Down_32x32x4, - Left_32x32x4, - Right_32x32x4, - Refresh_32x32x4, - Leveling_32x32x4, - Slider8x16x4, - Home_64x64x4, - BtnRounded_64x52x4, -}; - -#if HAS_TEMP_CHAMBER && HOTENDS > 1 - #define ITEM_E0 0 - #define ITEM_E1 1 - #define ITEM_BED 2 - #define ITEM_CHAMBER 3 - #define ITEM_FAN 4 - #define ITEMS_COUNT 5 - #define POS_Y 4 -#elif HAS_TEMP_CHAMBER - #define ITEM_E0 0 - #define ITEM_BED 1 - #define ITEM_CHAMBER 2 - #define ITEM_FAN 3 - #define ITEMS_COUNT 4 - #define POS_Y 4 -#elif HOTENDS > 1 - #define ITEM_E0 0 - #define ITEM_E1 1 - #define ITEM_BED 2 - #define ITEM_FAN 3 - #define ITEMS_COUNT 4 - #define POS_Y 4 -#else - #define ITEM_E0 0 - #define ITEM_BED 1 - #define ITEM_FAN 2 - #define ITEMS_COUNT 3 - #define POS_Y 4 + #define MENU_FONT_NAME Helvetica14 + #define SYMBOLS_FONT_NAME Helvetica14_symbols + #define MENU_ITEM_HEIGHT 36 + #define FONT_LINE_HEIGHT 24 #endif +#define MENU_LINE_HEIGHT (MENU_ITEM_HEIGHT + 2) diff --git a/Marlin/src/lcd/tft/ui_common.cpp b/Marlin/src/lcd/tft/ui_common.cpp new file mode 100644 index 0000000000..842fc3909c --- /dev/null +++ b/Marlin/src/lcd/tft/ui_common.cpp @@ -0,0 +1,246 @@ +/** + * 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 . + * + */ + +#include "../../inc/MarlinConfigPre.h" + +#if HAS_GRAPHICAL_TFT + +#include "ui_common.h" +#include "../lcdprint.h" +#include "../../libs/numtostr.h" +#include "../menu/menu.h" + +void menu_pause_option(); + +static xy_uint_t cursor; + +#if ENABLED(TOUCH_SCREEN) + bool draw_menu_navigation = false; +#endif + +void menu_line(const uint8_t row, uint16_t color) { + cursor.set(0, row); + tft.canvas(0, TFT_TOP_LINE_Y + cursor.y * MENU_LINE_HEIGHT, TFT_WIDTH, MENU_ITEM_HEIGHT); + tft.set_background(color); +} + +void menu_item(const uint8_t row, bool sel ) { + #if ENABLED(TOUCH_SCREEN) + if (row == 0) { + touch.clear(); + draw_menu_navigation = TERN(ADVANCED_PAUSE_FEATURE, ui.currentScreen != menu_pause_option, true); + } + #endif + + menu_line(row, sel ? COLOR_SELECTION_BG : COLOR_BACKGROUND); + #if ENABLED(TOUCH_SCREEN) + const TouchControlType tct = TERN(SINGLE_TOUCH_NAVIGATION, true, sel) ? MENU_CLICK : MENU_ITEM; + touch.add_control(tct, 0, TFT_TOP_LINE_Y + row * MENU_LINE_HEIGHT, TFT_WIDTH, MENU_ITEM_HEIGHT, encoderTopLine + row); + #endif +} + +// +// lcdprint.h functions +// + +#define TFT_COL_WIDTH ((TFT_WIDTH) / (LCD_WIDTH)) + +void lcd_gotopixel(const uint16_t x, const uint16_t y) { + if (x >= TFT_WIDTH) return; + cursor.set(x / (TFT_COL_WIDTH), y / MENU_LINE_HEIGHT); + tft.canvas(x, TFT_TOP_LINE_Y + y, (TFT_WIDTH) - x, MENU_ITEM_HEIGHT); + tft.set_background(COLOR_BACKGROUND); +} + +void lcd_moveto(const lcd_uint_t col, const lcd_uint_t row) { + lcd_gotopixel(int(col) * (TFT_COL_WIDTH), int(row) * MENU_LINE_HEIGHT); +} + +int lcd_put_wchar_max(wchar_t c, pixel_len_t max_length) { + if (max_length < 1) return 0; + tft_string.set(); + tft_string.add(c); + tft.add_text(MENU_TEXT_X_OFFSET, MENU_TEXT_Y_OFFSET, COLOR_MENU_TEXT, tft_string); + lcd_gotopixel((cursor.x + 1) * (TFT_COL_WIDTH) + tft_string.width(), cursor.y * MENU_LINE_HEIGHT); + return tft_string.width(); +} + +int lcd_put_u8str_max_P(PGM_P utf8_str_P, pixel_len_t max_length) { + if (max_length < 1) return 0; + tft_string.set(utf8_str_P); + tft_string.trim(); + tft_string.truncate(max_length); + tft.add_text(MENU_TEXT_X_OFFSET, MENU_TEXT_Y_OFFSET, COLOR_MENU_TEXT, tft_string); + lcd_gotopixel((cursor.x + 1) * (TFT_COL_WIDTH) + tft_string.width(), cursor.y * MENU_LINE_HEIGHT); + return tft_string.width(); +} + +int lcd_put_u8str_max(const char * utf8_str, pixel_len_t max_length) { + return lcd_put_u8str_max_P(utf8_str, max_length); +} + +void lcd_put_int(const int i) { + // 3 digits max for this one... + const char* str = i16tostr3left(int16_t(i)); + lcd_put_u8str_max(str, 3); +} + +// +// Menu Item methods +// + +// Draw a generic menu item with pre_char (if selected) and post_char +void MenuItemBase::_draw(const bool sel, const uint8_t row, PGM_P const pstr, const char pre_char, const char post_char) { + menu_item(row, sel); + + uint8_t *string = (uint8_t *)pstr; + MarlinImage image = noImage; + switch (*string) { + case 0x01: image = imgRefresh; break; // LCD_STR_REFRESH + case 0x02: image = imgDirectory; break; // LCD_STR_FOLDER + } + + uint8_t offset = MENU_TEXT_X_OFFSET; + if (image != noImage) { + string++; + offset = MENU_ITEM_ICON_SPACE; + tft.add_image(MENU_ITEM_ICON_X, MENU_ITEM_ICON_Y, image, COLOR_MENU_TEXT, sel ? COLOR_SELECTION_BG : COLOR_BACKGROUND); + } + + tft_string.set(string, itemIndex, itemString); + tft.add_text(offset, MENU_TEXT_Y_OFFSET, COLOR_MENU_TEXT, tft_string); +} + +// Draw a menu item with a (potentially) editable value +void MenuEditItemBase::draw(const bool sel, const uint8_t row, PGM_P const pstr, const char* const data, const bool pgm) { + menu_item(row, sel); + + tft_string.set(pstr, itemIndex, itemString); + tft.add_text(MENU_TEXT_X_OFFSET, MENU_TEXT_Y_OFFSET, COLOR_MENU_TEXT, tft_string); + if (data) { + tft_string.set(data); + tft.add_text(TFT_WIDTH - MENU_TEXT_X_OFFSET - tft_string.width(), MENU_TEXT_Y_OFFSET, COLOR_MENU_VALUE, tft_string); + } +} + +// Draw a static item with no left-right margin required. Centered by default. +void MenuItem_static::draw(const uint8_t row, PGM_P const pstr, const uint8_t style/*=SS_DEFAULT*/, const char * const vstr/*=nullptr*/) { + menu_item(row); + tft_string.set(pstr, itemIndex, itemString); + if (vstr) + tft_string.add(vstr); + tft.add_text(tft_string.center(TFT_WIDTH), MENU_TEXT_Y_OFFSET, COLOR_YELLOW, tft_string); +} + +#if ENABLED(SDSUPPORT) + + void MenuItem_sdbase::draw(const bool sel, const uint8_t row, PGM_P const, CardReader &theCard, const bool isDir) { + menu_item(row, sel); + if (isDir) + tft.add_image(MENU_ITEM_ICON_X, MENU_ITEM_ICON_Y, imgDirectory, COLOR_MENU_TEXT, sel ? COLOR_SELECTION_BG : COLOR_BACKGROUND); + tft.add_text(MENU_ITEM_ICON_SPACE, MENU_TEXT_Y_OFFSET, COLOR_MENU_TEXT, theCard.longest_filename()); + } + +#endif + +// +// MarlinUI methods +// + +bool MarlinUI::detected() { return true; } + +void MarlinUI::init_lcd() { + tft.init(); + tft.set_font(MENU_FONT_NAME); + #ifdef SYMBOLS_FONT_NAME + tft.add_glyphs(SYMBOLS_FONT_NAME); + #endif + TERN_(TOUCH_SCREEN, touch.init()); + clear_lcd(); +} + +void MarlinUI::clear_lcd() { + #if ENABLED(TOUCH_SCREEN) + touch.reset(); + draw_menu_navigation = false; + #endif + + tft.queue.reset(); + tft.fill(0, 0, TFT_WIDTH, TFT_HEIGHT, COLOR_BACKGROUND); + cursor.set(0, 0); +} + +#if ENABLED(TOUCH_SCREEN_CALIBRATION) + + void MarlinUI::touch_calibration_screen() { + uint16_t x, y; + + calibrationState calibration_stage = touch_calibration.get_calibration_state(); + + if (calibration_stage == CALIBRATION_NONE) { + defer_status_screen(true); + clear_lcd(); + calibration_stage = touch_calibration.calibration_start(); + } + else { + x = touch_calibration.calibration_points[_MIN(calibration_stage - 1, CALIBRATION_BOTTOM_RIGHT)].x; + y = touch_calibration.calibration_points[_MIN(calibration_stage - 1, CALIBRATION_BOTTOM_RIGHT)].y; + tft.canvas(x - 15, y - 15, 31, 31); + tft.set_background(COLOR_BACKGROUND); + } + + touch.clear(); + + if (calibration_stage < CALIBRATION_SUCCESS) { + switch (calibration_stage) { + case CALIBRATION_TOP_LEFT: tft_string.set(GET_TEXT(MSG_TOP_LEFT)); break; + case CALIBRATION_BOTTOM_LEFT: tft_string.set(GET_TEXT(MSG_BOTTOM_LEFT)); break; + case CALIBRATION_TOP_RIGHT: tft_string.set(GET_TEXT(MSG_TOP_RIGHT)); break; + case CALIBRATION_BOTTOM_RIGHT: tft_string.set(GET_TEXT(MSG_BOTTOM_RIGHT)); break; + default: break; + } + + x = touch_calibration.calibration_points[calibration_stage].x; + y = touch_calibration.calibration_points[calibration_stage].y; + + tft.canvas(x - 15, y - 15, 31, 31); + tft.set_background(COLOR_BACKGROUND); + tft.add_bar(0, 15, 31, 1, COLOR_TOUCH_CALIBRATION); + tft.add_bar(15, 0, 1, 31, COLOR_TOUCH_CALIBRATION); + + touch.add_control(CALIBRATE, 0, 0, TFT_WIDTH, TFT_HEIGHT, uint32_t(x) << 16 | uint32_t(y)); + } + else { + tft_string.set(calibration_stage == CALIBRATION_SUCCESS ? GET_TEXT(MSG_CALIBRATION_COMPLETED) : GET_TEXT(MSG_CALIBRATION_FAILED)); + defer_status_screen(false); + touch_calibration.calibration_end(); + touch.add_control(BACK, 0, 0, TFT_WIDTH, TFT_HEIGHT); + } + + tft.canvas(0, (TFT_HEIGHT - tft_string.font_height()) >> 1, TFT_WIDTH, tft_string.font_height()); + tft.set_background(COLOR_BACKGROUND); + tft.add_text(tft_string.center(TFT_WIDTH), 0, COLOR_MENU_TEXT, tft_string); + } + +#endif // TOUCH_SCREEN_CALIBRATION + +#endif // HAS_GRAPHICAL_TFT diff --git a/Marlin/src/lcd/tft/ui_common.h b/Marlin/src/lcd/tft/ui_common.h new file mode 100644 index 0000000000..d40e471171 --- /dev/null +++ b/Marlin/src/lcd/tft/ui_common.h @@ -0,0 +1,76 @@ +/** + * 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 + +#include "../../inc/MarlinConfigPre.h" + +#if !HAS_LCD_MENU + #error "Seriously? High resolution TFT screen without menu?" +#endif + +#include "tft.h" +#include "tft_image.h" + +#if ENABLED(TOUCH_SCREEN) + #include "touch.h" + extern bool draw_menu_navigation; +#endif + +#if HAS_UI_320x240 + #include "ui_320x240.h" +#elif HAS_UI_480x320 || HAS_UI_480x272 + #include "ui_480x320.h" +#endif + +void draw_heater_status(uint16_t x, uint16_t y, const int8_t Heater); +void draw_fan_status(uint16_t x, uint16_t y, const bool blink); + +void menu_line(const uint8_t row, uint16_t color=COLOR_BACKGROUND); +void menu_item(const uint8_t row, bool sel = false); + +#define ABSOLUTE_ZERO -273.15 + +#if HAS_TEMP_CHAMBER && HOTENDS > 1 + #define ITEM_E0 0 + #define ITEM_E1 1 + #define ITEM_BED 2 + #define ITEM_CHAMBER 3 + #define ITEM_FAN 4 + #define ITEMS_COUNT 5 +#elif HAS_TEMP_CHAMBER + #define ITEM_E0 0 + #define ITEM_BED 1 + #define ITEM_CHAMBER 2 + #define ITEM_FAN 3 + #define ITEMS_COUNT 4 +#elif HOTENDS > 1 + #define ITEM_E0 0 + #define ITEM_E1 1 + #define ITEM_BED 2 + #define ITEM_FAN 3 + #define ITEMS_COUNT 4 +#else + #define ITEM_E0 0 + #define ITEM_BED 1 + #define ITEM_FAN 2 + #define ITEMS_COUNT 3 +#endif diff --git a/Marlin/src/libs/BL24CXX.cpp b/Marlin/src/libs/BL24CXX.cpp index d34ed8340f..8de320d576 100644 --- a/Marlin/src/libs/BL24CXX.cpp +++ b/Marlin/src/libs/BL24CXX.cpp @@ -1,6 +1,5 @@ /** * Marlin 3D Printer Firmware - * * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] * * This program is free software: you can redistribute it and/or modify diff --git a/Marlin/src/libs/autoreport.h b/Marlin/src/libs/autoreport.h new file mode 100644 index 0000000000..9bde9f29fb --- /dev/null +++ b/Marlin/src/libs/autoreport.h @@ -0,0 +1,49 @@ +/** + * 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 + +#include "../inc/MarlinConfig.h" + +template +class AutoReporter { +public: + millis_t next_report_ms; + uint8_t report_interval; + + // Override this method + inline void auto_report() { } + + inline void set_interval(uint8_t seconds, const uint8_t limit=60) { + report_interval = _MIN(seconds, limit); + next_report_ms = millis() + SEC_TO_MS(seconds); + } + + inline void tick() { + if (!report_interval) return; + const millis_t ms = millis(); + if (ELAPSED(ms, next_report_ms)) { + next_report_ms = ms + SEC_TO_MS(report_interval); + PORT_REDIRECT(AR_PORT_INDEX); + auto_report(); + } + } +}; diff --git a/Marlin/src/libs/stopwatch.h b/Marlin/src/libs/stopwatch.h index 6e8e95a9a5..b64a36a90e 100644 --- a/Marlin/src/libs/stopwatch.h +++ b/Marlin/src/libs/stopwatch.h @@ -56,6 +56,7 @@ class Stopwatch { * @return true on success */ static bool stop(); + static inline bool abort() { return stop(); } // Alias by default /** * @brief Pause the stopwatch diff --git a/Marlin/src/libs/vector_3.cpp b/Marlin/src/libs/vector_3.cpp index fd93ba09ad..6f87a523e0 100644 --- a/Marlin/src/libs/vector_3.cpp +++ b/Marlin/src/libs/vector_3.cpp @@ -76,8 +76,6 @@ void vector_3::apply_rotation(const matrix_3x3 &matrix) { matrix.vectors[0][2] * _x + matrix.vectors[1][2] * _y + matrix.vectors[2][2] * _z }; } -extern const char SP_X_STR[], SP_Y_STR[], SP_Z_STR[]; - void vector_3::debug(PGM_P const title) { serialprintPGM(title); SERIAL_ECHOPAIR_F_P(SP_X_STR, x, 6); diff --git a/Marlin/src/module/endstops.cpp b/Marlin/src/module/endstops.cpp index b1c7c1c585..b9d2c1cdf5 100644 --- a/Marlin/src/module/endstops.cpp +++ b/Marlin/src/module/endstops.cpp @@ -27,7 +27,6 @@ #include "endstops.h" #include "stepper.h" -#include "../MarlinCore.h" #include "../sd/cardreader.h" #include "temperature.h" #include "../lcd/marlinui.h" diff --git a/Marlin/src/module/motion.cpp b/Marlin/src/module/motion.cpp index 99853f24df..f7fc66b27a 100644 --- a/Marlin/src/module/motion.cpp +++ b/Marlin/src/module/motion.cpp @@ -236,8 +236,17 @@ void report_current_position_projected() { } /** - * sync_plan_position - * + * Run out the planner buffer and re-sync the current + * position from the last-updated stepper positions. + */ +void quickstop_stepper() { + planner.quick_stop(); + planner.synchronize(); + set_current_from_steppers_for_axis(ALL_AXES); + sync_plan_position(); +} + +/** * Set the planner/stepper positions directly from current_position with * no kinematic translation. Used for homing axes and cartesian/core syncing. */ diff --git a/Marlin/src/module/motion.h b/Marlin/src/module/motion.h index 9352a4e4e6..887da1aa18 100644 --- a/Marlin/src/module/motion.h +++ b/Marlin/src/module/motion.h @@ -212,6 +212,8 @@ void report_current_position_projected(); void get_cartesian_from_steppers(); void set_current_from_steppers_for_axis(const AxisEnum axis); +void quickstop_stepper(); + /** * sync_plan_position * diff --git a/Marlin/src/module/printcounter.cpp b/Marlin/src/module/printcounter.cpp index ab87717f01..45072c8f01 100644 --- a/Marlin/src/module/printcounter.cpp +++ b/Marlin/src/module/printcounter.cpp @@ -41,6 +41,10 @@ Stopwatch print_job_timer; // Global Print Job Timer instance #include "../libs/buzzer.h" #endif +#if PRINTCOUNTER_SYNC + #include "../module/planner.h" +#endif + // Service intervals #if HAS_SERVICE_INTERVALS #if SERVICE_INTERVAL_1 > 0 @@ -160,6 +164,8 @@ void PrintCounter::saveStats() { // Refuses to save data if object is not loaded if (!isLoaded()) return; + TERN_(PRINTCOUNTER_SYNC, planner.synchronize()); + // Saves the struct to EEPROM persistentStore.access_start(); persistentStore.write_data(address + sizeof(uint8_t), (uint8_t*)&data, sizeof(printStatistics)); @@ -224,9 +230,12 @@ void PrintCounter::tick() { millis_t now = millis(); - static uint32_t update_next; // = 0 + static millis_t update_next; // = 0 if (ELAPSED(now, update_next)) { + update_next = now + updateInterval; + TERN_(DEBUG_PRINTCOUNTER, debug(PSTR("tick"))); + millis_t delta = deltaDuration(); data.printTime += delta; @@ -239,15 +248,15 @@ void PrintCounter::tick() { #if SERVICE_INTERVAL_3 > 0 data.nextService3 -= _MIN(delta, data.nextService3); #endif - - update_next = now + updateInterval * 1000; } - static uint32_t eeprom_next; // = 0 - if (ELAPSED(now, eeprom_next)) { - eeprom_next = now + saveInterval * 1000; - saveStats(); - } + #if PRINTCOUNTER_SAVE_INTERVAL > 0 + static millis_t eeprom_next; // = 0 + if (ELAPSED(now, eeprom_next)) { + eeprom_next = now + saveInterval; + saveStats(); + } + #endif } // @Override @@ -267,21 +276,20 @@ bool PrintCounter::start() { return false; } -// @Override -bool PrintCounter::stop() { +bool PrintCounter::_stop(const bool completed) { TERN_(DEBUG_PRINTCOUNTER, debug(PSTR("stop"))); - if (super::stop()) { - data.finishedPrints++; + const bool did_stop = super::stop(); + if (did_stop) { data.printTime += deltaDuration(); - - if (duration() > data.longestPrint) - data.longestPrint = duration(); - - saveStats(); - return true; + if (completed) { + data.finishedPrints++; + if (duration() > data.longestPrint) + data.longestPrint = duration(); + } } - else return false; + saveStats(); + return did_stop; } // @Override diff --git a/Marlin/src/module/printcounter.h b/Marlin/src/module/printcounter.h index 66d8cbb7b3..4deae45a65 100644 --- a/Marlin/src/module/printcounter.h +++ b/Marlin/src/module/printcounter.h @@ -71,19 +71,18 @@ class PrintCounter: public Stopwatch { * @brief Interval in seconds between counter updates * @details This const value defines what will be the time between each * accumulator update. This is different from the EEPROM save interval. - * - * @note The max value for this option is 60(s), otherwise integer - * overflow will happen. */ - static constexpr uint16_t updateInterval = 10; + static constexpr millis_t updateInterval = SEC_TO_MS(10); - /** - * @brief Interval in seconds between EEPROM saves - * @details This const value defines what will be the time between each - * EEPROM save cycle, the development team recommends to set this value - * no lower than 3600 secs (1 hour). - */ - static constexpr uint16_t saveInterval = 3600; + #if PRINTCOUNTER_SAVE_INTERVAL > 0 + /** + * @brief Interval in seconds between EEPROM saves + * @details This const value defines what will be the time between each + * EEPROM save cycle, the development team recommends to set this value + * no lower than 3600 secs (1 hour). + */ + static constexpr millis_t saveInterval = MIN_TO_MS(PRINTCOUNTER_SAVE_INTERVAL); + #endif /** * @brief Timestamp of the last call to deltaDuration() @@ -176,7 +175,10 @@ class PrintCounter: public Stopwatch { * The following functions are being overridden */ static bool start(); - static bool stop(); + static bool _stop(const bool completed); + static inline bool stop() { return _stop(true); } + static inline bool abort() { return _stop(false); } + static void reset(); #if HAS_SERVICE_INTERVALS diff --git a/Marlin/src/module/probe.cpp b/Marlin/src/module/probe.cpp index cc5c5e8815..94c409eb72 100644 --- a/Marlin/src/module/probe.cpp +++ b/Marlin/src/module/probe.cpp @@ -38,7 +38,7 @@ #include "../gcode/gcode.h" #include "../lcd/marlinui.h" -#include "../MarlinCore.h" // for stop(), disable_e_steppers +#include "../MarlinCore.h" // for stop(), disable_e_steppers(), wait_for_user_response() #if HAS_LEVELING #include "../feature/bedlevel/bedlevel.h" diff --git a/Marlin/src/module/settings.cpp b/Marlin/src/module/settings.cpp index 58cdd5296f..6908635d6e 100644 --- a/Marlin/src/module/settings.cpp +++ b/Marlin/src/module/settings.cpp @@ -36,7 +36,7 @@ */ // Change EEPROM version if the structure changes -#define EEPROM_VERSION "V82" +#define EEPROM_VERSION "V83" #define EEPROM_OFFSET 100 // Check the integrity of data offsets. @@ -176,8 +176,6 @@ static const uint32_t _DMA[] PROGMEM = DEFAULT_MAX_ACCELERATION; static const float _DASU[] PROGMEM = DEFAULT_AXIS_STEPS_PER_UNIT; static const feedRate_t _DMF[] PROGMEM = DEFAULT_MAX_FEEDRATE; -extern const char SP_X_STR[], SP_Y_STR[], SP_Z_STR[], SP_E_STR[]; - /** * Current EEPROM Layout * @@ -457,6 +455,11 @@ typedef struct SettingsDataStruct { #if ENABLED(SOUND_MENU_ITEM) bool buzzer_enabled; #endif + + #if HAS_MULTI_LANGUAGE + uint8_t ui_language; // M414 S + #endif + } SettingsData; //static_assert(sizeof(SettingsData) <= MARLIN_EEPROM_SIZE, "EEPROM too small to contain SettingsData!"); @@ -1382,6 +1385,13 @@ void MarlinSettings::postprocess() { EEPROM_WRITE(ui.buzzer_enabled); #endif + // + // Selected LCD language + // + #if HAS_MULTI_LANGUAGE + EEPROM_WRITE(ui.language); + #endif + // // Report final CRC and Data Size // @@ -2261,6 +2271,18 @@ void MarlinSettings::postprocess() { EEPROM_READ(ui.buzzer_enabled); #endif + // + // Selected LCD language + // + #if HAS_MULTI_LANGUAGE + { + uint8_t ui_language; + EEPROM_READ(ui_language); + if (ui_language >= NUM_LANGUAGES) ui_language = 0; + ui.set_language(ui_language); + } + #endif + // // Validate Final Size and CRC // @@ -3157,7 +3179,7 @@ void MarlinSettings::reset() { #elif ENABLED(AUTO_BED_LEVELING_UBL) - config_heading(forReplay, PSTR(""), false); + config_heading(forReplay, NUL_STR, false); if (!forReplay) { ubl.echo_name(); SERIAL_CHAR(':'); @@ -3846,6 +3868,11 @@ void MarlinSettings::reset() { CONFIG_ECHO_START(); SERIAL_ECHO_SP(2); M553_report(); CONFIG_ECHO_START(); SERIAL_ECHO_SP(2); M554_report(); #endif + + #if HAS_MULTI_LANGUAGE + CONFIG_ECHO_HEADING("UI Language:"); + SERIAL_ECHO_MSG(" M414 S", int(ui.language)); + #endif } #endif // !DISABLE_M503 diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index 85222a3463..e1fd00dcd6 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -27,14 +27,17 @@ // Useful when debugging thermocouples //#define IGNORE_THERMOCOUPLE_ERRORS +#include "../MarlinCore.h" +#include "../HAL/shared/Delay.h" +#include "../lcd/marlinui.h" + #include "temperature.h" #include "endstops.h" - -#include "../MarlinCore.h" #include "planner.h" -#include "../HAL/shared/Delay.h" -#include "../lcd/marlinui.h" +#if ENABLED(EMERGENCY_PARSER) + #include "motion.h" +#endif #if ENABLED(DWIN_CREALITY_LCD) #include "../lcd/dwin/e3v2/dwin.h" @@ -250,7 +253,7 @@ const char str_t_thermal_runaway[] PROGMEM = STR_T_THERMAL_RUNAWAY, */ void Temperature::report_fan_speed(const uint8_t target) { if (target >= FAN_COUNT) return; - PORT_REDIRECT(SERIAL_BOTH); + PORT_REDIRECT(SERIAL_ALL); SERIAL_ECHOLNPAIR("M106 P", target, " S", fan_speed[target]); } #endif @@ -377,6 +380,13 @@ volatile bool Temperature::raw_temps_ready = false; Temperature::soft_pwm_count_fan[FAN_COUNT]; #endif +#if ENABLED(SINGLENOZZLE_STANDBY_TEMP) + uint16_t Temperature::singlenozzle_temp[EXTRUDERS]; + #if HAS_FAN + uint8_t Temperature::singlenozzle_fan_speed[EXTRUDERS]; + #endif +#endif + #if ENABLED(PROBING_HEATERS_OFF) bool Temperature::paused; #endif @@ -1266,7 +1276,7 @@ void Temperature::manage_heater() { // temperature didn't drop at least MIN_COOLING_SLOPE_DEG_CHAMBER_VENT if (next_cool_check_ms_2 == 0 || ELAPSED(ms, next_cool_check_ms_2)) { if (old_temp - temp_chamber.celsius < float(MIN_COOLING_SLOPE_DEG_CHAMBER_VENT)) flag_chamber_excess_heat = true; //the bed is heating the chamber too much - next_cool_check_ms_2 = ms + 1000UL * MIN_COOLING_SLOPE_TIME_CHAMBER_VENT; + next_cool_check_ms_2 = ms + SEC_TO_MS(MIN_COOLING_SLOPE_TIME_CHAMBER_VENT); old_temp = temp_chamber.celsius; } } @@ -2176,7 +2186,6 @@ void Temperature::disable_all_heaters() { #endif - #if ENABLED(PROBING_HEATERS_OFF) void Temperature::pause(const bool p) { @@ -2195,6 +2204,24 @@ void Temperature::disable_all_heaters() { #endif // PROBING_HEATERS_OFF +#if ENABLED(SINGLENOZZLE_STANDBY_TEMP) + + void Temperature::singlenozzle_change(const uint8_t old_tool, const uint8_t new_tool) { + #if HAS_FAN + singlenozzle_fan_speed[old_tool] = fan_speed[0]; + fan_speed[0] = singlenozzle_fan_speed[new_tool]; + #endif + singlenozzle_temp[old_tool] = temp_hotend[0].target; + if (singlenozzle_temp[new_tool] && singlenozzle_temp[new_tool] != singlenozzle_temp[old_tool]) { + setTargetHotend(singlenozzle_temp[new_tool], 0); + TERN_(AUTOTEMP, planner.autotemp_update()); + TERN_(HAS_DISPLAY, set_heating_message(0)); + (void)wait_for_hotend(0, false); // Wait for heating or cooling + } + } + +#endif + #if HAS_MAX6675 #ifndef THERMOCOUPLE_MAX_ERRORS @@ -3096,20 +3123,12 @@ void Temperature::tick() { } #if ENABLED(AUTO_REPORT_TEMPERATURES) - - uint8_t Temperature::auto_report_temp_interval; - millis_t Temperature::next_temp_report_ms; - - void Temperature::auto_report_temperatures() { - if (auto_report_temp_interval && ELAPSED(millis(), next_temp_report_ms)) { - next_temp_report_ms = millis() + 1000UL * auto_report_temp_interval; - PORT_REDIRECT(SERIAL_BOTH); - print_heater_states(active_extruder); - SERIAL_EOL(); - } + Temperature::AutoReportTemp Temperature::auto_reporter; + void Temperature::AutoReportTemp::auto_report() { + print_heater_states(active_extruder); + SERIAL_EOL(); } - - #endif // AUTO_REPORT_TEMPERATURES + #endif #if HAS_HOTEND && HAS_DISPLAY void Temperature::set_heating_message(const uint8_t e) { @@ -3225,7 +3244,7 @@ void Temperature::tick() { // if the temperature did not drop at least MIN_COOLING_SLOPE_DEG if (!next_cool_check_ms || ELAPSED(now, next_cool_check_ms)) { if (old_temp - temp < float(MIN_COOLING_SLOPE_DEG)) break; - next_cool_check_ms = now + 1000UL * MIN_COOLING_SLOPE_TIME; + next_cool_check_ms = now + SEC_TO_MS(MIN_COOLING_SLOPE_TIME); old_temp = temp; } } @@ -3350,7 +3369,7 @@ void Temperature::tick() { // if the temperature did not drop at least MIN_COOLING_SLOPE_DEG_BED if (!next_cool_check_ms || ELAPSED(now, next_cool_check_ms)) { if (old_temp - temp < float(MIN_COOLING_SLOPE_DEG_BED)) break; - next_cool_check_ms = now + 1000UL * MIN_COOLING_SLOPE_TIME_BED; + next_cool_check_ms = now + SEC_TO_MS(MIN_COOLING_SLOPE_TIME_BED); old_temp = temp; } } @@ -3434,7 +3453,7 @@ void Temperature::tick() { SERIAL_ECHOLNPGM("Timed out waiting for probe temperature."); break; } - next_delta_check_ms = now + 1000UL * MIN_DELTA_SLOPE_TIME_PROBE; + next_delta_check_ms = now + SEC_TO_MS(MIN_DELTA_SLOPE_TIME_PROBE); old_temp = temp; } @@ -3539,7 +3558,7 @@ void Temperature::tick() { // if the temperature did not drop at least MIN_COOLING_SLOPE_DEG_CHAMBER if (!next_cool_check_ms || ELAPSED(now, next_cool_check_ms)) { if (old_temp - temp < float(MIN_COOLING_SLOPE_DEG_CHAMBER)) break; - next_cool_check_ms = now + 1000UL * MIN_COOLING_SLOPE_TIME_CHAMBER; + next_cool_check_ms = now + SEC_TO_MS(MIN_COOLING_SLOPE_TIME_CHAMBER); old_temp = temp; } } diff --git a/Marlin/src/module/temperature.h b/Marlin/src/module/temperature.h index f570fe2107..1401e0d354 100644 --- a/Marlin/src/module/temperature.h +++ b/Marlin/src/module/temperature.h @@ -33,6 +33,10 @@ #include "../feature/power.h" #endif +#if ENABLED(AUTO_REPORT_TEMPERATURES) + #include "../libs/autoreport.h" +#endif + #ifndef SOFT_PWM_SCALE #define SOFT_PWM_SCALE 0 #endif @@ -335,6 +339,14 @@ class Temperature { FORCE_INLINE static bool hotEnoughToExtrude(const uint8_t e) { return !tooColdToExtrude(e); } FORCE_INLINE static bool targetHotEnoughToExtrude(const uint8_t e) { return !targetTooColdToExtrude(e); } + #if ENABLED(SINGLENOZZLE_STANDBY_FAN) + static uint16_t singlenozzle_temp[EXTRUDERS]; + #if HAS_FAN + static uint8_t singlenozzle_fan_speed[EXTRUDERS]; + #endif + static void singlenozzle_change(const uint8_t old_tool, const uint8_t new_tool); + #endif + #if HEATER_IDLE_HANDLER // Heater idle handling. Marlin creates one per hotend and one for the heated bed. @@ -786,14 +798,8 @@ class Temperature { #endif ); #if ENABLED(AUTO_REPORT_TEMPERATURES) - static uint8_t auto_report_temp_interval; - static millis_t next_temp_report_ms; - static void auto_report_temperatures(); - static inline void set_auto_report_interval(uint8_t v) { - NOMORE(v, 60); - auto_report_temp_interval = v; - next_temp_report_ms = millis() + 1000UL * v; - } + class AutoReportTemp : public AutoReporter { void auto_report(); }; + static AutoReportTemp auto_reporter; #endif #endif diff --git a/Marlin/src/module/tool_change.cpp b/Marlin/src/module/tool_change.cpp index 95f32f2faa..867ae5d927 100644 --- a/Marlin/src/module/tool_change.cpp +++ b/Marlin/src/module/tool_change.cpp @@ -49,14 +49,6 @@ bool toolchange_extruder_ready[EXTRUDERS]; #endif -#if ENABLED(SINGLENOZZLE_STANDBY_TEMP) - uint16_t singlenozzle_temp[EXTRUDERS]; -#endif - -#if BOTH(HAS_FAN, SINGLENOZZLE_STANDBY_FAN) - uint8_t singlenozzle_fan_speed[EXTRUDERS]; -#endif - #if ENABLED(MAGNETIC_PARKING_EXTRUDER) || defined(EVENT_GCODE_AFTER_TOOLCHANGE) || (ENABLED(PARKING_EXTRUDER) && PARKING_EXTRUDER_SOLENOIDS_DELAY > 0) #include "../gcode/gcode.h" #endif @@ -836,7 +828,7 @@ inline void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_a // Cool down with fan #if HAS_FAN && TOOLCHANGE_FS_FAN >= 0 thermalManager.fan_speed[TOOLCHANGE_FS_FAN] = toolchange_settings.fan_speed; - gcode.dwell(toolchange_settings.fan_time * 1000); + gcode.dwell(SEC_TO_MS(toolchange_settings.fan_time)); thermalManager.fan_speed[TOOLCHANGE_FS_FAN] = 0; #endif @@ -1081,20 +1073,7 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) { const bool should_move = safe_to_move && !no_move && IsRunning(); if (should_move) { - #if BOTH(HAS_FAN, SINGLENOZZLE_STANDBY_FAN) - singlenozzle_fan_speed[old_tool] = thermalManager.fan_speed[0]; - thermalManager.fan_speed[0] = singlenozzle_fan_speed[new_tool]; - #endif - - #if ENABLED(SINGLENOZZLE_STANDBY_TEMP) - singlenozzle_temp[old_tool] = thermalManager.temp_hotend[0].target; - if (singlenozzle_temp[new_tool] && singlenozzle_temp[new_tool] != singlenozzle_temp[old_tool]) { - thermalManager.setTargetHotend(singlenozzle_temp[new_tool], 0); - TERN_(AUTOTEMP, planner.autotemp_update()); - TERN_(HAS_DISPLAY, thermalManager.set_heating_message(0)); - (void)thermalManager.wait_for_hotend(0, false); // Wait for heating or cooling - } - #endif + TERN_(SINGLENOZZLE_STANDBY_TEMP, thermalManager.singlenozzle_change(old_tool, new_tool)); #if ENABLED(TOOLCHANGE_FILAMENT_SWAP) if (should_swap && !too_cold) { @@ -1123,7 +1102,7 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) { // Cool down with fan #if HAS_FAN && TOOLCHANGE_FS_FAN >= 0 thermalManager.fan_speed[TOOLCHANGE_FS_FAN] = toolchange_settings.fan_speed; - gcode.dwell(toolchange_settings.fan_time * 1000); + gcode.dwell(SEC_TO_MS(toolchange_settings.fan_time)); thermalManager.fan_speed[TOOLCHANGE_FS_FAN] = 0; #endif } diff --git a/Marlin/src/module/tool_change.h b/Marlin/src/module/tool_change.h index 6b739604f0..4f88ca7432 100644 --- a/Marlin/src/module/tool_change.h +++ b/Marlin/src/module/tool_change.h @@ -114,14 +114,6 @@ #endif -#if ENABLED(SINGLENOZZLE_STANDBY_TEMP) - extern uint16_t singlenozzle_temp[EXTRUDERS]; -#endif - -#if BOTH(HAS_FAN, SINGLENOZZLE_STANDBY_FAN) - extern uint8_t singlenozzle_fan_speed[EXTRUDERS]; -#endif - TERN_(ELECTROMAGNETIC_SWITCHING_TOOLHEAD, void est_init()); TERN_(SWITCHING_TOOLHEAD, void swt_init()); diff --git a/Marlin/src/pins/lpc1768/pins_BTT_SKR_V1_4.h b/Marlin/src/pins/lpc1768/pins_BTT_SKR_V1_4.h index 2e9aba02cf..dfe86b12b7 100644 --- a/Marlin/src/pins/lpc1768/pins_BTT_SKR_V1_4.h +++ b/Marlin/src/pins/lpc1768/pins_BTT_SKR_V1_4.h @@ -60,6 +60,13 @@ #else #define X_MIN_PIN P1_26 // E0DET #endif +#elif ENABLED(X_DUAL_ENDSTOPS) + #ifndef X_MIN_PIN + #define X_MIN_PIN P1_29 // X-STOP + #endif + #ifndef X_MAX_PIN + #define X_MAX_PIN P1_26 // E0DET + #endif #else #define X_STOP_PIN P1_29 // X-STOP #endif @@ -71,6 +78,13 @@ #else #define Y_MIN_PIN P1_25 // E1DET #endif +#elif ENABLED(Y_DUAL_ENDSTOPS) + #ifndef Y_MIN_PIN + #define Y_MIN_PIN P1_28 // Y-STOP + #endif + #ifndef Y_MAX_PIN + #define Y_MAX_PIN P1_25 // E1DET + #endif #else #define Y_STOP_PIN P1_28 // Y-STOP #endif @@ -82,6 +96,13 @@ #else #define Z_MIN_PIN P1_00 // PWRDET #endif +#elif ENABLED(Z_MULTI_ENDSTOPS) + #ifndef Z_MIN_PIN + #define Z_MIN_PIN P1_27 // Z-STOP + #endif + #ifndef Z_MAX_PIN + #define Z_MAX_PIN P1_00 // PWRDET + #endif #else #ifndef Z_STOP_PIN #define Z_STOP_PIN P1_27 // Z-STOP @@ -337,6 +358,8 @@ #define LCD_PINS_ENABLE EXPA1_05_PIN #define LCD_PINS_D4 EXPA1_07_PIN + #define BEEPER_PIN EXPA1_10_PIN + #elif ENABLED(CR10_STOCKDISPLAY) #define BTN_ENC EXPA1_09_PIN // (58) open-drain #define LCD_PINS_RS EXPA1_04_PIN diff --git a/Marlin/src/pins/lpc1768/pins_MKS_SBASE.h b/Marlin/src/pins/lpc1768/pins_MKS_SBASE.h index ea9748ca54..fbddc66e7c 100644 --- a/Marlin/src/pins/lpc1768/pins_MKS_SBASE.h +++ b/Marlin/src/pins/lpc1768/pins_MKS_SBASE.h @@ -27,7 +27,7 @@ #if defined(MKS_HAS_LPC1769) && NOT_TARGET(MCU_LPC1769) #error "Oops! Make sure you have the LPC1769 environment selected in your IDE." -#elif NOT_TARGET(MKS_HAS_LPC1769, MCU_LPC1768) +#elif !defined(MKS_HAS_LPC1769) && NOT_TARGET(MCU_LPC1768) #error "Oops! Make sure you have the LPC1768 environment selected in your IDE." #endif diff --git a/Marlin/src/pins/lpc1768/pins_RAMPS_RE_ARM.h b/Marlin/src/pins/lpc1768/pins_RAMPS_RE_ARM.h index 7d0f494c34..65840308ca 100644 --- a/Marlin/src/pins/lpc1768/pins_RAMPS_RE_ARM.h +++ b/Marlin/src/pins/lpc1768/pins_RAMPS_RE_ARM.h @@ -325,6 +325,10 @@ #define LCD_PINS_ENABLE P0_18 // J3-10 & AUX-3 (SID, MOSI) #define LCD_PINS_D4 P2_06 // J3-8 & AUX-3 (SCK, CLK) +#elif ENABLED(ZONESTAR_LCD) + + #error "CAUTION! ZONESTAR_LCD on REARM requires wiring modifications. NB. ADCs are not 5V tolerant. Comment out this line to continue." + #elif IS_TFTGLCD_PANEL #if ENABLED(TFTGLCD_PANEL_SPI) diff --git a/Marlin/src/pins/pins.h b/Marlin/src/pins/pins.h index c0995e8826..737c8869d1 100644 --- a/Marlin/src/pins/pins.h +++ b/Marlin/src/pins/pins.h @@ -548,6 +548,8 @@ #include "stm32f1/pins_FLSUN_HISPEED.h" // STM32F1 env:flsun_hispeed #elif MB(BEAST) #include "stm32f1/pins_BEAST.h" // STM32F1 env:STM32F103RE +#elif MB(MINGDA_MPX_ARM_MINI) + #include "stm32f1/pins_MINGDA_MPX_ARM_MINI.h" // STM32F1 env:STM32F103RE // // ARM Cortex-M4F @@ -573,19 +575,19 @@ #elif MB(STEVAL_3DP001V1) #include "stm32f4/pins_STEVAL_3DP001V1.h" // STM32F4 env:STM32F401VE_STEVAL #elif MB(BTT_SKR_PRO_V1_1) - #include "stm32f4/pins_BTT_SKR_PRO_V1_1.h" // STM32F4 env:BIGTREE_SKR_PRO + #include "stm32f4/pins_BTT_SKR_PRO_V1_1.h" // STM32F4 env:BIGTREE_SKR_PRO env:BIGTREE_SKR_PRO_usb_flash_drive #elif MB(BTT_SKR_PRO_V1_2) - #include "stm32f4/pins_BTT_SKR_PRO_V1_2.h" // STM32F4 env:BIGTREE_SKR_PRO + #include "stm32f4/pins_BTT_SKR_PRO_V1_2.h" // STM32F4 env:BIGTREE_SKR_PRO env:BIGTREE_SKR_PRO_usb_flash_drive #elif MB(BTT_GTR_V1_0) - #include "stm32f4/pins_BTT_GTR_V1_0.h" // STM32F4 env:BIGTREE_GTR_V1_0 + #include "stm32f4/pins_BTT_GTR_V1_0.h" // STM32F4 env:BIGTREE_GTR_V1_0 env:BIGTREE_GTR_V1_0_usb_flash_drive #elif MB(BTT_BTT002_V1_0) #include "stm32f4/pins_BTT_BTT002_V1_0.h" // STM32F4 env:BIGTREE_BTT002 #elif MB(LERDGE_K) - #include "stm32f4/pins_LERDGE_K.h" // STM32F4 env:LERDGEK + #include "stm32f4/pins_LERDGE_K.h" // STM32F4 env:LERDGEK env:LERDGEK_usb_flash_drive #elif MB(LERDGE_S) - #include "stm32f4/pins_LERDGE_S.h" // STM32F4 env:LERDGES + #include "stm32f4/pins_LERDGE_S.h" // STM32F4 env:LERDGES env:LERDGES_usb_flash_drive #elif MB(LERDGE_X) - #include "stm32f4/pins_LERDGE_X.h" // STM32F4 env:LERDGEX + #include "stm32f4/pins_LERDGE_X.h" // STM32F4 env:LERDGEX env:LERDGEX_usb_flash_drive #elif MB(VAKE403D) #include "stm32f4/pins_VAKE403D.h" // STM32F4 #elif MB(FYSETC_S6) @@ -599,11 +601,13 @@ #elif MB(MKS_ROBIN_PRO_V2) #include "stm32f4/pins_MKS_ROBIN_PRO_V2.h" // STM32F4 env:mks_robin_pro2 #elif MB(MKS_ROBIN_NANO_V3) - #include "stm32f4/pins_MKS_ROBIN_NANO_V3.h" // STM32F4 env:mks_robin_nano_v3 + #include "stm32f4/pins_MKS_ROBIN_NANO_V3.h" // STM32F4 env:mks_robin_nano_v3 env:mks_robin_nano_v3_usb_flash_drive #elif MB(ANET_ET4) #include "stm32f4/pins_ANET_ET4.h" // STM32F4 env:Anet_ET4_OpenBLT #elif MB(ANET_ET4P) #include "stm32f4/pins_ANET_ET4P.h" // STM32F4 env:Anet_ET4_OpenBLT +#elif MB(FYSETC_CHEETAH_V20) + #include "stm32f4/pins_FYSETC_CHEETAH_V20.h" // STM32F4 env:FYSETC_CHEETAH_V20 // // ARM Cortex M7 diff --git a/Marlin/src/pins/ramps/pins_RAMPS.h b/Marlin/src/pins/ramps/pins_RAMPS.h index ab5711bd5c..5bcd877dcd 100644 --- a/Marlin/src/pins/ramps/pins_RAMPS.h +++ b/Marlin/src/pins/ramps/pins_RAMPS.h @@ -468,6 +468,7 @@ #elif ENABLED(ZONESTAR_LCD) + #error "CAUTION! ZONESTAR_LCD on RAMPS requires wiring modifications. It plugs into AUX2 but GND and 5V need to be swapped. Comment out this line to continue." #define LCD_PINS_RS 64 #define LCD_PINS_ENABLE 44 #define LCD_PINS_D4 63 diff --git a/Marlin/src/pins/sanguino/pins_SANGUINOLOLU_11.h b/Marlin/src/pins/sanguino/pins_SANGUINOLOLU_11.h index ffed79de79..af27159936 100644 --- a/Marlin/src/pins/sanguino/pins_SANGUINOLOLU_11.h +++ b/Marlin/src/pins/sanguino/pins_SANGUINOLOLU_11.h @@ -163,6 +163,8 @@ #define LCD_PINS_RS 17 #define LCD_PINS_ENABLE 16 #define LCD_PINS_D4 11 + #define KILL_PIN 10 + #define BEEPER_PIN 27 #ifndef BOARD_ST7920_DELAY_1 #define BOARD_ST7920_DELAY_1 DELAY_NS(0) diff --git a/Marlin/src/pins/stm32f1/pins_MINGDA_MPX_ARM_MINI.h b/Marlin/src/pins/stm32f1/pins_MINGDA_MPX_ARM_MINI.h new file mode 100644 index 0000000000..429cf14ac5 --- /dev/null +++ b/Marlin/src/pins/stm32f1/pins_MINGDA_MPX_ARM_MINI.h @@ -0,0 +1,176 @@ +/** + * 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 + +/** + * MKS Robin mini (STM32F130VET6) board pin assignments + */ + +#if NOT_TARGET(STM32F1, STM32F1xx) + #error "Oops! Select an STM32F1 board in 'Tools > Board.'" +#elif HOTENDS > 2 || E_STEPPERS > 2 + #error "MKS Robin supports up to 2 hotends / E-steppers. Comment out this line to continue." +#endif + +#define BOARD_INFO_NAME "Mingda MPX_ARM_MINI" + +#define BOARD_NO_NATIVE_USB +#define DISABLE_DEBUG + +// +// EEPROM +// + +/* +//Mingda used an unknown EEPROM chip ATMLH753, so I turned on the emulation below. +//It is connected to EEPROM PB6 PB7 + +#define I2C_EEPROM +#undef NO_EEPROM_SELECTED +#define MARLIN_EEPROM_SIZE 0x1000 // 4KB +#define USE_SHARED_EEPROM 1 // Use Platform-independent Arduino functions for I2C EEPROM +#define E2END 0xFFFF // EEPROM end address AT24C256 (32kB) +*/ + +#if EITHER(NO_EEPROM_SELECTED, FLASH_EEPROM_EMULATION) + #define FLASH_EEPROM_EMULATION + #define EEPROM_PAGE_SIZE 0x800U // 2KB + #define EEPROM_START_ADDRESS (0x8000000UL + (STM32_FLASH_SIZE) * 1024UL - (EEPROM_PAGE_SIZE) * 2UL) + #define MARLIN_EEPROM_SIZE EEPROM_PAGE_SIZE // 2KB +#endif + +#define SPI_DEVICE 2 + +// +// Limit Switches +// +#define X_MIN_PIN PD6 +#define X_MAX_PIN PG15 +#define Y_MIN_PIN PG9 +#define Y_MAX_PIN PG14 +#define Z_MIN_PIN PG10 +#define Z_MAX_PIN PG13 + +#ifndef FIL_RUNOUT_PIN + #define FIL_RUNOUT_PIN PG11 +#endif + +// +// Steppers +// +#define X_ENABLE_PIN PD13 +#define X_STEP_PIN PD12 +#define X_DIR_PIN PD11 + +#define Y_ENABLE_PIN PG4 +#define Y_STEP_PIN PG3 +#define Y_DIR_PIN PG2 + +#define Z_ENABLE_PIN PG7 +#define Z_STEP_PIN PG6 +#define Z_DIR_PIN PG5 + +#define E0_ENABLE_PIN PC7 +#define E0_STEP_PIN PC6 +#define E0_DIR_PIN PG8 + +// +// Temperature Sensors +// +//#define TEMP_0_PIN PF6 // THERM_E0 +//#define TEMP_0_PIN PB3 // E0 K+ +#define TEMP_BED_PIN PF7 // THERM_BED + +#define MAX6675_SS_PIN PB5 +#define MAX6675_SCK_PIN PB3 +#define MAX6675_DO_PIN PB4 +#define MAX6675_MOSI_PIN PA14 + +// +// Heaters / Fans +// +#define HEATER_0_PIN PB0 +#define HEATER_BED_PIN PB1 + +#define FAN_PIN PA0 // FAN + +// +// SD Card +// +#ifndef SDCARD_CONNECTION + #define SDCARD_CONNECTION ONBOARD +#endif + +#define SDIO_SUPPORT +#define SDIO_CLOCK 4500000 // 4.5 MHz +#define SDIO_READ_RETRIES 16 + +#define SD_DETECT_PIN PC5 +#define ONBOARD_SPI_DEVICE 1 // SPI1 +#define ONBOARD_SD_CS_PIN PC10 + +// +// LCD / Controller +// +#define BEEPER_PIN PE4 + +/** + * Note: MKS Robin TFT screens use various TFT controllers. + * If the screen stays white, disable 'LCD_RESET_PIN' + * to let the bootloader init the screen. + */ +#if HAS_FSMC_TFT + /** + * Note: MKS Robin TFT screens use various TFT controllers + * Supported screens are based on the ILI9341, ST7789V and ILI9328 (320x240) + * ILI9488 is not supported + * Define init sequences for other screens in u8g_dev_tft_320x240_upscale_from_128x64.cpp + * + * If the screen stays white, disable 'TFT_RESET_PIN' + * to let the bootloader init the screen. + * + * Setting an 'TFT_RESET_PIN' may cause a flicker when entering the LCD menu + * because Marlin uses the reset as a failsafe to revive a glitchy LCD. + */ + #define TFT_CS_PIN PD7 // NE4 + #define TFT_RS_PIN PG0 // A0 + + #define FSMC_CS_PIN TFT_CS_PIN + #define FSMC_RS_PIN TFT_RS_PIN + + #define LCD_USE_DMA_FSMC // Use DMA transfers to send data to the TFT + #define FSMC_DMA_DEV DMA2 + #define FSMC_DMA_CHANNEL DMA_CH5 + + #define TFT_RESET_PIN PF15 + #define TFT_BACKLIGHT_PIN PF11 + + #define TOUCH_BUTTONS_HW_SPI + #define TOUCH_BUTTONS_HW_SPI_DEVICE 1 +#endif + +#if NEED_TOUCH_PINS + #define TOUCH_CS_PIN PA4 // SPI2_NSS + #define TOUCH_SCK_PIN PA5 // SPI2_SCK + #define TOUCH_MISO_PIN PA6 // SPI2_MISO + #define TOUCH_MOSI_PIN PA7 // SPI2_MOSI +#endif diff --git a/Marlin/src/pins/stm32f4/pins_ANET_ET4.h b/Marlin/src/pins/stm32f4/pins_ANET_ET4.h index a63ed1ddf0..487080f46b 100644 --- a/Marlin/src/pins/stm32f4/pins_ANET_ET4.h +++ b/Marlin/src/pins/stm32f4/pins_ANET_ET4.h @@ -16,7 +16,7 @@ * 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 . + * along with this program. If not, see . * */ diff --git a/Marlin/src/pins/stm32f4/pins_ANET_ET4P.h b/Marlin/src/pins/stm32f4/pins_ANET_ET4P.h index eecabbaf98..f5ebf82a48 100644 --- a/Marlin/src/pins/stm32f4/pins_ANET_ET4P.h +++ b/Marlin/src/pins/stm32f4/pins_ANET_ET4P.h @@ -16,7 +16,7 @@ * 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 . + * along with this program. If not, see . * */ diff --git a/Marlin/src/pins/stm32f4/pins_BTT_GTR_V1_0.h b/Marlin/src/pins/stm32f4/pins_BTT_GTR_V1_0.h index 981064fa4d..cd9d60d2f0 100644 --- a/Marlin/src/pins/stm32f4/pins_BTT_GTR_V1_0.h +++ b/Marlin/src/pins/stm32f4/pins_BTT_GTR_V1_0.h @@ -39,6 +39,7 @@ #define HAS_OTG_USB_HOST_SUPPORT #define TP // Enable to define servo and probe pins +#define M5_EXTENDER // The M5 extender is attached // // Servos @@ -101,11 +102,13 @@ // // Pins on the extender // -//#define X_MIN_PIN PI4 -//#define X2_MIN_PIN PF12 -//#define Y_MIN_PIN PF4 -//#define Y2_MIN_PIN PI7 -//#define Z_MIN_PIN PF6 +#if ENABLED(M5_EXTENDER) + #define X2_STOP_PIN PI4 // M5 M1_STOP + #define Y2_STOP_PIN PF12 // M5 M5_STOP + #define Z2_STOP_PIN PF4 // M5 M2_STOP + #define Z3_STOP_PIN PI7 // M5 M4_STOP + #define Z4_STOP_PIN PF6 // M5 M3_STOP +#endif #if ENABLED(TP) && !defined(Z_MIN_PROBE_PIN) #define Z_MIN_PROBE_PIN PH11 // Z Probe must be PH11 @@ -156,39 +159,43 @@ #define E2_CS_PIN PC12 #endif -#define E3_STEP_PIN PF3 -#define E3_DIR_PIN PG3 -#define E3_ENABLE_PIN PF8 -#ifndef E3_CS_PIN - #define E3_CS_PIN PG4 -#endif +#if ENABLED(M5_EXTENDER) -#define E4_STEP_PIN PD14 -#define E4_DIR_PIN PD11 -#define E4_ENABLE_PIN PG2 -#ifndef E4_CS_PIN - #define E4_CS_PIN PE15 -#endif + #define E3_STEP_PIN PF3 + #define E3_DIR_PIN PG3 + #define E3_ENABLE_PIN PF8 + #ifndef E3_CS_PIN + #define E3_CS_PIN PG4 + #endif -#define E5_STEP_PIN PE12 -#define E5_DIR_PIN PE10 -#define E5_ENABLE_PIN PF14 -#ifndef E5_CS_PIN - #define E5_CS_PIN PE7 -#endif + #define E4_STEP_PIN PD14 + #define E4_DIR_PIN PD11 + #define E4_ENABLE_PIN PG2 + #ifndef E4_CS_PIN + #define E4_CS_PIN PE15 + #endif -#define E6_STEP_PIN PG0 -#define E6_DIR_PIN PG1 -#define E6_ENABLE_PIN PE8 -#ifndef E6_CS_PIN - #define E6_CS_PIN PF15 -#endif + #define E5_STEP_PIN PE12 + #define E5_DIR_PIN PE10 + #define E5_ENABLE_PIN PF14 + #ifndef E5_CS_PIN + #define E5_CS_PIN PE7 + #endif + + #define E6_STEP_PIN PG0 + #define E6_DIR_PIN PG1 + #define E6_ENABLE_PIN PE8 + #ifndef E6_CS_PIN + #define E6_CS_PIN PF15 + #endif + + #define E7_STEP_PIN PH12 + #define E7_DIR_PIN PH15 + #define E7_ENABLE_PIN PI0 + #ifndef E7_CS_PIN + #define E7_CS_PIN PH14 + #endif -#define E7_STEP_PIN PH12 -#define E7_DIR_PIN PH15 -#define E7_ENABLE_PIN PI0 -#ifndef E7_CS_PIN - #define E7_CS_PIN PH14 #endif // @@ -222,11 +229,11 @@ //#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 - //#define E5_HARDWARE_SERIAL Serial1 - //#define E6_HARDWARE_SERIAL Serial1 - //#define E7_HARDWARE_SERIAL Serial1 + //#define E3_HARDWARE_SERIAL Serial1 // M5 MOTOR 1 + //#define E4_HARDWARE_SERIAL Serial1 // M5 MOTOR 2 + //#define E5_HARDWARE_SERIAL Serial1 // M5 MOTOR 3 + //#define E6_HARDWARE_SERIAL Serial1 // M5 MOTOR 4 + //#define E7_HARDWARE_SERIAL Serial1 // M5 MOTOR 5 // // Software serial @@ -249,20 +256,22 @@ #define E2_SERIAL_TX_PIN PC12 #define E2_SERIAL_RX_PIN PC12 - #define E3_SERIAL_TX_PIN PG4 - #define E3_SERIAL_RX_PIN PG4 + #if ENABLED(M5_EXTENDER) + #define E3_SERIAL_TX_PIN PG4 + #define E3_SERIAL_RX_PIN PG4 - #define E4_SERIAL_TX_PIN PE15 - #define E4_SERIAL_RX_PIN PE15 + #define E4_SERIAL_TX_PIN PE15 + #define E4_SERIAL_RX_PIN PE15 - #define E5_SERIAL_TX_PIN PE7 - #define E5_SERIAL_RX_PIN PE7 + #define E5_SERIAL_TX_PIN PE7 + #define E5_SERIAL_RX_PIN PE7 - #define E6_SERIAL_TX_PIN PF15 - #define E6_SERIAL_RX_PIN PF15 + #define E6_SERIAL_TX_PIN PF15 + #define E6_SERIAL_RX_PIN PF15 - #define E7_SERIAL_TX_PIN PH14 - #define E7_SERIAL_RX_PIN PH14 + #define E7_SERIAL_TX_PIN PH14 + #define E7_SERIAL_RX_PIN PH14 + #endif // Reduce baud rate to improve software serial reliability #define TMC_BAUD_RATE 19200 @@ -275,11 +284,13 @@ #define TEMP_1_PIN PC2 // T2 <-> E1 #define TEMP_2_PIN PC3 // T3 <-> E2 -#define TEMP_3_PIN PA3 // T4 <-> E3 -#define TEMP_4_PIN PF9 // T5 <-> E4 -#define TEMP_5_PIN PF10 // T6 <-> E5 -#define TEMP_6_PIN PF7 // T7 <-> E6 -#define TEMP_7_PIN PF5 // T8 <-> E7 +#if ENABLED(M5_EXTENDER) + #define TEMP_3_PIN PA3 // M5 TEMP1 + #define TEMP_4_PIN PF9 // M5 TEMP2 + #define TEMP_5_PIN PF10 // M5 TEMP3 + #define TEMP_6_PIN PF7 // M5 TEMP4 + #define TEMP_7_PIN PF5 // M5 TEMP5 +#endif #define TEMP_BED_PIN PC0 // T0 <-> Bed @@ -289,8 +300,8 @@ #define THERMO_SCK_PIN PI1 // SCK #define THERMO_DO_PIN PI2 // MISO -#define THERMO_CS1_PIN PH9 // CS1 -#define THERMO_CS2_PIN PH2 // CS2 +#define THERMO_CS1_PIN PH9 // GTR K-TEMP +#define THERMO_CS2_PIN PH2 // M5 K-TEMP #define MAX6675_SS_PIN THERMO_CS1_PIN #define MAX6675_SS2_PIN THERMO_CS2_PIN @@ -304,11 +315,13 @@ #define HEATER_1_PIN PA1 // Heater1 #define HEATER_2_PIN PB0 // Heater2 -#define HEATER_3_PIN PD15 // Heater3 -#define HEATER_4_PIN PD13 // Heater4 -#define HEATER_5_PIN PD12 // Heater5 -#define HEATER_6_PIN PE13 // Heater6 -#define HEATER_7_PIN PI6 // Heater7 +#if ENABLED(M5_EXTENDER) + #define HEATER_3_PIN PD15 // M5 HEAT1 + #define HEATER_4_PIN PD13 // M5 HEAT2 + #define HEATER_5_PIN PD12 // M5 HEAT3 + #define HEATER_6_PIN PE13 // M5 HEAT4 + #define HEATER_7_PIN PI6 // M5 HEAT5 +#endif #define HEATER_BED_PIN PA2 // Hotbed @@ -316,11 +329,13 @@ #define FAN1_PIN PE6 // Fan1 #define FAN2_PIN PC8 // Fan2 -#define FAN3_PIN PI5 // Fan3 -#define FAN4_PIN PE9 // Fan4 -#define FAN5_PIN PE11 // Fan5 -//#define FAN6_PIN PC9 // Fan6 -//#define FAN7_PIN PE14 // Fan7 +#if ENABLED(M5_EXTENDER) + #define FAN3_PIN PI5 // M5 FAN1 + #define FAN4_PIN PE9 // M5 FAN2 + #define FAN5_PIN PE11 // M5 FAN3 + //#define FAN6_PIN PC9 // M5 FAN4 + //#define FAN7_PIN PE14 // M5 FAN5 +#endif #ifndef SDCARD_CONNECTION #define SDCARD_CONNECTION ONBOARD @@ -456,3 +471,4 @@ #endif // HAS_WIRED_LCD #undef TP +#undef M5_EXTENDER diff --git a/Marlin/src/pins/stm32f4/pins_FYSETC_CHEETAH_V20.h b/Marlin/src/pins/stm32f4/pins_FYSETC_CHEETAH_V20.h new file mode 100644 index 0000000000..18e689d1d9 --- /dev/null +++ b/Marlin/src/pins/stm32f4/pins_FYSETC_CHEETAH_V20.h @@ -0,0 +1,271 @@ +/** + * 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 + +#if NOT_TARGET(STM32F4) + #error "Oops! Select an STM32F4 board in 'Tools > Board.'" +#endif + +#define DEFAULT_MACHINE_NAME "3D Printer" + +#define BOARD_INFO_NAME "FYSETC Cheetah V2.0" +#define BOARD_WEBSITE_URL "fysetc.com" + +// USB Flash Drive support +//#define HAS_OTG_USB_HOST_SUPPORT + +// Ignore temp readings during development. +//#define BOGUS_TEMPERATURE_GRACE_PERIOD 2000 + +#if EITHER(NO_EEPROM_SELECTED, FLASH_EEPROM_EMULATION) + #define FLASH_EEPROM_EMULATION + #define FLASH_EEPROM_LEVELING + + #define FLASH_SECTOR 2 + #define FLASH_UNIT_SIZE 0x4000 // 16k + #define FLASH_ADDRESS_START 0x8008000 +#endif + +// +// Z Probe +// +#if ENABLED(BLTOUCH) + #error "You need to set jumper to 5v for Bltouch, then comment out this line to proceed." + #define SERVO0_PIN PA0 +#elif !defined(Z_MIN_PROBE_PIN) + #define Z_MIN_PROBE_PIN PA0 +#endif + +// +// Limit Switches +// +#define X_STOP_PIN PB4 +#define Y_STOP_PIN PB3 +#define Z_STOP_PIN PB1 + +// +// Filament runout +// +#define FIL_RUNOUT_PIN PB5 + +// +// Steppers +// +#define X_STEP_PIN PC0 +#define X_DIR_PIN PC1 +#define X_ENABLE_PIN PA8 + +#define Y_STEP_PIN PC14 +#define Y_DIR_PIN PC13 +#define Y_ENABLE_PIN PC15 + +#define Z_STEP_PIN PB9 +#define Z_DIR_PIN PB8 +#define Z_ENABLE_PIN PC2 + +#define E0_STEP_PIN PB2 +#define E0_DIR_PIN PA15 +#define E0_ENABLE_PIN PD2 + +#if HAS_TMC_UART + #define X_HARDWARE_SERIAL Serial2 + #define Y_HARDWARE_SERIAL Serial2 + #define Z_HARDWARE_SERIAL Serial2 + #define E0_HARDWARE_SERIAL Serial2 + + // Default TMC slave addresses + #ifndef X_SLAVE_ADDRESS + #define X_SLAVE_ADDRESS 0 + #endif + #ifndef Y_SLAVE_ADDRESS + #define Y_SLAVE_ADDRESS 2 + #endif + #ifndef Z_SLAVE_ADDRESS + #define Z_SLAVE_ADDRESS 1 + #endif + #ifndef E0_SLAVE_ADDRESS + #define E0_SLAVE_ADDRESS 3 + #endif +#endif + +// +// Heaters / Fans +// +#define HEATER_0_PIN PC6 +#define HEATER_BED_PIN PC7 +#ifndef FAN_PIN + #define FAN_PIN PA1 +#endif +#define FAN1_PIN PC8 + +// +// Temperature Sensors +// +#define TEMP_BED_PIN PC5 // Analog Input +#define TEMP_0_PIN PC4 // Analog Input + +// +// Misc. Functions +// +#define SDSS PA4 +#define SD_DETECT_PIN PC3 + +#ifndef RGB_LED_R_PIN + #define RGB_LED_R_PIN PB0 +#endif +#ifndef RGB_LED_G_PIN + #define RGB_LED_G_PIN PB7 +#endif +#ifndef RGB_LED_B_PIN + #define RGB_LED_B_PIN PB6 +#endif + +/** + * _____ _____ + * 5V | 1 2 | GND 5V | 1 2 | GND + * RESET | 3 4 | PC3 (SD_DETECT) (LCD_D7) PB7 | 3 4 | PB6 (LCD_D6) + * (SD_MOSI) PA7 5 6 | PC11 (BTN_EN2) (LCD_D5) PB14 5 6 | PB13 (LCD_D4) + * (SD_SS) PA4 | 7 8 | PC10 (BTN_EN1) (LCD_RS) PB12 | 7 8 | PB15 (LCD_EN) + * (SD_SCK) PA5 | 9 10| PA6 (SD_MISO) (BTN_ENC) PC12 | 9 10| PC9 (BEEPER) + * ----- ----- + * EXP2 EXP1 + */ + +/** +* _____ +* (BEEPER) PC9 | 1 2 | PC12 (BTN_ENC) +* (BTN_EN1) PC10 | 3 4 | PB14 (LCD_D5/MISO) +* (BTN_EN2) PC11 5 6 | PB13 (LCD_D4/SCK) +* (LCD_RS) PB12 | 7 8 | PB15 (LCD_EN/MOSI) +* GND | 9 10| 5V +* ----- +* EXP3 +*/ + +#define EXPA1_03_PIN PB7 +#define EXPA1_04_PIN PB6 +#define EXPA1_05_PIN PB14 +#define EXPA1_06_PIN PB13 +#define EXPA1_07_PIN PB12 +#define EXPA1_08_PIN PB15 +#define EXPA1_09_PIN PC12 +#define EXPA1_10_PIN PC9 + +#define EXPA2_03_PIN -1 +#define EXPA2_04_PIN PC3 +#define EXPA2_05_PIN PA7 +#define EXPA2_06_PIN PC11 +#define EXPA2_07_PIN PA4 +#define EXPA2_08_PIN PC10 +#define EXPA2_09_PIN PA5 +#define EXPA2_10_PIN PA6 + +#if HAS_WIRED_LCD + + #define BEEPER_PIN EXPA1_10_PIN + #define BTN_ENC EXPA1_09_PIN + + #if ENABLED(CR10_STOCKDISPLAY) + + #define LCD_PINS_RS EXPA1_07_PIN + + #define BTN_EN1 EXPA2_08_PIN + #define BTN_EN2 EXPA2_06_PIN + + #define LCD_PINS_ENABLE EXPA1_08_PIN + #define LCD_PINS_D4 EXPA1_06_PIN + + // CR10_STOCKDISPLAY default timing is too fast + #undef BOARD_ST7920_DELAY_1 + #undef BOARD_ST7920_DELAY_2 + #undef BOARD_ST7920_DELAY_3 + + #elif ENABLED(MKS_MINI_12864) + + #define DOGLCD_A0 EXPA1_04_PIN + #define DOGLCD_CS EXPA1_05_PIN + #define BTN_EN1 EXPA2_08_PIN + #define BTN_EN2 EXPA2_06_PIN + + #else + + #define LCD_PINS_RS EXPA1_07_PIN + + #define BTN_EN1 EXPA2_06_PIN + #define BTN_EN2 EXPA2_08_PIN + + #define LCD_PINS_ENABLE EXPA1_08_PIN + #define LCD_PINS_D4 EXPA1_06_PIN + + #if ENABLED(FYSETC_MINI_12864) + #define DOGLCD_CS EXPA1_08_PIN + #define DOGLCD_A0 EXPA1_07_PIN + //#define LCD_BACKLIGHT_PIN -1 + #define LCD_RESET_PIN EXPA1_06_PIN // 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 + #define RGB_LED_R_PIN EXPA1_05_PIN + #endif + #ifndef RGB_LED_G_PIN + #define RGB_LED_G_PIN EXPA1_04_PIN + #endif + #ifndef RGB_LED_B_PIN + #define RGB_LED_B_PIN EXPA1_03_PIN + #endif + #elif ENABLED(FYSETC_MINI_12864_2_1) + #define NEOPIXEL_PIN EXPA1_05_PIN + #endif + #endif // !FYSETC_MINI_12864 + + #if IS_ULTIPANEL + #define LCD_PINS_D5 EXPA1_05_PIN + #define LCD_PINS_D6 EXPA1_04_PIN + #define LCD_PINS_D7 EXPA1_03_PIN + + #if ENABLED(REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER) + #define BTN_ENC_EN LCD_PINS_D7 // Detect the presence of the encoder + #endif + + #endif + + #endif + +#endif // HAS_WIRED_LCD + +// Alter timing for graphical display +#if HAS_MARLINUI_U8GLIB + #ifndef BOARD_ST7920_DELAY_1 + #define BOARD_ST7920_DELAY_1 DELAY_NS(96) + #endif + #ifndef BOARD_ST7920_DELAY_2 + #define BOARD_ST7920_DELAY_2 DELAY_NS(48) + #endif + #ifndef BOARD_ST7920_DELAY_3 + #define BOARD_ST7920_DELAY_3 DELAY_NS(600) + #endif +#endif + +#if ENABLED(TOUCH_UI_FTDI_EVE) + #define BEEPER_PIN EXPA1_10_PIN + #define CLCD_MOD_RESET EXPA2_08_PIN + #define CLCD_SPI_CS EXPA2_06_PIN +#endif diff --git a/Marlin/src/pins/stm32f4/pins_LERDGE_K.h b/Marlin/src/pins/stm32f4/pins_LERDGE_K.h index 18cbdeaaf5..bf6df03562 100644 --- a/Marlin/src/pins/stm32f4/pins_LERDGE_K.h +++ b/Marlin/src/pins/stm32f4/pins_LERDGE_K.h @@ -29,6 +29,9 @@ #define I2C_EEPROM +// USB Flash Drive support +#define HAS_OTG_USB_HOST_SUPPORT + // // Servos // diff --git a/Marlin/src/pins/stm32f4/pins_LERDGE_S.h b/Marlin/src/pins/stm32f4/pins_LERDGE_S.h index 486aabfd8e..c6cfa98831 100644 --- a/Marlin/src/pins/stm32f4/pins_LERDGE_S.h +++ b/Marlin/src/pins/stm32f4/pins_LERDGE_S.h @@ -32,6 +32,9 @@ //#define I2C_EEPROM +// USB Flash Drive support +#define HAS_OTG_USB_HOST_SUPPORT + // // Servos // diff --git a/Marlin/src/pins/stm32f4/pins_LERDGE_X.h b/Marlin/src/pins/stm32f4/pins_LERDGE_X.h index c73b9927ac..606d932c57 100644 --- a/Marlin/src/pins/stm32f4/pins_LERDGE_X.h +++ b/Marlin/src/pins/stm32f4/pins_LERDGE_X.h @@ -32,6 +32,9 @@ #define I2C_EEPROM +// USB Flash Drive support +#define HAS_OTG_USB_HOST_SUPPORT + // // Servos // diff --git a/Marlin/src/pins/stm32f4/pins_MKS_ROBIN_NANO_V3.h b/Marlin/src/pins/stm32f4/pins_MKS_ROBIN_NANO_V3.h index 47997c4677..49ee420aae 100644 --- a/Marlin/src/pins/stm32f4/pins_MKS_ROBIN_NANO_V3.h +++ b/Marlin/src/pins/stm32f4/pins_MKS_ROBIN_NANO_V3.h @@ -16,7 +16,7 @@ * 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 . + * along with this program. If not, see . * */ #pragma once diff --git a/Marlin/src/sd/cardreader.cpp b/Marlin/src/sd/cardreader.cpp index 7b162f7343..e3732e5ef8 100644 --- a/Marlin/src/sd/cardreader.cpp +++ b/Marlin/src/sd/cardreader.cpp @@ -57,6 +57,11 @@ #include "../core/debug_out.h" #include "../libs/hex_print.h" +// extern + +PGMSTR(M23_STR, "M23 %s"); +PGMSTR(M24_STR, "M24"); + // public: card_flags_t CardReader::flag; @@ -481,7 +486,6 @@ void CardReader::release() { */ void CardReader::openAndPrintFile(const char *name) { char cmd[4 + strlen(name) + 1 + 3 + 1]; // Room for "M23 ", filename, "\n", "M24", and null - extern const char M23_STR[]; sprintf_P(cmd, M23_STR, name); for (char *c = &cmd[4]; *c; c++) *c = tolower(*c); strcat_P(cmd, PSTR("\nM24")); @@ -546,12 +550,11 @@ void openFailed(const char * const fname) { void announceOpen(const uint8_t doing, const char * const path) { if (doing) { - PORT_REDIRECT(SERIAL_BOTH); + PORT_REDIRECT(SERIAL_ALL); SERIAL_ECHO_START(); SERIAL_ECHOPGM("Now "); serialprintPGM(doing == 1 ? PSTR("doing") : PSTR("fresh")); SERIAL_ECHOLNPAIR(" file: ", path); - PORT_RESTORE(); } } @@ -613,10 +616,11 @@ void CardReader::openFileRead(char * const path, const uint8_t subcall_type/*=0* filesize = file.fileSize(); sdpos = 0; - PORT_REDIRECT(SERIAL_BOTH); - SERIAL_ECHOLNPAIR(STR_SD_FILE_OPENED, fname, STR_SD_SIZE, filesize); - SERIAL_ECHOLNPGM(STR_SD_FILE_SELECTED); - PORT_RESTORE(); + { // Don't remove this block, as the PORT_REDIRECT is a RAII + PORT_REDIRECT(SERIAL_ALL); + SERIAL_ECHOLNPAIR(STR_SD_FILE_OPENED, fname, STR_SD_SIZE, filesize); + SERIAL_ECHOLNPGM(STR_SD_FILE_SELECTED); + } selectFileByName(fname); ui.set_status(longFilename[0] ? longFilename : fname); @@ -1222,21 +1226,10 @@ void CardReader::fileHasFinished() { } #if ENABLED(AUTO_REPORT_SD_STATUS) - uint8_t CardReader::auto_report_sd_interval = 0; - millis_t CardReader::next_sd_report_ms; - #if HAS_MULTI_SERIAL - int8_t CardReader::auto_report_port; - #endif - - void CardReader::auto_report_sd_status() { - millis_t current_ms = millis(); - if (auto_report_sd_interval && ELAPSED(current_ms, next_sd_report_ms)) { - next_sd_report_ms = current_ms + 1000UL * auto_report_sd_interval; - PORT_REDIRECT(auto_report_port); - report_status(); - } - } -#endif // AUTO_REPORT_SD_STATUS + TERN_(HAS_MULTI_SERIAL, serial_index_t CardReader::auto_report_port); + CardReader::AutoReportSD CardReader::auto_reporter; + void CardReader::AutoReportSD::auto_report() { report_status(); } +#endif #if ENABLED(POWER_LOSS_RECOVERY) diff --git a/Marlin/src/sd/cardreader.h b/Marlin/src/sd/cardreader.h index b775d8a873..b10a5acd0d 100644 --- a/Marlin/src/sd/cardreader.h +++ b/Marlin/src/sd/cardreader.h @@ -27,6 +27,8 @@ #if ENABLED(SDSUPPORT) +extern const char M23_STR[], M24_STR[]; + #if BOTH(SDCARD_SORT_ALPHA, SDSORT_DYNAMIC_RAM) #define SD_RESORT 1 #endif @@ -57,6 +59,10 @@ typedef struct { ; } card_flags_t; +#if ENABLED(AUTO_REPORT_SD_STATUS) + #include "../libs/autoreport.h" +#endif + class CardReader { public: static card_flags_t flag; // Flags (above) @@ -170,13 +176,16 @@ public: static Sd2Card& getSd2Card() { return sd2card; } #if ENABLED(AUTO_REPORT_SD_STATUS) - static void auto_report_sd_status(); - static inline void set_auto_report_interval(uint8_t v) { - TERN_(HAS_MULTI_SERIAL, auto_report_port = serial_port_index); - NOMORE(v, 60); - auto_report_sd_interval = v; - next_sd_report_ms = millis() + 1000UL * v; - } + // + // SD Auto Reporting + // + #if HAS_MULTI_SERIAL + static serial_index_t auto_report_port; + #else + static constexpr serial_index_t auto_report_port = 0; + #endif + class AutoReportSD : public AutoReporter { void auto_report(); }; + static AutoReportSD auto_reporter; #endif private: @@ -258,17 +267,6 @@ private: static char proc_filenames[SD_PROCEDURE_DEPTH][MAXPATHNAMELENGTH]; #endif - // - // SD Auto Reporting - // - #if ENABLED(AUTO_REPORT_SD_STATUS) - static uint8_t auto_report_sd_interval; - static millis_t next_sd_report_ms; - #if HAS_MULTI_SERIAL - static int8_t auto_report_port; - #endif - #endif - // // Directory items // diff --git a/Marlin/src/sd/usb_flashdrive/lib-uhs3/UHS_host/UHS_macros.h b/Marlin/src/sd/usb_flashdrive/lib-uhs3/UHS_host/UHS_macros.h index c5458208d2..fb2e8b3871 100644 --- a/Marlin/src/sd/usb_flashdrive/lib-uhs3/UHS_host/UHS_macros.h +++ b/Marlin/src/sd/usb_flashdrive/lib-uhs3/UHS_host/UHS_macros.h @@ -144,169 +144,7 @@ e-mail : support@circuitsathome.com #define UHS_GET_DPI(x) (x) #endif -#ifndef __AVR__ -#ifndef __PGMSPACE_H_ -// This define should prevent reading the system pgmspace.h if included elsewhere -// This is not normally needed. -#define __PGMSPACE_H_ 1 -#endif - -#ifndef PROGMEM -#define PROGMEM -#endif -#ifndef PGM_P -#define PGM_P const char * -#endif -#ifndef PSTR -#define PSTR(str) (str) -#endif -#ifndef F -#define F(str) (str) -#endif -#ifndef _SFR_BYTE -#define _SFR_BYTE(n) (n) -#endif -#ifndef memchr_P -#define memchr_P(str, c, len) memchr((str), (c), (len)) -#endif -#ifndef memcmp_P -#define memcmp_P(a, b, n) memcmp((a), (b), (n)) -#endif -#ifndef memcpy_P -#define memcpy_P(dest, src, num) memcpy((dest), (src), (num)) -#endif -#ifndef memmem_P -#define memmem_P(a, alen, b, blen) memmem((a), (alen), (b), (blen)) -#endif -#ifndef memrchr_P -#define memrchr_P(str, val, len) memrchr((str), (val), (len)) -#endif -#ifndef strcat_P -#define strcat_P(dest, src) strcat((dest), (src)) -#endif -#ifndef strchr_P -#define strchr_P(str, c) strchr((str), (c)) -#endif -#ifndef strchrnul_P -#define strchrnul_P(str, c) strchrnul((str), (c)) -#endif -#ifndef strcmp_P -#define strcmp_P(a, b) strcmp((a), (b)) -#endif -#ifndef strcpy_P -#define strcpy_P(dest, src) strcpy((dest), (src)) -#endif -#ifndef strcasecmp_P -#define strcasecmp_P(a, b) strcasecmp((a), (b)) -#endif -#ifndef strcasestr_P -#define strcasestr_P(a, b) strcasestr((a), (b)) -#endif -#ifndef strlcat_P -#define strlcat_P(dest, src, len) strlcat((dest), (src), (len)) -#endif -#ifndef strlcpy_P -#define strlcpy_P(dest, src, len) strlcpy((dest), (src), (len)) -#endif -#ifndef strlen_P -#define strlen_P(s) strlen((const char *)(s)) -#endif -#ifndef strnlen_P -#define strnlen_P(str, len) strnlen((str), (len)) -#endif -#ifndef strncmp_P -#define strncmp_P(a, b, n) strncmp((a), (b), (n)) -#endif -#ifndef strncasecmp_P -#define strncasecmp_P(a, b, n) strncasecmp((a), (b), (n)) -#endif -#ifndef strncat_P -#define strncat_P(a, b, n) strncat((a), (b), (n)) -#endif -#ifndef strncpy_P -#define strncpy_P(a, b, n) strncmp((a), (b), (n)) -#endif -#ifndef strpbrk_P -#define strpbrk_P(str, chrs) strpbrk((str), (chrs)) -#endif -#ifndef strrchr_P -#define strrchr_P(str, c) strrchr((str), (c)) -#endif -#ifndef strsep_P -#define strsep_P(strp, delim) strsep((strp), (delim)) -#endif -#ifndef strspn_P -#define strspn_P(str, chrs) strspn((str), (chrs)) -#endif -#ifndef strstr_P -#define strstr_P(a, b) strstr((a), (b)) -#endif -#ifndef sprintf_P -#define sprintf_P(s, ...) sprintf((s), __VA_ARGS__) -#endif -#ifndef vfprintf_P -#define vfprintf_P(s, ...) vfprintf((s), __VA_ARGS__) -#endif -#ifndef printf_P -#define printf_P(...) printf(__VA_ARGS__) -#endif -#ifndef snprintf_P -#define snprintf_P(s, n, ...) ((s), (n), __VA_ARGS__) -#endif -#ifndef vsprintf_P -#define vsprintf_P(s, ...) ((s),__VA_ARGS__) -#endif -#ifndef vsnprintf_P -#define vsnprintf_P(s, n, ...) ((s), (n),__VA_ARGS__) -#endif -#ifndef fprintf_P -#define fprintf_P(s, ...) ((s), __VA_ARGS__) -#endif - -#ifndef pgm_read_byte -#define pgm_read_byte(addr) (*(const unsigned char *)(addr)) -#endif -#ifndef pgm_read_word -#define pgm_read_word(addr) (*(const unsigned short *)(addr)) -#endif -#ifndef pgm_read_dword -#define pgm_read_dword(addr) (*(const unsigned long *)(addr)) -#endif -#ifndef pgm_read_float -#define pgm_read_float(addr) (*(const float *)(addr)) -#endif - -#ifndef pgm_read_byte_near -#define pgm_read_byte_near(addr) pgm_read_byte(addr) -#endif -#ifndef pgm_read_word_near -#define pgm_read_word_near(addr) pgm_read_word(addr) -#endif -#ifndef pgm_read_dword_near -#define pgm_read_dword_near(addr) pgm_read_dword(addr) -#endif -#ifndef pgm_read_float_near -#define pgm_read_float_near(addr) pgm_read_float(addr) -#endif -#ifndef pgm_read_byte_far -#define pgm_read_byte_far(addr) pgm_read_byte(addr) -#endif -#ifndef pgm_read_word_far -#define pgm_read_word_far(addr) pgm_read_word(addr) -#endif -#ifndef pgm_read_dword_far -#define pgm_read_dword_far(addr) pgm_read_dword(addr) -#endif -#ifndef pgm_read_float_far -#define pgm_read_float_far(addr) pgm_read_float(addr) -#endif - -#ifndef pgm_read_pointer -#define pgm_read_pointer -#endif - -#endif - +#include "../../../../HAL/shared/progmem.h" //////////////////////////////////////////////////////////////////////////////// // HANDY MACROS diff --git a/buildroot/share/PlatformIO/boards/FYSETC_CHEETAH_V20.json b/buildroot/share/PlatformIO/boards/FYSETC_CHEETAH_V20.json new file mode 100644 index 0000000000..ff082fdc1f --- /dev/null +++ b/buildroot/share/PlatformIO/boards/FYSETC_CHEETAH_V20.json @@ -0,0 +1,66 @@ +{ + "build": { + "core": "stm32", + "cpu": "cortex-m4", + "extra_flags": "-DSTM32F401xx", + "f_cpu": "84000000L", + "hwids": [ + [ + "0x1EAF", + "0x0003" + ], + [ + "0x0483", + "0x3748" + ] + ], + "ldscript": "stm32f401rc.ld", + "mcu": "stm32f401rct6", + "variant": "FYSETC_CHEETAH_V20" + }, + "debug": { + "jlink_device": "STM32F401RC", + "openocd_target": "stm32f4x", + "svd_path": "STM32F40x.svd", + "tools": { + "stlink": { + "server": { + "arguments": [ + "-f", + "scripts/interface/stlink.cfg", + "-c", + "transport select hla_swd", + "-f", + "scripts/target/stm32f4x.cfg", + "-c", + "reset_config none" + ], + "executable": "bin/openocd", + "package": "tool-openocd" + } + } + } + }, + "frameworks": [ + "arduino", + "stm32cube" + ], + "name": "STM32F401RC (64k RAM. 256k Flash)", + "upload": { + "disable_flushing": false, + "maximum_ram_size": 65536, + "maximum_size": 262144, + "protocol": "stlink", + "protocols": [ + "stlink", + "dfu", + "jlink" + ], + "offset_address": "0x800C000", + "require_upload_port": true, + "use_1200bps_touch": false, + "wait_for_upload_port": false + }, + "url": "https://www.fysetc.com", + "vendor": "Generic" +} diff --git a/buildroot/share/PlatformIO/scripts/common-dependencies.py b/buildroot/share/PlatformIO/scripts/common-dependencies.py index 2f4ad3e502..4500f529a6 100644 --- a/buildroot/share/PlatformIO/scripts/common-dependencies.py +++ b/buildroot/share/PlatformIO/scripts/common-dependencies.py @@ -69,16 +69,23 @@ def add_to_feat_cnf(feature, flines): except: FEATURE_CONFIG[feature] = {} + # Get a reference to the FEATURE_CONFIG under construction feat = FEATURE_CONFIG[feature] - atoms = re.sub(',\\s*', '\n', flines).strip().split('\n') - for dep in atoms: - parts = dep.split('=') + + # Split up passed lines on commas or newlines and iterate + # Add common options to the features config under construction + # For lib_deps replace a previous instance of the same library + atoms = re.sub(r',\\s*', '\n', flines).strip().split('\n') + for line in atoms: + parts = line.split('=') name = parts.pop(0) - rest = '='.join(parts) if name in ['build_flags', 'extra_scripts', 'src_filter', 'lib_ignore']: - feat[name] = rest + feat[name] = '='.join(parts) else: - feat['lib_deps'] += [dep] + for dep in line.split(','): + lib_name = re.sub(r'@([~^]|[<>]=?)?[\d.]+', '', dep.strip()).split('=').pop(0) + lib_re = re.compile('(?!^' + lib_name + '\\b)') + feat['lib_deps'] = list(filter(lib_re.match, feat['lib_deps'])) + [dep] def load_config(): config = configparser.ConfigParser() @@ -185,8 +192,8 @@ def apply_features_config(): blab("Adding src_filter for %s... " % feature) src_filter = ' '.join(env.GetProjectOption('src_filter')) # first we need to remove the references to the same folder - my_srcs = re.findall( r'[+-](<.*?>)', feat['src_filter']) - cur_srcs = re.findall( r'[+-](<.*?>)', src_filter) + my_srcs = re.findall(r'[+-](<.*?>)', feat['src_filter']) + cur_srcs = re.findall(r'[+-](<.*?>)', src_filter) for d in my_srcs: if d in cur_srcs: src_filter = re.sub(r'[+-]' + d, '', src_filter) diff --git a/buildroot/share/PlatformIO/scripts/fysetc_cheetah_v20.py b/buildroot/share/PlatformIO/scripts/fysetc_cheetah_v20.py new file mode 100644 index 0000000000..10471d3753 --- /dev/null +++ b/buildroot/share/PlatformIO/scripts/fysetc_cheetah_v20.py @@ -0,0 +1,9 @@ +import os +Import("env") + +custom_ld_script = os.path.abspath("buildroot/share/PlatformIO/variants/FYSETC_CHEETAH_V20/ldscript.ld") +for i, flag in enumerate(env["LINKFLAGS"]): + if "-Wl,-T" in flag: + env["LINKFLAGS"][i] = "-Wl,-T" + custom_ld_script + elif flag == "-T": + env["LINKFLAGS"][i + 1] = custom_ld_script diff --git a/buildroot/share/PlatformIO/variants/FYSETC_CHEETAH_V20/PeripheralPins.c b/buildroot/share/PlatformIO/variants/FYSETC_CHEETAH_V20/PeripheralPins.c new file mode 100644 index 0000000000..3957069f28 --- /dev/null +++ b/buildroot/share/PlatformIO/variants/FYSETC_CHEETAH_V20/PeripheralPins.c @@ -0,0 +1,266 @@ +/* + ******************************************************************************* + * Copyright (c) 2019, STMicroelectronics + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************* + * Automatically generated from STM32F401R[(B-C)|(D-E)]Tx.xml + */ +#include "Arduino.h" +#include "PeripheralPins.h" + +/* ===== + * Note: Commented lines are alternative possibilities which are not used per default. + * If you change them, you will have to know what you do + * ===== + */ + +//*** ADC *** + +#ifdef HAL_ADC_MODULE_ENABLED +WEAK const PinMap PinMap_ADC[] = { + {PA_0, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 0, 0)}, // ADC1_IN0 + {PA_1, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 1, 0)}, // ADC1_IN1 + {PA_2, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 2, 0)}, // ADC1_IN2 + {PA_3, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 3, 0)}, // ADC1_IN3 + {PA_4, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 4, 0)}, // ADC1_IN4 + {PA_5, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 5, 0)}, // ADC1_IN5 + {PA_6, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 6, 0)}, // ADC1_IN6 + {PA_7, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 7, 0)}, // ADC1_IN7 + {PB_0, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 8, 0)}, // ADC1_IN8 + {PB_1, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 9, 0)}, // ADC1_IN9 + {PC_0, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 10, 0)}, // ADC1_IN10 + {PC_1, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 11, 0)}, // ADC1_IN11 + {PC_2, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 12, 0)}, // ADC1_IN12 + {PC_3, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 13, 0)}, // ADC1_IN13 + {PC_4, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 14, 0)}, // ADC1_IN14 + {PC_5, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 15, 0)}, // ADC1_IN15 + {NC, NP, 0} +}; +#endif + +//*** No DAC *** + +//*** I2C *** + +#ifdef HAL_I2C_MODULE_ENABLED +WEAK const PinMap PinMap_I2C_SDA[] = { + {PB_3, I2C2, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_NOPULL, GPIO_AF9_I2C2)}, + {PB_4, I2C3, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_NOPULL, GPIO_AF9_I2C3)}, + {PB_7, I2C1, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_NOPULL, GPIO_AF4_I2C1)}, + {PB_9, I2C1, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_NOPULL, GPIO_AF4_I2C1)}, + {PC_9, I2C3, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_NOPULL, GPIO_AF4_I2C3)}, + {NC, NP, 0} +}; +#endif + +#ifdef HAL_I2C_MODULE_ENABLED +WEAK const PinMap PinMap_I2C_SCL[] = { + {PA_8, I2C3, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_NOPULL, GPIO_AF4_I2C3)}, + {PB_6, I2C1, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_NOPULL, GPIO_AF4_I2C1)}, + {PB_8, I2C1, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_NOPULL, GPIO_AF4_I2C1)}, + {PB_10, I2C2, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_NOPULL, GPIO_AF4_I2C2)}, + {NC, NP, 0} +}; +#endif + +//*** PWM *** + +#ifdef HAL_TIM_MODULE_ENABLED +WEAK const PinMap PinMap_PWM[] = { + // {PA_0, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM2, 1, 0)}, // TIM2_CH1 + {PA_0, TIM5, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM5, 1, 0)}, // TIM5_CH1 + // {PA_1, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM2, 2, 0)}, // TIM2_CH2 + {PA_1, TIM5, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM5, 2, 0)}, // TIM5_CH2 + // {PA_2, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM2, 3, 0)}, // TIM2_CH3 + {PA_2, TIM5, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM5, 3, 0)}, // TIM5_CH3 + // {PA_2, TIM9, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_TIM9, 1, 0)}, // TIM9_CH1 + // {PA_3, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM2, 4, 0)}, // TIM2_CH4 + {PA_3, TIM5, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM5, 4, 0)}, // TIM5_CH4 + // {PA_3, TIM9, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_TIM9, 2, 0)}, // TIM9_CH2 + {PA_5, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM2, 1, 0)}, // TIM2_CH1 + {PA_6, TIM3, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM3, 1, 0)}, // TIM3_CH1 + // {PA_7, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM1, 1, 1)}, // TIM1_CH1N + {PA_7, TIM3, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM3, 2, 0)}, // TIM3_CH2 + {PA_8, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM1, 1, 0)}, // TIM1_CH1 + {PA_9, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM1, 2, 0)}, // TIM1_CH2 + {PA_10, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM1, 3, 0)}, // TIM1_CH3 + {PA_11, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM1, 4, 0)}, // TIM1_CH4 + {PA_15, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM2, 1, 0)}, // TIM2_CH1 + // {PB_0, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM1, 2, 1)}, // TIM1_CH2N + {PB_0, TIM3, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM3, 3, 0)}, // TIM3_CH3 + // {PB_1, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM1, 3, 1)}, // TIM1_CH3N + {PB_1, TIM3, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM3, 4, 0)}, // TIM3_CH4 + {PB_3, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM2, 2, 0)}, // TIM2_CH2 + {PB_4, TIM3, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM3, 1, 0)}, // TIM3_CH1 + {PB_5, TIM3, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM3, 2, 0)}, // TIM3_CH2 + {PB_6, TIM4, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM4, 1, 0)}, // TIM4_CH1 + {PB_7, TIM4, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM4, 2, 0)}, // TIM4_CH2 + {PB_8, TIM4, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM4, 3, 0)}, // TIM4_CH3 + // {PB_8, TIM10, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_TIM10, 1, 0)}, // TIM10_CH1 + {PB_9, TIM4, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM4, 4, 0)}, // TIM4_CH4 + // {PB_9, TIM11, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_TIM11, 1, 0)}, // TIM11_CH1 + {PB_10, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM2, 3, 0)}, // TIM2_CH3 + {PB_13, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM1, 1, 1)}, // TIM1_CH1N + {PB_14, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM1, 2, 1)}, // TIM1_CH2N + {PB_15, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM1, 3, 1)}, // TIM1_CH3N + {PC_6, TIM3, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM3, 1, 0)}, // TIM3_CH1 + {PC_7, TIM3, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM3, 2, 0)}, // TIM3_CH2 + {PC_8, TIM3, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM3, 3, 0)}, // TIM3_CH3 + {PC_9, TIM3, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM3, 4, 0)}, // TIM3_CH4 + {NC, NP, 0} +}; +#endif + +//*** SERIAL *** + +#ifdef HAL_UART_MODULE_ENABLED +WEAK const PinMap PinMap_UART_TX[] = { + {PA_2, USART2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART2)}, + {PA_9, USART1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART1)}, + {PA_11, USART6, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_USART6)}, + {PB_6, USART1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART1)}, + {PC_6, USART6, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_USART6)}, + {NC, NP, 0} +}; +#endif + +#ifdef HAL_UART_MODULE_ENABLED +WEAK const PinMap PinMap_UART_RX[] = { + {PA_3, USART2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART2)}, + {PA_10, USART1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART1)}, + {PA_12, USART6, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_USART6)}, + {PB_7, USART1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART1)}, + {PC_7, USART6, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_USART6)}, + {NC, NP, 0} +}; +#endif + +#ifdef HAL_UART_MODULE_ENABLED +WEAK const PinMap PinMap_UART_RTS[] = { + {PA_1, USART2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART2)}, + {PA_12, USART1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART1)}, + {NC, NP, 0} +}; +#endif + +#ifdef HAL_UART_MODULE_ENABLED +WEAK const PinMap PinMap_UART_CTS[] = { + {PA_0, USART2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART2)}, + {PA_11, USART1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART1)}, + {NC, NP, 0} +}; +#endif + +//*** SPI *** + +#ifdef HAL_SPI_MODULE_ENABLED +WEAK const PinMap PinMap_SPI_MOSI[] = { + {PA_7, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + // {PB_5, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PB_5, SPI3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF6_SPI3)}, + {PB_15, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, + {PC_3, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, + {PC_12, SPI3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF6_SPI3)}, + {NC, NP, 0} +}; +#endif + +#ifdef HAL_SPI_MODULE_ENABLED +WEAK const PinMap PinMap_SPI_MISO[] = { + {PA_6, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + // {PB_4, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PB_4, SPI3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF6_SPI3)}, + {PB_14, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, + {PC_2, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, + {PC_11, SPI3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF6_SPI3)}, + {NC, NP, 0} +}; +#endif + +#ifdef HAL_SPI_MODULE_ENABLED +WEAK const PinMap PinMap_SPI_SCLK[] = { + {PA_5, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + // {PB_3, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PB_3, SPI3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF6_SPI3)}, + {PB_10, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, + {PB_13, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, + {PC_10, SPI3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF6_SPI3)}, + {NC, NP, 0} +}; +#endif + +#ifdef HAL_SPI_MODULE_ENABLED +WEAK const PinMap PinMap_SPI_SSEL[] = { + {PA_4, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + // {PA_4, SPI3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF6_SPI3)}, + // {PA_15, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PA_15, SPI3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF6_SPI3)}, + {PB_9, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, + {PB_12, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, + {NC, NP, 0} +}; +#endif + +//*** No CAN *** + +//*** No ETHERNET *** + +//*** No QUADSPI *** + +//*** USB *** + +#ifdef HAL_PCD_MODULE_ENABLED +WEAK const PinMap PinMap_USB_OTG_FS[] = { +#ifndef ARDUINO_CoreBoard_F401RC + {PA_8, USB_OTG_FS, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_OTG_FS)}, // USB_OTG_FS_SOF + {PA_9, USB_OTG_FS, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, GPIO_AF_NONE)}, // USB_OTG_FS_VBUS + {PA_10, USB_OTG_FS, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_PULLUP, GPIO_AF10_OTG_FS)}, // USB_OTG_FS_ID +#endif + {PA_11, USB_OTG_FS, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_OTG_FS)}, // USB_OTG_FS_DM + {PA_12, USB_OTG_FS, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_OTG_FS)}, // USB_OTG_FS_DP + {NC, NP, 0} +}; +#endif + +//*** No USB_OTG_HS *** + +//*** SD *** + +#ifdef HAL_SD_MODULE_ENABLED +WEAK const PinMap PinMap_SD[] = { + {PB_8, SDIO, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_SDIO)}, // SDIO_D4 + {PB_9, SDIO, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_SDIO)}, // SDIO_D5 + {PC_6, SDIO, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_SDIO)}, // SDIO_D6 + {PC_7, SDIO, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_SDIO)}, // SDIO_D7 + {PC_8, SDIO, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_SDIO)}, // SDIO_D0 + {PC_9, SDIO, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_SDIO)}, // SDIO_D1 + {PC_10, SDIO, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_SDIO)}, // SDIO_D2 + {PC_11, SDIO, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_SDIO)}, // SDIO_D3 + {PC_12, SDIO, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF12_SDIO)}, // SDIO_CK + {PD_2, SDIO, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF12_SDIO)}, // SDIO_CMD + {NC, NP, 0} +}; +#endif diff --git a/buildroot/share/PlatformIO/variants/FYSETC_CHEETAH_V20/PinNamesVar.h b/buildroot/share/PlatformIO/variants/FYSETC_CHEETAH_V20/PinNamesVar.h new file mode 100644 index 0000000000..e1536bcf30 --- /dev/null +++ b/buildroot/share/PlatformIO/variants/FYSETC_CHEETAH_V20/PinNamesVar.h @@ -0,0 +1,33 @@ +/* SYS_WKUP */ +#ifdef PWR_WAKEUP_PIN1 + SYS_WKUP1 = PA_0, +#endif +#ifdef PWR_WAKEUP_PIN2 + SYS_WKUP2 = NC, +#endif +#ifdef PWR_WAKEUP_PIN3 + SYS_WKUP3 = NC, +#endif +#ifdef PWR_WAKEUP_PIN4 + SYS_WKUP4 = NC, +#endif +#ifdef PWR_WAKEUP_PIN5 + SYS_WKUP5 = NC, +#endif +#ifdef PWR_WAKEUP_PIN6 + SYS_WKUP6 = NC, +#endif +#ifdef PWR_WAKEUP_PIN7 + SYS_WKUP7 = NC, +#endif +#ifdef PWR_WAKEUP_PIN8 + SYS_WKUP8 = NC, +#endif +/* USB */ +#ifdef USBCON + USB_OTG_FS_SOF = PA_8, + USB_OTG_FS_VBUS = PA_9, + USB_OTG_FS_ID = PA_10, + USB_OTG_FS_DM = PA_11, + USB_OTG_FS_DP = PA_12, +#endif \ No newline at end of file diff --git a/buildroot/share/PlatformIO/variants/FYSETC_CHEETAH_V20/hal_conf_custom.h b/buildroot/share/PlatformIO/variants/FYSETC_CHEETAH_V20/hal_conf_custom.h new file mode 100644 index 0000000000..1b9df2b47a --- /dev/null +++ b/buildroot/share/PlatformIO/variants/FYSETC_CHEETAH_V20/hal_conf_custom.h @@ -0,0 +1,496 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_conf.h + * @brief HAL configuration file. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2017 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F4xx_HAL_CONF_CUSTOM +#define __STM32F4xx_HAL_CONF_CUSTOM + +#ifdef __cplusplus +extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* ########################## Module Selection ############################## */ + /** + * @brief This is the list of modules to be used in the HAL driver + */ +#define HAL_MODULE_ENABLED +#define HAL_ADC_MODULE_ENABLED +/* #define HAL_CAN_MODULE_ENABLED */ +/* #define HAL_CAN_LEGACY_MODULE_ENABLED */ +#define HAL_CRC_MODULE_ENABLED +/* #define HAL_CEC_MODULE_ENABLED */ +/* #define HAL_CRYP_MODULE_ENABLED */ +//#define HAL_DAC_MODULE_ENABLED +/* #define HAL_DCMI_MODULE_ENABLED */ +#define HAL_DMA_MODULE_ENABLED +/* #define HAL_DMA2D_MODULE_ENABLED */ +/* #define HAL_ETH_MODULE_ENABLED */ +#define HAL_FLASH_MODULE_ENABLED +/* #define HAL_NAND_MODULE_ENABLED */ +/* #define HAL_NOR_MODULE_ENABLED */ +/* #define HAL_PCCARD_MODULE_ENABLED */ +/* #define HAL_SRAM_MODULE_ENABLED */ +/* #define HAL_SDRAM_MODULE_ENABLED */ +/* #define HAL_HASH_MODULE_ENABLED */ +#define HAL_GPIO_MODULE_ENABLED +/* #define HAL_EXTI_MODULE_ENABLED */ +#define HAL_I2C_MODULE_ENABLED +/* #define HAL_SMBUS_MODULE_ENABLED */ +/* #define HAL_I2S_MODULE_ENABLED */ +#define HAL_IWDG_MODULE_ENABLED +/* #define HAL_LTDC_MODULE_ENABLED */ +/* #define HAL_DSI_MODULE_ENABLED */ +#define HAL_PWR_MODULE_ENABLED +/* #define HAL_QSPI_MODULE_ENABLED */ +#define HAL_RCC_MODULE_ENABLED +/* #define HAL_RNG_MODULE_ENABLED */ +#define HAL_RTC_MODULE_ENABLED +/* #define HAL_SAI_MODULE_ENABLED */ +//#define HAL_SD_MODULE_ENABLED +#define HAL_SPI_MODULE_ENABLED +#define HAL_TIM_MODULE_ENABLED +/* #define HAL_UART_MODULE_ENABLED */ +/* #define HAL_USART_MODULE_ENABLED */ +/* #define HAL_IRDA_MODULE_ENABLED */ +/* #define HAL_SMARTCARD_MODULE_ENABLED */ +/* #define HAL_WWDG_MODULE_ENABLED */ +#define HAL_CORTEX_MODULE_ENABLED +#ifndef HAL_PCD_MODULE_ENABLED + #define HAL_PCD_MODULE_ENABLED //Since STM32 v3.10700.191028 this is automatically added if any type of USB is enabled (as in Arduino IDE) +#endif +/* #define HAL_HCD_MODULE_ENABLED */ +/* #define HAL_FMPI2C_MODULE_ENABLED */ +/* #define HAL_SPDIFRX_MODULE_ENABLED */ +/* #define HAL_DFSDM_MODULE_ENABLED */ +/* #define HAL_LPTIM_MODULE_ENABLED */ +/* #define HAL_MMC_MODULE_ENABLED */ + +/* ########################## HSE/HSI Values adaptation ##################### */ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSE is used as system clock source, directly or through the PLL). + */ +#ifndef HSE_VALUE +#define HSE_VALUE 8000000U /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#ifndef HSE_STARTUP_TIMEOUT +#define HSE_STARTUP_TIMEOUT 100U /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSI is used as system clock source, directly or through the PLL). + */ +#ifndef HSI_VALUE +#define HSI_VALUE 16000000U /*!< Value of the Internal oscillator in Hz */ +#endif /* HSI_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#ifndef LSI_VALUE +#define LSI_VALUE 32000U /*!< LSI Typical Value in Hz */ +#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz +The real value may vary depending on the variations +in voltage and temperature. */ +/** + * @brief External Low Speed oscillator (LSE) value. + */ +#ifndef LSE_VALUE +#define LSE_VALUE 32768U /*!< Value of the External Low Speed oscillator in Hz */ +#endif /* LSE_VALUE */ + +#ifndef LSE_STARTUP_TIMEOUT +#define LSE_STARTUP_TIMEOUT 5000U /*!< Time out for LSE start up, in ms */ +#endif /* LSE_STARTUP_TIMEOUT */ + +/** + * @brief External clock source for I2S peripheral + * This value is used by the I2S HAL module to compute the I2S clock source + * frequency, this source is inserted directly through I2S_CKIN pad. + */ +#ifndef EXTERNAL_CLOCK_VALUE +#define EXTERNAL_CLOCK_VALUE 12288000U /*!< Value of the External oscillator in Hz*/ +#endif /* EXTERNAL_CLOCK_VALUE */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ########################### System Configuration ######################### */ +/** + * @brief This is the HAL system configuration section + */ +#if !defined (VDD_VALUE) +#define VDD_VALUE 3300U /*!< Value of VDD in mv */ +#endif +#if !defined (TICK_INT_PRIORITY) +#define TICK_INT_PRIORITY 0x00U /*!< tick interrupt priority */ +#endif +#if !defined (USE_RTOS) +#define USE_RTOS 0U +#endif +#if !defined (PREFETCH_ENABLE) +#define PREFETCH_ENABLE 1U +#endif +#if !defined (INSTRUCTION_CACHE_ENABLE) +#define INSTRUCTION_CACHE_ENABLE 1U +#endif +#if !defined (DATA_CACHE_ENABLE) +#define DATA_CACHE_ENABLE 1U +#endif + +#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */ +#define USE_HAL_CAN_REGISTER_CALLBACKS 0U /* CAN register callback disabled */ +#define USE_HAL_CEC_REGISTER_CALLBACKS 0U /* CEC register callback disabled */ +#define USE_HAL_CRYP_REGISTER_CALLBACKS 0U /* CRYP register callback disabled */ +#define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */ +#define USE_HAL_DCMI_REGISTER_CALLBACKS 0U /* DCMI register callback disabled */ +#define USE_HAL_DFSDM_REGISTER_CALLBACKS 0U /* DFSDM register callback disabled */ +#define USE_HAL_DMA2D_REGISTER_CALLBACKS 0U /* DMA2D register callback disabled */ +#define USE_HAL_DSI_REGISTER_CALLBACKS 0U /* DSI register callback disabled */ +#define USE_HAL_ETH_REGISTER_CALLBACKS 0U /* ETH register callback disabled */ +#define USE_HAL_HASH_REGISTER_CALLBACKS 0U /* HASH register callback disabled */ +#define USE_HAL_HCD_REGISTER_CALLBACKS 0U /* HCD register callback disabled */ +#define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */ +#define USE_HAL_FMPI2C_REGISTER_CALLBACKS 0U /* FMPI2C register callback disabled */ +#define USE_HAL_I2S_REGISTER_CALLBACKS 0U /* I2S register callback disabled */ +#define USE_HAL_IRDA_REGISTER_CALLBACKS 0U /* IRDA register callback disabled */ +#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U /* LPTIM register callback disabled */ +#define USE_HAL_LTDC_REGISTER_CALLBACKS 0U /* LTDC register callback disabled */ +#define USE_HAL_MMC_REGISTER_CALLBACKS 0U /* MMC register callback disabled */ +#define USE_HAL_NAND_REGISTER_CALLBACKS 0U /* NAND register callback disabled */ +#define USE_HAL_NOR_REGISTER_CALLBACKS 0U /* NOR register callback disabled */ +#define USE_HAL_PCCARD_REGISTER_CALLBACKS 0U /* PCCARD register callback disabled */ +#define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */ +#define USE_HAL_QSPI_REGISTER_CALLBACKS 0U /* QSPI register callback disabled */ +#define USE_HAL_RNG_REGISTER_CALLBACKS 0U /* RNG register callback disabled */ +#define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */ +#define USE_HAL_SAI_REGISTER_CALLBACKS 0U /* SAI register callback disabled */ +#define USE_HAL_SD_REGISTER_CALLBACKS 0U /* SD register callback disabled */ +#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U /* SMARTCARD register callback disabled */ +#define USE_HAL_SDRAM_REGISTER_CALLBACKS 0U /* SDRAM register callback disabled */ +#define USE_HAL_SRAM_REGISTER_CALLBACKS 0U /* SRAM register callback disabled */ +#define USE_HAL_SPDIFRX_REGISTER_CALLBACKS 0U /* SPDIFRX register callback disabled */ +#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U /* SMBUS register callback disabled */ +#define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */ +#define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */ +#define USE_HAL_UART_REGISTER_CALLBACKS 0U /* UART register callback disabled */ +#define USE_HAL_USART_REGISTER_CALLBACKS 0U /* USART register callback disabled */ +#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */ + +/* ########################## Assert Selection ############################## */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ +/* #define USE_FULL_ASSERT 1U */ + +/* ################## Ethernet peripheral configuration ##################### */ + +/* Section 1 : Ethernet peripheral configuration */ + +/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ +#define MAC_ADDR0 2U +#define MAC_ADDR1 0U +#define MAC_ADDR2 0U +#define MAC_ADDR3 0U +#define MAC_ADDR4 0U +#define MAC_ADDR5 0U + +/* Definition of the Ethernet driver buffers size and count */ +#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ +#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ +#define ETH_RXBUFNB ((uint32_t)4U) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ +#define ETH_TXBUFNB ((uint32_t)4U) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ + +/* Section 2: PHY configuration section */ + +/* DP83848_PHY_ADDRESS Address*/ +#define DP83848_PHY_ADDRESS 0x01U +/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ +#define PHY_RESET_DELAY 0x000000FFU +/* PHY Configuration delay */ +#define PHY_CONFIG_DELAY 0x00000FFFU + +#define PHY_READ_TO 0x0000FFFFU +#define PHY_WRITE_TO 0x0000FFFFU + +/* Section 3: Common PHY Registers */ + +#define PHY_BCR ((uint16_t)0x0000) /*!< Transceiver Basic Control Register */ +#define PHY_BSR ((uint16_t)0x0001) /*!< Transceiver Basic Status Register */ + +#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ +#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ +#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ +#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ +#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ +#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ +#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ +#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ +#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ +#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ + +#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ +#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ +#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ + +/* Section 4: Extended PHY Registers */ +#define PHY_SR ((uint16_t)0x10U) /*!< PHY status register Offset */ + +#define PHY_SPEED_STATUS ((uint16_t)0x0002U) /*!< PHY Speed mask */ +#define PHY_DUPLEX_STATUS ((uint16_t)0x0004U) /*!< PHY Duplex mask */ + +/* ################## SPI peripheral configuration ########################## */ + +/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver + * Activated: CRC code is present inside driver + * Deactivated: CRC code cleaned from driver + */ +#ifndef USE_SPI_CRC +#define USE_SPI_CRC 0U +#endif + +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ + +#ifdef HAL_RCC_MODULE_ENABLED +#include "stm32f4xx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED +#include "stm32f4xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_EXTI_MODULE_ENABLED +#include "stm32f4xx_hal_exti.h" +#endif /* HAL_EXTI_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED +#include "stm32f4xx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED +#include "stm32f4xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED +#include "stm32f4xx_hal_adc.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_CAN_MODULE_ENABLED +#include "stm32f4xx_hal_can.h" +#endif /* HAL_CAN_MODULE_ENABLED */ + +#ifdef HAL_CAN_LEGACY_MODULE_ENABLED +#include "stm32f4xx_hal_can_legacy.h" +#endif /* HAL_CAN_LEGACY_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED +#include "stm32f4xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_CRYP_MODULE_ENABLED +#include "stm32f4xx_hal_cryp.h" +#endif /* HAL_CRYP_MODULE_ENABLED */ + +#ifdef HAL_DMA2D_MODULE_ENABLED +#include "stm32f4xx_hal_dma2d.h" +#endif /* HAL_DMA2D_MODULE_ENABLED */ + +#ifdef HAL_DAC_MODULE_ENABLED +#include "stm32f4xx_hal_dac.h" +#endif /* HAL_DAC_MODULE_ENABLED */ + +#ifdef HAL_DCMI_MODULE_ENABLED +#include "stm32f4xx_hal_dcmi.h" +#endif /* HAL_DCMI_MODULE_ENABLED */ + +#ifdef HAL_ETH_MODULE_ENABLED +#include "stm32f4xx_hal_eth.h" +#endif /* HAL_ETH_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED +#include "stm32f4xx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_SRAM_MODULE_ENABLED +#include "stm32f4xx_hal_sram.h" +#endif /* HAL_SRAM_MODULE_ENABLED */ + +#ifdef HAL_NOR_MODULE_ENABLED +#include "stm32f4xx_hal_nor.h" +#endif /* HAL_NOR_MODULE_ENABLED */ + +#ifdef HAL_NAND_MODULE_ENABLED +#include "stm32f4xx_hal_nand.h" +#endif /* HAL_NAND_MODULE_ENABLED */ + +#ifdef HAL_PCCARD_MODULE_ENABLED +#include "stm32f4xx_hal_pccard.h" +#endif /* HAL_PCCARD_MODULE_ENABLED */ + +#ifdef HAL_SDRAM_MODULE_ENABLED +#include "stm32f4xx_hal_sdram.h" +#endif /* HAL_SDRAM_MODULE_ENABLED */ + +#ifdef HAL_HASH_MODULE_ENABLED +#include "stm32f4xx_hal_hash.h" +#endif /* HAL_HASH_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED +#include "stm32f4xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_SMBUS_MODULE_ENABLED +#include "stm32f4xx_hal_smbus.h" +#endif /* HAL_SMBUS_MODULE_ENABLED */ + +#ifdef HAL_I2S_MODULE_ENABLED +#include "stm32f4xx_hal_i2s.h" +#endif /* HAL_I2S_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED +#include "stm32f4xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_LTDC_MODULE_ENABLED +#include "stm32f4xx_hal_ltdc.h" +#endif /* HAL_LTDC_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED +#include "stm32f4xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_RNG_MODULE_ENABLED +#include "stm32f4xx_hal_rng.h" +#endif /* HAL_RNG_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED +#include "stm32f4xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_SAI_MODULE_ENABLED +#include "stm32f4xx_hal_sai.h" +#endif /* HAL_SAI_MODULE_ENABLED */ + +#ifdef HAL_SD_MODULE_ENABLED +#include "stm32f4xx_hal_sd.h" +#endif /* HAL_SD_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED +#include "stm32f4xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED +#include "stm32f4xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED +#include "stm32f4xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED +#include "stm32f4xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED +#include "stm32f4xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED +#include "stm32f4xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED +#include "stm32f4xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED +#include "stm32f4xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +#ifdef HAL_HCD_MODULE_ENABLED +#include "stm32f4xx_hal_hcd.h" +#endif /* HAL_HCD_MODULE_ENABLED */ + +#ifdef HAL_DSI_MODULE_ENABLED +#include "stm32f4xx_hal_dsi.h" +#endif /* HAL_DSI_MODULE_ENABLED */ + +#ifdef HAL_QSPI_MODULE_ENABLED +#include "stm32f4xx_hal_qspi.h" +#endif /* HAL_QSPI_MODULE_ENABLED */ + +#ifdef HAL_CEC_MODULE_ENABLED +#include "stm32f4xx_hal_cec.h" +#endif /* HAL_CEC_MODULE_ENABLED */ + +#ifdef HAL_FMPI2C_MODULE_ENABLED +#include "stm32f4xx_hal_fmpi2c.h" +#endif /* HAL_FMPI2C_MODULE_ENABLED */ + +#ifdef HAL_SPDIFRX_MODULE_ENABLED +#include "stm32f4xx_hal_spdifrx.h" +#endif /* HAL_SPDIFRX_MODULE_ENABLED */ + +#ifdef HAL_DFSDM_MODULE_ENABLED +#include "stm32f4xx_hal_dfsdm.h" +#endif /* HAL_DFSDM_MODULE_ENABLED */ + +#ifdef HAL_LPTIM_MODULE_ENABLED +#include "stm32f4xx_hal_lptim.h" +#endif /* HAL_LPTIM_MODULE_ENABLED */ + +#ifdef HAL_MMC_MODULE_ENABLED +#include "stm32f4xx_hal_mmc.h" +#endif /* HAL_MMC_MODULE_ENABLED */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ +#define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ +void assert_failed(uint8_t *file, uint32_t line); +#else +#define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_HAL_CONF_CUSTOM_H */ + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/buildroot/share/PlatformIO/variants/FYSETC_CHEETAH_V20/ldscript.ld b/buildroot/share/PlatformIO/variants/FYSETC_CHEETAH_V20/ldscript.ld new file mode 100644 index 0000000000..2dbc5177ac --- /dev/null +++ b/buildroot/share/PlatformIO/variants/FYSETC_CHEETAH_V20/ldscript.ld @@ -0,0 +1,187 @@ +/* +***************************************************************************** +** + +** File : LinkerScript.ld +** +** Abstract : Linker script for STM32F401RETx Device with +** 512KByte FLASH, 96KByte RAM +** +** Set heap size, stack size and stack location according +** to application requirements. +** +** Set memory bank area and size if external memory is used. +** +** Target : STMicroelectronics STM32 +** +** +** Distribution: The file is distributed as is, without any warranty +** of any kind. +** +***************************************************************************** +** @attention +** +**

© COPYRIGHT(c) 2014 Ac6

+** +** Redistribution and use in source and binary forms, with or without modification, +** are permitted provided that the following conditions are met: +** 1. Redistributions of source code must retain the above copyright notice, +** this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright notice, +** this list of conditions and the following disclaimer in the documentation +** and/or other materials provided with the distribution. +** 3. Neither the name of Ac6 nor the names of its contributors +** may be used to endorse or promote products derived from this software +** without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +***************************************************************************** +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Highest address of the user mode stack */ +_estack = 0x20010000; /* end of RAM */ + +/* Generate a link error if heap and stack don't fit into RAM */ +_Min_Heap_Size = 0x200;; /* required amount of heap */ +_Min_Stack_Size = 0x400;; /* required amount of stack */ + +/* Specify the memory areas */ +MEMORY +{ +FLASH (rx) : ORIGIN = 0x800C000, LENGTH = 256K +RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K +} + +/* Define output sections */ +SECTIONS +{ + /* The startup code goes first into FLASH */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >FLASH + + /* The program code and other data goes into FLASH */ + .text ALIGN(4): + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + /* Constant data goes into FLASH */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >FLASH + + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH + .ARM : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >FLASH + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH + + /* used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections goes into RAM, load LMA copy after code */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + } >RAM AT> FLASH + + + /* Uninitialized data section */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + + /* User_heap_stack section, used to check that there is enough RAM left */ + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(8); + } >RAM + + + + /* Remove information from the standard libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} \ No newline at end of file diff --git a/buildroot/share/PlatformIO/variants/FYSETC_CHEETAH_V20/variant.cpp b/buildroot/share/PlatformIO/variants/FYSETC_CHEETAH_V20/variant.cpp new file mode 100644 index 0000000000..71f3509ed5 --- /dev/null +++ b/buildroot/share/PlatformIO/variants/FYSETC_CHEETAH_V20/variant.cpp @@ -0,0 +1,238 @@ +/* + Copyright (c) 2011 Arduino. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "pins_arduino.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Digital PinName array +const PinName digitalPin[] = { + PA_0, // Digital pin 0 + PA_1, // Digital pin 1 + PA_2, // Digital pin 2 + PA_3, // Digital pin 3 + PA_4, // Digital pin 4 + PA_5, // Digital pin 5 + PA_6, // Digital pin 6 + PA_7, // Digital pin 7 + PA_8, // Digital pin 8 + PA_9, // Digital pin 9 + PA_10, // Digital pin 10 + PA_11, // Digital pin 11 + PA_12, // Digital pin 12 + PA_13, // Digital pin 13 + PA_14, // Digital pin 14 + PA_15, // Digital pin 15 + + PB_0, // Digital pin 16 + PB_1, // Digital pin 17 + PB_2, // Digital pin 18 + PB_3, // Digital pin 19 + PB_4, // Digital pin 20 + PB_5, // Digital pin 21 + PB_6, // Digital pin 22 + PB_7, // Digital pin 23 + PB_8, // Digital pin 24 + PB_9, // Digital pin 25 + PB_10, // Digital pin 26 + PB_12, // Digital pin 27 + PB_13, // Digital pin 28 + PB_14, // Digital pin 29 + PB_15, // Digital pin 30 + + PC_0, // Digital pin 31 + PC_1, // Digital pin 32 + PC_2, // Digital pin 33 + PC_3, // Digital pin 34 + PC_4, // Digital pin 35 + PC_5, // Digital pin 36 + PC_6, // Digital pin 37 + PC_7, // Digital pin 38 + PC_8, // Digital pin 39 + PC_9, // Digital pin 40 + PC_10, // Digital pin 41 + PC_11, // Digital pin 42 + PC_12, // Digital pin 43 + PC_13, // Digital pin 44 + PC_14, // Digital pin 45 + PC_15, // Digital pin 46 + + PD_2, // Digital pin 47 + + PH_0, // Digital pin 48, used by the external oscillator + PH_1 // Digital pin 49, used by the external oscillator +}; + +// Analog (Ax) pin number array +const uint32_t analogInputPin[] = { + 0, // A0, PA0 + 1, // A1, PA1 + 2, // A2, PA2 + 3, // A3, PA3 + 4, // A4, PA4 + 5, // A5, PA5 + 6, // A6, PA6 + 7, // A7, PA7 + 16, // A8, PB0 + 17, // A9, PB1 + 31, // A10, PC0 + 32, // A11, PC1 + 33, // A12, PC2 + 34, // A13, PC3 + 35, // A14, PC4 + 36 // A15, PC5 +}; + +#ifdef __cplusplus +} +#endif + +// ---------------------------------------------------------------------------- + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * @brief Configures the System clock source, PLL Multiplier and Divider factors, + * AHB/APBx prescalers and Flash settings + * @note This function should be called only once the RCC clock configuration + * is reset to the default reset state (done in SystemInit() function). + * @param None + * @retval None + */ + +/******************************************************************************/ +/* PLL (clocked by HSE) used as System clock source */ +/******************************************************************************/ +static uint8_t SetSysClock_PLL_HSE(uint8_t bypass) +{ + RCC_OscInitTypeDef RCC_OscInitStruct; + RCC_ClkInitTypeDef RCC_ClkInitStruct; + + /* The voltage scaling allows optimizing the power consumption when the device is + clocked below the maximum system frequency, to update the voltage scaling value + regarding system frequency refer to product datasheet. */ + __HAL_RCC_PWR_CLK_ENABLE(); + __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2); + + // Enable HSE oscillator and activate PLL with HSE as source + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; + if (bypass == 0) { + RCC_OscInitStruct.HSEState = RCC_HSE_ON; // External 8 MHz xtal on OSC_IN/OSC_OUT + } else { + RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS; // External 8 MHz clock on OSC_IN + } + + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.PLL.PLLM = HSE_VALUE / 1000000L; // Expects an 8 MHz external clock by default. Redefine HSE_VALUE if not + RCC_OscInitStruct.PLL.PLLN = 336; // VCO output clock = 336 MHz (1 MHz * 336) + RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4; // PLLCLK = 84 MHz (336 MHz / 4) + RCC_OscInitStruct.PLL.PLLQ = 7; // USB clock = 48 MHz (336 MHz / 7) --> OK for USB + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { + return 0; // FAIL + } + + // Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // 84 MHz + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // 84 MHz + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; // 42 MHz + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; // 84 MHz + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) { + return 0; // FAIL + } + + /* Output clock on MCO1 pin(PA8) for debugging purpose */ + /* + if (bypass == 0) + HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, RCC_MCODIV_2); // 4 MHz + else + HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, RCC_MCODIV_1); // 8 MHz + */ + + return 1; // OK +} + +/******************************************************************************/ +/* PLL (clocked by HSI) used as System clock source */ +/******************************************************************************/ +uint8_t SetSysClock_PLL_HSI(void) +{ + RCC_OscInitTypeDef RCC_OscInitStruct; + RCC_ClkInitTypeDef RCC_ClkInitStruct; + + /* The voltage scaling allows optimizing the power consumption when the device is + clocked below the maximum system frequency, to update the voltage scaling value + regarding system frequency refer to product datasheet. */ + __HAL_RCC_PWR_CLK_ENABLE(); + __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2); + + // Enable HSI oscillator and activate PLL with HSI as source + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_HSE; + RCC_OscInitStruct.HSIState = RCC_HSI_ON; + RCC_OscInitStruct.HSEState = RCC_HSE_OFF; + RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; + RCC_OscInitStruct.PLL.PLLM = 16; // VCO input clock = 1 MHz (16 MHz / 16) + RCC_OscInitStruct.PLL.PLLN = 336; // VCO output clock = 336 MHz (1 MHz * 336) + RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4; // PLLCLK = 84 MHz (336 MHz / 4) + RCC_OscInitStruct.PLL.PLLQ = 7; // USB clock = 48 MHz (336 MHz / 7) --> freq is ok but not precise enough + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { + return 0; // FAIL + } + + /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers */ + RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // 84 MHz + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // 84 MHz + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; // 42 MHz + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; // 84 MHz + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) { + return 0; // FAIL + } + + /* Output clock on MCO1 pin(PA8) for debugging purpose */ + //HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSI, RCC_MCODIV_1); // 16 MHz + + return 1; // OK +} + +WEAK void SystemClock_Config(void) +{ + /* 1- If fail try to start with HSE and external xtal */ + if (SetSysClock_PLL_HSE(0) == 0) { + /* 2- Try to start with HSE and external clock */ + if (SetSysClock_PLL_HSE(1) == 0) { + /* 3- If fail start with HSI clock */ + if (SetSysClock_PLL_HSI() == 0) { + Error_Handler(); + } + } + } + /* Output clock on MCO2 pin(PC9) for debugging purpose */ + //HAL_RCC_MCOConfig(RCC_MCO2, RCC_MCO2SOURCE_SYSCLK, RCC_MCODIV_4); +} + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/buildroot/share/PlatformIO/variants/FYSETC_CHEETAH_V20/variant.h b/buildroot/share/PlatformIO/variants/FYSETC_CHEETAH_V20/variant.h new file mode 100644 index 0000000000..d0fb0d9db0 --- /dev/null +++ b/buildroot/share/PlatformIO/variants/FYSETC_CHEETAH_V20/variant.h @@ -0,0 +1,151 @@ +/* + Copyright (c) 2011 Arduino. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef _VARIANT_ARDUINO_STM32_ +#define _VARIANT_ARDUINO_STM32_ + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + + +// | DIGITAL | ANALOG | USART | TWI | SPI | SPECIAL | +// |---------|--------|-----------|----------|------------------------|-----------| +#define PA0 A0 // | 0 | A0 | | | | | +#define PA1 A1 // | 1 | A1 | | | | | +#define PA2 A2 // | 2 | A2 | USART2_TX | | | | +#define PA3 A3 // | 3 | A3 | USART2_RX | | | | +#define PA4 A4 // | 4 | A4 | | | SPI1_SS, (SPI3_SS) | | +#define PA5 A5 // | 5 | A5 | | | SPI1_SCK | | +#define PA6 A6 // | 6 | A6 | | | SPI1_MISO | | +#define PA7 A7 // | 7 | A7 | | | SPI1_MOSI | | +#define PA8 8 // | 8 | | | TWI3_SCL | | | +#define PA9 9 // | 9 | | USART1_TX | | | | +#define PA10 10 // | 10 | | USART1_RX | | | | +#define PA11 11 // | 11 | | USART6_TX | | | | +#define PA12 12 // | 12 | | USART6_RX | | | | +#define PA13 13 // | 13 | | | | | SWD_SWDIO | +#define PA14 14 // | 14 | | | | | SWD_SWCLK | +#define PA15 15 // | 15 | | | | SPI3_SS, (SPI1_SS) | | +// |---------|--------|-----------|----------|------------------------|-----------| +#define PB0 A8 // | 16 | A8 | | | | | +#define PB1 A9 // | 17 | A9 | | | | | +#define PB2 18 // | 18 | | | | | BOOT1 | +#define PB3 19 // | 19 | | | TWI2_SDA | SPI3_SCK, (SPI1_SCK) | | +#define PB4 20 // | 20 | | | TWI3_SDA | SPI3_MISO, (SPI1_MISO) | | +#define PB5 21 // | 21 | | | | SPI3_MOSI, (SPI1_MOSI) | | +#define PB6 22 // | 22 | | USART1_TX | TWI1_SCL | | | +#define PB7 23 // | 23 | | USART1_RX | TWI1_SDA | | | +#define PB8 24 // | 24 | | | TWI1_SCL | | | +#define PB9 25 // | 25 | | | TWI1_SDA | SPI2_SS | | +#define PB10 26 // | 26 | | | TWI2_SCL | SPI2_SCK | | +#define PB12 27 // | 27 | | | | SPI2_SS | | +#define PB13 28 // | 28 | | | | SPI2_SCK | | +#define PB14 29 // | 29 | | | | SPI2_MISO | | +#define PB15 30 // | 30 | | | | SPI2_MOSI | | +// |---------|--------|-----------|----------|------------------------|-----------| +#define PC0 A10 // | 31 | A10 | | | | | +#define PC1 A11 // | 32 | A11 | | | | | +#define PC2 A12 // | 33 | A12 | | | SPI2_MISO | | +#define PC3 A13 // | 34 | A13 | | | SPI2_MOSI | | +#define PC4 A14 // | 35 | A14 | | | | | +#define PC5 A15 // | 36 | A15 | | | | | +#define PC6 37 // | 37 | | USART6_TX | | | | +#define PC7 38 // | 38 | | USART6_RX | | | | +#define PC8 39 // | 39 | | | | | | +#define PC9 40 // | 40 | | | TWI3_SDA | | | +#define PC10 41 // | 41 | | | | SPI3_SCK | | +#define PC11 42 // | 42 | | | | SPI3_MISO | | +#define PC12 43 // | 43 | | | | SPI3_MOSI | | +#define PC13 44 // | 44 | | | | | | +#define PC14 45 // | 45 | | | | | OSC32_IN | +#define PC15 46 // | 46 | | | | | OSC32_OUT | +// |---------|--------|-----------|----------|------------------------|-----------| +#define PD2 47 // | 47 | | | | | | +// |---------|--------|-----------|----------|------------------------|-----------| +#define PH0 48 // | 48 | | | | | OSC_IN | +#define PH1 49 // | 49 | | | | | OSC_OUT | +// |---------|--------|-----------|----------|------------------------|-----------| + +// This must be a literal +#define NUM_DIGITAL_PINS 50 +#define NUM_ANALOG_INPUTS 16 + +// SPI definitions +#define PIN_SPI_SS PA4 +#define PIN_SPI_SS1 PA4 +#define PIN_SPI_MOSI PA7 +#define PIN_SPI_MISO PA6 +#define PIN_SPI_SCK PA5 + + +// Timer Definitions +#define TIMER_TONE TIM2 +#define TIMER_SERVO TIM5 +#define TIMER_SERIAL TIM11 + +// UART Definitions +//#define ENABLE_HWSERIAL1 done automatically by the #define SERIAL_UART_INSTANCE below +#define ENABLE_HWSERIAL2 + + +// Define here Serial instance number to map on Serial generic name (if not already used by SerialUSB) +#define SERIAL_UART_INSTANCE 1 //1 for Serial = Serial1 (USART1) + +// Default pin used for 'Serial' instance +// Mandatory for Firmata +#define PIN_SERIAL_RX PA10 +#define PIN_SERIAL_TX PA9 + +// Used when user instanciate a hardware Serial using its peripheral name. +// Example: HardwareSerial mySerial(USART3); +// will use PIN_SERIAL3_RX and PIN_SERIAL3_TX if defined. +#define PIN_SERIAL1_RX PA10 +#define PIN_SERIAL1_TX PA9 +#define PIN_SERIAL2_RX PA3 +#define PIN_SERIAL2_TX PA2 + +#ifdef __cplusplus +} // extern "C" +#endif +/*---------------------------------------------------------------------------- + * Arduino objects - C++ only + *----------------------------------------------------------------------------*/ + +#ifdef __cplusplus + // These serial port names are intended to allow libraries and architecture-neutral + // sketches to automatically default to the correct port name for a particular type + // of use. For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN, + // the first hardware serial port whose RX/TX pins are not dedicated to another use. + // + // SERIAL_PORT_MONITOR Port which normally prints to the Arduino Serial Monitor + // + // SERIAL_PORT_USBVIRTUAL Port which is USB virtual serial + // + // SERIAL_PORT_LINUXBRIDGE Port which connects to a Linux system via Bridge library + // + // SERIAL_PORT_HARDWARE Hardware serial port, physical RX & TX pins. + // + // SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX + // pins are NOT connected to anything by default. + #define SERIAL_PORT_MONITOR Serial + #define SERIAL_PORT_HARDWARE Serial1 + #define SERIAL_PORT_HARDWARE_OPEN Serial2 +#endif + +#endif /* _VARIANT_ARDUINO_STM32_ */ \ No newline at end of file diff --git a/buildroot/share/fonts/genallfont.sh b/buildroot/share/fonts/genallfont.sh index 820da187df..0a66990212 100755 --- a/buildroot/share/fonts/genallfont.sh +++ b/buildroot/share/fonts/genallfont.sh @@ -62,7 +62,7 @@ OLDWD=`pwd` # # By default loop through all languages # -LANGS_DEFAULT="an bg ca cz da de el el_gr en es eu fi fr gl hr hu it jp_kana ko_KR nl pl pt pt_br ro ru sk tr uk vi zh_CN zh_TW test" +LANGS_DEFAULT="an bg ca cz da de el el_gr en es eu fi fr gl hr hu it jp_kana ko_KR nl pl pt pt_br ro ru sk sv tr uk vi zh_CN zh_TW test" # # Generate data for language list MARLIN_LANGS or all if not provided diff --git a/buildroot/share/git/mftest b/buildroot/share/git/mftest index fda864672a..11d0ac3881 100755 --- a/buildroot/share/git/mftest +++ b/buildroot/share/git/mftest @@ -138,6 +138,15 @@ if ((AUTO_BUILD)); then # # List environments that apply to the current MOTHERBOARD. # + case $(uname | tr '[:upper:]' '[:lower:]') in + darwin) SYS='mac' ;; + *linux) SYS='lin' ;; + win*) SYS='win' ;; + msys*) SYS='win' ;; + cygwin*) SYS='win' ;; + mingw*) SYS='win' ;; + *) SYS='uni' ;; + esac echo ; echo -n "Auto " ; ((AUTO_BUILD == 2)) && echo "Upload..." || echo "Build..." 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 ; } @@ -145,7 +154,7 @@ if ((AUTO_BUILD)); then BNUM=$( $SED -E 's/^.+BOARD_[^ ]+ +([0-9]+).+$/\1/' <<<"$BLINE" ) BDESC=$( $SED -E 's/^.+\/\/ *(.+)$/\1/' <<<"$BLINE" ) [[ -z $BNUM ]] && { echo "Error - Can't find $MB in boards list." ; exit 1 ; } - ENVS=( $( grep -EA1 "MB\(.*\b$MB\b.*\)" Marlin/src/pins/pins.h | grep -E '#include.+//.+env:[^ ]+' | grep -oE 'env:[^ ]+' | $SED -E 's/env://' ) ) + ENVS=( $( grep -EA1 "MB\(.*\b$MB\b.*\)" Marlin/src/pins/pins.h | grep -E "#include.+//.+(env|$SYS):[^ ]+" | grep -oE "(env|$SYS):[^ ]+" | $SED -E "s/(env|$SYS)://" ) ) [[ -z $ENVS ]] && { errout "Error - Can't find target(s) for $MB ($BNUM)." ; exit 1 ; } ECOUNT=${#ENVS[*]} diff --git a/buildroot/tests/FYSETC_F6-tests b/buildroot/tests/FYSETC_F6-tests index cc7f334099..e1eb6684a5 100755 --- a/buildroot/tests/FYSETC_F6-tests +++ b/buildroot/tests/FYSETC_F6-tests @@ -39,6 +39,7 @@ exec_test $1 $2 "DELTA, RAMPS, L6470, UBL, Allen Key, EEPROM, OLED_PANEL_TINYBOY restore_configs opt_set MOTHERBOARD BOARD_FYSETC_F6_13 opt_set LCD_LANGUAGE vi +opt_set LCD_LANGUAGE_2 fr opt_set X_DRIVER_TYPE TMC2160 opt_set Y_DRIVER_TYPE TMC5160 opt_set Z_DRIVER_TYPE TMC2208_STANDALONE diff --git a/buildroot/tests/FYSETC_S6-tests b/buildroot/tests/FYSETC_S6-tests index 18951ebb79..c7f7a16bbd 100755 --- a/buildroot/tests/FYSETC_S6-tests +++ b/buildroot/tests/FYSETC_S6-tests @@ -9,6 +9,7 @@ set -e # Build examples restore_configs use_example_configs FYSETC/S6 +opt_enable MEATPACK opt_set Y_DRIVER_TYPE TMC2209 opt_set Z_DRIVER_TYPE TMC2130 exec_test $1 $2 "FYSETC S6 Example" "$3" diff --git a/buildroot/tests/mega2560-tests b/buildroot/tests/mega2560-tests index 12bbceab87..105258d402 100755 --- a/buildroot/tests/mega2560-tests +++ b/buildroot/tests/mega2560-tests @@ -72,7 +72,7 @@ opt_set TEMP_SENSOR_1 1 opt_set TEMP_SENSOR_2 1 opt_set TEMP_SENSOR_3 1 opt_set TEMP_SENSOR_4 1 -opt_enable ZONESTAR_LCD Z_PROBE_SERVO_NR Z_SERVO_ANGLES DEACTIVATE_SERVOS_AFTER_MOVE BOOT_MARLIN_LOGO_ANIMATED \ +opt_enable VIKI2 Z_PROBE_SERVO_NR Z_SERVO_ANGLES DEACTIVATE_SERVOS_AFTER_MOVE BOOT_MARLIN_LOGO_ANIMATED \ AUTO_BED_LEVELING_3POINT DEBUG_LEVELING_FEATURE EEPROM_SETTINGS EEPROM_CHITCHAT M114_DETAIL \ NO_VOLUMETRICS EXTENDED_CAPABILITIES_REPORT AUTO_REPORT_TEMPERATURES AUTOTEMP G38_PROBE_TARGET JOYSTICK \ DIRECT_STEPPING DETECT_BROKEN_ENDSTOP \ @@ -200,11 +200,11 @@ exec_test $1 $2 "Azteeg X3 | Mixing Extruder (x5) | Gradient Mix | Greek" "$3" # #restore_configs #opt_enable REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER SDSUPPORT -#for lang in an bg ca cz da de el el_gr en es eu fi fr gl hr hu it jp_kana nl pl pt pt_br ro ru sk tr uk vi zh_CN zh_TW test; do opt_set LCD_LANGUAGE $lang; echo "compile with language $lang ..."; exec_test $1 $2 "Stuff" "$3"; done +#for lang in an bg ca cz da de el el_gr en es eu fi fr gl hr hu it jp_kana nl pl pt pt_br ro ru sk sv tr uk vi zh_CN zh_TW test; do opt_set LCD_LANGUAGE $lang; echo "compile with language $lang ..."; exec_test $1 $2 "Stuff" "$3"; done # #restore_configs #opt_enable REPRAP_DISCOUNT_SMART_CONTROLLER SDSUPPORT -#for lang in an bg ca cz da de el el_gr en es eu fi fr gl hr hu it jp_kana nl pl pt pt_br ro ru sk tr uk vi zh_CN zh_TW test; do opt_set LCD_LANGUAGE $lang; echo "compile with language $lang ..."; exec_test $1 $2 "Stuff" "$3"; done +#for lang in an bg ca cz da de el el_gr en es eu fi fr gl hr hu it jp_kana nl pl pt pt_br ro ru sk sv tr uk vi zh_CN zh_TW test; do opt_set LCD_LANGUAGE $lang; echo "compile with language $lang ..."; exec_test $1 $2 "Stuff" "$3"; done ######## Example Configurations ############## # diff --git a/buildroot/tests/mks_robin_nano35-tests b/buildroot/tests/mks_robin_nano35-tests index 3c5d1bb66f..6e2f9f1b0c 100755 --- a/buildroot/tests/mks_robin_nano35-tests +++ b/buildroot/tests/mks_robin_nano35-tests @@ -30,9 +30,9 @@ exec_test $1 $2 "MKS Robin v2 nano Emulated DOGM SPI" "$3" # use_example_configs Mks/Robin opt_set MOTHERBOARD BOARD_MKS_ROBIN_NANO_V2 -opt_disable TFT_INTERFACE_FSMC TFT_COLOR_UI TOUCH_SCREEN TFT_RES_320x240 -opt_enable TFT_INTERFACE_SPI TFT_LVGL_UI TFT_RES_480x320 -exec_test $1 $2 "MKS Robin v2 nano LVGL SPI" "$3" +opt_disable TFT_INTERFACE_FSMC TFT_COLOR_UI TOUCH_SCREEN TFT_RES_320x240 SERIAL_PORT_2 +opt_enable TFT_INTERFACE_SPI TFT_LVGL_UI TFT_RES_480x320 MKS_WIFI_MODULE +exec_test $1 $2 "MKS Robin v2 nano LVGL SPI w/ WiFi" "$3" # # MKS Robin v2 nano New Color UI 480x320 SPI diff --git a/buildroot/tests/run_tests b/buildroot/tests/run_tests index a0eef6a05f..c4286f4695 100755 --- a/buildroot/tests/run_tests +++ b/buildroot/tests/run_tests @@ -20,7 +20,7 @@ exec_test () { if [[ -z "$VERBOSE_PLATFORMIO" ]] ; then silent="--silent" else - silent="" + silent="-v" fi if platformio run --project-dir $1 -e $2 $silent; then printf "\033[0;32mPassed\033[0m\n" diff --git a/buildroot/tests/sanguino1284p-tests b/buildroot/tests/sanguino1284p-tests index a513f095f9..55cdf418da 100755 --- a/buildroot/tests/sanguino1284p-tests +++ b/buildroot/tests/sanguino1284p-tests @@ -7,7 +7,7 @@ set -e # -# Build with the default configurations +# Start with default configurations... # restore_configs opt_set MOTHERBOARD BOARD_SANGUINOLOLU_12 @@ -16,6 +16,13 @@ opt_enable MINIPANEL USE_CONTROLLER_FAN CONTROLLER_FAN_EDITABLE opt_set CONTROLLER_FAN_PIN 27 exec_test $1 $2 "Default Configuration | MINIPANAL | CONTROLLER_FAN" "$3" +# +# Start with default configurations... +# +restore_configs +opt_set MOTHERBOARD BOARD_MELZI +opt_enable ZONESTAR_LCD +exec_test $1 $2 "Default Configuration | ZONESTAR_LCD " "$3" # clean up restore_configs diff --git a/docs/Serial.md b/docs/Serial.md new file mode 100644 index 0000000000..317f5f8c93 --- /dev/null +++ b/docs/Serial.md @@ -0,0 +1,44 @@ +# Serial port architecture in Marlin + +Marlin is targeting a pletora of different CPU architecture and platforms. Each of these platforms has its own serial interface. +While many provide a Arduino-like Serial class, it's not all of them, and the differences in the existing API create a very complex brain teaser for writing code that works more or less on each platform. + +Moreover, many platform have intrinsic needs about serial port (like forwarding the output on multiple serial port, providing a *serial-like* telnet server, mixing USB-based serial port with SD card emulation) that are difficult to handle cleanly in the other platform serial logic. + + +Starting with version `2.0.9`, Marlin provides a common interface for its serial needs. + +## Common interface + +This interface is declared in `Marlin/src/core/serial_base.h` +Any implementation will need to follow this interface for being used transparently in Marlin's codebase. + +The implementation was written to prioritize performance over abstraction, so the base interface is not using virtual inheritance to avoid the cost of virtual dispatching while calling methods. +Instead, the Curiously Recurring Template Pattern (**CRTP**) is used so that, upon compilation, the interface abstraction does not incur a performance cost. + +Because some platform do not follow the same interface, the missing method in the actual low-level implementation are detected via SFINAE and a wrapper is generated when such method are missing. See `CALL_IF_EXISTS` macro in `Marlin/src/core/macros.h` for the documentation of this technic. + +## Composing the desired feature +The different specificities for each architecture are provided by composing the serial type based on desired functionality. +In the `Marlin/src/core/serial_hook.h` file, the different serial feature are declared and defined in each templated type: +1. `BaseSerial` is a simple 1:1 wrapper to the underlying, Arduino compatible, `Serial`'s class. It derives from it. You'll use this if the platform does not do anything specific for the `Serial` object (for example, if an interrupt callback calls directly the serial **instance** in the platform's framework code, this is not the right class to use). This wrapper is completely inlined so that it does not generate any code upon compilation. `BaseSerial` constructor forwards any parameter to the platform's `Serial`'s constructor. +2. `ForwardSerial` is a composing wrapper. It references an actual Arduino compatible `Serial` instance. You'll use this if the instance is declared in the platform's framework and is being referred directly in the framework. This is not as efficient as the `BaseSerial` implementation since static dereferencing is done for each method call (it'll still be faster than virtual dispatching) +3. `ConditionalSerial` is working a bit like the `ForwardSerial` interface, but it checks a boolean condition before calling the referenced instance. You'll use it when the serial output can be switch off at runtime, for example in a *telnet* like serial output that should not emit any packet if no client is connected. +4. `RuntimeSerial` is providing a runtime-modifiable hooking method for its `write` and `msgDone` method. You'll use it if you need to capture the serial output of Marlin, for example to display the G-Code parser's output on a GUI interface. The hooking interface is setup via the `setHook` method. +5. `MultiSerial` is a runtime modifiable serial output multiplexer. It can output (*respectively input*) to 2 different interface based on a port *mask*. You'll use this if you need to output the same serial stream to multiple port. You can plug a `MultiSerial` to itself to duplicate to more than 2 ports. + +## Plumbing +Since all the types above are using CRTP, it's possible to combine them to get the appropriate functionality. +This is easily done via type definition of the feature. + +For example, to present a serial interface that's outputting to 2 serial port, the first one being hooked at runtime and the second one connected to a runtime switchable telnet client, you'll declare the type to use as: +``` +typedef MultiSerial< RuntimeSerial, ConditionalSerial > Serial0Type; +``` + +## Emergency parser +By default, the serial base interface provide an emergency parser that's only enable for serial classes that support it. +Because of this condition, all underlying type takes a first `bool emergencyParserEnabled` argument to their constructor. You must take into account this parameter when defining the actual type used. + + +*This document was written by [X-Ryl669](https://blog.cyril.by) and is under [CC-SA license](https://creativecommons.org/licenses/by-sa)* \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index b6ed572bfb..556b5769c5 100644 --- a/platformio.ini +++ b/platformio.ini @@ -39,6 +39,7 @@ default_src_filter = + - - + - - - + - - - - @@ -61,7 +62,11 @@ default_src_filter = + - - + - - - - + - + - - - - - - - - + - + - - - - - @@ -78,7 +83,7 @@ default_src_filter = + - - + - - - - - - + - - - - - - - @@ -93,6 +98,7 @@ default_src_filter = + - - + - - - + - - - - - @@ -113,7 +119,7 @@ default_src_filter = + - - + - - - - - + - - - - - @@ -140,6 +146,7 @@ default_src_filter = + - - + - - - + - - - - @@ -191,7 +198,7 @@ default_src_filter = + - - + - - - - - - - + - - - - - - - @@ -200,6 +207,7 @@ default_src_filter = + - - + - - - - + - - - extra_scripts = pre:buildroot/share/PlatformIO/scripts/common-dependencies.py @@ -225,11 +233,11 @@ HAS_MOTOR_CURRENT_I2C = SlowSoftI2CMaster HAS_TMC26X = TMC26XStepper=https://github.com/trinamic/TMC26XStepper/archive/master.zip src_filter=+ HAS_L64XX = Arduino-L6470@0.8.0 - src_filter=+ + + + src_filter=+ + + + NEOPIXEL_LED = Adafruit NeoPixel@1.5.0 src_filter=+ MAX6675_._IS_MAX31865 = Adafruit MAX31865 library@~1.1.0 -USES_LIQUIDCRYSTAL = LiquidCrystal@1.5.0 +USES_LIQUIDCRYSTAL = bitbucket-fmalpartida/LiquidCrystal@1.5.0 USES_LIQUIDCRYSTAL_I2C = marcoschwartz/LiquidCrystal_I2C@1.1.4 USES_LIQUIDTWI2 = LiquidTWI2@1.2.7 HAS_WIRED_LCD = src_filter=+ @@ -239,6 +247,8 @@ HAS_MARLINUI_U8GLIB = U8glib-HAL@~0.4.1 HAS_(FSMC|SPI)_TFT = src_filter=+ + + HAS_FSMC_TFT = src_filter=+ + HAS_SPI_TFT = src_filter=+ + +I2C_EEPROM = src_filter=+ +SPI_EEPROM = src_filter=+ HAS_GRAPHICAL_TFT = src_filter=+ DWIN_CREALITY_LCD = src_filter=+ IS_TFTGLCD_PANEL = src_filter=+ @@ -257,6 +267,7 @@ HAS_MENU_DELTA_CALIBRATE = src_filter=+ HAS_MENU_FILAMENT = src_filter=+ LCD_INFO_MENU = src_filter=+ HAS_MENU_JOB_RECOVERY = src_filter=+ +HAS_MULTI_LANGUAGE = src_filter=+ HAS_MENU_LED = src_filter=+ HAS_MENU_MEDIA = src_filter=+ HAS_MENU_MIXER = src_filter=+ @@ -278,6 +289,7 @@ EXTUI_EXAMPLE = src_filter=+ MALYAN_LCD = src_filter=+ USE_UHS2_USB = src_filter=+ USE_UHS3_USB = src_filter=+ +USB_FLASH_DRIVE_SUPPORT = src_filter=+ AUTO_BED_LEVELING_BILINEAR = src_filter=+ AUTO_BED_LEVELING_(3POINT|(BI)?LINEAR) = src_filter=+ MESH_BED_LEVELING = src_filter=+ + @@ -296,7 +308,7 @@ EMERGENCY_PARSER = src_filter=+ - IIC_BL24CXX_EEPROM = src_filter=+ HAS_SPI_FLASH = src_filter=+ -HAS_ETHERNET = src_filter=+ +HAS_ETHERNET = src_filter=+ + HAS_FANMUX = src_filter=+ FILAMENT_WIDTH_SENSOR = src_filter=+ + FWRETRACT = src_filter=+ + @@ -310,6 +322,7 @@ PCA9632 = src_filter=+ PRINTER_EVENT_LEDS = src_filter=+ TEMP_STAT_LEDS = src_filter=+ MAX7219_DEBUG = src_filter=+ + +MEATPACK = src_filter=+ MIXING_EXTRUDER = src_filter=+ + HAS_PRUSA_MMU1 = src_filter=+ HAS_PRUSA_MMU2 = src_filter=+ + @@ -329,7 +342,7 @@ Z_STEPPER_AUTO_ALIGN = src_filter=+ + ASSISTED_TRAMMING = src_filter=+ + HAS_MESH = src_filter=+ -HAS_LEVELING = src_filter=+ +HAS_LEVELING = src_filter=+ + DELTA_AUTO_CALIBRATION = src_filter=+ CALIBRATION_GCODE = src_filter=+ Z_MIN_PROBE_REPEATABILITY_TEST = src_filter=+ @@ -379,7 +392,7 @@ BABYSTEPPING = src_filter=+ + G38_PROBE_TARGET = src_filter=+ MAGNETIC_PARKING_EXTRUDER = src_filter=+ -SDSUPPORT = src_filter=+ +SDSUPPORT = src_filter=+ + + + + + + HAS_MEDIA_SUBCALLS = src_filter=+ GCODE_REPEAT_MARKERS = src_filter=+ + HAS_EXTRUDERS = src_filter=+ + @@ -395,7 +408,9 @@ BEZIER_CURVE_SUPPORT = src_filter=+ + HAS_BED_PROBE = src_filter=+ + + + IS_SCARA = src_filter=+ +HAS_SERVOS = src_filter=+ + MORGAN_SCARA = src_filter=+ +HAS_MICROSTEPS = src_filter=+ (ESP3D_)?WIFISUPPORT = AsyncTCP, ESP Async WebServer ESP3DLib=https://github.com/luc-github/ESP3DLib.git arduinoWebSockets=https://github.com/Links2004/arduinoWebSockets.git @@ -695,7 +710,7 @@ extra_scripts = ${common.extra_scripts} src_filter = ${common.default_src_filter} + + lib_deps = ${common.lib_deps} Servo -custom_marlin.USES_LIQUIDCRYSTAL = LiquidCrystal@1.0.0 +custom_marlin.USES_LIQUIDCRYSTAL = arduino-libraries/LiquidCrystal@~1.0.7 custom_marlin.NEOPIXEL_LED = Adafruit NeoPixel=https://github.com/p3p/Adafruit_NeoPixel/archive/1.5.0.zip build_flags = ${common.build_flags} -DU8G_HAL_LINKS -IMarlin/src/HAL/LPC1768/include -IMarlin/src/HAL/LPC1768/u8g # debug options for backtrace @@ -1185,6 +1200,18 @@ extra_scripts = ${common.extra_scripts} pre:buildroot/share/PlatformIO/scripts/generic_create_variant.py buildroot/share/PlatformIO/scripts/STEVAL__F401XX.py +# +# STM32F401RC +# +[env:FYSETC_CHEETAH_V20] +platform = ${common_stm32.platform} +extends = common_stm32 +board = FYSETC_CHEETAH_V20 +build_flags = ${common_stm32.build_flags} -DSTM32F401xC -DVECT_TAB_OFFSET=0xC000 +extra_scripts = ${common.extra_scripts} + pre:buildroot/share/PlatformIO/scripts/generic_create_variant.py + buildroot/share/PlatformIO/scripts/FYSETC_CHEETAH_V20.py + # # FLYF407ZG # @@ -1362,6 +1389,14 @@ build_unflags = ${common_stm32.build_unflags} -DUSBCON -DUSBD_USE_CDC -DUS extends = lerdge_common board_build.firmware = Lerdge_X_firmware_force.bin +# +# Lerdge X with USB Flash Drive Support +# +[env:LERDGEX_usb_flash_drive] +extends = LERDGEX +platform_packages = ${stm32_flash_drive.platform_packages} +build_flags = ${stm32_flash_drive.build_flags} + # # Lerdge S # @@ -1369,6 +1404,14 @@ board_build.firmware = Lerdge_X_firmware_force.bin extends = lerdge_common board_build.firmware = Lerdge_firmware_force.bin +# +# Lerdge S with USB Flash Drive Support +# +[env:LERDGES_usb_flash_drive] +extends = LERDGES +platform_packages = ${stm32_flash_drive.platform_packages} +build_flags = ${stm32_flash_drive.build_flags} + # # Lerdge K # @@ -1378,6 +1421,14 @@ board_build.firmware = Lerdge_K_firmware_force.bin build_flags = ${lerdge_common.build_flags} -DLERDGEK +# +# Lerdge K with USB Flash Drive Support +# +[env:LERDGEK_usb_flash_drive] +extends = LERDGEK +platform_packages = ${stm32_flash_drive.platform_packages} +build_flags = ${stm32_flash_drive.build_flags} + # # RUMBA32 # @@ -1475,6 +1526,23 @@ build_flags = ${stm32_flash_drive.build_flags} -DUSE_USB_HS_IN_FS -DUSBD_USE_CDC +# +# Mingda MPX_ARM_MINI +# + +[env:mingda_mpx_arm_mini] +platform = ${common_stm32.platform} +extends = common_stm32 +board = genericSTM32F103ZE +board_build.core = stm32 +board_build.variant = MARLIN_F103Zx +board_build.ldscript = ldscript.ld +board_build.offset = 0x10000 +build_flags = ${common_stm32.build_flags} -DENABLE_HWSERIAL3 -DTIMER_SERIAL=TIM5 +build_unflags = ${common_stm32.build_unflags} -DUSBCON -DUSBD_USE_CDC +extra_scripts = ${common.extra_scripts} pre:buildroot/share/PlatformIO/scripts/generic_create_variant.py buildroot/share/PlatformIO/scripts/stm32_bootloader.py + + ################################# # # # Other Architectures #