diff --git a/.github/workflows/test-builds.yml b/.github/workflows/test-builds.yml
index fdb81fbdc9..b228783799 100644
--- a/.github/workflows/test-builds.yml
+++ b/.github/workflows/test-builds.yml
@@ -41,6 +41,7 @@ jobs:
- mega2560
- teensy31
- teensy35
+ - teensy41
- SAMD51_grandcentral_m4
# Extended AVR Environments
@@ -70,6 +71,7 @@ jobs:
- mks_robin_stm32
- ARMED
- FYSETC_S6
+ - STM32F070CB_malyan
- STM32F070RB_malyan
- malyan_M300
- mks_robin_lite
diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h
index 8cd2faf7f8..dec1a81bee 100644
--- a/Marlin/Configuration.h
+++ b/Marlin/Configuration.h
@@ -34,9 +34,8 @@
* - Extra features
*
* Advanced settings can be found in Configuration_adv.h
- *
*/
-#define CONFIGURATION_H_VERSION 020006
+#define CONFIGURATION_H_VERSION 020007
//===========================================================================
//============================= Getting Started =============================
@@ -390,6 +389,7 @@
* 21 : Pt100 with circuit in the Ultimainboard V2.x with 3.3v excitation (STM32 \ LPC176x....)
* 22 : 100k (hotend) with 4.7k pullup to 3.3V and 220R to analog input (as in GTM32 Pro vB)
* 23 : 100k (bed) with 4.7k pullup to 3.3v and 220R to analog input (as in GTM32 Pro vB)
+ * 30 : Kis3d Silicone heating mat 200W/300W with 6mm precision cast plate (EN AW 5083) NTC100K / B3950 (4.7k pullup)
* 201 : Pt100 with circuit in Overlord, similar to Ultimainboard V2.x
* 60 : 100k Maker's Tool Works Kapton Bed Thermistor beta=3950
* 61 : 100k Formbot / Vivedino 3950 350C thermistor 4.7k pullup
@@ -486,24 +486,17 @@
//#define PID_AUTOTUNE_MENU // Add PID auto-tuning to the "Advanced Settings" menu. (~250 bytes of PROGMEM)
//#define PID_PARAMS_PER_HOTEND // Uses separate PID parameters for each extruder (useful for mismatched extruders)
// Set/get with gcode: M301 E[extruder number, 0-2]
-
- // If you are using a pre-configured hotend then you can use one of the value sets by uncommenting it
-
- // Ultimaker
- #define DEFAULT_Kp 22.2
- #define DEFAULT_Ki 1.08
- #define DEFAULT_Kd 114
-
- // MakerGear
- //#define DEFAULT_Kp 7.0
- //#define DEFAULT_Ki 0.1
- //#define DEFAULT_Kd 12
-
- // Mendel Parts V9 on 12V
- //#define DEFAULT_Kp 63.0
- //#define DEFAULT_Ki 2.25
- //#define DEFAULT_Kd 440
-
+ #if ENABLED(PID_PARAMS_PER_HOTEND)
+ // Specify between 1 and HOTENDS values per array.
+ // If fewer than EXTRUDER values are provided, the last element will be repeated.
+ #define DEFAULT_Kp_LIST { 22.20, 20.0 }
+ #define DEFAULT_Ki_LIST { 1.08, 1.0 }
+ #define DEFAULT_Kd_LIST { 114.00, 112.0 }
+ #else
+ #define DEFAULT_Kp 22.20
+ #define DEFAULT_Ki 1.08
+ #define DEFAULT_Kd 114.00
+ #endif
#endif // PIDTEMP
//===========================================================================
@@ -539,18 +532,12 @@
//#define MIN_BED_POWER 0
//#define PID_BED_DEBUG // Sends debug data to the serial port.
- //120V 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)
- //from FOPDT model - kp=.39 Tp=405 Tdead=66, Tc set to 79.2, aggressive factor of .15 (vs .1, 1, 10)
+ // 120V 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)
+ // from FOPDT model - kp=.39 Tp=405 Tdead=66, Tc set to 79.2, aggressive factor of .15 (vs .1, 1, 10)
#define DEFAULT_bedKp 10.00
#define DEFAULT_bedKi .023
#define DEFAULT_bedKd 305.4
- //120V 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)
- //from pidautotune
- //#define DEFAULT_bedKp 97.1
- //#define DEFAULT_bedKi 1.41
- //#define DEFAULT_bedKd 1675.16
-
// FIND YOUR OWN: "M303 E-1 C8 S90" to run autotune on the bed at 90 degreesC for 8 cycles.
#endif // PIDTEMPBED
@@ -608,7 +595,7 @@
// @section machine
-// Uncomment one of these options to enable CoreXY, CoreXZ, or CoreYZ kinematics
+// Enable one of the options below for CoreXY, CoreXZ, or CoreYZ kinematics,
// either in the usual order or reversed
//#define COREXY
//#define COREXZ
@@ -616,6 +603,7 @@
//#define COREYX
//#define COREZX
//#define COREZY
+//#define MARKFORGED_XY // MarkForged. See https://reprap.org/forum/read.php?152,504042
//===========================================================================
//============================== Endstop Settings ===========================
@@ -866,7 +854,6 @@
* - For simple switches connect...
* - normally-closed switches to GND and D32.
* - normally-open switches to 5V and D32.
- *
*/
//#define Z_MIN_PROBE_PIN 32 // Pin 32 is the RAMPS default
@@ -1578,7 +1565,6 @@
*
* Caveats: The ending Z should be the same as starting Z.
* Attention: EXPERIMENTAL. G-code arguments may change.
- *
*/
//#define NOZZLE_CLEAN_FEATURE
@@ -1731,7 +1717,6 @@
*
* SD Card support is disabled by default. If your controller has an SD slot,
* you must uncomment the following option or it won't work.
- *
*/
//#define SDSUPPORT
@@ -1968,6 +1953,14 @@
//
//#define FF_INTERFACEBOARD
+//
+// TFT GLCD Panel with Marlin UI
+// Panel connected to main board by SPI or I2C interface.
+// See https://github.com/Serhiy-K/TFTGLCDAdapter
+//
+//#define TFTGLCD_PANEL_SPI
+//#define TFTGLCD_PANEL_I2C
+
//=============================================================================
//======================= LCD / Controller Selection =======================
//========================= (Graphical LCDs) ========================
@@ -2171,6 +2164,9 @@
// Touch-screen LCD for Malyan M200/M300 printers
//
//#define MALYAN_LCD
+#if ENABLED(MALYAN_LCD)
+ #define LCD_SERIAL_PORT 1 // Default is 1 for Malyan M200
+#endif
//
// Touch UI for FTDI EVE (FT800/FT810) displays
@@ -2184,7 +2180,7 @@
//#define ANYCUBIC_LCD_I3MEGA
//#define ANYCUBIC_LCD_CHIRON
#if EITHER(ANYCUBIC_LCD_I3MEGA, ANYCUBIC_LCD_CHIRON)
- #define ANYCUBIC_LCD_SERIAL_PORT 3
+ #define LCD_SERIAL_PORT 3 // Default is 3 for Anycubic
//#define ANYCUBIC_LCD_DEBUG
#endif
@@ -2343,7 +2339,6 @@
* *** CAUTION ***
*
* LED Type. Enable only one of the following two options.
- *
*/
//#define RGB_LED
//#define RGBW_LED
diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h
index e4b3fbf2ae..b6ea64c2af 100644
--- a/Marlin/Configuration_adv.h
+++ b/Marlin/Configuration_adv.h
@@ -29,9 +29,8 @@
* Some of these settings can damage your printer if improperly set!
*
* Basic settings can be found in Configuration.h
- *
*/
-#define CONFIGURATION_ADV_H_VERSION 020006
+#define CONFIGURATION_ADV_H_VERSION 020007
// @section temperature
@@ -738,7 +737,6 @@
* | 4 3 | 1 4 | 2 1 | 3 2 |
* | | | | |
* | 1 2 | 2 3 | 3 4 | 4 1 |
- *
*/
#ifndef Z_STEPPER_ALIGN_XY
//#define Z_STEPPERS_ORIENTATION 0
@@ -773,7 +771,6 @@
//
//#define ASSISTED_TRAMMING
#if ENABLED(ASSISTED_TRAMMING)
-
// Define positions for probing points, use the hotend as reference not the sensor.
#define TRAMMING_POINT_XY { { 20, 20 }, { 200, 20 }, { 200, 200 }, { 20, 200 } }
@@ -786,6 +783,9 @@
// Enable to restore leveling setup after operation
#define RESTORE_LEVELING_AFTER_G35
+ // Add a menu item for Assisted Tramming
+ //#define ASSISTED_TRAMMING_MENU_ITEM
+
/**
* Screw thread:
* M3: 30 = Clockwise, 31 = Counter-Clockwise
@@ -793,7 +793,6 @@
* M5: 50 = Clockwise, 51 = Counter-Clockwise
*/
#define TRAMMING_SCREW_THREAD 30
-
#endif
// @section motion
@@ -1105,23 +1104,26 @@
#define BOOTSCREEN_TIMEOUT 4000 // (ms) Total Duration to display the boot screen(s)
#endif
-#if HAS_GRAPHICAL_LCD && EITHER(SDSUPPORT, LCD_SET_PROGRESS_MANUALLY)
- //#define PRINT_PROGRESS_SHOW_DECIMALS // Show progress with decimal digits
- //#define SHOW_REMAINING_TIME // Display estimated time to completion
+#if EITHER(SDSUPPORT, LCD_SET_PROGRESS_MANUALLY) && ANY(HAS_MARLINUI_U8GLIB, HAS_MARLINUI_HD44780, IS_TFTGLCD_PANEL)
+ //#define SHOW_REMAINING_TIME // Display estimated time to completion
#if ENABLED(SHOW_REMAINING_TIME)
- //#define USE_M73_REMAINING_TIME // Use remaining time from M73 command instead of estimation
- //#define ROTATE_PROGRESS_DISPLAY // Display (P)rogress, (E)lapsed, and (R)emaining time
+ //#define USE_M73_REMAINING_TIME // Use remaining time from M73 command instead of estimation
+ //#define ROTATE_PROGRESS_DISPLAY // Display (P)rogress, (E)lapsed, and (R)emaining time
#endif
-#endif
-#if HAS_CHARACTER_LCD && EITHER(SDSUPPORT, LCD_SET_PROGRESS_MANUALLY)
- //#define LCD_PROGRESS_BAR // Show a progress bar on HD44780 LCDs for SD printing
- #if ENABLED(LCD_PROGRESS_BAR)
- #define PROGRESS_BAR_BAR_TIME 2000 // (ms) Amount of time to show the bar
- #define PROGRESS_BAR_MSG_TIME 3000 // (ms) Amount of time to show the status message
- #define PROGRESS_MSG_EXPIRE 0 // (ms) Amount of time to retain the status message (0=forever)
- //#define PROGRESS_MSG_ONCE // Show the message for MSG_TIME then clear it
- //#define LCD_PROGRESS_BAR_TEST // Add a menu item to test the progress bar
+ #if HAS_MARLINUI_U8GLIB
+ //#define PRINT_PROGRESS_SHOW_DECIMALS // Show progress with decimal digits
+ #endif
+
+ #if EITHER(HAS_MARLINUI_HD44780, IS_TFTGLCD_PANEL)
+ //#define LCD_PROGRESS_BAR // Show a progress bar on HD44780 LCDs for SD printing
+ #if ENABLED(LCD_PROGRESS_BAR)
+ #define PROGRESS_BAR_BAR_TIME 2000 // (ms) Amount of time to show the bar
+ #define PROGRESS_BAR_MSG_TIME 3000 // (ms) Amount of time to show the status message
+ #define PROGRESS_MSG_EXPIRE 0 // (ms) Amount of time to retain the status message (0=forever)
+ //#define PROGRESS_MSG_ONCE // Show the message for MSG_TIME then clear it
+ //#define LCD_PROGRESS_BAR_TEST // Add a menu item to test the progress bar
+ #endif
#endif
#endif
@@ -1164,6 +1166,7 @@
#if ENABLED(POWER_LOSS_RECOVERY)
#define PLR_ENABLED_DEFAULT false // Power Loss Recovery enabled by default. (Set with 'M413 Sn' & M500)
//#define BACKUP_POWER_SUPPLY // Backup power / UPS to move the steppers on power loss
+ //#define POWER_LOSS_RECOVER_ZHOME // Z homing is needed for proper recovery. 99.9% of the time this should be disabled!
//#define POWER_LOSS_ZRAISE 2 // (mm) Z axis raise on resume (on power loss with UPS)
//#define POWER_LOSS_PIN 44 // Pin to detect power loss. Set to -1 to disable default pin on boards without module.
//#define POWER_LOSS_STATE HIGH // State of pin indicating power loss
@@ -1324,7 +1327,7 @@
* controller events, as there is a trade-off between reliable
* printing performance versus fast display updates.
*/
-#if HAS_GRAPHICAL_LCD
+#if HAS_MARLINUI_U8GLIB
// Show SD percentage next to the progress bar
//#define DOGM_SD_PERCENT
@@ -1394,18 +1397,18 @@
//#define MARLIN_SNAKE
//#define GAMES_EASTER_EGG // Add extra blank lines above the "Games" sub-menu
-#endif // HAS_GRAPHICAL_LCD
+#endif // HAS_MARLINUI_U8GLIB
//
// Additional options for DGUS / DWIN displays
//
#if HAS_DGUS_LCD
- #define DGUS_SERIAL_PORT 3
- #define DGUS_BAUDRATE 115200
+ #define LCD_SERIAL_PORT 3
+ #define LCD_BAUDRATE 115200
#define DGUS_RX_BUFFER_SIZE 128
#define DGUS_TX_BUFFER_SIZE 48
- //#define DGUS_SERIAL_STATS_RX_BUFFER_OVERRUNS // Fix Rx overrun situation (Currently only for AVR)
+ //#define SERIAL_STATS_RX_BUFFER_OVERRUNS // Fix Rx overrun situation (Currently only for AVR)
#define DGUS_UPDATE_INTERVAL_MS 500 // (ms) Interval between automatic screen updates
@@ -1572,6 +1575,7 @@
#if ENABLED(BABYSTEPPING)
//#define INTEGRATED_BABYSTEPPING // EXPERIMENTAL integration of babystepping into the Stepper ISR
//#define BABYSTEP_WITHOUT_HOMING
+ //#define BABYSTEP_ALWAYS_AVAILABLE // Allow babystepping at all times (not just during movement).
//#define BABYSTEP_XY // Also enable X/Y Babystepping. Not supported on DELTA!
#define BABYSTEP_INVERT_Z false // Change if Z babysteps should go the other way
//#define BABYSTEP_MILLIMETER_UNITS // Specify BABYSTEP_MULTIPLICATOR_(XY|Z) in mm instead of micro-steps
@@ -1582,7 +1586,6 @@
#if ENABLED(DOUBLECLICK_FOR_Z_BABYSTEPPING)
#define DOUBLECLICK_MAX_INTERVAL 1250 // Maximum interval between clicks, in milliseconds.
// Note: Extra time may be added to mitigate controller latency.
- //#define BABYSTEP_ALWAYS_AVAILABLE // Allow babystepping at all times (not just during movement).
//#define MOVE_Z_WHEN_IDLE // Jump to the move Z menu on doubleclick when printer is idle.
#if ENABLED(MOVE_Z_WHEN_IDLE)
#define MOVE_Z_IDLE_MULTIPLICATOR 1 // Multiply 1mm by this factor for the move step size.
@@ -1950,7 +1953,6 @@
* Be sure to turn off auto-retract during filament change.
*
* Note that M207 / M208 / M209 settings are saved to EEPROM.
- *
*/
//#define FWRETRACT
#if ENABLED(FWRETRACT)
@@ -1976,7 +1978,7 @@
* Universal tool change settings.
* Applies to all types of extruders except where explicitly noted.
*/
-#if EXTRUDERS > 1
+#if HAS_MULTI_EXTRUDER
// Z raise distance for tool-change, as needed for some extruders
#define TOOLCHANGE_ZRAISE 2 // (mm)
//#define TOOLCHANGE_ZRAISE_BEFORE_RETRACT // Apply raise before swap retraction (if enabled)
@@ -2040,7 +2042,7 @@
//#define TOOLCHANGE_PARK_X_ONLY // X axis only move
//#define TOOLCHANGE_PARK_Y_ONLY // Y axis only move
#endif
-#endif // EXTRUDERS > 1
+#endif // HAS_MULTI_EXTRUDER
/**
* Advanced Pause
@@ -2487,7 +2489,7 @@
#define E7_HYBRID_THRESHOLD 30
/**
- * Use StallGuard2 to home / probe X, Y, Z.
+ * Use StallGuard to home / probe X, Y, Z.
*
* TMC2130, TMC2160, TMC2209, TMC2660, TMC5130, and TMC5160 only
* Connect the stepper driver's DIAG1 pin to the X/Y endstop pin.
@@ -2508,6 +2510,8 @@
*
* IMPROVE_HOMING_RELIABILITY tunes acceleration and jerk when
* homing and adds a guard period for endstop triggering.
+ *
+ * Comment *_STALL_SENSITIVITY to disable sensorless homing for that axis.
*/
//#define SENSORLESS_HOMING // StallGuard capable drivers only
@@ -3227,6 +3231,7 @@
//#define HOST_ACTION_COMMANDS
#if ENABLED(HOST_ACTION_COMMANDS)
//#define HOST_PROMPT_SUPPORT
+ //#define HOST_START_MENU_ITEM // Add a menu item that tells the host to start
#endif
/**
@@ -3334,6 +3339,7 @@
#define JOY_X_LIMITS { 5600, 8190-100, 8190+100, 10800 } // min, deadzone start, deadzone end, max
#define JOY_Y_LIMITS { 5600, 8250-100, 8250+100, 11000 }
#define JOY_Z_LIMITS { 4800, 8080-100, 8080+100, 11550 }
+ //#define JOYSTICK_DEBUG
#endif
/**
@@ -3411,10 +3417,10 @@
#if ENABLED(PRUSA_MMU2)
// Serial port used for communication with MMU2.
- // For AVR enable the UART port used for the MMU. (e.g., internalSerial)
+ // For AVR enable the UART port used for the MMU. (e.g., mmuSerial)
// For 32-bit boards check your HAL for available serial ports. (e.g., Serial2)
- #define INTERNAL_SERIAL_PORT 2
- #define MMU2_SERIAL internalSerial
+ #define MMU2_SERIAL_PORT 2
+ #define MMU2_SERIAL mmuSerial
// Use hardware reset for MMU if a pin is defined for it
//#define MMU2_RST_PIN 23
@@ -3465,7 +3471,7 @@
*/
//#define MMU_EXTRUDER_SENSOR
#if ENABLED(MMU_EXTRUDER_SENSOR)
- #define MMU_LOADING_ATTEMPTS_NR 5 //max. number of attempts to load filament if first load fail
+ #define MMU_LOADING_ATTEMPTS_NR 5 // max. number of attempts to load filament if first load fail
#endif
/**
diff --git a/Marlin/Makefile b/Marlin/Makefile
index 95135ab594..68dd05bdfb 100644
--- a/Marlin/Makefile
+++ b/Marlin/Makefile
@@ -170,110 +170,114 @@ else ifeq ($(HARDWARE_MOTHERBOARD),1100)
else ifeq ($(HARDWARE_MOTHERBOARD),1101)
# Velleman K8400 Controller (derived from 3Drag Controller)
else ifeq ($(HARDWARE_MOTHERBOARD),1102)
-# Velleman K8600 Controller (derived from 3Drag Controller)
+# Velleman K8600 Controller (Vertex Nano)
else ifeq ($(HARDWARE_MOTHERBOARD),1103)
-# 2PrintBeta BAM&DICE with STK drivers
+# Velleman K8800 Controller (Vertex Delta)
else ifeq ($(HARDWARE_MOTHERBOARD),1104)
-# 2PrintBeta BAM&DICE Due with STK drivers
+# 2PrintBeta BAM&DICE with STK drivers
else ifeq ($(HARDWARE_MOTHERBOARD),1105)
-# MKS BASE v1.0
+# 2PrintBeta BAM&DICE Due with STK drivers
else ifeq ($(HARDWARE_MOTHERBOARD),1106)
-# MKS v1.4 with A4982 stepper drivers
+# MKS BASE v1.0
else ifeq ($(HARDWARE_MOTHERBOARD),1107)
-# MKS v1.5 with Allegro A4982 stepper drivers
+# MKS v1.4 with A4982 stepper drivers
else ifeq ($(HARDWARE_MOTHERBOARD),1108)
-# MKS v1.6 with Allegro A4982 stepper drivers
+# MKS v1.5 with Allegro A4982 stepper drivers
else ifeq ($(HARDWARE_MOTHERBOARD),1109)
-# MKS BASE 1.0 with Heroic HR4982 stepper drivers
+# MKS v1.6 with Allegro A4982 stepper drivers
else ifeq ($(HARDWARE_MOTHERBOARD),1110)
-# MKS GEN v1.3 or 1.4
+# MKS BASE 1.0 with Heroic HR4982 stepper drivers
else ifeq ($(HARDWARE_MOTHERBOARD),1111)
-# MKS GEN L
+# MKS GEN v1.3 or 1.4
else ifeq ($(HARDWARE_MOTHERBOARD),1112)
-# zrib V2.0 control board (Chinese knock off RAMPS replica)
+# MKS GEN L
else ifeq ($(HARDWARE_MOTHERBOARD),1113)
-# BigTreeTech or BIQU KFB2.0
+# zrib V2.0 control board (Chinese knock off RAMPS replica)
else ifeq ($(HARDWARE_MOTHERBOARD),1114)
-# Felix 2.0+ Electronics Board (RAMPS like)
+# BigTreeTech or BIQU KFB2.0
else ifeq ($(HARDWARE_MOTHERBOARD),1115)
-# Invent-A-Part RigidBoard
+# Felix 2.0+ Electronics Board (RAMPS like)
else ifeq ($(HARDWARE_MOTHERBOARD),1116)
-# Invent-A-Part RigidBoard V2
+# Invent-A-Part RigidBoard
else ifeq ($(HARDWARE_MOTHERBOARD),1117)
-# Sainsmart 2-in-1 board
+# Invent-A-Part RigidBoard V2
else ifeq ($(HARDWARE_MOTHERBOARD),1118)
-# Ultimaker
+# Sainsmart 2-in-1 board
else ifeq ($(HARDWARE_MOTHERBOARD),1119)
-# Ultimaker (Older electronics. Pre 1.5.4. This is rare)
+# Ultimaker
else ifeq ($(HARDWARE_MOTHERBOARD),1120)
+# Ultimaker (Older electronics. Pre 1.5.4. This is rare)
+else ifeq ($(HARDWARE_MOTHERBOARD),1121)
MCU ?= atmega1280
# Azteeg X3
-else ifeq ($(HARDWARE_MOTHERBOARD),1121)
-# Azteeg X3 Pro
else ifeq ($(HARDWARE_MOTHERBOARD),1122)
-# Ultimainboard 2.x (Uses TEMP_SENSOR 20)
+# Azteeg X3 Pro
else ifeq ($(HARDWARE_MOTHERBOARD),1123)
-# Rumba
+# Ultimainboard 2.x (Uses TEMP_SENSOR 20)
else ifeq ($(HARDWARE_MOTHERBOARD),1124)
-# Raise3D Rumba
+# Rumba
else ifeq ($(HARDWARE_MOTHERBOARD),1125)
-# Rapide Lite RL200 Rumba
+# Raise3D Rumba
else ifeq ($(HARDWARE_MOTHERBOARD),1126)
-# Formbot T-Rex 2 Plus
+# Rapide Lite RL200 Rumba
else ifeq ($(HARDWARE_MOTHERBOARD),1127)
-# Formbot T-Rex 3
+# Formbot T-Rex 2 Plus
else ifeq ($(HARDWARE_MOTHERBOARD),1128)
-# Formbot Raptor
+# Formbot T-Rex 3
else ifeq ($(HARDWARE_MOTHERBOARD),1129)
-# Formbot Raptor 2
+# Formbot Raptor
else ifeq ($(HARDWARE_MOTHERBOARD),1130)
-# bq ZUM Mega 3D
+# Formbot Raptor 2
else ifeq ($(HARDWARE_MOTHERBOARD),1131)
-# MakeBoard Mini v2.1.2 is a control board sold by MicroMake
+# bq ZUM Mega 3D
else ifeq ($(HARDWARE_MOTHERBOARD),1132)
-# TriGorilla Anycubic version 1.3 based on RAMPS EFB
+# MakeBoard Mini v2.1.2 is a control board sold by MicroMake
else ifeq ($(HARDWARE_MOTHERBOARD),1133)
-# TriGorilla Anycubic version 1.4 based on RAMPS EFB
+# TriGorilla Anycubic version 1.3 based on RAMPS EFB
else ifeq ($(HARDWARE_MOTHERBOARD),1134)
-# TriGorilla Anycubic version 1.4 Rev 1.1
+# TriGorilla Anycubic version 1.4 based on RAMPS EFB
else ifeq ($(HARDWARE_MOTHERBOARD),1135)
-# Creality: Ender-4, CR-8
+# TriGorilla Anycubic version 1.4 Rev 1.1
else ifeq ($(HARDWARE_MOTHERBOARD),1136)
-# Creality: CR10S, CR20, CR-X
+# Creality: Ender-4, CR-8
else ifeq ($(HARDWARE_MOTHERBOARD),1137)
-# Dagoma F5
+# Creality: CR10S, CR20, CR-X
else ifeq ($(HARDWARE_MOTHERBOARD),1138)
-# FYSETC F6 1.3
+# Dagoma F5
else ifeq ($(HARDWARE_MOTHERBOARD),1139)
-# FYSETC F6 1.5
+# FYSETC F6 1.3
else ifeq ($(HARDWARE_MOTHERBOARD),1140)
-# Duplicator i3 Plus
+# FYSETC F6 1.5
else ifeq ($(HARDWARE_MOTHERBOARD),1141)
-# VORON
+# Duplicator i3 Plus
else ifeq ($(HARDWARE_MOTHERBOARD),1142)
-# TRONXY V3 1.0
+# VORON
else ifeq ($(HARDWARE_MOTHERBOARD),1143)
-# Z-Bolt X Series
+# TRONXY V3 1.0
else ifeq ($(HARDWARE_MOTHERBOARD),1144)
-# TT OSCAR
+# Z-Bolt X Series
else ifeq ($(HARDWARE_MOTHERBOARD),1145)
-# Overlord/Overlord Pro
+# TT OSCAR
else ifeq ($(HARDWARE_MOTHERBOARD),1146)
-# ADIMLab Gantry v1
+# Overlord/Overlord Pro
else ifeq ($(HARDWARE_MOTHERBOARD),1147)
-# ADIMLab Gantry v2
+# ADIMLab Gantry v1
else ifeq ($(HARDWARE_MOTHERBOARD),1148)
-# BIQU Tango V1
+# ADIMLab Gantry v2
else ifeq ($(HARDWARE_MOTHERBOARD),1149)
-# MKS GEN L V2
+# BIQU Tango V1
else ifeq ($(HARDWARE_MOTHERBOARD),1150)
-# Copymaster 3D
+# MKS GEN L V2
else ifeq ($(HARDWARE_MOTHERBOARD),1151)
-# Ortur 4
+# MKS GEN L V2.1
else ifeq ($(HARDWARE_MOTHERBOARD),1152)
-# Tenlog D3 Hero
+# Copymaster 3D
else ifeq ($(HARDWARE_MOTHERBOARD),1153)
+# Ortur 4
+else ifeq ($(HARDWARE_MOTHERBOARD),1154)
+# Tenlog D3 Hero
+else ifeq ($(HARDWARE_MOTHERBOARD),1155)
#
# RAMBo and derivatives
@@ -694,7 +698,7 @@ ifeq ($(HARDWARE_VARIANT), Teensy)
LIB_CXXSRC += usb_api.cpp
else ifeq ($(HARDWARE_VARIANT), archim)
- CDEFS += -DARDUINO_SAM_ARCHIM -DARDUINO_ARCH_SAM -D__SAM3X8E__ -DUSB_VID=0x27b1 -DUSB_PID=0x0001 -DUSBCON '-DUSB_MANUFACTURER="UltiMachine"' '-DUSB_PRODUCT="Archim"'
+ CDEFS += -DARDUINO_SAM_ARCHIM -DARDUINO_ARCH_SAM -D__SAM3X8E__ -DUSB_VID=0x27b1 -DUSB_PID=0x0001 -DUSBCON '-DUSB_MANUFACTURER="UltiMachine"' '-DUSB_PRODUCT_STRING="Archim"'
LIB_CXXSRC += variant.cpp IPAddress.cpp Reset.cpp RingBuffer.cpp Stream.cpp UARTClass.cpp USARTClass.cpp abi.cpp new.cpp watchdog.cpp CDC.cpp PluggableUSB.cpp USBCore.cpp
LIB_SRC += cortex_handlers.c iar_calls_sam3.c syscalls_sam3.c dtostrf.c itoa.c
diff --git a/Marlin/src/HAL/AVR/HAL.h b/Marlin/src/HAL/AVR/HAL.h
index 609375e386..b606d0c231 100644
--- a/Marlin/src/HAL/AVR/HAL.h
+++ b/Marlin/src/HAL/AVR/HAL.h
@@ -15,6 +15,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
+ *
*/
#pragma once
@@ -81,54 +82,29 @@ typedef int8_t pin_t;
// Serial ports
#ifdef USBCON
- #if ENABLED(BLUETOOTH)
- #define MYSERIAL0 bluetoothSerial
- #else
- #define MYSERIAL0 Serial
- #endif
- #define NUM_SERIAL 1
+ #define MYSERIAL0 TERN(BLUETOOTH, bluetoothSerial, Serial)
#else
#if !WITHIN(SERIAL_PORT, -1, 3)
#error "SERIAL_PORT must be from -1 to 3. Please update your configuration."
#endif
-
#define MYSERIAL0 customizedSerial1
#ifdef SERIAL_PORT_2
#if !WITHIN(SERIAL_PORT_2, -1, 3)
#error "SERIAL_PORT_2 must be from -1 to 3. Please update your configuration."
- #elif SERIAL_PORT_2 == SERIAL_PORT
- #error "SERIAL_PORT_2 must be different than SERIAL_PORT. Please update your configuration."
#endif
#define MYSERIAL1 customizedSerial2
- #define NUM_SERIAL 2
- #else
- #define NUM_SERIAL 1
#endif
#endif
-#ifdef DGUS_SERIAL_PORT
- #if !WITHIN(DGUS_SERIAL_PORT, -1, 3)
- #error "DGUS_SERIAL_PORT must be from -1 to 3. Please update your configuration."
- #elif DGUS_SERIAL_PORT == SERIAL_PORT
- #error "DGUS_SERIAL_PORT must be different than SERIAL_PORT. Please update your configuration."
- #elif defined(SERIAL_PORT_2) && DGUS_SERIAL_PORT == SERIAL_PORT_2
- #error "DGUS_SERIAL_PORT must be different than SERIAL_PORT_2. Please update your configuration."
+#ifdef LCD_SERIAL_PORT
+ #if !WITHIN(LCD_SERIAL_PORT, -1, 3)
+ #error "LCD_SERIAL_PORT must be from -1 to 3. Please update your configuration."
#endif
- #define DGUS_SERIAL internalDgusSerial
-
- #define DGUS_SERIAL_GET_TX_BUFFER_FREE DGUS_SERIAL.get_tx_buffer_free
-#endif
-
-#ifdef ANYCUBIC_LCD_SERIAL_PORT
- #if !WITHIN(ANYCUBIC_LCD_SERIAL_PORT, -1, 3)
- #error "ANYCUBIC_LCD_SERIAL_PORT must be from -1 to 3. Please update your configuration."
- #elif ANYCUBIC_LCD_SERIAL_PORT == SERIAL_PORT
- #error "ANYCUBIC_LCD_SERIAL_PORT must be different than SERIAL_PORT. Please update your configuration."
- #elif defined(SERIAL_PORT_2) && ANYCUBIC_LCD_SERIAL_PORT == SERIAL_PORT_2
- #error "ANYCUBIC_LCD_SERIAL_PORT must be different than SERIAL_PORT_2. Please update your configuration."
+ #define LCD_SERIAL lcdSerial
+ #if HAS_DGUS_LCD
+ #define SERIAL_GET_TX_BUFFER_FREE() LCD_SERIAL.get_tx_buffer_free()
#endif
- #define ANYCUBIC_LCD_SERIAL anycubicLcdSerial
#endif
// ------------------------
diff --git a/Marlin/src/HAL/AVR/MarlinSerial.cpp b/Marlin/src/HAL/AVR/MarlinSerial.cpp
index 3d44a3f59f..63599efd41 100644
--- a/Marlin/src/HAL/AVR/MarlinSerial.cpp
+++ b/Marlin/src/HAL/AVR/MarlinSerial.cpp
@@ -40,407 +40,370 @@
#if !defined(USBCON) && (defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(UBRR2H) || defined(UBRR3H))
- #include "MarlinSerial.h"
- #include "../../MarlinCore.h"
+#include "MarlinSerial.h"
+#include "../../MarlinCore.h"
+
+#if ENABLED(DIRECT_STEPPING)
+ #include "../../feature/direct_stepping.h"
+#endif
+
+template typename MarlinSerial::ring_buffer_r MarlinSerial::rx_buffer = { 0, 0, { 0 } };
+template typename MarlinSerial::ring_buffer_t MarlinSerial::tx_buffer = { 0 };
+template bool MarlinSerial::_written = false;
+template uint8_t MarlinSerial::xon_xoff_state = MarlinSerial::XON_XOFF_CHAR_SENT | MarlinSerial::XON_CHAR;
+template uint8_t MarlinSerial::rx_dropped_bytes = 0;
+template uint8_t MarlinSerial::rx_buffer_overruns = 0;
+template uint8_t MarlinSerial::rx_framing_errors = 0;
+template typename MarlinSerial::ring_buffer_pos_t MarlinSerial::rx_max_enqueued = 0;
+
+// A SW memory barrier, to ensure GCC does not overoptimize loops
+#define sw_barrier() asm volatile("": : :"memory");
+
+#include "../../feature/e_parser.h"
+
+// "Atomically" read the RX head index value without disabling interrupts:
+// This MUST be called with RX interrupts enabled, and CAN'T be called
+// from the RX ISR itself!
+template
+FORCE_INLINE typename MarlinSerial::ring_buffer_pos_t MarlinSerial::atomic_read_rx_head() {
+ if (Cfg::RX_SIZE > 256) {
+ // Keep reading until 2 consecutive reads return the same value,
+ // meaning there was no update in-between caused by an interrupt.
+ // This works because serial RX interrupts happen at a slower rate
+ // than successive reads of a variable, so 2 consecutive reads with
+ // the same value means no interrupt updated it.
+ ring_buffer_pos_t vold, vnew = rx_buffer.head;
+ sw_barrier();
+ do {
+ vold = vnew;
+ vnew = rx_buffer.head;
+ sw_barrier();
+ } while (vold != vnew);
+ return vnew;
+ }
+ else {
+ // With an 8bit index, reads are always atomic. No need for special handling
+ return rx_buffer.head;
+ }
+}
+
+template
+volatile bool MarlinSerial::rx_tail_value_not_stable = false;
+template
+volatile uint16_t MarlinSerial::rx_tail_value_backup = 0;
+
+// Set RX tail index, taking into account the RX ISR could interrupt
+// the write to this variable in the middle - So a backup strategy
+// is used to ensure reads of the correct values.
+// -Must NOT be called from the RX ISR -
+template
+FORCE_INLINE void MarlinSerial::atomic_set_rx_tail(typename MarlinSerial::ring_buffer_pos_t value) {
+ if (Cfg::RX_SIZE > 256) {
+ // Store the new value in the backup
+ rx_tail_value_backup = value;
+ sw_barrier();
+ // Flag we are about to change the true value
+ rx_tail_value_not_stable = true;
+ sw_barrier();
+ // Store the new value
+ rx_buffer.tail = value;
+ sw_barrier();
+ // Signal the new value is completely stored into the value
+ rx_tail_value_not_stable = false;
+ sw_barrier();
+ }
+ else
+ rx_buffer.tail = value;
+}
+
+// Get the RX tail index, taking into account the read could be
+// interrupting in the middle of the update of that index value
+// -Called from the RX ISR -
+template
+FORCE_INLINE typename MarlinSerial::ring_buffer_pos_t MarlinSerial::atomic_read_rx_tail() {
+ if (Cfg::RX_SIZE > 256) {
+ // If the true index is being modified, return the backup value
+ if (rx_tail_value_not_stable) return rx_tail_value_backup;
+ }
+ // The true index is stable, return it
+ return rx_buffer.tail;
+}
+
+// (called with RX interrupts disabled)
+template
+FORCE_INLINE void MarlinSerial::store_rxd_char() {
+
+ static EmergencyParser::State emergency_state; // = EP_RESET
+
+ // This must read the R_UCSRA register before reading the received byte to detect error causes
+ if (Cfg::DROPPED_RX && B_DOR && !++rx_dropped_bytes) --rx_dropped_bytes;
+ if (Cfg::RX_OVERRUNS && B_DOR && !++rx_buffer_overruns) --rx_buffer_overruns;
+ if (Cfg::RX_FRAMING_ERRORS && B_FE && !++rx_framing_errors) --rx_framing_errors;
+
+ // Read the character from the USART
+ uint8_t c = R_UDR;
#if ENABLED(DIRECT_STEPPING)
- #include "../../feature/direct_stepping.h"
+ if (page_manager.maybe_store_rxd_char(c)) return;
#endif
- template typename MarlinSerial::ring_buffer_r MarlinSerial::rx_buffer = { 0, 0, { 0 } };
- template typename MarlinSerial::ring_buffer_t MarlinSerial::tx_buffer = { 0 };
- template bool MarlinSerial::_written = false;
- template uint8_t MarlinSerial::xon_xoff_state = MarlinSerial::XON_XOFF_CHAR_SENT | MarlinSerial::XON_CHAR;
- template uint8_t MarlinSerial::rx_dropped_bytes = 0;
- template uint8_t MarlinSerial::rx_buffer_overruns = 0;
- template uint8_t MarlinSerial::rx_framing_errors = 0;
- template typename MarlinSerial::ring_buffer_pos_t MarlinSerial::rx_max_enqueued = 0;
+ // Get the tail - Nothing can alter its value while this ISR is executing, but there's
+ // a chance that this ISR interrupted the main process while it was updating the index.
+ // The backup mechanism ensures the correct value is always returned.
+ const ring_buffer_pos_t t = atomic_read_rx_tail();
- // A SW memory barrier, to ensure GCC does not overoptimize loops
- #define sw_barrier() asm volatile("": : :"memory");
+ // Get the head pointer - This ISR is the only one that modifies its value, so it's safe to read here
+ ring_buffer_pos_t h = rx_buffer.head;
- #include "../../feature/e_parser.h"
+ // Get the next element
+ ring_buffer_pos_t i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
- // "Atomically" read the RX head index value without disabling interrupts:
- // This MUST be called with RX interrupts enabled, and CAN'T be called
- // from the RX ISR itself!
- template
- FORCE_INLINE typename MarlinSerial::ring_buffer_pos_t MarlinSerial::atomic_read_rx_head() {
- if (Cfg::RX_SIZE > 256) {
- // Keep reading until 2 consecutive reads return the same value,
- // meaning there was no update in-between caused by an interrupt.
- // This works because serial RX interrupts happen at a slower rate
- // than successive reads of a variable, so 2 consecutive reads with
- // the same value means no interrupt updated it.
- ring_buffer_pos_t vold, vnew = rx_buffer.head;
- sw_barrier();
- do {
- vold = vnew;
- vnew = rx_buffer.head;
- sw_barrier();
- } while (vold != vnew);
- return vnew;
- }
- else {
- // With an 8bit index, reads are always atomic. No need for special handling
- return rx_buffer.head;
- }
+ if (Cfg::EMERGENCYPARSER) emergency_parser.update(emergency_state, c);
+
+ // If the character is to be stored at the index just before the tail
+ // (such that the head would advance to the current tail), the RX FIFO is
+ // full, so don't write the character or advance the head.
+ if (i != t) {
+ rx_buffer.buffer[h] = c;
+ h = i;
+ }
+ else if (Cfg::DROPPED_RX && !++rx_dropped_bytes)
+ --rx_dropped_bytes;
+
+ if (Cfg::MAX_RX_QUEUED) {
+ // Calculate count of bytes stored into the RX buffer
+ const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
+
+ // Keep track of the maximum count of enqueued bytes
+ NOLESS(rx_max_enqueued, rx_count);
}
- template
- volatile bool MarlinSerial::rx_tail_value_not_stable = false;
- template
- volatile uint16_t MarlinSerial::rx_tail_value_backup = 0;
+ if (Cfg::XONOFF) {
+ // If the last char that was sent was an XON
+ if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XON_CHAR) {
- // Set RX tail index, taking into account the RX ISR could interrupt
- // the write to this variable in the middle - So a backup strategy
- // is used to ensure reads of the correct values.
- // -Must NOT be called from the RX ISR -
- template
- FORCE_INLINE void MarlinSerial::atomic_set_rx_tail(typename MarlinSerial::ring_buffer_pos_t value) {
- if (Cfg::RX_SIZE > 256) {
- // Store the new value in the backup
- rx_tail_value_backup = value;
- sw_barrier();
- // Flag we are about to change the true value
- rx_tail_value_not_stable = true;
- sw_barrier();
- // Store the new value
- rx_buffer.tail = value;
- sw_barrier();
- // Signal the new value is completely stored into the value
- rx_tail_value_not_stable = false;
- sw_barrier();
- }
- else
- rx_buffer.tail = value;
- }
-
- // Get the RX tail index, taking into account the read could be
- // interrupting in the middle of the update of that index value
- // -Called from the RX ISR -
- template
- FORCE_INLINE typename MarlinSerial::ring_buffer_pos_t MarlinSerial::atomic_read_rx_tail() {
- if (Cfg::RX_SIZE > 256) {
- // If the true index is being modified, return the backup value
- if (rx_tail_value_not_stable) return rx_tail_value_backup;
- }
- // The true index is stable, return it
- return rx_buffer.tail;
- }
-
- // (called with RX interrupts disabled)
- template
- FORCE_INLINE void MarlinSerial::store_rxd_char() {
-
- static EmergencyParser::State emergency_state; // = EP_RESET
-
- // This must read the R_UCSRA register before reading the received byte to detect error causes
- if (Cfg::DROPPED_RX && B_DOR && !++rx_dropped_bytes) --rx_dropped_bytes;
- if (Cfg::RX_OVERRUNS && B_DOR && !++rx_buffer_overruns) --rx_buffer_overruns;
- if (Cfg::RX_FRAMING_ERRORS && B_FE && !++rx_framing_errors) --rx_framing_errors;
-
- // Read the character from the USART
- uint8_t c = R_UDR;
-
- #if ENABLED(DIRECT_STEPPING)
- if (page_manager.maybe_store_rxd_char(c)) return;
- #endif
-
- // Get the tail - Nothing can alter its value while this ISR is executing, but there's
- // a chance that this ISR interrupted the main process while it was updating the index.
- // The backup mechanism ensures the correct value is always returned.
- const ring_buffer_pos_t t = atomic_read_rx_tail();
-
- // Get the head pointer - This ISR is the only one that modifies its value, so it's safe to read here
- ring_buffer_pos_t h = rx_buffer.head;
-
- // Get the next element
- ring_buffer_pos_t i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
-
- if (Cfg::EMERGENCYPARSER) emergency_parser.update(emergency_state, c);
-
- // If the character is to be stored at the index just before the tail
- // (such that the head would advance to the current tail), the RX FIFO is
- // full, so don't write the character or advance the head.
- if (i != t) {
- rx_buffer.buffer[h] = c;
- h = i;
- }
- else if (Cfg::DROPPED_RX && !++rx_dropped_bytes)
- --rx_dropped_bytes;
-
- if (Cfg::MAX_RX_QUEUED) {
- // Calculate count of bytes stored into the RX buffer
+ // Bytes stored into the RX buffer
const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
- // Keep track of the maximum count of enqueued bytes
- NOLESS(rx_max_enqueued, rx_count);
- }
+ // If over 12.5% of RX buffer capacity, send XOFF before running out of
+ // RX buffer space .. 325 bytes @ 250kbits/s needed to let the host react
+ // and stop sending bytes. This translates to 13mS propagation time.
+ if (rx_count >= (Cfg::RX_SIZE) / 8) {
- if (Cfg::XONOFF) {
- // If the last char that was sent was an XON
- if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XON_CHAR) {
+ // At this point, definitely no TX interrupt was executing, since the TX ISR can't be preempted.
+ // Don't enable the TX interrupt here as a means to trigger the XOFF char, because if it happens
+ // to be in the middle of trying to disable the RX interrupt in the main program, eventually the
+ // enabling of the TX interrupt could be undone. The ONLY reliable thing this can do to ensure
+ // the sending of the XOFF char is to send it HERE AND NOW.
- // Bytes stored into the RX buffer
- const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
+ // About to send the XOFF char
+ xon_xoff_state = XOFF_CHAR | XON_XOFF_CHAR_SENT;
- // If over 12.5% of RX buffer capacity, send XOFF before running out of
- // RX buffer space .. 325 bytes @ 250kbits/s needed to let the host react
- // and stop sending bytes. This translates to 13mS propagation time.
- if (rx_count >= (Cfg::RX_SIZE) / 8) {
+ // Wait until the TX register becomes empty and send it - Here there could be a problem
+ // - While waiting for the TX register to empty, the RX register could receive a new
+ // character. This must also handle that situation!
+ while (!B_UDRE) {
- // At this point, definitely no TX interrupt was executing, since the TX ISR can't be preempted.
- // Don't enable the TX interrupt here as a means to trigger the XOFF char, because if it happens
- // to be in the middle of trying to disable the RX interrupt in the main program, eventually the
- // enabling of the TX interrupt could be undone. The ONLY reliable thing this can do to ensure
- // the sending of the XOFF char is to send it HERE AND NOW.
+ if (B_RXC) {
+ // A char arrived while waiting for the TX buffer to be empty - Receive and process it!
- // About to send the XOFF char
- xon_xoff_state = XOFF_CHAR | XON_XOFF_CHAR_SENT;
+ i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
- // Wait until the TX register becomes empty and send it - Here there could be a problem
- // - While waiting for the TX register to empty, the RX register could receive a new
- // character. This must also handle that situation!
- while (!B_UDRE) {
+ // Read the character from the USART
+ c = R_UDR;
- if (B_RXC) {
- // A char arrived while waiting for the TX buffer to be empty - Receive and process it!
+ if (Cfg::EMERGENCYPARSER) emergency_parser.update(emergency_state, c);
- i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
-
- // Read the character from the USART
- c = R_UDR;
-
- if (Cfg::EMERGENCYPARSER) emergency_parser.update(emergency_state, c);
-
- // If the character is to be stored at the index just before the tail
- // (such that the head would advance to the current tail), the FIFO is
- // full, so don't write the character or advance the head.
- if (i != t) {
- rx_buffer.buffer[h] = c;
- h = i;
- }
- else if (Cfg::DROPPED_RX && !++rx_dropped_bytes)
- --rx_dropped_bytes;
+ // If the character is to be stored at the index just before the tail
+ // (such that the head would advance to the current tail), the FIFO is
+ // full, so don't write the character or advance the head.
+ if (i != t) {
+ rx_buffer.buffer[h] = c;
+ h = i;
}
- sw_barrier();
+ else if (Cfg::DROPPED_RX && !++rx_dropped_bytes)
+ --rx_dropped_bytes;
}
-
- R_UDR = XOFF_CHAR;
-
- // Clear the TXC bit -- "can be cleared by writing a one to its bit
- // location". This makes sure flush() won't return until the bytes
- // actually got written
- B_TXC = 1;
-
- // At this point there could be a race condition between the write() function
- // and this sending of the XOFF char. This interrupt could happen between the
- // wait to be empty TX buffer loop and the actual write of the character. Since
- // the TX buffer is full because it's sending the XOFF char, the only way to be
- // sure the write() function will succeed is to wait for the XOFF char to be
- // completely sent. Since an extra character could be received during the wait
- // it must also be handled!
- while (!B_UDRE) {
-
- if (B_RXC) {
- // A char arrived while waiting for the TX buffer to be empty - Receive and process it!
-
- i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
-
- // Read the character from the USART
- c = R_UDR;
-
- if (Cfg::EMERGENCYPARSER)
- emergency_parser.update(emergency_state, c);
-
- // If the character is to be stored at the index just before the tail
- // (such that the head would advance to the current tail), the FIFO is
- // full, so don't write the character or advance the head.
- if (i != t) {
- rx_buffer.buffer[h] = c;
- h = i;
- }
- else if (Cfg::DROPPED_RX && !++rx_dropped_bytes)
- --rx_dropped_bytes;
- }
- sw_barrier();
- }
-
- // At this point everything is ready. The write() function won't
- // have any issues writing to the UART TX register if it needs to!
+ sw_barrier();
}
+
+ R_UDR = XOFF_CHAR;
+
+ // Clear the TXC bit -- "can be cleared by writing a one to its bit
+ // location". This makes sure flush() won't return until the bytes
+ // actually got written
+ B_TXC = 1;
+
+ // At this point there could be a race condition between the write() function
+ // and this sending of the XOFF char. This interrupt could happen between the
+ // wait to be empty TX buffer loop and the actual write of the character. Since
+ // the TX buffer is full because it's sending the XOFF char, the only way to be
+ // sure the write() function will succeed is to wait for the XOFF char to be
+ // completely sent. Since an extra character could be received during the wait
+ // it must also be handled!
+ while (!B_UDRE) {
+
+ if (B_RXC) {
+ // A char arrived while waiting for the TX buffer to be empty - Receive and process it!
+
+ i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
+
+ // Read the character from the USART
+ c = R_UDR;
+
+ if (Cfg::EMERGENCYPARSER)
+ emergency_parser.update(emergency_state, c);
+
+ // If the character is to be stored at the index just before the tail
+ // (such that the head would advance to the current tail), the FIFO is
+ // full, so don't write the character or advance the head.
+ if (i != t) {
+ rx_buffer.buffer[h] = c;
+ h = i;
+ }
+ else if (Cfg::DROPPED_RX && !++rx_dropped_bytes)
+ --rx_dropped_bytes;
+ }
+ sw_barrier();
+ }
+
+ // At this point everything is ready. The write() function won't
+ // have any issues writing to the UART TX register if it needs to!
}
}
-
- // Store the new head value - The main loop will retry until the value is stable
- rx_buffer.head = h;
}
- // (called with TX irqs disabled)
- template
- FORCE_INLINE void MarlinSerial::_tx_udr_empty_irq() {
- if (Cfg::TX_SIZE > 0) {
- // Read positions
- uint8_t t = tx_buffer.tail;
- const uint8_t h = tx_buffer.head;
+ // Store the new head value - The main loop will retry until the value is stable
+ rx_buffer.head = h;
+}
- if (Cfg::XONOFF) {
- // If an XON char is pending to be sent, do it now
- if (xon_xoff_state == XON_CHAR) {
+// (called with TX irqs disabled)
+template
+FORCE_INLINE void MarlinSerial::_tx_udr_empty_irq() {
+ if (Cfg::TX_SIZE > 0) {
+ // Read positions
+ uint8_t t = tx_buffer.tail;
+ const uint8_t h = tx_buffer.head;
- // Send the character
- R_UDR = XON_CHAR;
+ if (Cfg::XONOFF) {
+ // If an XON char is pending to be sent, do it now
+ if (xon_xoff_state == XON_CHAR) {
- // clear the TXC bit -- "can be cleared by writing a one to its bit
- // location". This makes sure flush() won't return until the bytes
- // actually got written
- B_TXC = 1;
+ // Send the character
+ R_UDR = XON_CHAR;
- // Remember we sent it.
- xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
+ // clear the TXC bit -- "can be cleared by writing a one to its bit
+ // location". This makes sure flush() won't return until the bytes
+ // actually got written
+ B_TXC = 1;
- // If nothing else to transmit, just disable TX interrupts.
- if (h == t) B_UDRIE = 0; // (Non-atomic, could be reenabled by the main program, but eventually this will succeed)
+ // Remember we sent it.
+ xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
- return;
- }
- }
+ // If nothing else to transmit, just disable TX interrupts.
+ if (h == t) B_UDRIE = 0; // (Non-atomic, could be reenabled by the main program, but eventually this will succeed)
- // If nothing to transmit, just disable TX interrupts. This could
- // happen as the result of the non atomicity of the disabling of RX
- // interrupts that could end reenabling TX interrupts as a side effect.
- if (h == t) {
- B_UDRIE = 0; // (Non-atomic, could be reenabled by the main program, but eventually this will succeed)
return;
}
-
- // There is something to TX, Send the next byte
- const uint8_t c = tx_buffer.buffer[t];
- t = (t + 1) & (Cfg::TX_SIZE - 1);
- R_UDR = c;
- tx_buffer.tail = t;
-
- // Clear the TXC bit (by writing a one to its bit location).
- // Ensures flush() won't return until the bytes are actually written/
- B_TXC = 1;
-
- // Disable interrupts if there is nothing to transmit following this byte
- if (h == t) B_UDRIE = 0; // (Non-atomic, could be reenabled by the main program, but eventually this will succeed)
- }
- }
-
- // Public Methods
- template
- void MarlinSerial::begin(const long baud) {
- uint16_t baud_setting;
- bool useU2X = true;
-
- #if F_CPU == 16000000UL && SERIAL_PORT == 0
- // Hard-coded exception for compatibility with the bootloader shipped
- // with the Duemilanove and previous boards, and the firmware on the
- // 8U2 on the Uno and Mega 2560.
- if (baud == 57600) useU2X = false;
- #endif
-
- R_UCSRA = 0;
- if (useU2X) {
- B_U2X = 1;
- baud_setting = (F_CPU / 4 / baud - 1) / 2;
- }
- else
- baud_setting = (F_CPU / 8 / baud - 1) / 2;
-
- // assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register)
- R_UBRRH = baud_setting >> 8;
- R_UBRRL = baud_setting;
-
- B_RXEN = 1;
- B_TXEN = 1;
- B_RXCIE = 1;
- if (Cfg::TX_SIZE > 0) B_UDRIE = 0;
- _written = false;
- }
-
- template
- void MarlinSerial::end() {
- B_RXEN = 0;
- B_TXEN = 0;
- B_RXCIE = 0;
- B_UDRIE = 0;
- }
-
- template
- int MarlinSerial::peek() {
- const ring_buffer_pos_t h = atomic_read_rx_head(), t = rx_buffer.tail;
- return h == t ? -1 : rx_buffer.buffer[t];
- }
-
- template
- int MarlinSerial::read() {
- const ring_buffer_pos_t h = atomic_read_rx_head();
-
- // Read the tail. Main thread owns it, so it is safe to directly read it
- ring_buffer_pos_t t = rx_buffer.tail;
-
- // If nothing to read, return now
- if (h == t) return -1;
-
- // Get the next char
- const int v = rx_buffer.buffer[t];
- t = (ring_buffer_pos_t)(t + 1) & (Cfg::RX_SIZE - 1);
-
- // Advance tail - Making sure the RX ISR will always get an stable value, even
- // if it interrupts the writing of the value of that variable in the middle.
- atomic_set_rx_tail(t);
-
- if (Cfg::XONOFF) {
- // If the XOFF char was sent, or about to be sent...
- if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XOFF_CHAR) {
- // Get count of bytes in the RX buffer
- const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
- if (rx_count < (Cfg::RX_SIZE) / 10) {
- if (Cfg::TX_SIZE > 0) {
- // Signal we want an XON character to be sent.
- xon_xoff_state = XON_CHAR;
- // Enable TX ISR. Non atomic, but it will eventually enable them
- B_UDRIE = 1;
- }
- else {
- // If not using TX interrupts, we must send the XON char now
- xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
- while (!B_UDRE) sw_barrier();
- R_UDR = XON_CHAR;
- }
- }
- }
}
- return v;
+ // If nothing to transmit, just disable TX interrupts. This could
+ // happen as the result of the non atomicity of the disabling of RX
+ // interrupts that could end reenabling TX interrupts as a side effect.
+ if (h == t) {
+ B_UDRIE = 0; // (Non-atomic, could be reenabled by the main program, but eventually this will succeed)
+ return;
+ }
+
+ // There is something to TX, Send the next byte
+ const uint8_t c = tx_buffer.buffer[t];
+ t = (t + 1) & (Cfg::TX_SIZE - 1);
+ R_UDR = c;
+ tx_buffer.tail = t;
+
+ // Clear the TXC bit (by writing a one to its bit location).
+ // Ensures flush() won't return until the bytes are actually written/
+ B_TXC = 1;
+
+ // Disable interrupts if there is nothing to transmit following this byte
+ if (h == t) B_UDRIE = 0; // (Non-atomic, could be reenabled by the main program, but eventually this will succeed)
}
+}
- template
- typename MarlinSerial::ring_buffer_pos_t MarlinSerial::available() {
- const ring_buffer_pos_t h = atomic_read_rx_head(), t = rx_buffer.tail;
- return (ring_buffer_pos_t)(Cfg::RX_SIZE + h - t) & (Cfg::RX_SIZE - 1);
+// Public Methods
+template
+void MarlinSerial::begin(const long baud) {
+ uint16_t baud_setting;
+ bool useU2X = true;
+
+ #if F_CPU == 16000000UL && SERIAL_PORT == 0
+ // Hard-coded exception for compatibility with the bootloader shipped
+ // with the Duemilanove and previous boards, and the firmware on the
+ // 8U2 on the Uno and Mega 2560.
+ if (baud == 57600) useU2X = false;
+ #endif
+
+ R_UCSRA = 0;
+ if (useU2X) {
+ B_U2X = 1;
+ baud_setting = (F_CPU / 4 / baud - 1) / 2;
}
+ else
+ baud_setting = (F_CPU / 8 / baud - 1) / 2;
- template
- void MarlinSerial::flush() {
+ // assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register)
+ R_UBRRH = baud_setting >> 8;
+ R_UBRRL = baud_setting;
- // Set the tail to the head:
- // - Read the RX head index in a safe way. (See atomic_read_rx_head.)
- // - Set the tail, making sure the RX ISR will always get a stable value, even
- // if it interrupts the writing of the value of that variable in the middle.
- atomic_set_rx_tail(atomic_read_rx_head());
+ B_RXEN = 1;
+ B_TXEN = 1;
+ B_RXCIE = 1;
+ if (Cfg::TX_SIZE > 0) B_UDRIE = 0;
+ _written = false;
+}
- if (Cfg::XONOFF) {
- // If the XOFF char was sent, or about to be sent...
- if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XOFF_CHAR) {
+template
+void MarlinSerial::end() {
+ B_RXEN = 0;
+ B_TXEN = 0;
+ B_RXCIE = 0;
+ B_UDRIE = 0;
+}
+
+template
+int MarlinSerial::peek() {
+ const ring_buffer_pos_t h = atomic_read_rx_head(), t = rx_buffer.tail;
+ return h == t ? -1 : rx_buffer.buffer[t];
+}
+
+template
+int MarlinSerial::read() {
+ const ring_buffer_pos_t h = atomic_read_rx_head();
+
+ // Read the tail. Main thread owns it, so it is safe to directly read it
+ ring_buffer_pos_t t = rx_buffer.tail;
+
+ // If nothing to read, return now
+ if (h == t) return -1;
+
+ // Get the next char
+ const int v = rx_buffer.buffer[t];
+ t = (ring_buffer_pos_t)(t + 1) & (Cfg::RX_SIZE - 1);
+
+ // Advance tail - Making sure the RX ISR will always get an stable value, even
+ // if it interrupts the writing of the value of that variable in the middle.
+ atomic_set_rx_tail(t);
+
+ if (Cfg::XONOFF) {
+ // If the XOFF char was sent, or about to be sent...
+ if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XOFF_CHAR) {
+ // Get count of bytes in the RX buffer
+ const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
+ if (rx_count < (Cfg::RX_SIZE) / 10) {
if (Cfg::TX_SIZE > 0) {
// Signal we want an XON character to be sent.
xon_xoff_state = XON_CHAR;
- // Enable TX ISR. Non atomic, but it will eventually enable it.
+ // Enable TX ISR. Non atomic, but it will eventually enable them
B_UDRIE = 1;
}
else {
@@ -453,363 +416,384 @@
}
}
- template
- void MarlinSerial::write(const uint8_t c) {
- if (Cfg::TX_SIZE == 0) {
+ return v;
+}
- _written = true;
- while (!B_UDRE) sw_barrier();
+template
+typename MarlinSerial::ring_buffer_pos_t MarlinSerial::available() {
+ const ring_buffer_pos_t h = atomic_read_rx_head(), t = rx_buffer.tail;
+ return (ring_buffer_pos_t)(Cfg::RX_SIZE + h - t) & (Cfg::RX_SIZE - 1);
+}
+
+template
+void MarlinSerial::flush() {
+
+ // Set the tail to the head:
+ // - Read the RX head index in a safe way. (See atomic_read_rx_head.)
+ // - Set the tail, making sure the RX ISR will always get a stable value, even
+ // if it interrupts the writing of the value of that variable in the middle.
+ atomic_set_rx_tail(atomic_read_rx_head());
+
+ if (Cfg::XONOFF) {
+ // If the XOFF char was sent, or about to be sent...
+ if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XOFF_CHAR) {
+ if (Cfg::TX_SIZE > 0) {
+ // Signal we want an XON character to be sent.
+ xon_xoff_state = XON_CHAR;
+ // Enable TX ISR. Non atomic, but it will eventually enable it.
+ B_UDRIE = 1;
+ }
+ else {
+ // If not using TX interrupts, we must send the XON char now
+ xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
+ while (!B_UDRE) sw_barrier();
+ R_UDR = XON_CHAR;
+ }
+ }
+ }
+}
+
+template
+void MarlinSerial::write(const uint8_t c) {
+ if (Cfg::TX_SIZE == 0) {
+
+ _written = true;
+ while (!B_UDRE) sw_barrier();
+ R_UDR = c;
+
+ }
+ else {
+
+ _written = true;
+
+ // If the TX interrupts are disabled and the data register
+ // is empty, just write the byte to the data register and
+ // be done. This shortcut helps significantly improve the
+ // effective datarate at high (>500kbit/s) bitrates, where
+ // interrupt overhead becomes a slowdown.
+ // Yes, there is a race condition between the sending of the
+ // XOFF char at the RX ISR, but it is properly handled there
+ if (!B_UDRIE && B_UDRE) {
R_UDR = c;
+ // clear the TXC bit -- "can be cleared by writing a one to its bit
+ // location". This makes sure flush() won't return until the bytes
+ // actually got written
+ B_TXC = 1;
+ return;
+ }
+
+ const uint8_t i = (tx_buffer.head + 1) & (Cfg::TX_SIZE - 1);
+
+ // If global interrupts are disabled (as the result of being called from an ISR)...
+ if (!ISRS_ENABLED()) {
+
+ // Make room by polling if it is possible to transmit, and do so!
+ while (i == tx_buffer.tail) {
+
+ // If we can transmit another byte, do it.
+ if (B_UDRE) _tx_udr_empty_irq();
+
+ // Make sure compiler rereads tx_buffer.tail
+ sw_barrier();
+ }
}
else {
-
- _written = true;
-
- // If the TX interrupts are disabled and the data register
- // is empty, just write the byte to the data register and
- // be done. This shortcut helps significantly improve the
- // effective datarate at high (>500kbit/s) bitrates, where
- // interrupt overhead becomes a slowdown.
- // Yes, there is a race condition between the sending of the
- // XOFF char at the RX ISR, but it is properly handled there
- if (!B_UDRIE && B_UDRE) {
- R_UDR = c;
-
- // clear the TXC bit -- "can be cleared by writing a one to its bit
- // location". This makes sure flush() won't return until the bytes
- // actually got written
- B_TXC = 1;
- return;
- }
-
- const uint8_t i = (tx_buffer.head + 1) & (Cfg::TX_SIZE - 1);
-
- // If global interrupts are disabled (as the result of being called from an ISR)...
- if (!ISRS_ENABLED()) {
-
- // Make room by polling if it is possible to transmit, and do so!
- while (i == tx_buffer.tail) {
-
- // If we can transmit another byte, do it.
- if (B_UDRE) _tx_udr_empty_irq();
-
- // Make sure compiler rereads tx_buffer.tail
- sw_barrier();
- }
- }
- else {
- // Interrupts are enabled, just wait until there is space
- while (i == tx_buffer.tail) sw_barrier();
- }
-
- // Store new char. head is always safe to move
- tx_buffer.buffer[tx_buffer.head] = c;
- tx_buffer.head = i;
-
- // Enable TX ISR - Non atomic, but it will eventually enable TX ISR
- B_UDRIE = 1;
+ // Interrupts are enabled, just wait until there is space
+ while (i == tx_buffer.tail) sw_barrier();
}
+
+ // Store new char. head is always safe to move
+ tx_buffer.buffer[tx_buffer.head] = c;
+ tx_buffer.head = i;
+
+ // Enable TX ISR - Non atomic, but it will eventually enable TX ISR
+ B_UDRIE = 1;
}
+}
- template
- void MarlinSerial::flushTX() {
+template
+void MarlinSerial::flushTX() {
- if (Cfg::TX_SIZE == 0) {
- // No bytes written, no need to flush. This special case is needed since there's
- // no way to force the TXC (transmit complete) bit to 1 during initialization.
- if (!_written) return;
+ if (Cfg::TX_SIZE == 0) {
+ // No bytes written, no need to flush. This special case is needed since there's
+ // no way to force the TXC (transmit complete) bit to 1 during initialization.
+ if (!_written) return;
+ // Wait until everything was transmitted
+ while (!B_TXC) sw_barrier();
+
+ // At this point nothing is queued anymore (DRIE is disabled) and
+ // the hardware finished transmission (TXC is set).
+
+ }
+ else {
+
+ // No bytes written, no need to flush. This special case is needed since there's
+ // no way to force the TXC (transmit complete) bit to 1 during initialization.
+ if (!_written) return;
+
+ // If global interrupts are disabled (as the result of being called from an ISR)...
+ if (!ISRS_ENABLED()) {
+
+ // Wait until everything was transmitted - We must do polling, as interrupts are disabled
+ while (tx_buffer.head != tx_buffer.tail || !B_TXC) {
+
+ // If there is more space, send an extra character
+ if (B_UDRE) _tx_udr_empty_irq();
+
+ sw_barrier();
+ }
+
+ }
+ else {
// Wait until everything was transmitted
- while (!B_TXC) sw_barrier();
-
- // At this point nothing is queued anymore (DRIE is disabled) and
- // the hardware finished transmission (TXC is set).
-
- }
- else {
-
- // No bytes written, no need to flush. This special case is needed since there's
- // no way to force the TXC (transmit complete) bit to 1 during initialization.
- if (!_written) return;
-
- // If global interrupts are disabled (as the result of being called from an ISR)...
- if (!ISRS_ENABLED()) {
-
- // Wait until everything was transmitted - We must do polling, as interrupts are disabled
- while (tx_buffer.head != tx_buffer.tail || !B_TXC) {
-
- // If there is more space, send an extra character
- if (B_UDRE) _tx_udr_empty_irq();
-
- sw_barrier();
- }
-
- }
- else {
- // Wait until everything was transmitted
- while (tx_buffer.head != tx_buffer.tail || !B_TXC) sw_barrier();
- }
-
- // At this point nothing is queued anymore (DRIE is disabled) and
- // the hardware finished transmission (TXC is set).
- }
- }
-
- /**
- * 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;
+ while (tx_buffer.head != tx_buffer.tail || !B_TXC) sw_barrier();
}
- // 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;
+ // At this point nothing is queued anymore (DRIE is disabled) and
+ // the hardware finished transmission (TXC is set).
+ }
+}
- // 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);
+/**
+ * Imports from print.h
+ */
- // 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;
- }
+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();
+}
+
+ISR(SERIAL_REGNAME(USART, SERIAL_PORT, _UDRE_vect)) {
+ MarlinSerial>::_tx_udr_empty_irq();
+}
+
+// Preinstantiate
+template class MarlinSerial>;
+
+// Instantiate
+MarlinSerial> customizedSerial1;
+
+#ifdef SERIAL_PORT_2
// Hookup ISR handlers
- ISR(SERIAL_REGNAME(USART,SERIAL_PORT,_RX_vect)) {
- MarlinSerial>::store_rxd_char();
+ ISR(SERIAL_REGNAME(USART, SERIAL_PORT_2, _RX_vect)) {
+ MarlinSerial>::store_rxd_char();
}
- ISR(SERIAL_REGNAME(USART,SERIAL_PORT,_UDRE_vect)) {
- MarlinSerial>::_tx_udr_empty_irq();
+ ISR(SERIAL_REGNAME(USART, SERIAL_PORT_2, _UDRE_vect)) {
+ MarlinSerial>::_tx_udr_empty_irq();
}
// Preinstantiate
- template class MarlinSerial>;
+ template class MarlinSerial>;
// Instantiate
- MarlinSerial> customizedSerial1;
+ MarlinSerial> customizedSerial2;
- #ifdef SERIAL_PORT_2
+#endif
- // Hookup ISR handlers
- ISR(SERIAL_REGNAME(USART,SERIAL_PORT_2,_RX_vect)) {
- MarlinSerial>::store_rxd_char();
+#ifdef MMU2_SERIAL_PORT
+
+ ISR(SERIAL_REGNAME(USART, MMU2_SERIAL_PORT, _RX_vect)) {
+ MarlinSerial>::store_rxd_char();
+ }
+
+ ISR(SERIAL_REGNAME(USART, MMU2_SERIAL_PORT, _UDRE_vect)) {
+ MarlinSerial>::_tx_udr_empty_irq();
+ }
+
+ // Preinstantiate
+ template class MarlinSerial>;
+
+ // Instantiate
+ MarlinSerial> mmuSerial;
+
+#endif
+
+#ifdef LCD_SERIAL_PORT
+
+ ISR(SERIAL_REGNAME(USART, LCD_SERIAL_PORT, _RX_vect)) {
+ MarlinSerial>::store_rxd_char();
+ }
+
+ ISR(SERIAL_REGNAME(USART, LCD_SERIAL_PORT, _UDRE_vect)) {
+ MarlinSerial>::_tx_udr_empty_irq();
+ }
+
+ // Preinstantiate
+ template class MarlinSerial>;
+
+ // Instantiate
+ MarlinSerial> lcdSerial;
+
+ #if HAS_DGUS_LCD
+ template
+ typename MarlinSerial::ring_buffer_pos_t MarlinSerial::get_tx_buffer_free() {
+ const ring_buffer_pos_t t = tx_buffer.tail, // next byte to send.
+ h = tx_buffer.head; // next pos for queue.
+ int ret = t - h - 1;
+ if (ret < 0) ret += Cfg::TX_SIZE + 1;
+ return ret;
}
-
- ISR(SERIAL_REGNAME(USART,SERIAL_PORT_2,_UDRE_vect)) {
- MarlinSerial>::_tx_udr_empty_irq();
- }
-
- // Preinstantiate
- template class MarlinSerial>;
-
- // Instantiate
- MarlinSerial> customizedSerial2;
-
#endif
+#endif
+
#endif // !USBCON && (UBRRH || UBRR0H || UBRR1H || UBRR2H || UBRR3H)
-#ifdef INTERNAL_SERIAL_PORT
-
- ISR(SERIAL_REGNAME(USART,INTERNAL_SERIAL_PORT,_RX_vect)) {
- MarlinSerial>::store_rxd_char();
- }
-
- ISR(SERIAL_REGNAME(USART,INTERNAL_SERIAL_PORT,_UDRE_vect)) {
- MarlinSerial>::_tx_udr_empty_irq();
- }
-
- // Preinstantiate
- template class MarlinSerial>;
-
- // Instantiate
- MarlinSerial> internalSerial;
-
-#endif
-
-#ifdef DGUS_SERIAL_PORT
-
- template
- typename MarlinSerial::ring_buffer_pos_t MarlinSerial::get_tx_buffer_free() {
- const ring_buffer_pos_t t = tx_buffer.tail, // next byte to send.
- h = tx_buffer.head; // next pos for queue.
- int ret = t - h - 1;
- if (ret < 0) ret += Cfg::TX_SIZE + 1;
- return ret;
- }
-
- ISR(SERIAL_REGNAME(USART,DGUS_SERIAL_PORT,_RX_vect)) {
- MarlinSerial>::store_rxd_char();
- }
-
- ISR(SERIAL_REGNAME(USART,DGUS_SERIAL_PORT,_UDRE_vect)) {
- MarlinSerial>::_tx_udr_empty_irq();
- }
-
- // Preinstantiate
- template class MarlinSerial>;
-
- // Instantiate
- MarlinSerial> internalDgusSerial;
-
-#endif
-
-#ifdef ANYCUBIC_LCD_SERIAL_PORT
-
- ISR(SERIAL_REGNAME(USART,ANYCUBIC_LCD_SERIAL_PORT,_RX_vect)) {
- MarlinSerial>::store_rxd_char();
- }
-
- ISR(SERIAL_REGNAME(USART,ANYCUBIC_LCD_SERIAL_PORT,_UDRE_vect)) {
- MarlinSerial>::_tx_udr_empty_irq();
- }
-
- // Preinstantiate
- template class MarlinSerial>;
-
- // Instantiate
- MarlinSerial> anycubicLcdSerial;
-
-#endif
-
// For AT90USB targets use the UART for BT interfacing
#if defined(USBCON) && ENABLED(BLUETOOTH)
HardwareSerial bluetoothSerial;
diff --git a/Marlin/src/HAL/AVR/MarlinSerial.h b/Marlin/src/HAL/AVR/MarlinSerial.h
index e8bfc5583a..8a0423d143 100644
--- a/Marlin/src/HAL/AVR/MarlinSerial.h
+++ b/Marlin/src/HAL/AVR/MarlinSerial.h
@@ -48,11 +48,11 @@
// These are macros to build serial port register names for the selected SERIAL_PORT (C preprocessor
// requires two levels of indirection to expand macro values properly)
- #define SERIAL_REGNAME(registerbase,number,suffix) SERIAL_REGNAME_INTERNAL(registerbase,number,suffix)
+ #define SERIAL_REGNAME(registerbase,number,suffix) _SERIAL_REGNAME(registerbase,number,suffix)
#if SERIAL_PORT == 0 && (!defined(UBRR0H) || !defined(UDR0)) // use un-numbered registers if necessary
- #define SERIAL_REGNAME_INTERNAL(registerbase,number,suffix) registerbase##suffix
+ #define _SERIAL_REGNAME(registerbase,number,suffix) registerbase##suffix
#else
- #define SERIAL_REGNAME_INTERNAL(registerbase,number,suffix) registerbase##number##suffix
+ #define _SERIAL_REGNAME(registerbase,number,suffix) registerbase##number##suffix
#endif
// Registers used by MarlinSerial class (expanded depending on selected serial port)
@@ -217,10 +217,12 @@
static ring_buffer_pos_t available();
static void write(const uint8_t c);
static void flushTX();
- #ifdef DGUS_SERIAL_PORT
+ #if HAS_DGUS_LCD
static ring_buffer_pos_t get_tx_buffer_free();
#endif
+ 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; }
@@ -278,55 +280,50 @@
#endif // !USBCON
-#ifdef INTERNAL_SERIAL_PORT
+#ifdef MMU2_SERIAL_PORT
template
- struct MarlinInternalSerialCfg {
+ struct MMU2SerialCfg {
static constexpr int PORT = serial;
+ static constexpr bool XONOFF = false;
+ static constexpr bool EMERGENCYPARSER = false;
+ static constexpr bool DROPPED_RX = false;
+ static constexpr bool RX_FRAMING_ERRORS = false;
+ static constexpr bool MAX_RX_QUEUED = false;
static constexpr unsigned int RX_SIZE = 32;
static constexpr unsigned int TX_SIZE = 32;
- static constexpr bool XONOFF = false;
- static constexpr bool EMERGENCYPARSER = false;
- static constexpr bool DROPPED_RX = false;
static constexpr bool RX_OVERRUNS = false;
- static constexpr bool RX_FRAMING_ERRORS = false;
- static constexpr bool MAX_RX_QUEUED = false;
};
- extern MarlinSerial> internalSerial;
+ extern MarlinSerial> mmuSerial;
#endif
-#ifdef DGUS_SERIAL_PORT
+#ifdef LCD_SERIAL_PORT
+
template
- struct MarlinInternalSerialCfg {
- static constexpr int PORT = serial;
- static constexpr unsigned int RX_SIZE = DGUS_RX_BUFFER_SIZE;
- static constexpr unsigned int TX_SIZE = DGUS_TX_BUFFER_SIZE;
- static constexpr bool XONOFF = false;
- static constexpr bool EMERGENCYPARSER = false;
- static constexpr bool DROPPED_RX = false;
- static constexpr bool RX_OVERRUNS = BOTH(HAS_DGUS_LCD, DGUS_SERIAL_STATS_RX_BUFFER_OVERRUNS);
- static constexpr bool RX_FRAMING_ERRORS = false;
- static constexpr bool MAX_RX_QUEUED = false;
+ struct LCDSerialCfg {
+ static constexpr int PORT = serial;
+ static constexpr bool XONOFF = false;
+ static constexpr bool EMERGENCYPARSER = ENABLED(EMERGENCY_PARSER);
+ static constexpr bool DROPPED_RX = false;
+ static constexpr bool RX_FRAMING_ERRORS = false;
+ static constexpr bool MAX_RX_QUEUED = false;
+ #if HAS_DGUS_LCD
+ static constexpr unsigned int RX_SIZE = DGUS_RX_BUFFER_SIZE;
+ static constexpr unsigned int TX_SIZE = DGUS_TX_BUFFER_SIZE;
+ static constexpr bool RX_OVERRUNS = ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS);
+ #elif EITHER(ANYCUBIC_LCD_I3MEGA, ANYCUBIC_LCD_CHIRON)
+ static constexpr unsigned int RX_SIZE = 64;
+ static constexpr unsigned int TX_SIZE = 128;
+ static constexpr bool RX_OVERRUNS = false;
+ #else
+ static constexpr unsigned int RX_SIZE = 64;
+ static constexpr unsigned int TX_SIZE = 128;
+ static constexpr bool RX_OVERRUNS = false
+ #endif
};
- extern MarlinSerial> internalDgusSerial;
-#endif
+ extern MarlinSerial> lcdSerial;
-#ifdef ANYCUBIC_LCD_SERIAL_PORT
- template
- struct AnycubicLcdSerialCfg {
- static constexpr int PORT = serial;
- static constexpr unsigned int RX_SIZE = 64;
- static constexpr unsigned int TX_SIZE = 128;
- static constexpr bool XONOFF = false;
- static constexpr bool EMERGENCYPARSER = false;
- static constexpr bool DROPPED_RX = false;
- static constexpr bool RX_OVERRUNS = false;
- static constexpr bool RX_FRAMING_ERRORS = false;
- static constexpr bool MAX_RX_QUEUED = false;
- };
-
- extern MarlinSerial> anycubicLcdSerial;
#endif
// Use the UART for Bluetooth in AT90USB configurations
diff --git a/Marlin/src/HAL/AVR/Servo.cpp b/Marlin/src/HAL/AVR/Servo.cpp
index 66ed993c6f..526352b773 100644
--- a/Marlin/src/HAL/AVR/Servo.cpp
+++ b/Marlin/src/HAL/AVR/Servo.cpp
@@ -48,7 +48,6 @@
* readMicroseconds() - Get the last-written servo pulse width in microseconds.
* attached() - Return true if a servo is attached.
* detach() - Stop an attached servo from pulsing its i/o pin.
- *
*/
#ifdef __AVR__
diff --git a/Marlin/src/HAL/AVR/fastio.h b/Marlin/src/HAL/AVR/fastio.h
index bd6935aaf0..dd01634661 100644
--- a/Marlin/src/HAL/AVR/fastio.h
+++ b/Marlin/src/HAL/AVR/fastio.h
@@ -29,11 +29,17 @@
#include
-#define AVR_AT90USB1286_FAMILY (defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1286P__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB646P__) || defined(__AVR_AT90USB647__))
-#define AVR_ATmega1284_FAMILY (defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) || defined(__AVR_ATmega1284P__))
-#define AVR_ATmega2560_FAMILY (defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__))
-#define AVR_ATmega2561_FAMILY (defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__))
-#define AVR_ATmega328_FAMILY (defined(__AVR_ATmega168__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__))
+#if defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1286P__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB646P__) || defined(__AVR_AT90USB647__)
+ #define AVR_AT90USB1286_FAMILY 1
+#elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) || defined(__AVR_ATmega1284P__)
+ #define AVR_ATmega1284_FAMILY 1
+#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
+ #define AVR_ATmega2560_FAMILY 1
+#elif defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
+ #define AVR_ATmega2561_FAMILY 1
+#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__)
+ #define AVR_ATmega328_FAMILY 1
+#endif
/**
* Include Ports and Functions
diff --git a/Marlin/src/HAL/AVR/pinsDebug.h b/Marlin/src/HAL/AVR/pinsDebug.h
index d73f520d14..dac6b1b150 100644
--- a/Marlin/src/HAL/AVR/pinsDebug.h
+++ b/Marlin/src/HAL/AVR/pinsDebug.h
@@ -26,7 +26,9 @@
#define NUMBER_PINS_TOTAL NUM_DIGITAL_PINS
-#define AVR_ATmega2560_FAMILY_PLUS_70 MB(BQ_ZUM_MEGA_3D, MIGHTYBOARD_REVE, MINIRAMBO, SCOOVO_X9H)
+#if MB(BQ_ZUM_MEGA_3D, MIGHTYBOARD_REVE, MINIRAMBO, SCOOVO_X9H, TRIGORILLA_14)
+ #define AVR_ATmega2560_FAMILY_PLUS_70 1
+#endif
#if AVR_AT90USB1286_FAMILY
diff --git a/Marlin/src/HAL/AVR/pinsDebug_plus_70.h b/Marlin/src/HAL/AVR/pinsDebug_plus_70.h
index 46c03088d2..db3fdf1f76 100644
--- a/Marlin/src/HAL/AVR/pinsDebug_plus_70.h
+++ b/Marlin/src/HAL/AVR/pinsDebug_plus_70.h
@@ -22,15 +22,12 @@
* Structures for 2560 family boards that use more than 70 pins
*/
-#undef NUM_DIGITAL_PINS
-#if MB(BQ_ZUM_MEGA_3D)
+#if MB(BQ_ZUM_MEGA_3D, MINIRAMBO, SCOOVO_X9H, TRIGORILLA_14)
+ #undef NUM_DIGITAL_PINS
#define NUM_DIGITAL_PINS 85
#elif MB(MIGHTYBOARD_REVE)
+ #undef NUM_DIGITAL_PINS
#define NUM_DIGITAL_PINS 80
-#elif MB(MINIRAMBO)
- #define NUM_DIGITAL_PINS 85
-#elif MB(SCOOVO_X9H)
- #define NUM_DIGITAL_PINS 85
#endif
#define PA 1
diff --git a/Marlin/src/HAL/AVR/timers.h b/Marlin/src/HAL/AVR/timers.h
index 6c40d32209..82eb8b14b1 100644
--- a/Marlin/src/HAL/AVR/timers.h
+++ b/Marlin/src/HAL/AVR/timers.h
@@ -15,6 +15,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
+ *
*/
#pragma once
diff --git a/Marlin/src/HAL/AVR/u8g_com_HAL_AVR_sw_spi.cpp b/Marlin/src/HAL/AVR/u8g_com_HAL_AVR_sw_spi.cpp
index c29b195578..cb95a48ccc 100644
--- a/Marlin/src/HAL/AVR/u8g_com_HAL_AVR_sw_spi.cpp
+++ b/Marlin/src/HAL/AVR/u8g_com_HAL_AVR_sw_spi.cpp
@@ -57,7 +57,7 @@
#include "../../inc/MarlinConfigPre.h"
-#if HAS_GRAPHICAL_LCD
+#if HAS_MARLINUI_U8GLIB
#include "../shared/Marduino.h"
#include "../shared/Delay.h"
@@ -189,5 +189,5 @@ uint8_t u8g_com_HAL_AVR_sw_sp_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void
return 1;
}
-#endif // HAS_GRAPHICAL_LCD
+#endif // HAS_MARLINUI_U8GLIB
#endif // ARDUINO_ARCH_SAM
diff --git a/Marlin/src/HAL/DUE/HAL.h b/Marlin/src/HAL/DUE/HAL.h
index 31409c76dd..7a057fdae4 100644
--- a/Marlin/src/HAL/DUE/HAL.h
+++ b/Marlin/src/HAL/DUE/HAL.h
@@ -38,59 +38,36 @@
#include
+#define _MSERIAL(X) Serial##X
+#define MSERIAL(X) _MSERIAL(X)
+#define Serial0 Serial
+
// Define MYSERIAL0/1 before MarlinSerial includes!
#if SERIAL_PORT == -1 || ENABLED(EMERGENCY_PARSER)
#define MYSERIAL0 customizedSerial1
-#elif SERIAL_PORT == 0
- #define MYSERIAL0 Serial
-#elif SERIAL_PORT == 1
- #define MYSERIAL0 Serial1
-#elif SERIAL_PORT == 2
- #define MYSERIAL0 Serial2
-#elif SERIAL_PORT == 3
- #define MYSERIAL0 Serial3
+#elif WITHIN(SERIAL_PORT, 0, 3)
+ #define MYSERIAL0 MSERIAL(SERIAL_PORT)
#else
#error "The required SERIAL_PORT must be from -1 to 3. Please update your configuration."
#endif
#ifdef SERIAL_PORT_2
- #if SERIAL_PORT_2 == SERIAL_PORT
- #error "SERIAL_PORT_2 must be different from SERIAL_PORT. Please update your configuration."
- #elif SERIAL_PORT_2 == -1 || ENABLED(EMERGENCY_PARSER)
+ #if SERIAL_PORT_2 == -1 || ENABLED(EMERGENCY_PARSER)
#define MYSERIAL1 customizedSerial2
- #elif SERIAL_PORT_2 == 0
- #define MYSERIAL1 Serial
- #elif SERIAL_PORT_2 == 1
- #define MYSERIAL1 Serial1
- #elif SERIAL_PORT_2 == 2
- #define MYSERIAL1 Serial2
- #elif SERIAL_PORT_2 == 3
- #define MYSERIAL1 Serial3
+ #elif WITHIN(SERIAL_PORT_2, 0, 3)
+ #define MYSERIAL1 MSERIAL(SERIAL_PORT_2)
#else
#error "SERIAL_PORT_2 must be from -1 to 3. Please update your configuration."
#endif
- #define NUM_SERIAL 2
-#else
- #define NUM_SERIAL 1
#endif
-#ifdef DGUS_SERIAL_PORT
- #if DGUS_SERIAL_PORT == SERIAL_PORT
- #error "DGUS_SERIAL_PORT must be different from SERIAL_PORT. Please update your configuration."
- #elif defined(SERIAL_PORT_2) && DGUS_SERIAL_PORT == SERIAL_PORT_2
- #error "DGUS_SERIAL_PORT must be different than SERIAL_PORT_2. Please update your configuration."
- #elif DGUS_SERIAL_PORT == -1
- #define DGUS_SERIAL internalDgusSerial
- #elif DGUS_SERIAL_PORT == 0
- #define DGUS_SERIAL Serial
- #elif DGUS_SERIAL_PORT == 1
- #define DGUS_SERIAL Serial1
- #elif DGUS_SERIAL_PORT == 2
- #define DGUS_SERIAL Serial2
- #elif DGUS_SERIAL_PORT == 3
- #define DGUS_SERIAL Serial3
+#ifdef LCD_SERIAL_PORT
+ #if LCD_SERIAL_PORT == -1
+ #define LCD_SERIAL lcdSerial
+ #elif WITHIN(LCD_SERIAL_PORT, 0, 3)
+ #define LCD_SERIAL MSERIAL(LCD_SERIAL_PORT)
#else
- #error "DGUS_SERIAL_PORT must be from -1 to 3. Please update your configuration."
+ #error "LCD_SERIAL_PORT must be from -1 to 3. Please update your configuration."
#endif
#endif
diff --git a/Marlin/src/HAL/DUE/HAL_SPI.cpp b/Marlin/src/HAL/DUE/HAL_SPI.cpp
index 6d8f7ef819..54ae8eceb1 100644
--- a/Marlin/src/HAL/DUE/HAL_SPI.cpp
+++ b/Marlin/src/HAL/DUE/HAL_SPI.cpp
@@ -595,7 +595,7 @@
SPI_Enable(SPI0);
SET_OUTPUT(DAC0_SYNC);
- #if EXTRUDERS > 1
+ #if HAS_MULTI_EXTRUDER
SET_OUTPUT(DAC1_SYNC);
WRITE(DAC1_SYNC, HIGH);
#endif
@@ -759,7 +759,6 @@
*
* All of the above can be avoided by defining FORCE_SOFT_SPI to force the
* display to use software SPI.
- *
*/
void spiInit(uint8_t spiRate=6) { // Default to slowest rate if not specified)
diff --git a/Marlin/src/HAL/DUE/MarlinSerial.h b/Marlin/src/HAL/DUE/MarlinSerial.h
index dfafa15141..a194eba2f3 100644
--- a/Marlin/src/HAL/DUE/MarlinSerial.h
+++ b/Marlin/src/HAL/DUE/MarlinSerial.h
@@ -122,6 +122,8 @@ public:
static void write(const uint8_t c);
static void flushTX();
+ 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; }
diff --git a/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_shared_hw_spi.cpp b/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_shared_hw_spi.cpp
index 2ef7011b1c..be4b49c0f9 100644
--- a/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_shared_hw_spi.cpp
+++ b/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_shared_hw_spi.cpp
@@ -52,14 +52,13 @@
* 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.
- *
*/
#ifdef __SAM3X8E__
#include "../../../inc/MarlinConfigPre.h"
-#if HAS_GRAPHICAL_LCD
+#if HAS_MARLINUI_U8GLIB
#include
@@ -145,6 +144,6 @@ uint8_t u8g_com_HAL_DUE_shared_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_va
return 1;
}
-#endif // HAS_GRAPHICAL_LCD
+#endif // HAS_MARLINUI_U8GLIB
-#endif //__SAM3X8E__
+#endif // __SAM3X8E__
diff --git a/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_sw_spi.cpp b/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_sw_spi.cpp
index 54c244d4f6..ea7204fa36 100644
--- a/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_sw_spi.cpp
+++ b/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_sw_spi.cpp
@@ -57,7 +57,7 @@
#include "../../../inc/MarlinConfigPre.h"
-#if HAS_GRAPHICAL_LCD && DISABLED(U8GLIB_ST7920)
+#if HAS_MARLINUI_U8GLIB && DISABLED(U8GLIB_ST7920)
#undef SPI_SPEED
#define SPI_SPEED 2 // About 2 MHz
@@ -144,5 +144,5 @@ uint8_t u8g_com_HAL_DUE_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void
return 1;
}
-#endif // HAS_GRAPHICAL_LCD && !U8GLIB_ST7920
+#endif // HAS_MARLINUI_U8GLIB && !U8GLIB_ST7920
#endif // ARDUINO_ARCH_SAM
diff --git a/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_sw_spi_shared.cpp b/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_sw_spi_shared.cpp
index 960df1bd86..615a386c35 100644
--- a/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_sw_spi_shared.cpp
+++ b/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_sw_spi_shared.cpp
@@ -57,7 +57,7 @@
#include "../../../inc/MarlinConfigPre.h"
-#if HAS_GRAPHICAL_LCD
+#if HAS_MARLINUI_U8GLIB
#include "../../shared/Delay.h"
@@ -108,5 +108,5 @@ void u8g_spiSend_sw_DUE_mode_3(uint8_t val) { // 3.5MHz
}
}
-#endif // HAS_GRAPHICAL_LCD
+#endif // HAS_MARLINUI_U8GLIB
#endif // ARDUINO_ARCH_SAM
diff --git a/Marlin/src/HAL/DUE/eeprom_flash.cpp b/Marlin/src/HAL/DUE/eeprom_flash.cpp
index d98f06039f..67f1f9e40f 100644
--- a/Marlin/src/HAL/DUE/eeprom_flash.cpp
+++ b/Marlin/src/HAL/DUE/eeprom_flash.cpp
@@ -53,7 +53,6 @@
* per page. We can't emulate EE endurance with FLASH for all
* bytes, but we can emulate endurance for a given percent of
* bytes.
- *
*/
//#define EE_EMU_DEBUG
diff --git a/Marlin/src/HAL/DUE/pinsDebug.h b/Marlin/src/HAL/DUE/pinsDebug.h
index 28687ff267..a99ca8ecce 100644
--- a/Marlin/src/HAL/DUE/pinsDebug.h
+++ b/Marlin/src/HAL/DUE/pinsDebug.h
@@ -179,5 +179,4 @@ void pwm_details(int32_t pin) {
* ----------------+--------
* ID | PB11
* VBOF | PB10
- *
*/
diff --git a/Marlin/src/HAL/DUE/usb/compiler.h b/Marlin/src/HAL/DUE/usb/compiler.h
index 7b746543c4..879007fa2a 100644
--- a/Marlin/src/HAL/DUE/usb/compiler.h
+++ b/Marlin/src/HAL/DUE/usb/compiler.h
@@ -173,11 +173,11 @@
# define __always_inline __forceinline
#elif (defined __GNUC__)
#ifdef __always_inline
-# undef __always_inline
+# undef __always_inline
#endif
-# define __always_inline inline __attribute__((__always_inline__))
+# define __always_inline inline __attribute__((__always_inline__))
#elif (defined __ICCARM__)
-# define __always_inline _Pragma("inline=forced")
+# define __always_inline _Pragma("inline=forced")
#endif
/**
@@ -188,11 +188,11 @@
* heuristics and not inline the function.
*/
#ifdef __CC_ARM
-# define __no_inline __attribute__((noinline))
+# define __no_inline __attribute__((noinline))
#elif (defined __GNUC__)
-# define __no_inline __attribute__((__noinline__))
+# define __no_inline __attribute__((__noinline__))
#elif (defined __ICCARM__)
-# define __no_inline _Pragma("inline=never")
+# define __no_inline _Pragma("inline=never")
#endif
/*! \brief This macro is used to test fatal errors.
@@ -211,9 +211,9 @@
# else
#undef TEST_SUITE_DEFINE_ASSERT_MACRO
# define Assert(expr) \
- {\
- if (!(expr)) while (true);\
- }
+ {\
+ if (!(expr)) while (true);\
+ }
# endif
#else
# define Assert(expr) ((void) 0)
@@ -1106,17 +1106,16 @@ static inline uint16_t convert_byte_array_to_16_bit(uint8_t *data)
/* Converts a 8 Byte array into a 32-Bit value */
static inline uint32_t convert_byte_array_to_32_bit(uint8_t *data)
{
- union
- {
- uint32_t u32;
- uint8_t u8[8];
- }long_addr;
- uint8_t index;
- for (index = 0; index < 4; index++)
- {
- long_addr.u8[index] = *data++;
- }
- return long_addr.u32;
+ union
+ {
+ uint32_t u32;
+ uint8_t u8[8];
+ }long_addr;
+ uint8_t index;
+ for (index = 0; index < 4; index++) {
+ long_addr.u8[index] = *data++;
+ }
+ return long_addr.u32;
}
/**
diff --git a/Marlin/src/HAL/ESP32/HAL.h b/Marlin/src/HAL/ESP32/HAL.h
index c91f9efff0..f6fa46dd93 100644
--- a/Marlin/src/HAL/ESP32/HAL.h
+++ b/Marlin/src/HAL/ESP32/HAL.h
@@ -15,6 +15,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
+ *
*/
#pragma once
@@ -58,9 +59,6 @@ extern portMUX_TYPE spinlock;
#else
#define MYSERIAL1 webSocketSerial
#endif
- #define NUM_SERIAL 2
-#else
- #define NUM_SERIAL 1
#endif
#define CRITICAL_SECTION_START() portENTER_CRITICAL(&spinlock)
diff --git a/Marlin/src/HAL/ESP32/WebSocketSerial.cpp b/Marlin/src/HAL/ESP32/WebSocketSerial.cpp
index 533f873e4f..ca7f47a1f8 100644
--- a/Marlin/src/HAL/ESP32/WebSocketSerial.cpp
+++ b/Marlin/src/HAL/ESP32/WebSocketSerial.cpp
@@ -86,7 +86,7 @@ int RingBuffer::read() {
ring_buffer_pos_t RingBuffer::read(uint8_t *buffer) {
ring_buffer_pos_t len = available();
- for(ring_buffer_pos_t i = 0; read_index != write_index; i++) {
+ for (ring_buffer_pos_t i = 0; read_index != write_index; i++) {
buffer[i] = data[read_index];
read_index = NEXT_INDEX(read_index, size);
}
@@ -139,9 +139,8 @@ size_t WebSocketSerial::write(const uint8_t c) {
size_t WebSocketSerial::write(const uint8_t* buffer, size_t size) {
size_t written = 0;
- for(size_t i = 0; i < size; i++) {
+ for (size_t i = 0; i < size; i++)
written += write(buffer[i]);
- }
return written;
}
diff --git a/Marlin/src/HAL/ESP32/ota.h b/Marlin/src/HAL/ESP32/ota.h
index 7f9b237aa6..546ace82db 100644
--- a/Marlin/src/HAL/ESP32/ota.h
+++ b/Marlin/src/HAL/ESP32/ota.h
@@ -15,6 +15,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
+ *
*/
#pragma once
diff --git a/Marlin/src/HAL/HAL.h b/Marlin/src/HAL/HAL.h
index c7b7531442..8b6a978d21 100644
--- a/Marlin/src/HAL/HAL.h
+++ b/Marlin/src/HAL/HAL.h
@@ -25,6 +25,12 @@
#include HAL_PATH(.,HAL.h)
+#ifdef SERIAL_PORT_2
+ #define NUM_SERIAL 2
+#else
+ #define NUM_SERIAL 1
+#endif
+
#define HAL_ADC_RANGE _BV(HAL_ADC_RESOLUTION)
#ifndef I2C_ADDRESS
diff --git a/Marlin/src/HAL/LINUX/HAL.h b/Marlin/src/HAL/LINUX/HAL.h
index 96e121d915..778ba2db4d 100644
--- a/Marlin/src/HAL/LINUX/HAL.h
+++ b/Marlin/src/HAL/LINUX/HAL.h
@@ -62,7 +62,6 @@ uint8_t _getc();
extern HalSerial usb_serial;
#define MYSERIAL0 usb_serial
-#define NUM_SERIAL 1
#define ST7920_DELAY_1 DELAY_NS(600)
#define ST7920_DELAY_2 DELAY_NS(750)
diff --git a/Marlin/src/HAL/LINUX/include/serial.h b/Marlin/src/HAL/LINUX/include/serial.h
index 154e95aec2..e916249389 100644
--- a/Marlin/src/HAL/LINUX/include/serial.h
+++ b/Marlin/src/HAL/LINUX/include/serial.h
@@ -33,7 +33,6 @@
* Generic RingBuffer
* T type of the buffer array
* S size of the buffer (must be power of 2)
- *
*/
template class RingBuffer {
public:
@@ -79,6 +78,7 @@ public:
#if ENABLED(EMERGENCY_PARSER)
EmergencyParser::State emergency_state;
+ static inline bool emergency_parser_enabled() { return true; }
#endif
HalSerial() { host_connected = true; }
diff --git a/Marlin/src/HAL/LINUX/main.cpp b/Marlin/src/HAL/LINUX/main.cpp
index 4eeef318e7..481f059030 100644
--- a/Marlin/src/HAL/LINUX/main.cpp
+++ b/Marlin/src/HAL/LINUX/main.cpp
@@ -107,7 +107,7 @@ int main() {
std::thread write_serial (write_serial_thread);
std::thread read_serial (read_serial_thread);
- #if NUM_SERIAL > 0
+ #ifdef MYSERIAL0
MYSERIAL0.begin(BAUDRATE);
SERIAL_ECHOLNPGM("x86_64 Initialized");
SERIAL_FLUSHTX();
diff --git a/Marlin/src/HAL/LINUX/servo_private.h b/Marlin/src/HAL/LINUX/servo_private.h
index 122cfef3ea..bcc8d2037f 100644
--- a/Marlin/src/HAL/LINUX/servo_private.h
+++ b/Marlin/src/HAL/LINUX/servo_private.h
@@ -45,7 +45,6 @@
* Version 2 Copyright (c) 2009 Michael Margolis. All right reserved.
*
* The only modification was to update/delete macros to match the LPC176x.
- *
*/
#include
diff --git a/Marlin/src/HAL/LINUX/spi_pins.h b/Marlin/src/HAL/LINUX/spi_pins.h
index a444196f04..01ba28e5b6 100644
--- a/Marlin/src/HAL/LINUX/spi_pins.h
+++ b/Marlin/src/HAL/LINUX/spi_pins.h
@@ -24,7 +24,7 @@
#include "../../core/macros.h"
#include "../../inc/MarlinConfigPre.h"
-#if BOTH(HAS_GRAPHICAL_LCD, SDSUPPORT) && (LCD_PINS_D4 == SCK_PIN || LCD_PINS_ENABLE == MOSI_PIN || DOGLCD_SCK == SCK_PIN || DOGLCD_MOSI == MOSI_PIN)
+#if BOTH(HAS_MARLINUI_U8GLIB, SDSUPPORT) && (LCD_PINS_D4 == SCK_PIN || LCD_PINS_ENABLE == MOSI_PIN || DOGLCD_SCK == SCK_PIN || DOGLCD_MOSI == MOSI_PIN)
#define LPC_SOFTWARE_SPI // If the SD card and LCD adapter share the same SPI pins, then software SPI is currently
// needed due to the speed and mode required for communicating with each device being different.
// This requirement can be removed if the SPI access to these devices is updated to use
diff --git a/Marlin/src/HAL/LPC1768/HAL.h b/Marlin/src/HAL/LPC1768/HAL.h
index 0153bacf42..3118aed1b2 100644
--- a/Marlin/src/HAL/LPC1768/HAL.h
+++ b/Marlin/src/HAL/LPC1768/HAL.h
@@ -63,58 +63,35 @@ extern "C" volatile uint32_t _millis;
#define ST7920_DELAY_3 DELAY_NS(750)
#endif
+#define _MSERIAL(X) MSerial##X
+#define MSERIAL(X) _MSERIAL(X)
+#define MSerial0 MSerial
+
#if SERIAL_PORT == -1
#define MYSERIAL0 UsbSerial
-#elif SERIAL_PORT == 0
- #define MYSERIAL0 MSerial
-#elif SERIAL_PORT == 1
- #define MYSERIAL0 MSerial1
-#elif SERIAL_PORT == 2
- #define MYSERIAL0 MSerial2
-#elif SERIAL_PORT == 3
- #define MYSERIAL0 MSerial3
+#elif WITHIN(SERIAL_PORT, 0, 3)
+ #define MYSERIAL0 MSERIAL(SERIAL_PORT)
#else
#error "SERIAL_PORT must be from -1 to 3. Please update your configuration."
#endif
#ifdef SERIAL_PORT_2
- #if SERIAL_PORT_2 == SERIAL_PORT
- #error "SERIAL_PORT_2 must be different than SERIAL_PORT. Please update your configuration."
- #elif SERIAL_PORT_2 == -1
+ #if SERIAL_PORT_2 == -1
#define MYSERIAL1 UsbSerial
- #elif SERIAL_PORT_2 == 0
- #define MYSERIAL1 MSerial
- #elif SERIAL_PORT_2 == 1
- #define MYSERIAL1 MSerial1
- #elif SERIAL_PORT_2 == 2
- #define MYSERIAL1 MSerial2
- #elif SERIAL_PORT_2 == 3
- #define MYSERIAL1 MSerial3
+ #elif WITHIN(SERIAL_PORT_2, 0, 3)
+ #define MYSERIAL1 MSERIAL(SERIAL_PORT_2)
#else
#error "SERIAL_PORT_2 must be from -1 to 3. Please update your configuration."
#endif
- #define NUM_SERIAL 2
-#else
- #define NUM_SERIAL 1
#endif
-#ifdef DGUS_SERIAL_PORT
- #if DGUS_SERIAL_PORT == SERIAL_PORT
- #error "DGUS_SERIAL_PORT must be different than SERIAL_PORT. Please update your configuration."
- #elif defined(SERIAL_PORT_2) && DGUS_SERIAL_PORT == SERIAL_PORT_2
- #error "DGUS_SERIAL_PORT must be different than SERIAL_PORT_2. Please update your configuration."
- #elif DGUS_SERIAL_PORT == -1
- #define DGUS_SERIAL UsbSerial
- #elif DGUS_SERIAL_PORT == 0
- #define DGUS_SERIAL MSerial
- #elif DGUS_SERIAL_PORT == 1
- #define DGUS_SERIAL MSerial1
- #elif DGUS_SERIAL_PORT == 2
- #define DGUS_SERIAL MSerial2
- #elif DGUS_SERIAL_PORT == 3
- #define DGUS_SERIAL MSerial3
+#ifdef LCD_SERIAL_PORT
+ #if LCD_SERIAL_PORT == -1
+ #define LCD_SERIAL UsbSerial
+ #elif WITHIN(LCD_SERIAL_PORT, 0, 3)
+ #define LCD_SERIAL MSERIAL(LCD_SERIAL_PORT)
#else
- #error "DGUS_SERIAL_PORT must be from -1 to 3. Please update your configuration."
+ #error "LCD_SERIAL_PORT must be from -1 to 3. Please update your configuration."
#endif
#endif
diff --git a/Marlin/src/HAL/LPC1768/HAL_SPI.cpp b/Marlin/src/HAL/LPC1768/HAL_SPI.cpp
index 00b4310d1d..b3d2908ac9 100644
--- a/Marlin/src/HAL/LPC1768/HAL_SPI.cpp
+++ b/Marlin/src/HAL/LPC1768/HAL_SPI.cpp
@@ -39,10 +39,10 @@
* Some of the LCD interfaces/adapters result in the LCD SPI and the SD card
* SPI sharing pins. The SCK, MOSI & MISO pins can NOT be set/cleared with
* WRITE nor digitalWrite when the hardware SPI module within the LPC17xx is
- * active. If any of these pins are shared then the software SPI must be used.
+ * active. If any of these pins are shared then the software SPI must be used.
*
- * A more sophisticated hardware SPI can be found at the following link. This
- * implementation has not been fully debugged.
+ * A more sophisticated hardware SPI can be found at the following link.
+ * This implementation has not been fully debugged.
* https://github.com/MarlinFirmware/Marlin/tree/071c7a78f27078fd4aee9a3ef365fcf5e143531e
*/
@@ -100,72 +100,25 @@
#else
- // decide which HW SPI device to use
- #ifndef LPC_HW_SPI_DEV
- #if (SCK_PIN == P0_07 && MISO_PIN == P0_08 && MOSI_PIN == P0_09)
- #define LPC_HW_SPI_DEV 1
- #else
- #if (SCK_PIN == P0_15 && MISO_PIN == P0_17 && MOSI_PIN == P0_18)
- #define LPC_HW_SPI_DEV 0
- #else
- #error "Invalid pins selected for hardware SPI"
- #endif
- #endif
- #endif
- #if LPC_HW_SPI_DEV == 0
- #define LPC_SSPn LPC_SSP0
- #else
- #define LPC_SSPn LPC_SSP1
- #endif
-
void spiBegin() { // setup SCK, MOSI & MISO pins for SSP0
- PINSEL_CFG_Type PinCfg; // data structure to hold init values
- PinCfg.Funcnum = 2;
- PinCfg.OpenDrain = 0;
- PinCfg.Pinmode = 0;
- PinCfg.Pinnum = LPC176x::pin_bit(SCK_PIN);
- PinCfg.Portnum = LPC176x::pin_port(SCK_PIN);
- PINSEL_ConfigPin(&PinCfg);
- SET_OUTPUT(SCK_PIN);
-
- PinCfg.Pinnum = LPC176x::pin_bit(MISO_PIN);
- PinCfg.Portnum = LPC176x::pin_port(MISO_PIN);
- PINSEL_ConfigPin(&PinCfg);
- SET_INPUT(MISO_PIN);
-
- PinCfg.Pinnum = LPC176x::pin_bit(MOSI_PIN);
- PinCfg.Portnum = LPC176x::pin_port(MOSI_PIN);
- PINSEL_ConfigPin(&PinCfg);
- SET_OUTPUT(MOSI_PIN);
- // divide PCLK by 2 for SSP0
- CLKPWR_SetPCLKDiv(LPC_HW_SPI_DEV == 0 ? CLKPWR_PCLKSEL_SSP0 : CLKPWR_PCLKSEL_SSP1, CLKPWR_PCLKSEL_CCLK_DIV_2);
- spiInit(0);
- SSP_Cmd(LPC_SSPn, ENABLE); // start SSP running
+ spiInit(SPI_SPEED);
}
void spiInit(uint8_t spiRate) {
- // table to convert Marlin spiRates (0-5 plus default) into bit rates
- uint32_t Marlin_speed[7]; // CPSR is always 2
- Marlin_speed[0] = 8333333; //(SCR: 2) desired: 8,000,000 actual: 8,333,333 +4.2% SPI_FULL_SPEED
- Marlin_speed[1] = 4166667; //(SCR: 5) desired: 4,000,000 actual: 4,166,667 +4.2% SPI_HALF_SPEED
- Marlin_speed[2] = 2083333; //(SCR: 11) desired: 2,000,000 actual: 2,083,333 +4.2% SPI_QUARTER_SPEED
- Marlin_speed[3] = 1000000; //(SCR: 24) desired: 1,000,000 actual: 1,000,000 SPI_EIGHTH_SPEED
- Marlin_speed[4] = 500000; //(SCR: 49) desired: 500,000 actual: 500,000 SPI_SPEED_5
- Marlin_speed[5] = 250000; //(SCR: 99) desired: 250,000 actual: 250,000 SPI_SPEED_6
- Marlin_speed[6] = 125000; //(SCR:199) desired: 125,000 actual: 125,000 Default from HAL.h
- // setup for SPI mode
- SSP_CFG_Type HW_SPI_init; // data structure to hold init values
- SSP_ConfigStructInit(&HW_SPI_init); // set values for SPI mode
- HW_SPI_init.ClockRate = Marlin_speed[_MIN(spiRate, 6)]; // put in the specified bit rate
- HW_SPI_init.Mode |= SSP_CR1_SSP_EN;
- SSP_Init(LPC_SSPn, &HW_SPI_init); // puts the values into the proper bits in the SSP0 registers
+ #if MISO_PIN == BOARD_SPI1_MISO_PIN
+ SPI.setModule(1);
+ #elif MISO_PIN == BOARD_SPI2_MISO_PIN
+ SPI.setModule(2);
+ #endif
+ SPI.setDataSize(DATA_SIZE_8BIT);
+ SPI.setDataMode(SPI_MODE0);
+
+ SPI.setClock(SPISettings::spiRate2Clock(spiRate));
+ SPI.begin();
}
static uint8_t doio(uint8_t b) {
- /* send and receive a single byte */
- SSP_SendData(LPC_SSPn, b & 0x00FF);
- while (SSP_GetStatus(LPC_SSPn, SSP_STAT_BUSY)); // wait for it to finish
- return SSP_ReceiveData(LPC_SSPn) & 0x00FF;
+ return SPI.transfer(b & 0x00FF) & 0x00FF;
}
void spiSend(uint8_t b) { doio(b); }
@@ -217,63 +170,74 @@ static inline void waitSpiTxEnd(LPC_SSP_TypeDef *spi_d) {
while (SSP_GetStatus(spi_d, SSP_STAT_BUSY) == SET) { /* nada */ } // wait until BSY=0
}
+// Retain the pin init state of the SPI, to avoid init more than once,
+// even if more instances of SPIClass exist
+static bool spiInitialised[BOARD_NR_SPI] = { false };
+
SPIClass::SPIClass(uint8_t device) {
// Init things specific to each SPI device
// clock divider setup is a bit of hack, and needs to be improved at a later date.
- PINSEL_CFG_Type PinCfg; // data structure to hold init values
#if BOARD_NR_SPI >= 1
_settings[0].spi_d = LPC_SSP0;
- // _settings[0].clockDivider = determine_baud_rate(_settings[0].spi_d, _settings[0].clock);
- PinCfg.Funcnum = 2;
- PinCfg.OpenDrain = 0;
- PinCfg.Pinmode = 0;
- PinCfg.Pinnum = LPC176x::pin_bit(BOARD_SPI1_SCK_PIN);
- PinCfg.Portnum = LPC176x::pin_port(BOARD_SPI1_SCK_PIN);
- PINSEL_ConfigPin(&PinCfg);
- SET_OUTPUT(BOARD_SPI1_SCK_PIN);
-
- PinCfg.Pinnum = LPC176x::pin_bit(BOARD_SPI1_MISO_PIN);
- PinCfg.Portnum = LPC176x::pin_port(BOARD_SPI1_MISO_PIN);
- PINSEL_ConfigPin(&PinCfg);
- SET_INPUT(BOARD_SPI1_MISO_PIN);
-
- PinCfg.Pinnum = LPC176x::pin_bit(BOARD_SPI1_MOSI_PIN);
- PinCfg.Portnum = LPC176x::pin_port(BOARD_SPI1_MOSI_PIN);
- PINSEL_ConfigPin(&PinCfg);
- SET_OUTPUT(BOARD_SPI1_MOSI_PIN);
+ _settings[0].dataMode = SPI_MODE0;
+ _settings[0].dataSize = DATA_SIZE_8BIT;
+ _settings[0].clock = SPI_CLOCK_MAX;
+ //_settings[0].clockDivider = determine_baud_rate(_settings[0].spi_d, _settings[0].clock);
#endif
#if BOARD_NR_SPI >= 2
_settings[1].spi_d = LPC_SSP1;
- // _settings[1].clockDivider = determine_baud_rate(_settings[1].spi_d, _settings[1].clock);
- PinCfg.Funcnum = 2;
- PinCfg.OpenDrain = 0;
- PinCfg.Pinmode = 0;
- PinCfg.Pinnum = LPC176x::pin_bit(BOARD_SPI2_SCK_PIN);
- PinCfg.Portnum = LPC176x::pin_port(BOARD_SPI2_SCK_PIN);
- PINSEL_ConfigPin(&PinCfg);
- SET_OUTPUT(BOARD_SPI2_SCK_PIN);
-
- PinCfg.Pinnum = LPC176x::pin_bit(BOARD_SPI2_MISO_PIN);
- PinCfg.Portnum = LPC176x::pin_port(BOARD_SPI2_MISO_PIN);
- PINSEL_ConfigPin(&PinCfg);
- SET_INPUT(BOARD_SPI2_MISO_PIN);
-
- PinCfg.Pinnum = LPC176x::pin_bit(BOARD_SPI2_MOSI_PIN);
- PinCfg.Portnum = LPC176x::pin_port(BOARD_SPI2_MOSI_PIN);
- PINSEL_ConfigPin(&PinCfg);
- SET_OUTPUT(BOARD_SPI2_MOSI_PIN);
+ _settings[1].dataMode = SPI_MODE0;
+ _settings[1].dataSize = DATA_SIZE_8BIT;
+ _settings[1].clock = SPI_CLOCK_MAX;
+ //_settings[1].clockDivider = determine_baud_rate(_settings[1].spi_d, _settings[1].clock);
#endif
setModule(device);
- /* Initialize GPDMA controller */
- //TODO: call once in the constructor? or each time?
+ // Init the GPDMA controller
+ // TODO: call once in the constructor? or each time?
GPDMA_Init();
}
void SPIClass::begin() {
+ // Init the SPI pins in the first begin call
+ if ((_currentSetting->spi_d == LPC_SSP0 && spiInitialised[0] == false) ||
+ (_currentSetting->spi_d == LPC_SSP1 && spiInitialised[1] == false)) {
+ pin_t sck, miso, mosi;
+ if (_currentSetting->spi_d == LPC_SSP0) {
+ sck = BOARD_SPI1_SCK_PIN;
+ miso = BOARD_SPI1_MISO_PIN;
+ mosi = BOARD_SPI1_MOSI_PIN;
+ spiInitialised[0] = true;
+ }
+ else if (_currentSetting->spi_d == LPC_SSP1) {
+ sck = BOARD_SPI2_SCK_PIN;
+ miso = BOARD_SPI2_MISO_PIN;
+ mosi = BOARD_SPI2_MOSI_PIN;
+ spiInitialised[1] = true;
+ }
+ PINSEL_CFG_Type PinCfg; // data structure to hold init values
+ PinCfg.Funcnum = 2;
+ PinCfg.OpenDrain = 0;
+ PinCfg.Pinmode = 0;
+ PinCfg.Pinnum = LPC176x::pin_bit(sck);
+ PinCfg.Portnum = LPC176x::pin_port(sck);
+ PINSEL_ConfigPin(&PinCfg);
+ SET_OUTPUT(sck);
+
+ PinCfg.Pinnum = LPC176x::pin_bit(miso);
+ PinCfg.Portnum = LPC176x::pin_port(miso);
+ PINSEL_ConfigPin(&PinCfg);
+ SET_INPUT(miso);
+
+ PinCfg.Pinnum = LPC176x::pin_bit(mosi);
+ PinCfg.Portnum = LPC176x::pin_port(mosi);
+ PINSEL_ConfigPin(&PinCfg);
+ SET_OUTPUT(mosi);
+ }
+
updateSettings();
SSP_Cmd(_currentSetting->spi_d, ENABLE); // start SSP running
}
@@ -287,7 +251,7 @@ void SPIClass::beginTransaction(const SPISettings &cfg) {
}
uint8_t SPIClass::transfer(const uint16_t b) {
- /* send and receive a single byte */
+ // Send and receive a single byte
SSP_ReceiveData(_currentSetting->spi_d); // read any previous data
SSP_SendData(_currentSetting->spi_d, b);
waitSpiTxEnd(_currentSetting->spi_d); // wait for it to finish
@@ -295,8 +259,7 @@ uint8_t SPIClass::transfer(const uint16_t b) {
}
uint16_t SPIClass::transfer16(const uint16_t data) {
- return (transfer((data >> 8) & 0xFF) << 8)
- | (transfer(data & 0xFF) & 0xFF);
+ return (transfer((data >> 8) & 0xFF) << 8) | (transfer(data & 0xFF) & 0xFF);
}
void SPIClass::end() {
@@ -320,7 +283,7 @@ void SPIClass::dmaSend(void *buf, uint16_t length, bool minc) {
// Destination memory - Not used
GPDMACfg.DstMemAddr = 0;
// Transfer size
- GPDMACfg.TransferSize = (minc ? length : 1);
+ GPDMACfg.TransferSize = length;
// Transfer width
GPDMACfg.TransferWidth = (_currentSetting->dataSize == DATA_SIZE_16BIT) ? GPDMA_WIDTH_HALFWORD : GPDMA_WIDTH_BYTE;
// Transfer type
@@ -335,26 +298,24 @@ void SPIClass::dmaSend(void *buf, uint16_t length, bool minc) {
// Enable dma on SPI
SSP_DMACmd(_currentSetting->spi_d, SSP_DMA_TX, ENABLE);
- // if minc=false, I'm repeating the same byte 'length' times, as I could not find yet how do GPDMA without memory increment
- do {
- // Setup channel with given parameter
- GPDMA_Setup(&GPDMACfg);
+ // Only increase memory if minc is true
+ GPDMACfg.MemoryIncrease = (minc ? GPDMA_DMACCxControl_SI : 0);
- // enabled dma
- GPDMA_ChannelCmd(0, ENABLE);
+ // Setup channel with given parameter
+ GPDMA_Setup(&GPDMACfg);
- // wait data transfer
- while (!GPDMA_IntGetStatus(GPDMA_STAT_INTTC, 0) && !GPDMA_IntGetStatus(GPDMA_STAT_INTERR, 0)) { }
+ // Enable DMA
+ GPDMA_ChannelCmd(0, ENABLE);
- // clear err and int
- GPDMA_ClearIntPending (GPDMA_STATCLR_INTTC, 0);
- GPDMA_ClearIntPending (GPDMA_STATCLR_INTERR, 0);
+ // Wait for data transfer
+ while (!GPDMA_IntGetStatus(GPDMA_STAT_RAWINTTC, 0) && !GPDMA_IntGetStatus(GPDMA_STAT_RAWINTERR, 0)) { }
- // dma disable
- GPDMA_ChannelCmd(0, DISABLE);
+ // Clear err and int
+ GPDMA_ClearIntPending (GPDMA_STATCLR_INTTC, 0);
+ GPDMA_ClearIntPending (GPDMA_STATCLR_INTERR, 0);
- --length;
- } while (!minc && length > 0);
+ // Disable DMA
+ GPDMA_ChannelCmd(0, DISABLE);
waitSpiTxEnd(_currentSetting->spi_d);
@@ -382,7 +343,7 @@ void SPIClass::setBitOrder(uint8_t bitOrder) {
}
void SPIClass::setDataMode(uint8_t dataMode) {
- _currentSetting->dataSize = dataMode;
+ _currentSetting->dataMode = dataMode;
}
void SPIClass::setDataSize(uint32_t ds) {
@@ -413,19 +374,19 @@ void SPIClass::updateSettings() {
switch (_currentSetting->dataMode) {
case SPI_MODE0:
HW_SPI_init.CPHA = SSP_CPHA_FIRST;
- HW_SPI_init.CPOL = SSP_CPOL_HI;
+ HW_SPI_init.CPOL = SSP_CPOL_HI;
break;
case SPI_MODE1:
HW_SPI_init.CPHA = SSP_CPHA_SECOND;
- HW_SPI_init.CPOL = SSP_CPOL_HI;
+ HW_SPI_init.CPOL = SSP_CPOL_HI;
break;
case SPI_MODE2:
HW_SPI_init.CPHA = SSP_CPHA_FIRST;
- HW_SPI_init.CPOL = SSP_CPOL_LO;
+ HW_SPI_init.CPOL = SSP_CPOL_LO;
break;
case SPI_MODE3:
HW_SPI_init.CPHA = SSP_CPHA_SECOND;
- HW_SPI_init.CPOL = SSP_CPOL_LO;
+ HW_SPI_init.CPOL = SSP_CPOL_LO;
break;
default:
break;
diff --git a/Marlin/src/HAL/LPC1768/MarlinSerial.cpp b/Marlin/src/HAL/LPC1768/MarlinSerial.cpp
index c3fb3bd0e4..5374e005d3 100644
--- a/Marlin/src/HAL/LPC1768/MarlinSerial.cpp
+++ b/Marlin/src/HAL/LPC1768/MarlinSerial.cpp
@@ -24,28 +24,28 @@
#include "../../inc/MarlinConfigPre.h"
#include "MarlinSerial.h"
-#if (defined(SERIAL_PORT) && SERIAL_PORT == 0) || (defined(SERIAL_PORT_2) && SERIAL_PORT_2 == 0) || (defined(DGUS_SERIAL_PORT) && DGUS_SERIAL_PORT == 0)
+#if USING_SERIAL_0
MarlinSerial MSerial(LPC_UART0);
extern "C" void UART0_IRQHandler() {
MSerial.IRQHandler();
}
#endif
-#if SERIAL_PORT == 1 || SERIAL_PORT_2 == 1 || DGUS_SERIAL_PORT == 1
+#if USING_SERIAL_1
MarlinSerial MSerial1((LPC_UART_TypeDef *) LPC_UART1);
extern "C" void UART1_IRQHandler() {
MSerial1.IRQHandler();
}
#endif
-#if SERIAL_PORT == 2 || SERIAL_PORT_2 == 2 || DGUS_SERIAL_PORT == 2
+#if USING_SERIAL_2
MarlinSerial MSerial2(LPC_UART2);
extern "C" void UART2_IRQHandler() {
MSerial2.IRQHandler();
}
#endif
-#if SERIAL_PORT == 3 || SERIAL_PORT_2 == 3 || DGUS_SERIAL_PORT == 3
+#if USING_SERIAL_3
MarlinSerial MSerial3(LPC_UART3);
extern "C" void UART3_IRQHandler() {
MSerial3.IRQHandler();
diff --git a/Marlin/src/HAL/LPC1768/MarlinSerial.h b/Marlin/src/HAL/LPC1768/MarlinSerial.h
index 98ce73d377..8d6b64378a 100644
--- a/Marlin/src/HAL/LPC1768/MarlinSerial.h
+++ b/Marlin/src/HAL/LPC1768/MarlinSerial.h
@@ -57,6 +57,7 @@ public:
}
EmergencyParser::State emergency_state;
+ static inline bool emergency_parser_enabled() { return true; }
#endif
};
diff --git a/Marlin/src/HAL/LPC1768/Servo.h b/Marlin/src/HAL/LPC1768/Servo.h
index e953cb9204..eb12fd20f4 100644
--- a/Marlin/src/HAL/LPC1768/Servo.h
+++ b/Marlin/src/HAL/LPC1768/Servo.h
@@ -46,7 +46,6 @@
* Version 2 Copyright (c) 2009 Michael Margolis. All right reserved.
*
* The only modification was to update/delete macros to match the LPC176x.
- *
*/
#include
diff --git a/Marlin/src/HAL/LPC1768/inc/SanityCheck.h b/Marlin/src/HAL/LPC1768/inc/SanityCheck.h
index 0a4e59c6c4..fd82e2884a 100644
--- a/Marlin/src/HAL/LPC1768/inc/SanityCheck.h
+++ b/Marlin/src/HAL/LPC1768/inc/SanityCheck.h
@@ -24,7 +24,7 @@
#if PIO_PLATFORM_VERSION < 1001
#error "nxplpc-arduino-lpc176x package is out of date, Please update the PlatformIO platforms, frameworks and libraries. You may need to remove the platform and let it reinstall automatically."
#endif
-#if PIO_FRAMEWORK_VERSION < 2002
+#if PIO_FRAMEWORK_VERSION < 2005
#error "framework-arduino-lpc176x package is out of date, Please update the PlatformIO platforms, frameworks and libraries."
#endif
@@ -89,7 +89,10 @@ static_assert(DISABLED(BAUD_RATE_GCODE), "BAUD_RATE_GCODE is not yet supported o
* Serial2 | P0_10 | P0_11 |
* Serial3 | P0_00 | P0_01 |
*/
-#if (defined(SERIAL_PORT) && SERIAL_PORT == 0) || (defined(SERIAL_PORT_2) && SERIAL_PORT_2 == 0) || (defined(DGUS_SERIAL_PORT) && DGUS_SERIAL_PORT == 0)
+#define ANY_TX(N,V...) DO(IS_TX##N,||,V)
+#define ANY_RX(N,V...) DO(IS_RX##N,||,V)
+
+#if USING_SERIAL_0
#define IS_TX0(P) (P == P0_02)
#define IS_RX0(P) (P == P0_03)
#if IS_TX0(TMC_SW_MISO) || IS_RX0(TMC_SW_MOSI)
@@ -103,60 +106,67 @@ static_assert(DISABLED(BAUD_RATE_GCODE), "BAUD_RATE_GCODE is not yet supported o
#undef IS_RX0
#endif
-#if SERIAL_PORT == 1 || SERIAL_PORT_2 == 1 || DGUS_SERIAL_PORT == 1
+#if USING_SERIAL_1
#define IS_TX1(P) (P == P0_15)
#define IS_RX1(P) (P == P0_16)
+ #define _IS_TX1_1 IS_TX1
+ #define _IS_RX1_1 IS_RX1
#if IS_TX1(TMC_SW_SCK)
#error "Serial port pins (1) conflict with other pins!"
- #elif HAS_SPI_LCD
+ #elif HAS_WIRED_LCD
#if IS_TX1(BTN_EN2) || IS_RX1(BTN_EN1)
#error "Serial port pins (1) conflict with Encoder Buttons!"
- #elif IS_TX1(SCK_PIN) || IS_TX1(LCD_PINS_D4) || IS_TX1(DOGLCD_SCK) || IS_TX1(LCD_RESET_PIN) || IS_TX1(LCD_PINS_RS) || IS_TX1(SHIFT_CLK) \
- || IS_RX1(LCD_SDSS) || IS_RX1(LCD_PINS_RS) || IS_RX1(MISO_PIN) || IS_RX1(DOGLCD_A0) || IS_RX1(SS_PIN) || IS_RX1(LCD_SDSS) || IS_RX1(DOGLCD_CS) || IS_RX1(LCD_RESET_PIN) || IS_RX1(LCD_BACKLIGHT_PIN)
+ #elif ANY_TX(1, SCK_PIN, LCD_PINS_D4, DOGLCD_SCK, LCD_RESET_PIN, LCD_PINS_RS, SHIFT_CLK) \
+ || ANY_RX(1, LCD_SDSS, LCD_PINS_RS, MISO_PIN, DOGLCD_A0, SS_PIN, LCD_SDSS, DOGLCD_CS, LCD_RESET_PIN, LCD_BACKLIGHT_PIN)
#error "Serial port pins (1) conflict with LCD pins!"
#endif
#endif
#undef IS_TX1
#undef IS_RX1
+ #undef _IS_TX1_1
+ #undef _IS_RX1_1
#endif
-#if SERIAL_PORT == 2 || SERIAL_PORT_2 == 2 || DGUS_SERIAL_PORT == 2
+#if USING_SERIAL_2
#define IS_TX2(P) (P == P0_10)
#define IS_RX2(P) (P == P0_11)
- #if IS_TX2(X2_ENABLE_PIN) || IS_RX2(X2_DIR_PIN) || IS_RX2(X2_STEP_PIN) || (AXIS_HAS_SPI(X2) && IS_TX2(X2_CS_PIN))
+ #define _IS_TX2_1 IS_TX2
+ #define _IS_RX2_1 IS_RX2
+ #if IS_TX2(X2_ENABLE_PIN) || ANY_RX(2, X2_DIR_PIN, X2_STEP_PIN) || (AXIS_HAS_SPI(X2) && IS_TX2(X2_CS_PIN))
#error "Serial port pins (2) conflict with X2 pins!"
- #elif IS_TX2(Y2_ENABLE_PIN) || IS_RX2(Y2_DIR_PIN) || IS_RX2(Y2_STEP_PIN) || (AXIS_HAS_SPI(Y2) && IS_TX2(Y2_CS_PIN))
+ #elif IS_TX2(Y2_ENABLE_PIN) || ANY_RX(2, Y2_DIR_PIN, Y2_STEP_PIN) || (AXIS_HAS_SPI(Y2) && IS_TX2(Y2_CS_PIN))
#error "Serial port pins (2) conflict with Y2 pins!"
- #elif IS_TX2(Z2_ENABLE_PIN) || IS_RX2(Z2_DIR_PIN) || IS_RX2(Z2_STEP_PIN) || (AXIS_HAS_SPI(Z2) && IS_TX2(Z2_CS_PIN))
+ #elif IS_TX2(Z2_ENABLE_PIN) || ANY_RX(2, Z2_DIR_PIN, Z2_STEP_PIN) || (AXIS_HAS_SPI(Z2) && IS_TX2(Z2_CS_PIN))
#error "Serial port pins (2) conflict with Z2 pins!"
- #elif IS_TX2(Z3_ENABLE_PIN) || IS_RX2(Z3_DIR_PIN) || IS_RX2(Z3_STEP_PIN) || (AXIS_HAS_SPI(Z3) && IS_TX2(Z3_CS_PIN))
+ #elif IS_TX2(Z3_ENABLE_PIN) || ANY_RX(2, Z3_DIR_PIN, Z3_STEP_PIN) || (AXIS_HAS_SPI(Z3) && IS_TX2(Z3_CS_PIN))
#error "Serial port pins (2) conflict with Z3 pins!"
- #elif IS_TX2(Z4_ENABLE_PIN) || IS_RX2(Z4_DIR_PIN) || IS_RX2(Z4_STEP_PIN) || (AXIS_HAS_SPI(Z4) && IS_TX2(Z4_CS_PIN))
+ #elif IS_TX2(Z4_ENABLE_PIN) || ANY_RX(2, Z4_DIR_PIN, Z4_STEP_PIN) || (AXIS_HAS_SPI(Z4) && IS_TX2(Z4_CS_PIN))
#error "Serial port pins (2) conflict with Z4 pins!"
- #elif IS_RX2(X_DIR_PIN) || IS_RX2(Y_DIR_PIN)
+ #elif ANY_RX(2, X_DIR_PIN, Y_DIR_PIN)
#error "Serial port pins (2) conflict with other pins!"
#elif Y_HOME_DIR < 0 && IS_TX2(Y_STOP_PIN)
#error "Serial port pins (2) conflict with Y endstop pin!"
#elif HAS_CUSTOM_PROBE_PIN && IS_TX2(Z_MIN_PROBE_PIN)
#error "Serial port pins (2) conflict with probe pin!"
- #elif IS_TX2(X_ENABLE_PIN) || IS_RX2(X_DIR_PIN) || IS_TX2(Y_ENABLE_PIN) || IS_RX2(Y_DIR_PIN)
+ #elif ANY_TX(2, X_ENABLE_PIN, Y_ENABLE_PIN) || ANY_RX(2, X_DIR_PIN, Y_DIR_PIN)
#error "Serial port pins (2) conflict with X/Y stepper pins!"
- #elif EXTRUDERS > 1 && (IS_TX2(E1_ENABLE_PIN) || (AXIS_HAS_SPI(E1) && IS_TX2(E1_CS_PIN)))
+ #elif HAS_MULTI_EXTRUDER && (IS_TX2(E1_ENABLE_PIN) || (AXIS_HAS_SPI(E1) && IS_TX2(E1_CS_PIN)))
#error "Serial port pins (2) conflict with E1 stepper pins!"
- #elif EXTRUDERS && (IS_RX2(E0_DIR_PIN) || IS_RX2(E0_STEP_PIN))
+ #elif EXTRUDERS && ANY_RX(2, E0_DIR_PIN, E0_STEP_PIN)
#error "Serial port pins (2) conflict with E stepper pins!"
#endif
#undef IS_TX2
#undef IS_RX2
+ #undef _IS_TX2_1
+ #undef _IS_RX2_1
#endif
-#if SERIAL_PORT == 3 || SERIAL_PORT_2 == 3 || DGUS_SERIAL_PORT == 3
+#if USING_SERIAL_3
#define PIN_IS_TX3(P) (PIN_EXISTS(P) && P##_PIN == P0_00)
#define PIN_IS_RX3(P) (P##_PIN == P0_01)
#if PIN_IS_TX3(X_MIN) || PIN_IS_RX3(X_MAX)
#error "Serial port pins (3) conflict with X endstop pins!"
- #elif PIN_IS_TX3(Y_SERIAL_TX) || PIN_IS_TX3(Y_SERIAL_RX) \
- || PIN_IS_RX3(X_SERIAL_TX) || PIN_IS_RX3(X_SERIAL_RX)
+ #elif PIN_IS_TX3(Y_SERIAL_TX) || PIN_IS_TX3(Y_SERIAL_RX) || PIN_IS_RX3(X_SERIAL_TX) || PIN_IS_RX3(X_SERIAL_RX)
#error "Serial port pins (3) conflict with X/Y axis UART pins!"
#elif PIN_IS_TX3(X2_DIR) || PIN_IS_RX3(X2_STEP)
#error "Serial port pins (3) conflict with X2 pins!"
@@ -168,13 +178,16 @@ static_assert(DISABLED(BAUD_RATE_GCODE), "BAUD_RATE_GCODE is not yet supported o
#error "Serial port pins (3) conflict with Z3 pins!"
#elif PIN_IS_TX3(Z4_DIR) || PIN_IS_RX3(Z4_STEP)
#error "Serial port pins (3) conflict with Z4 pins!"
- #elif EXTRUDERS > 1 && (PIN_IS_TX3(E1_DIR) || PIN_IS_RX3(E1_STEP))
+ #elif HAS_MULTI_EXTRUDER && (PIN_IS_TX3(E1_DIR) || PIN_IS_RX3(E1_STEP))
#error "Serial port pins (3) conflict with E1 pins!"
#endif
#undef PIN_IS_TX3
#undef PIN_IS_RX3
#endif
+#undef ANY_TX
+#undef ANY_RX
+
//
// Flag any i2c pin conflicts
//
@@ -214,7 +227,7 @@ static_assert(DISABLED(BAUD_RATE_GCODE), "BAUD_RATE_GCODE is not yet supported o
#error "One or more i2c (1) pins overlaps with Z3 pins! Disable i2c peripherals."
#elif PIN_IS_SDA1(Z4_DIR) || PIN_IS_SCL1(Z4_STEP)
#error "One or more i2c (1) pins overlaps with Z4 pins! Disable i2c peripherals."
- #elif EXTRUDERS > 1 && (PIN_IS_SDA1(E1_DIR) || PIN_IS_SCL1(E1_STEP))
+ #elif HAS_MULTI_EXTRUDER && (PIN_IS_SDA1(E1_DIR) || PIN_IS_SCL1(E1_STEP))
#error "One or more i2c (1) pins overlaps with E1 pins! Disable i2c peripherals."
#endif
#undef PIN_IS_SDA1
@@ -240,9 +253,9 @@ static_assert(DISABLED(BAUD_RATE_GCODE), "BAUD_RATE_GCODE is not yet supported o
#error "i2c SDA2 overlaps with Z3 enable pin! Disable i2c peripherals."
#elif PIN_IS_SDA2(Z4_ENABLE)
#error "i2c SDA2 overlaps with Z4 enable pin! Disable i2c peripherals."
- #elif EXTRUDERS > 1 && PIN_IS_SDA2(E1_ENABLE)
+ #elif HAS_MULTI_EXTRUDER && PIN_IS_SDA2(E1_ENABLE)
#error "i2c SDA2 overlaps with E1 enable pin! Disable i2c peripherals."
- #elif EXTRUDERS > 1 && AXIS_HAS_SPI(E1) && PIN_IS_SDA2(E1_CS)
+ #elif HAS_MULTI_EXTRUDER && AXIS_HAS_SPI(E1) && PIN_IS_SDA2(E1_CS)
#error "i2c SDA2 overlaps with E1 CS pin! Disable i2c peripherals."
#elif EXTRUDERS && (PIN_IS_SDA2(E0_STEP) || PIN_IS_SDA2(E0_DIR))
#error "i2c SCL2 overlaps with E0 STEP/DIR pin! Disable i2c peripherals."
diff --git a/Marlin/src/HAL/LPC1768/include/SPI.h b/Marlin/src/HAL/LPC1768/include/SPI.h
index e2645b9290..9da2a32556 100644
--- a/Marlin/src/HAL/LPC1768/include/SPI.h
+++ b/Marlin/src/HAL/LPC1768/include/SPI.h
@@ -61,7 +61,9 @@
class SPISettings {
public:
- SPISettings(uint32_t speed, int, int) : spi_speed(speed) {};
+ SPISettings(uint32_t spiRate, int inBitOrder, int inDataMode) {
+ init_AlwaysInline(spiRate2Clock(spiRate), inBitOrder, inDataMode, DATA_SIZE_8BIT);
+ }
SPISettings(uint32_t inClock, uint8_t inBitOrder, uint8_t inDataMode, uint32_t inDataSize) {
if (__builtin_constant_p(inClock))
init_AlwaysInline(inClock, inBitOrder, inDataMode, inDataSize);
@@ -72,7 +74,19 @@ public:
init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT);
}
- uint32_t spiRate() const { return spi_speed; }
+ //uint32_t spiRate() const { return spi_speed; }
+
+ static inline uint32_t spiRate2Clock(uint32_t spiRate) {
+ uint32_t Marlin_speed[7]; // CPSR is always 2
+ Marlin_speed[0] = 8333333; //(SCR: 2) desired: 8,000,000 actual: 8,333,333 +4.2% SPI_FULL_SPEED
+ Marlin_speed[1] = 4166667; //(SCR: 5) desired: 4,000,000 actual: 4,166,667 +4.2% SPI_HALF_SPEED
+ Marlin_speed[2] = 2083333; //(SCR: 11) desired: 2,000,000 actual: 2,083,333 +4.2% SPI_QUARTER_SPEED
+ Marlin_speed[3] = 1000000; //(SCR: 24) desired: 1,000,000 actual: 1,000,000 SPI_EIGHTH_SPEED
+ Marlin_speed[4] = 500000; //(SCR: 49) desired: 500,000 actual: 500,000 SPI_SPEED_5
+ Marlin_speed[5] = 250000; //(SCR: 99) desired: 250,000 actual: 250,000 SPI_SPEED_6
+ Marlin_speed[6] = 125000; //(SCR:199) desired: 125,000 actual: 125,000 Default from HAL.h
+ return Marlin_speed[spiRate > 6 ? 6 : spiRate];
+ }
private:
void init_MightInline(uint32_t inClock, uint8_t inBitOrder, uint8_t inDataMode, uint32_t inDataSize) {
@@ -85,7 +99,7 @@ private:
dataSize = inDataSize;
}
- uint32_t spi_speed;
+ //uint32_t spi_speed;
uint32_t clock;
uint32_t dataSize;
//uint32_t clockDivider;
@@ -122,7 +136,7 @@ public:
void end();
void beginTransaction(const SPISettings&);
- void endTransaction() {};
+ void endTransaction() {}
// Transfer using 1 "Data Size"
uint8_t transfer(uint16_t data);
diff --git a/Marlin/src/HAL/LPC1768/spi_pins.h b/Marlin/src/HAL/LPC1768/spi_pins.h
index 2e6749bf57..b4da5d4df2 100644
--- a/Marlin/src/HAL/LPC1768/spi_pins.h
+++ b/Marlin/src/HAL/LPC1768/spi_pins.h
@@ -23,7 +23,7 @@
#include "../../core/macros.h"
-#if BOTH(SDSUPPORT, HAS_GRAPHICAL_LCD) && (LCD_PINS_D4 == SCK_PIN || LCD_PINS_ENABLE == MOSI_PIN || DOGLCD_SCK == SCK_PIN || DOGLCD_MOSI == MOSI_PIN)
+#if BOTH(SDSUPPORT, HAS_MARLINUI_U8GLIB) && (LCD_PINS_D4 == SCK_PIN || LCD_PINS_ENABLE == MOSI_PIN || DOGLCD_SCK == SCK_PIN || DOGLCD_MOSI == MOSI_PIN)
#define LPC_SOFTWARE_SPI // If the SD card and LCD adapter share the same SPI pins, then software SPI is currently
// needed due to the speed and mode required for communicating with each device being different.
// This requirement can be removed if the SPI access to these devices is updated to use
diff --git a/Marlin/src/HAL/LPC1768/tft/xpt2046.cpp b/Marlin/src/HAL/LPC1768/tft/xpt2046.cpp
index c72e5f0eac..5f96630043 100644
--- a/Marlin/src/HAL/LPC1768/tft/xpt2046.cpp
+++ b/Marlin/src/HAL/LPC1768/tft/xpt2046.cpp
@@ -72,7 +72,6 @@ bool XPT2046::getRawPoint(int16_t *x, int16_t *y) {
if (!isTouched()) return false;
*x = getRawData(XPT2046_X);
*y = getRawData(XPT2046_Y);
- SERIAL_ECHOLNPAIR("X: ", *x, ", Y: ", *y);
return isTouched();
}
diff --git a/Marlin/src/HAL/LPC1768/timers.h b/Marlin/src/HAL/LPC1768/timers.h
index 23dc20e2eb..e6744fb005 100644
--- a/Marlin/src/HAL/LPC1768/timers.h
+++ b/Marlin/src/HAL/LPC1768/timers.h
@@ -21,7 +21,6 @@
#pragma once
/**
- *
* HAL For LPC1768
*/
diff --git a/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_hw_spi.cpp b/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_hw_spi.cpp
index befc348fab..057e10e0f5 100644
--- a/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_hw_spi.cpp
+++ b/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_hw_spi.cpp
@@ -57,7 +57,7 @@
#include "../../../inc/MarlinConfigPre.h"
-#if HAS_GRAPHICAL_LCD
+#if HAS_MARLINUI_U8GLIB
#include
#include "../../shared/HAL_SPI.h"
@@ -124,6 +124,6 @@ uint8_t u8g_com_HAL_LPC1768_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val,
return 1;
}
-#endif // HAS_GRAPHICAL_LCD
+#endif // HAS_MARLINUI_U8GLIB
#endif // TARGET_LPC1768
diff --git a/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_ssd_hw_i2c.cpp b/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_ssd_hw_i2c.cpp
index f03be9ab34..6f7efba4ae 100644
--- a/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_ssd_hw_i2c.cpp
+++ b/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_ssd_hw_i2c.cpp
@@ -77,7 +77,7 @@
#include "../../../inc/MarlinConfigPre.h"
-#if HAS_GRAPHICAL_LCD
+#if HAS_MARLINUI_U8GLIB
#include
@@ -193,6 +193,6 @@ uint8_t u8g_com_HAL_LPC1768_ssd_hw_i2c_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_v
return 1;
}
-#endif // HAS_GRAPHICAL_LCD
+#endif // HAS_MARLINUI_U8GLIB
#endif // TARGET_LPC1768
diff --git a/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_st7920_hw_spi.cpp b/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_st7920_hw_spi.cpp
index 1500c22a0d..592e27f6c0 100644
--- a/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_st7920_hw_spi.cpp
+++ b/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_st7920_hw_spi.cpp
@@ -57,7 +57,7 @@
#include "../../../inc/MarlinConfigPre.h"
-#if HAS_GRAPHICAL_LCD
+#if HAS_MARLINUI_U8GLIB
#include
#include "../../shared/HAL_SPI.h"
@@ -133,6 +133,6 @@ uint8_t u8g_com_HAL_LPC1768_ST7920_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t ar
return 1;
}
-#endif // HAS_GRAPHICAL_LCD
+#endif // HAS_MARLINUI_U8GLIB
#endif // TARGET_LPC1768
diff --git a/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_sw_spi.cpp b/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_sw_spi.cpp
index 4f52f7dd01..ca9d6ecfbe 100644
--- a/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_sw_spi.cpp
+++ b/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_sw_spi.cpp
@@ -57,7 +57,7 @@
#include "../../../inc/MarlinConfigPre.h"
-#if HAS_GRAPHICAL_LCD && DISABLED(U8GLIB_ST7920)
+#if HAS_MARLINUI_U8GLIB && DISABLED(U8GLIB_ST7920)
#include
@@ -203,5 +203,5 @@ uint8_t u8g_com_HAL_LPC1768_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val,
return 1;
}
-#endif // HAS_GRAPHICAL_LCD && !U8GLIB_ST7920
+#endif // HAS_MARLINUI_U8GLIB && !U8GLIB_ST7920
#endif // TARGET_LPC1768
diff --git a/Marlin/src/HAL/LPC1768/usb_serial.cpp b/Marlin/src/HAL/LPC1768/usb_serial.cpp
index 63a570efdf..d225ce4188 100644
--- a/Marlin/src/HAL/LPC1768/usb_serial.cpp
+++ b/Marlin/src/HAL/LPC1768/usb_serial.cpp
@@ -26,7 +26,9 @@
#if ENABLED(EMERGENCY_PARSER)
#include "../../feature/e_parser.h"
+
EmergencyParser::State emergency_state;
+
bool CDC_RecvCallback(const char buffer) {
emergency_parser.update(emergency_state, buffer);
return true;
diff --git a/Marlin/src/HAL/SAMD51/HAL.h b/Marlin/src/HAL/SAMD51/HAL.h
index ea0f694cdc..7fd826a1b6 100644
--- a/Marlin/src/HAL/SAMD51/HAL.h
+++ b/Marlin/src/HAL/SAMD51/HAL.h
@@ -35,58 +35,34 @@
// MYSERIAL0 required before MarlinSerial includes!
+ #define _MSERIAL(X) Serial##X
+ #define MSERIAL(X) _MSERIAL(INCREMENT(X))
+
#if SERIAL_PORT == -1
#define MYSERIAL0 Serial
- #elif SERIAL_PORT == 0
- #define MYSERIAL0 Serial1
- #elif SERIAL_PORT == 1
- #define MYSERIAL0 Serial2
- #elif SERIAL_PORT == 2
- #define MYSERIAL0 Serial3
- #elif SERIAL_PORT == 3
- #define MYSERIAL0 Serial4
+ #elif WITHIN(SERIAL_PORT, 0, 3)
+ #define MYSERIAL0 MSERIAL(SERIAL_PORT)
#else
#error "SERIAL_PORT must be from -1 to 3. Please update your configuration."
#endif
#ifdef SERIAL_PORT_2
- #if SERIAL_PORT_2 == SERIAL_PORT
- #error "SERIAL_PORT_2 must be different than SERIAL_PORT. Please update your configuration."
- #elif SERIAL_PORT_2 == -1
+ #if SERIAL_PORT_2 == -1
#define MYSERIAL1 Serial
- #elif SERIAL_PORT_2 == 0
- #define MYSERIAL1 Serial1
- #elif SERIAL_PORT_2 == 1
- #define MYSERIAL1 Serial2
- #elif SERIAL_PORT_2 == 2
- #define MYSERIAL1 Serial3
- #elif SERIAL_PORT_2 == 3
- #define MYSERIAL1 Serial4
+ #elif WITHIN(SERIAL_PORT_2, 0, 3)
+ #define MYSERIAL1 MSERIAL(SERIAL_PORT_2)
#else
#error "SERIAL_PORT_2 must be from -1 to 3. Please update your configuration."
#endif
- #define NUM_SERIAL 2
- #else
- #define NUM_SERIAL 1
#endif
- #ifdef DGUS_SERIAL_PORT
- #if DGUS_SERIAL_PORT == SERIAL_PORT
- #error "DGUS_SERIAL_PORT must be different than SERIAL_PORT. Please update your configuration."
- #elif defined(SERIAL_PORT_2) && DGUS_SERIAL_PORT == SERIAL_PORT_2
- #error "DGUS_SERIAL_PORT must be different than SERIAL_PORT_2. Please update your configuration."
- #elif DGUS_SERIAL_PORT == -1
- #define DGUS_SERIAL Serial
- #elif DGUS_SERIAL_PORT == 0
- #define DGUS_SERIAL Serial1
- #elif DGUS_SERIAL_PORT == 1
- #define DGUS_SERIAL Serial2
- #elif DGUS_SERIAL_PORT == 2
- #define DGUS_SERIAL Serial3
- #elif DGUS_SERIAL_PORT == 2
- #define DGUS_SERIAL Serial4
+ #ifdef LCD_SERIAL_PORT
+ #if LCD_SERIAL_PORT == -1
+ #define LCD_SERIAL Serial
+ #elif WITHIN(LCD_SERIAL_PORT, 0, 3)
+ #define LCD_SERIAL MSERIAL(LCD_SERIAL_PORT)
#else
- #error "DGUS_SERIAL_PORT must be from -1 to 3. Please update your configuration."
+ #error "LCD_SERIAL_PORT must be from -1 to 3. Please update your configuration."
#endif
#endif
diff --git a/Marlin/src/HAL/SAMD51/QSPIFlash.h b/Marlin/src/HAL/SAMD51/QSPIFlash.h
index b6f22769ff..db4abec91c 100644
--- a/Marlin/src/HAL/SAMD51/QSPIFlash.h
+++ b/Marlin/src/HAL/SAMD51/QSPIFlash.h
@@ -24,7 +24,6 @@
* THE SOFTWARE.
*
* Derived from Adafruit_SPIFlash class with no SdFat references
- *
*/
#pragma once
diff --git a/Marlin/src/HAL/SAMD51/pinsDebug.h b/Marlin/src/HAL/SAMD51/pinsDebug.h
index c28937d6c6..81376db79a 100644
--- a/Marlin/src/HAL/SAMD51/pinsDebug.h
+++ b/Marlin/src/HAL/SAMD51/pinsDebug.h
@@ -150,5 +150,4 @@ void pwm_details(int32_t pin) {
* 93 | PA10 | QSPI: IO2
* 94 | PA11 | QSPI: IO3
* 95 | PB31 | SD: DETECT
- *
*/
diff --git a/Marlin/src/HAL/STM32/HAL.h b/Marlin/src/HAL/STM32/HAL.h
index 08081331b7..60ab45374a 100644
--- a/Marlin/src/HAL/STM32/HAL.h
+++ b/Marlin/src/HAL/STM32/HAL.h
@@ -43,83 +43,40 @@
// ------------------------
// Defines
// ------------------------
+#define _MSERIAL(X) MSerial##X
+#define MSERIAL(X) _MSERIAL(X)
-#if SERIAL_PORT == 0
- #error "SERIAL_PORT cannot be 0. (Port 0 does not exist.) Please update your configuration."
-#elif SERIAL_PORT == -1
+#if SERIAL_PORT == -1
#define MYSERIAL0 SerialUSB
-#elif SERIAL_PORT == 1
- #define MYSERIAL0 MSerial1
-#elif SERIAL_PORT == 2
- #define MYSERIAL0 MSerial2
-#elif SERIAL_PORT == 3
- #define MYSERIAL0 MSerial3
-#elif SERIAL_PORT == 4
- #define MYSERIAL0 MSerial4
-#elif SERIAL_PORT == 5
- #define MYSERIAL0 MSerial5
-#elif SERIAL_PORT == 6
- #define MYSERIAL0 MSerial6
+#elif WITHIN(SERIAL_PORT, 1, 6)
+ #define MYSERIAL0 MSERIAL(SERIAL_PORT)
#else
- #error "SERIAL_PORT must be from -1 to 6. Please update your configuration."
+ #error "SERIAL_PORT must be -1 or from 1 to 6. Please update your configuration."
#endif
#ifdef SERIAL_PORT_2
- #define NUM_SERIAL 2
- #if SERIAL_PORT_2 == 0
- #error "SERIAL_PORT_2 cannot be 0. (Port 0 does not exist.) Please update your configuration."
- #elif SERIAL_PORT_2 == SERIAL_PORT
- #error "SERIAL_PORT_2 must be different than SERIAL_PORT. Please update your configuration."
- #elif SERIAL_PORT_2 == -1
+ #if SERIAL_PORT_2 == -1
#define MYSERIAL1 SerialUSB
- #elif SERIAL_PORT_2 == 1
- #define MYSERIAL1 MSerial1
- #elif SERIAL_PORT_2 == 2
- #define MYSERIAL1 MSerial2
- #elif SERIAL_PORT_2 == 3
- #define MYSERIAL1 MSerial3
- #elif SERIAL_PORT_2 == 4
- #define MYSERIAL1 MSerial4
- #elif SERIAL_PORT_2 == 5
- #define MYSERIAL1 MSerial5
- #elif SERIAL_PORT_2 == 6
- #define MYSERIAL1 MSerial6
+ #elif WITHIN(SERIAL_PORT_2, 1, 6)
+ #define MYSERIAL1 MSERIAL(SERIAL_PORT_2)
#else
- #error "SERIAL_PORT_2 must be from -1 to 6. Please update your configuration."
+ #error "SERIAL_PORT_2 must be -1 or from 1 to 6. Please update your configuration."
#endif
-#else
- #define NUM_SERIAL 1
#endif
-#if HAS_DGUS_LCD
- #if DGUS_SERIAL_PORT == 0
- #error "DGUS_SERIAL_PORT cannot be 0. (Port 0 does not exist.) Please update your configuration."
- #elif DGUS_SERIAL_PORT == SERIAL_PORT
- #error "DGUS_SERIAL_PORT must be different than SERIAL_PORT. Please update your configuration."
- #elif defined(SERIAL_PORT_2) && DGUS_SERIAL_PORT == SERIAL_PORT_2
- #error "DGUS_SERIAL_PORT must be different than SERIAL_PORT_2. Please update your configuration."
- #elif DGUS_SERIAL_PORT == -1
- #define DGUS_SERIAL SerialUSB
- #elif DGUS_SERIAL_PORT == 1
- #define DGUS_SERIAL MSerial1
- #elif DGUS_SERIAL_PORT == 2
- #define DGUS_SERIAL MSerial2
- #elif DGUS_SERIAL_PORT == 3
- #define DGUS_SERIAL MSerial3
- #elif DGUS_SERIAL_PORT == 4
- #define DGUS_SERIAL MSerial4
- #elif DGUS_SERIAL_PORT == 5
- #define DGUS_SERIAL MSerial5
- #elif DGUS_SERIAL_PORT == 6
- #define DGUS_SERIAL MSerial6
+#ifdef LCD_SERIAL_PORT
+ #if LCD_SERIAL_PORT == -1
+ #define LCD_SERIAL SerialUSB
+ #elif WITHIN(LCD_SERIAL_PORT, 1, 6)
+ #define LCD_SERIAL MSERIAL(LCD_SERIAL_PORT)
#else
- #error "DGUS_SERIAL_PORT must be from -1 to 6. Please update your configuration."
+ #error "LCD_SERIAL_PORT must be -1 or from 1 to 6. Please update your configuration."
+ #endif
+ #if HAS_DGUS_LCD
+ #define SERIAL_GET_TX_BUFFER_FREE() LCD_SERIAL.availableForWrite()
#endif
-
- #define DGUS_SERIAL_GET_TX_BUFFER_FREE DGUS_SERIAL.availableForWrite
#endif
-
/**
* TODO: review this to return 1 for pins that are not analog input
*/
diff --git a/Marlin/src/HAL/STM32/MarlinSerial.cpp b/Marlin/src/HAL/STM32/MarlinSerial.cpp
index 8d99ab7855..a146664366 100644
--- a/Marlin/src/HAL/STM32/MarlinSerial.cpp
+++ b/Marlin/src/HAL/STM32/MarlinSerial.cpp
@@ -49,16 +49,14 @@
DECLARE_SERIAL_PORT_EXP(SERIAL_PORT_2)
#endif
-#if defined(DGUS_SERIAL_PORT) && DGUS_SERIAL_PORT >= 0
- DECLARE_SERIAL_PORT_EXP(DGUS_SERIAL_PORT)
+#if defined(LCD_SERIAL_PORT) && LCD_SERIAL_PORT >= 0
+ DECLARE_SERIAL_PORT_EXP(LCD_SERIAL_PORT)
#endif
void MarlinSerial::begin(unsigned long baud, uint8_t config) {
HardwareSerial::begin(baud, config);
- // replace the IRQ callback with the one we have defined
- #if ENABLED(EMERGENCY_PARSER)
- _serial.rx_callback = _rx_callback;
- #endif
+ // Replace the IRQ callback with the one we have defined
+ TERN_(EMERGENCY_PARSER, _serial.rx_callback = _rx_callback);
}
// This function is Copyright (c) 2006 Nicholas Zambetti.
diff --git a/Marlin/src/HAL/STM32/MarlinSerial.h b/Marlin/src/HAL/STM32/MarlinSerial.h
index 5ab97ff3a9..3611cc78d7 100644
--- a/Marlin/src/HAL/STM32/MarlinSerial.h
+++ b/Marlin/src/HAL/STM32/MarlinSerial.h
@@ -35,6 +35,10 @@ public:
#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); }
diff --git a/Marlin/src/HAL/STM32/SoftwareSerial.cpp b/Marlin/src/HAL/STM32/SoftwareSerial.cpp
deleted file mode 100644
index 2228a177be..0000000000
--- a/Marlin/src/HAL/STM32/SoftwareSerial.cpp
+++ /dev/null
@@ -1,396 +0,0 @@
-/*
- * SoftwareSerial.cpp (formerly NewSoftSerial.cpp)
- *
- * Multi-instance software serial library for Arduino/Wiring
- * -- Interrupt-driven receive and other improvements by ladyada
- *
- * -- Tuning, circular buffer, derivation from class Print/Stream,
- * multi-instance support, porting to 8MHz processors,
- * various optimizations, PROGMEM delay tables, inverse logic and
- * direct port writing by Mikal Hart
- * -- Pin change interrupt macros by Paul Stoffregen
- * -- 20MHz processor support by Garrett Mace
- * -- ATmega1280/2560 support by Brett Hagman
- * -- STM32 support by Armin van der Togt
- *
- * 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
- *
- * The latest version of this library can always be found at
- * http://arduiniana.org.
- */
-
-//
-// Includes
-//
-#if defined(PLATFORMIO) && defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC)
-
-#include "../../inc/MarlinConfig.h"
-
-#include "SoftwareSerial.h"
-
-#define OVERSAMPLE 3 // in RX, Timer will generate interruption OVERSAMPLE time during a bit. Thus OVERSAMPLE ticks in a bit. (interrupt not synchonized with edge).
-
-// defined in bit-periods
-#define HALFDUPLEX_SWITCH_DELAY 5
-// It's best to define TIMER_SERIAL in variant.h. If not defined, we choose one here
-// The order is based on (lack of) features and compare channels, we choose the simplest available
-// because we only need an update interrupt
-#if !defined(TIMER_SERIAL)
-#if defined(TIM18_BASE)
-#define TIMER_SERIAL TIM18
-#elif defined(TIM7_BASE)
-#define TIMER_SERIAL TIM7
-#elif defined(TIM6_BASE)
-#define TIMER_SERIAL TIM6
-#elif defined(TIM22_BASE)
-#define TIMER_SERIAL TIM22
-#elif defined(TIM21_BASE)
-#define TIMER_SERIAL TIM21
-#elif defined(TIM17_BASE)
-#define TIMER_SERIAL TIM17
-#elif defined(TIM16_BASE)
-#define TIMER_SERIAL TIM16
-#elif defined(TIM15_BASE)
-#define TIMER_SERIAL TIM15
-#elif defined(TIM14_BASE)
-#define TIMER_SERIAL TIM14
-#elif defined(TIM13_BASE)
-#define TIMER_SERIAL TIM13
-#elif defined(TIM11_BASE)
-#define TIMER_SERIAL TIM11
-#elif defined(TIM10_BASE)
-#define TIMER_SERIAL TIM10
-#elif defined(TIM12_BASE)
-#define TIMER_SERIAL TIM12
-#elif defined(TIM19_BASE)
-#define TIMER_SERIAL TIM19
-#elif defined(TIM9_BASE)
-#define TIMER_SERIAL TIM9
-#elif defined(TIM5_BASE)
-#define TIMER_SERIAL TIM5
-#elif defined(TIM4_BASE)
-#define TIMER_SERIAL TIM4
-#elif defined(TIM3_BASE)
-#define TIMER_SERIAL TIM3
-#elif defined(TIM2_BASE)
-#define TIMER_SERIAL TIM2
-#elif defined(TIM20_BASE)
-#define TIMER_SERIAL TIM20
-#elif defined(TIM8_BASE)
-#define TIMER_SERIAL TIM8
-#elif defined(TIM1_BASE)
-#define TIMER_SERIAL TIM1
-#else
-#error No suitable timer found for SoftwareSerial, define TIMER_SERIAL in variant.h
-#endif
-#endif
-//
-// Statics
-//
-HardwareTimer SoftwareSerial::timer(TIMER_SERIAL);
-const IRQn_Type SoftwareSerial::timer_interrupt_number = static_cast(getTimerUpIrq(TIMER_SERIAL));
-uint32_t SoftwareSerial::timer_interrupt_priority = NVIC_EncodePriority(NVIC_GetPriorityGrouping(), TIM_IRQ_PRIO, TIM_IRQ_SUBPRIO);
-SoftwareSerial *SoftwareSerial::active_listener = nullptr;
-SoftwareSerial *volatile SoftwareSerial::active_out = nullptr;
-SoftwareSerial *volatile SoftwareSerial::active_in = nullptr;
-int32_t SoftwareSerial::tx_tick_cnt = 0; // OVERSAMPLE ticks needed for a bit
-int32_t volatile SoftwareSerial::rx_tick_cnt = 0; // OVERSAMPLE ticks needed for a bit
-uint32_t SoftwareSerial::tx_buffer = 0;
-int32_t SoftwareSerial::tx_bit_cnt = 0;
-uint32_t SoftwareSerial::rx_buffer = 0;
-int32_t SoftwareSerial::rx_bit_cnt = -1; // rx_bit_cnt = -1 : waiting for start bit
-uint32_t SoftwareSerial::cur_speed = 0;
-
-void SoftwareSerial::setInterruptPriority(uint32_t preemptPriority, uint32_t subPriority) {
- timer_interrupt_priority = NVIC_EncodePriority(NVIC_GetPriorityGrouping(), preemptPriority, subPriority);
-}
-
-//
-// Private methods
-//
-
-void SoftwareSerial::setSpeed(uint32_t speed) {
- if (speed != cur_speed) {
- timer.pause();
- if (speed != 0) {
- // Disable the timer
- uint32_t clock_rate, cmp_value;
- // Get timer clock
- clock_rate = timer.getTimerClkFreq();
- int pre = 1;
- // Calculate prescale an compare value
- do {
- cmp_value = clock_rate / (speed * OVERSAMPLE);
- if (cmp_value >= UINT16_MAX) {
- clock_rate /= 2;
- pre *= 2;
- }
- } while (cmp_value >= UINT16_MAX);
- timer.setPrescaleFactor(pre);
- timer.setOverflow(cmp_value);
- timer.setCount(0);
- timer.attachInterrupt(&handleInterrupt);
- timer.resume();
- NVIC_SetPriority(timer_interrupt_number, timer_interrupt_priority);
- }
- else
- timer.detachInterrupt();
- cur_speed = speed;
- }
-}
-
-// This function sets the current object as the "listening"
-// one and returns true if it replaces another
-bool SoftwareSerial::listen() {
- if (active_listener != this) {
- // wait for any transmit to complete as we may change speed
- while (active_out);
- active_listener->stopListening();
- rx_tick_cnt = 1; // 1 : next interrupt will decrease rx_tick_cnt to 0 which means RX pin level will be considered.
- rx_bit_cnt = -1; // rx_bit_cnt = -1 : waiting for start bit
- setSpeed(_speed);
- active_listener = this;
- if (!_half_duplex) active_in = this;
- return true;
- }
- return false;
-}
-
-// Stop listening. Returns true if we were actually listening.
-bool SoftwareSerial::stopListening() {
- if (active_listener == this) {
- // wait for any output to complete
- while (active_out);
- if (_half_duplex) setRXTX(false);
- active_listener = nullptr;
- active_in = nullptr;
- // turn off ints
- setSpeed(0);
- return true;
- }
- return false;
-}
-
-inline void SoftwareSerial::setTX() {
- if (_inverse_logic)
- LL_GPIO_ResetOutputPin(_transmitPinPort, _transmitPinNumber);
- else
- LL_GPIO_SetOutputPin(_transmitPinPort, _transmitPinNumber);
- pinMode(_transmitPin, OUTPUT);
-}
-
-inline void SoftwareSerial::setRX() {
- pinMode(_receivePin, _inverse_logic ? INPUT_PULLDOWN : INPUT_PULLUP); // pullup for normal logic!
-}
-
-inline void SoftwareSerial::setRXTX(bool input) {
- if (_half_duplex) {
- if (input) {
- if (active_in != this) {
- setRX();
- rx_bit_cnt = -1; // rx_bit_cnt = -1 : waiting for start bit
- rx_tick_cnt = 2; // 2 : next interrupt will be discarded. 2 interrupts required to consider RX pin level
- active_in = this;
- }
- }
- else {
- if (active_in == this) {
- setTX();
- active_in = nullptr;
- }
- }
- }
-}
-
-inline void SoftwareSerial::send() {
- if (--tx_tick_cnt <= 0) { // if tx_tick_cnt > 0 interrupt is discarded. Only when tx_tick_cnt reaches 0 is TX pin set.
- if (tx_bit_cnt++ < 10) { // tx_bit_cnt < 10 transmission is not finished (10 = 1 start +8 bits + 1 stop)
- // Send data (including start and stop bits)
- if (tx_buffer & 1)
- LL_GPIO_SetOutputPin(_transmitPinPort, _transmitPinNumber);
- else
- LL_GPIO_ResetOutputPin(_transmitPinPort, _transmitPinNumber);
- tx_buffer >>= 1;
- tx_tick_cnt = OVERSAMPLE; // Wait OVERSAMPLE ticks to send next bit
- }
- else { // Transmission finished
- tx_tick_cnt = 1;
- if (_output_pending) {
- active_out = nullptr;
-
- // In half-duplex mode wait HALFDUPLEX_SWITCH_DELAY bit-periods after the byte has
- // been transmitted before allowing the switch to RX mode
- }
- else if (tx_bit_cnt > 10 + OVERSAMPLE * HALFDUPLEX_SWITCH_DELAY) {
- if (_half_duplex && active_listener == this) setRXTX(true);
- active_out = nullptr;
- }
- }
- }
-}
-
-//
-// The receive routine called by the interrupt handler
-//
-inline void SoftwareSerial::recv() {
- if (--rx_tick_cnt <= 0) { // if rx_tick_cnt > 0 interrupt is discarded. Only when rx_tick_cnt reaches 0 is RX pin considered
- bool inbit = LL_GPIO_IsInputPinSet(_receivePinPort, _receivePinNumber) ^ _inverse_logic;
- if (rx_bit_cnt == -1) { // rx_bit_cnt = -1 : waiting for start bit
- if (!inbit) {
- // got start bit
- rx_bit_cnt = 0; // rx_bit_cnt == 0 : start bit received
- rx_tick_cnt = OVERSAMPLE + 1; // Wait 1 bit (OVERSAMPLE ticks) + 1 tick in order to sample RX pin in the middle of the edge (and not too close to the edge)
- rx_buffer = 0;
- }
- else
- rx_tick_cnt = 1; // Waiting for start bit, but wrong level. Wait for next Interrupt to check RX pin level
- }
- else if (rx_bit_cnt >= 8) { // rx_bit_cnt >= 8 : waiting for stop bit
- if (inbit) {
- // Stop-bit read complete. Add to buffer.
- uint8_t next = (_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF;
- if (next != _receive_buffer_head) {
- // save new data in buffer: tail points to byte destination
- _receive_buffer[_receive_buffer_tail] = rx_buffer; // save new byte
- _receive_buffer_tail = next;
- }
- else // rx_bit_cnt = x with x = [0..7] correspond to new bit x received
- _buffer_overflow = true;
- }
- // Full trame received. Restart waiting for start bit at next interrupt
- rx_tick_cnt = 1;
- rx_bit_cnt = -1;
- }
- else {
- // data bits
- rx_buffer >>= 1;
- if (inbit) rx_buffer |= 0x80;
- rx_bit_cnt++; // Prepare for next bit
- rx_tick_cnt = OVERSAMPLE; // Wait OVERSAMPLE ticks before sampling next bit
- }
- }
-}
-
-//
-// Interrupt handling
-//
-
-/* static */
-inline void SoftwareSerial::handleInterrupt(HardwareTimer*) {
- if (active_in) active_in->recv();
- if (active_out) active_out->send();
-}
-
-//
-// Constructor
-//
-SoftwareSerial::SoftwareSerial(uint16_t receivePin, uint16_t transmitPin, bool inverse_logic /* = false */) :
- _receivePin(receivePin),
- _transmitPin(transmitPin),
- _receivePinPort(digitalPinToPort(receivePin)),
- _receivePinNumber(STM_LL_GPIO_PIN(digitalPinToPinName(receivePin))),
- _transmitPinPort(digitalPinToPort(transmitPin)),
- _transmitPinNumber(STM_LL_GPIO_PIN(digitalPinToPinName(transmitPin))),
- _speed(0),
- _buffer_overflow(false),
- _inverse_logic(inverse_logic),
- _half_duplex(receivePin == transmitPin),
- _output_pending(0),
- _receive_buffer_tail(0),
- _receive_buffer_head(0)
-{
- if ((receivePin < NUM_DIGITAL_PINS) || (transmitPin < NUM_DIGITAL_PINS)) {
- /* Enable GPIO clock for tx and rx pin*/
- set_GPIO_Port_Clock(STM_PORT(digitalPinToPinName(transmitPin)));
- set_GPIO_Port_Clock(STM_PORT(digitalPinToPinName(receivePin)));
- }
- else
- _Error_Handler("ERROR: invalid pin number\n", -1);
-}
-
-//
-// Destructor
-//
-SoftwareSerial::~SoftwareSerial() { end(); }
-
-//
-// Public methods
-//
-
-void SoftwareSerial::begin(long speed) {
- #ifdef FORCE_BAUD_RATE
- speed = FORCE_BAUD_RATE;
- #endif
- _speed = speed;
- if (!_half_duplex) {
- setTX();
- setRX();
- listen();
- }
- else
- setTX();
-}
-
-void SoftwareSerial::end() {
- stopListening();
-}
-
-// Read data from buffer
-int SoftwareSerial::read() {
- // Empty buffer?
- if (_receive_buffer_head == _receive_buffer_tail) return -1;
-
- // Read from "head"
- uint8_t d = _receive_buffer[_receive_buffer_head]; // grab next byte
- _receive_buffer_head = (_receive_buffer_head + 1) % _SS_MAX_RX_BUFF;
- return d;
-}
-
-int SoftwareSerial::available() {
- return (_receive_buffer_tail + _SS_MAX_RX_BUFF - _receive_buffer_head) % _SS_MAX_RX_BUFF;
-}
-
-size_t SoftwareSerial::write(uint8_t b) {
- // wait for previous transmit to complete
- _output_pending = 1;
- while (active_out) { /* nada */ }
- // add start and stop bits.
- tx_buffer = b << 1 | 0x200;
- if (_inverse_logic) tx_buffer = ~tx_buffer;
- tx_bit_cnt = 0;
- tx_tick_cnt = OVERSAMPLE;
- setSpeed(_speed);
- if (_half_duplex) setRXTX(false);
- _output_pending = 0;
- // make us active
- active_out = this;
- return 1;
-}
-
-void SoftwareSerial::flush() {
- noInterrupts();
- _receive_buffer_head = _receive_buffer_tail = 0;
- interrupts();
-}
-
-int SoftwareSerial::peek() {
- // Empty buffer?
- if (_receive_buffer_head == _receive_buffer_tail) return -1;
-
- // Read from "head"
- return _receive_buffer[_receive_buffer_head];
-}
-
-#endif // ARDUINO_ARCH_STM32 && !STM32GENERIC
diff --git a/Marlin/src/HAL/STM32/SoftwareSerial.h b/Marlin/src/HAL/STM32/SoftwareSerial.h
deleted file mode 100644
index 1a4f742c32..0000000000
--- a/Marlin/src/HAL/STM32/SoftwareSerial.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/**
- * SoftwareSerial.h (formerly NewSoftSerial.h)
- *
- * Multi-instance software serial library for Arduino/Wiring
- * -- Interrupt-driven receive and other improvements by ladyada
- * (https://ladyada.net)
- * -- Tuning, circular buffer, derivation from class Print/Stream,
- * multi-instance support, porting to 8MHz processors,
- * various optimizations, PROGMEM delay tables, inverse logic and
- * direct port writing by Mikal Hart (http://www.arduiniana.org)
- * -- Pin change interrupt macros by Paul Stoffregen (https://www.pjrc.com)
- * -- 20MHz processor support by Garrett Mace (http://www.macetech.com)
- * -- ATmega1280/2560 support by Brett Hagman (https://www.roguerobotics.com/)
- *
- * 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
- *
- * The latest version of this library can always be found at
- * http://arduiniana.org.
- */
-#pragma once
-
-#include
-
-/******************************************************************************
- * Definitions
- ******************************************************************************/
-
-#define _SS_MAX_RX_BUFF 64 // RX buffer size
-
-class SoftwareSerial : public Stream {
- private:
- // per object data
- uint16_t _receivePin;
- uint16_t _transmitPin;
- GPIO_TypeDef *_receivePinPort;
- uint32_t _receivePinNumber;
- GPIO_TypeDef *_transmitPinPort;
- uint32_t _transmitPinNumber;
- uint32_t _speed;
-
- uint16_t _buffer_overflow: 1;
- uint16_t _inverse_logic: 1;
- uint16_t _half_duplex: 1;
- uint16_t _output_pending: 1;
-
- unsigned char _receive_buffer[_SS_MAX_RX_BUFF];
- volatile uint8_t _receive_buffer_tail;
- volatile uint8_t _receive_buffer_head;
-
- uint32_t delta_start = 0;
-
- // static data
- static HardwareTimer timer;
- static const IRQn_Type timer_interrupt_number;
- static uint32_t timer_interrupt_priority;
- static SoftwareSerial *active_listener;
- static SoftwareSerial *volatile active_out;
- static SoftwareSerial *volatile active_in;
- static int32_t tx_tick_cnt;
- static volatile int32_t rx_tick_cnt;
- static uint32_t tx_buffer;
- static int32_t tx_bit_cnt;
- static uint32_t rx_buffer;
- static int32_t rx_bit_cnt;
- static uint32_t cur_speed;
-
- // private methods
- void send();
- void recv();
- void setTX();
- void setRX();
- void setSpeed(uint32_t speed);
- void setRXTX(bool input);
- static void handleInterrupt(HardwareTimer *timer);
-
- public:
- // public methods
-
- SoftwareSerial(uint16_t receivePin, uint16_t transmitPin, bool inverse_logic=false);
- virtual ~SoftwareSerial();
- void begin(long speed);
- bool listen();
- void end();
- bool isListening() { return active_listener == this; }
- bool stopListening();
- bool overflow() {
- bool ret = _buffer_overflow;
- if (ret) _buffer_overflow = false;
- return ret;
- }
- int peek();
-
- virtual size_t write(uint8_t byte);
- virtual int read();
- virtual int available();
- virtual void flush();
- operator bool() { return true; }
-
- static void setInterruptPriority(uint32_t preemptPriority, uint32_t subPriority);
-
- using Print::write;
-};
diff --git a/Marlin/src/HAL/STM32/pinsDebug_STM32GENERIC.h b/Marlin/src/HAL/STM32/pinsDebug_STM32GENERIC.h
index 5ff40debea..9069d9f7bd 100644
--- a/Marlin/src/HAL/STM32/pinsDebug_STM32GENERIC.h
+++ b/Marlin/src/HAL/STM32/pinsDebug_STM32GENERIC.h
@@ -98,7 +98,7 @@ static inline void pwm_details(const pin_t pin) {
timer_dev * const tdev = PIN_MAP[pin].timer_device;
const uint8_t channel = PIN_MAP[pin].timer_channel;
const char num = (
- #if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY)
+ #if EITHER(STM32_HIGH_DENSITY, STM32_XL_DENSITY)
tdev == &timer8 ? '8' :
tdev == &timer5 ? '5' :
#endif
diff --git a/Marlin/src/HAL/STM32/tft/tft_fsmc.cpp b/Marlin/src/HAL/STM32/tft/tft_fsmc.cpp
index f11fab39db..3a080d5e27 100644
--- a/Marlin/src/HAL/STM32/tft/tft_fsmc.cpp
+++ b/Marlin/src/HAL/STM32/tft/tft_fsmc.cpp
@@ -87,7 +87,7 @@ void TFT_FSMC::Init() {
__HAL_RCC_FSMC_CLK_ENABLE();
- for(uint16_t i = 0; PinMap_FSMC[i].pin != NC; i++)
+ for (uint16_t i = 0; PinMap_FSMC[i].pin != NC; i++)
pinmap_pinout(PinMap_FSMC[i].pin, PinMap_FSMC);
pinmap_pinout(digitalPinToPinName(TFT_CS_PIN), PinMap_FSMC_CS);
pinmap_pinout(digitalPinToPinName(TFT_RS_PIN), PinMap_FSMC_RS);
diff --git a/Marlin/src/HAL/STM32/tft/xpt2046.cpp b/Marlin/src/HAL/STM32/tft/xpt2046.cpp
index 49e64da6a1..921e377a9f 100644
--- a/Marlin/src/HAL/STM32/tft/xpt2046.cpp
+++ b/Marlin/src/HAL/STM32/tft/xpt2046.cpp
@@ -155,9 +155,9 @@ uint16_t XPT2046::getRawData(const XPTCoordinate coordinate) {
uint16_t XPT2046::HardwareIO(uint16_t data) {
__HAL_SPI_ENABLE(&SPIx);
- while((SPIx.Instance->SR & SPI_FLAG_TXE) != SPI_FLAG_TXE) {}
+ while ((SPIx.Instance->SR & SPI_FLAG_TXE) != SPI_FLAG_TXE) {}
SPIx.Instance->DR = data;
- while((SPIx.Instance->SR & SPI_FLAG_RXNE) != SPI_FLAG_RXNE) {}
+ while ((SPIx.Instance->SR & SPI_FLAG_RXNE) != SPI_FLAG_RXNE) {}
__HAL_SPI_DISABLE(&SPIx);
return SPIx.Instance->DR;
diff --git a/Marlin/src/HAL/STM32/timers.cpp b/Marlin/src/HAL/STM32/timers.cpp
index 1196731448..c0ba19abe5 100644
--- a/Marlin/src/HAL/STM32/timers.cpp
+++ b/Marlin/src/HAL/STM32/timers.cpp
@@ -110,7 +110,6 @@
// ------------------------
HardwareTimer *timer_instance[NUM_HARDWARE_TIMERS] = { NULL };
-bool timer_enabled[NUM_HARDWARE_TIMERS] = { false };
// ------------------------
// Public functions
@@ -135,6 +134,7 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
* which changes the prescaler when an IRQ frequency change is needed
* (for example when steppers are turned on)
*/
+
timer_instance[timer_num]->setPrescaleFactor(STEPPER_TIMER_PRESCALE); //the -1 is done internally
timer_instance[timer_num]->setOverflow(_MIN(hal_timer_t(HAL_TIMER_TYPE_MAX), (HAL_TIMER_RATE) / (STEPPER_TIMER_PRESCALE) /* /frequency */), TICK_FORMAT);
break;
@@ -145,15 +145,13 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
break;
}
+ // Disable preload. Leaving it default-enabled can cause the timer to stop if it happens
+ // to exit the ISR after the start time for the next interrupt has already passed.
+ timer_instance[timer_num]->setPreloadEnable(false);
+
HAL_timer_enable_interrupt(timer_num);
- /*
- * Initializes (and unfortunately starts) the timer.
- * This is needed to set correct IRQ priority at the moment but causes
- * no harm since every call to HAL_timer_start() is actually followed by
- * a call to HAL_timer_enable_interrupt() which means that there isn't
- * a case in which you want the timer to run without a callback.
- */
+ // Start the timer.
timer_instance[timer_num]->resume(); // First call to resume() MUST follow the attachInterrupt()
// This is fixed in Arduino_Core_STM32 1.8.
@@ -161,47 +159,34 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
// timer_instance[timer_num]->setInterruptPriority
switch (timer_num) {
case STEP_TIMER_NUM:
- HAL_NVIC_SetPriority(STEP_TIMER_IRQ_NAME, STEP_TIMER_IRQ_PRIO, 0);
+ timer_instance[timer_num]->setInterruptPriority(STEP_TIMER_IRQ_PRIO, 0);
break;
case TEMP_TIMER_NUM:
- HAL_NVIC_SetPriority(TEMP_TIMER_IRQ_NAME, TEMP_TIMER_IRQ_PRIO, 0);
+ timer_instance[timer_num]->setInterruptPriority(TEMP_TIMER_IRQ_PRIO, 0);
break;
}
}
}
void HAL_timer_enable_interrupt(const uint8_t timer_num) {
- if (HAL_timer_initialized(timer_num) && !timer_enabled[timer_num]) {
- timer_enabled[timer_num] = true;
+ if (HAL_timer_initialized(timer_num) && !timer_instance[timer_num]->hasInterrupt()) {
switch (timer_num) {
case STEP_TIMER_NUM:
- timer_instance[timer_num]->attachInterrupt(Step_Handler);
- break;
- case TEMP_TIMER_NUM:
- timer_instance[timer_num]->attachInterrupt(Temp_Handler);
- break;
+ timer_instance[timer_num]->attachInterrupt(Step_Handler);
+ break;
+ case TEMP_TIMER_NUM:
+ timer_instance[timer_num]->attachInterrupt(Temp_Handler);
+ break;
}
}
}
void HAL_timer_disable_interrupt(const uint8_t timer_num) {
- if (HAL_timer_interrupt_enabled(timer_num)) {
- timer_instance[timer_num]->detachInterrupt();
- timer_enabled[timer_num] = false;
- }
+ if (HAL_timer_initialized(timer_num)) timer_instance[timer_num]->detachInterrupt();
}
bool HAL_timer_interrupt_enabled(const uint8_t timer_num) {
- return HAL_timer_initialized(timer_num) && timer_enabled[timer_num];
-}
-
-// Only for use within the HAL
-TIM_TypeDef * HAL_timer_device(const uint8_t timer_num) {
- switch (timer_num) {
- case STEP_TIMER_NUM: return STEP_TIMER_DEV;
- case TEMP_TIMER_NUM: return TEMP_TIMER_DEV;
- }
- return nullptr;
+ return HAL_timer_initialized(timer_num) && timer_instance[timer_num]->hasInterrupt();
}
void SetTimerInterruptPriorities() {
@@ -209,4 +194,87 @@ void SetTimerInterruptPriorities() {
TERN_(HAS_SERVOS, libServo::setInterruptPriority(SERVO_TIMER_IRQ_PRIO, 0));
}
+// This is a terrible hack to replicate the behavior used in the framework's SoftwareSerial.cpp
+// to choose a serial timer. It will select TIM7 on most boards used by Marlin, but this is more
+// resiliant to new MCUs which may not have a TIM7. Best practice is to explicitly specify
+// TIMER_SERIAL to avoid relying on framework selections which may not be predictable.
+#if !defined(TIMER_SERIAL)
+ #if defined (TIM18_BASE)
+ #define TIMER_SERIAL TIM18
+ #elif defined (TIM7_BASE)
+ #define TIMER_SERIAL TIM7
+ #elif defined (TIM6_BASE)
+ #define TIMER_SERIAL TIM6
+ #elif defined (TIM22_BASE)
+ #define TIMER_SERIAL TIM22
+ #elif defined (TIM21_BASE)
+ #define TIMER_SERIAL TIM21
+ #elif defined (TIM17_BASE)
+ #define TIMER_SERIAL TIM17
+ #elif defined (TIM16_BASE)
+ #define TIMER_SERIAL TIM16
+ #elif defined (TIM15_BASE)
+ #define TIMER_SERIAL TIM15
+ #elif defined (TIM14_BASE)
+ #define TIMER_SERIAL TIM14
+ #elif defined (TIM13_BASE)
+ #define TIMER_SERIAL TIM13
+ #elif defined (TIM11_BASE)
+ #define TIMER_SERIAL TIM11
+ #elif defined (TIM10_BASE)
+ #define TIMER_SERIAL TIM10
+ #elif defined (TIM12_BASE)
+ #define TIMER_SERIAL TIM12
+ #elif defined (TIM19_BASE)
+ #define TIMER_SERIAL TIM19
+ #elif defined (TIM9_BASE)
+ #define TIMER_SERIAL TIM9
+ #elif defined (TIM5_BASE)
+ #define TIMER_SERIAL TIM5
+ #elif defined (TIM4_BASE)
+ #define TIMER_SERIAL TIM4
+ #elif defined (TIM3_BASE)
+ #define TIMER_SERIAL TIM3
+ #elif defined (TIM2_BASE)
+ #define TIMER_SERIAL TIM2
+ #elif defined (TIM20_BASE)
+ #define TIMER_SERIAL TIM20
+ #elif defined (TIM8_BASE)
+ #define TIMER_SERIAL TIM8
+ #elif defined (TIM1_BASE)
+ #define TIMER_SERIAL TIM1
+ #else
+ #error No suitable timer found for SoftwareSerial, define TIMER_SERIAL in variant.h
+ #endif
+#endif
+
+// Place all timers used into an array, then recursively check for duplicates during compilation.
+// This does not currently account for timers used for PWM, such as for fans.
+// Timers are actually pointers. Convert to integers to simplify constexpr logic.
+static constexpr uintptr_t timers_in_use[] = {
+ uintptr_t(TEMP_TIMER_DEV), // Override in pins file
+ uintptr_t(STEP_TIMER_DEV), // Override in pins file
+ #if HAS_TMC_SW_SERIAL
+ uintptr_t(TIMER_SERIAL), // Set in variant.h, or as a define in platformio.h if not present in variant.h
+ #endif
+ #if ENABLED(SPEAKER)
+ uintptr_t(TIMER_TONE), // Set in variant.h, or as a define in platformio.h if not present in variant.h
+ #endif
+ #if HAS_SERVOS
+ uintptr_t(TIMER_SERVO), // Set in variant.h, or as a define in platformio.h if not present in variant.h
+ #endif
+ };
+
+static constexpr bool verify_no_duplicate_timers() {
+ LOOP_L_N(i, COUNT(timers_in_use))
+ LOOP_S_L_N(j, i + 1, COUNT(timers_in_use))
+ if (timers_in_use[i] == timers_in_use[j]) return false;
+ return true;
+}
+
+// If this assertion fails at compile time, review the timers_in_use array. If default_envs is
+// defined properly in platformio.ini, VS Code can evaluate the array when hovering over it,
+// making it easy to identify the conflicting timers.
+static_assert(verify_no_duplicate_timers(), "One or more timer conflict detected");
+
#endif // ARDUINO_ARCH_STM32 && !STM32GENERIC
diff --git a/Marlin/src/HAL/STM32/timers.h b/Marlin/src/HAL/STM32/timers.h
index 000f86043b..5515219ead 100644
--- a/Marlin/src/HAL/STM32/timers.h
+++ b/Marlin/src/HAL/STM32/timers.h
@@ -30,8 +30,18 @@
#define FORCE_INLINE __attribute__((always_inline)) inline
+// STM32 timers may be 16 or 32 bit. Limiting HAL_TIMER_TYPE_MAX to 16 bits
+// avoids issues with STM32F0 MCUs, which seem to pause timers if UINT32_MAX
+// is written to the register. STM32F4 timers do not manifest this issue,
+// even when writing to 16 bit timers.
+//
+// The range of the timer can be queried at runtime using IS_TIM_32B_COUNTER_INSTANCE.
+// This is a more expensive check than a simple compile-time constant, so its
+// implementation is deferred until the desire for a 32-bit range outweighs the cost
+// of adding a run-time check and HAL_TIMER_TYPE_MAX is refactored to allow unique
+// values for each timer.
#define hal_timer_t uint32_t
-#define HAL_TIMER_TYPE_MAX 0xFFFFFFFF // Timers can be 16 or 32 bit
+#define HAL_TIMER_TYPE_MAX UINT16_MAX
#ifndef STEP_TIMER_NUM
#define STEP_TIMER_NUM 0 // Timer Index for Stepper
@@ -61,14 +71,14 @@
#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(TEMP_TIMER_NUM)
#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(TEMP_TIMER_NUM)
-extern void Step_Handler(HardwareTimer *htim);
-extern void Temp_Handler(HardwareTimer *htim);
+extern void Step_Handler();
+extern void Temp_Handler();
#ifndef HAL_STEP_TIMER_ISR
- #define HAL_STEP_TIMER_ISR() void Step_Handler(HardwareTimer *htim)
+ #define HAL_STEP_TIMER_ISR() void Step_Handler()
#endif
#ifndef HAL_TEMP_TIMER_ISR
- #define HAL_TEMP_TIMER_ISR() void Temp_Handler(HardwareTimer *htim)
+ #define HAL_TEMP_TIMER_ISR() void Temp_Handler()
#endif
// ------------------------
@@ -90,8 +100,6 @@ bool HAL_timer_interrupt_enabled(const uint8_t timer_num);
// Exposed here to allow all timer priority information to reside in timers.cpp
void SetTimerInterruptPriorities();
-//TIM_TypeDef* HAL_timer_device(const uint8_t timer_num); no need to be public for now. not public = not used externally
-
// FORCE_INLINE because these are used in performance-critical situations
FORCE_INLINE bool HAL_timer_initialized(const uint8_t timer_num) {
return timer_instance[timer_num] != NULL;
diff --git a/Marlin/src/HAL/STM32F1/HAL.h b/Marlin/src/HAL/STM32F1/HAL.h
index 5a0b046009..5c03593eb0 100644
--- a/Marlin/src/HAL/STM32F1/HAL.h
+++ b/Marlin/src/HAL/STM32F1/HAL.h
@@ -46,12 +46,14 @@
#include "msc_sd.h"
#endif
+#include "MarlinSerial.h"
+
// ------------------------
// Defines
// ------------------------
#ifndef STM32_FLASH_SIZE
- #if defined(MCU_STM32F103RE) || defined(MCU_STM32F103VE)
+ #if EITHER(MCU_STM32F103RE, MCU_STM32F103VE)
#define STM32_FLASH_SIZE 512
#else
#define STM32_FLASH_SIZE 256
@@ -64,86 +66,50 @@
#else
#define UsbSerial MarlinCompositeSerial
#endif
- #define MSerial1 Serial1
- #define MSerial2 Serial2
- #define MSerial3 Serial3
- #define MSerial4 Serial4
- #define MSerial5 Serial5
-#else
- #define MSerial1 Serial
- #define MSerial2 Serial1
- #define MSerial3 Serial2
- #define MSerial4 Serial3
- #define MSerial5 Serial4
#endif
-#if SERIAL_PORT == 0
- #error "SERIAL_PORT cannot be 0. (Port 0 does not exist.) Please update your configuration."
-#elif SERIAL_PORT == -1
- #define MYSERIAL0 UsbSerial
-#elif SERIAL_PORT == 1
- #define MYSERIAL0 MSerial1
-#elif SERIAL_PORT == 2
- #define MYSERIAL0 MSerial2
-#elif SERIAL_PORT == 3
- #define MYSERIAL0 MSerial3
-#elif SERIAL_PORT == 4
- #define MYSERIAL0 MSerial4
-#elif SERIAL_PORT == 5
- #define MYSERIAL0 MSerial5
+#define _MSERIAL(X) MSerial##X
+#define MSERIAL(X) _MSERIAL(X)
+
+#if EITHER(STM32_HIGH_DENSITY, STM32_XL_DENSITY)
+ #define NUM_UARTS 5
#else
- #error "SERIAL_PORT must be from -1 to 5. Please update your configuration."
+ #define NUM_UARTS 3
+#endif
+
+#if SERIAL_PORT == -1
+ #define MYSERIAL0 UsbSerial
+#elif WITHIN(SERIAL_PORT, 1, NUM_UARTS)
+ #define MYSERIAL0 MSERIAL(SERIAL_PORT)
+#elif NUM_UARTS == 5
+ #error "SERIAL_PORT must be -1 or from 1 to 5. Please update your configuration."
+#else
+ #error "SERIAL_PORT must be -1 or from 1 to 3. Please update your configuration."
#endif
#ifdef SERIAL_PORT_2
- #if SERIAL_PORT_2 == 0
- #error "SERIAL_PORT_2 cannot be 0. (Port 0 does not exist.) Please update your configuration."
- #elif SERIAL_PORT_2 == SERIAL_PORT
- #error "SERIAL_PORT_2 must be different than SERIAL_PORT. Please update your configuration."
- #elif SERIAL_PORT_2 == -1
+ #if SERIAL_PORT_2 == -1
#define MYSERIAL1 UsbSerial
- #elif SERIAL_PORT_2 == 1
- #define MYSERIAL1 MSerial1
- #elif SERIAL_PORT_2 == 2
- #define MYSERIAL1 MSerial2
- #elif SERIAL_PORT_2 == 3
- #define MYSERIAL1 MSerial3
- #elif SERIAL_PORT_2 == 4
- #define MYSERIAL1 MSerial4
- #elif SERIAL_PORT_2 == 5
- #define MYSERIAL1 MSerial5
+ #elif WITHIN(SERIAL_PORT_2, 1, NUM_UARTS)
+ #define MYSERIAL1 MSERIAL(SERIAL_PORT_2)
+ #elif NUM_UARTS == 5
+ #error "SERIAL_PORT_2 must be -1 or from 1 to 5. Please update your configuration."
#else
- #error "SERIAL_PORT_2 must be from -1 to 5. Please update your configuration."
- #endif
- #define NUM_SERIAL 2
-#else
- #define NUM_SERIAL 1
-#endif
-
-#ifdef DGUS_SERIAL
- #if DGUS_SERIAL_PORT == 0
- #error "DGUS_SERIAL_PORT cannot be 0. (Port 0 does not exist.) Please update your configuration."
- #elif DGUS_SERIAL_PORT == SERIAL_PORT
- #error "DGUS_SERIAL_PORT must be different than SERIAL_PORT. Please update your configuration."
- #elif defined(SERIAL_PORT_2) && DGUS_SERIAL_PORT == SERIAL_PORT_2
- #error "DGUS_SERIAL_PORT must be different than SERIAL_PORT_2. Please update your configuration."
- #elif DGUS_SERIAL_PORT == -1
- #define DGUS_SERIAL UsbSerial
- #elif DGUS_SERIAL_PORT == 1
- #define DGUS_SERIAL MSerial1
- #elif DGUS_SERIAL_PORT == 2
- #define DGUS_SERIAL MSerial2
- #elif DGUS_SERIAL_PORT == 3
- #define DGUS_SERIAL MSerial3
- #elif DGUS_SERIAL_PORT == 4
- #define DGUS_SERIAL MSerial4
- #elif DGUS_SERIAL_PORT == 5
- #define DGUS_SERIAL MSerial5
- #else
- #error "DGUS_SERIAL_PORT must be from -1 to 5. Please update your configuration."
+ #error "SERIAL_PORT_2 must be -1 or from 1 to 3. Please update your configuration."
#endif
#endif
+#ifdef LCD_SERIAL_PORT
+ #if LCD_SERIAL_PORT == -1
+ #define LCD_SERIAL UsbSerial
+ #elif WITHIN(LCD_SERIAL_PORT, 1, NUM_UARTS)
+ #define LCD_SERIAL MSERIAL(LCD_SERIAL_PORT)
+ #elif NUM_UARTS == 5
+ #error "LCD_SERIAL_PORT must be -1 or from 1 to 5. Please update your configuration."
+ #else
+ #error "LCD_SERIAL_PORT must be -1 or from 1 to 3. Please update your configuration."
+ #endif
+#endif
// Set interrupt grouping for this MCU
void HAL_init();
diff --git a/Marlin/src/HAL/STM32F1/MarlinSerial.cpp b/Marlin/src/HAL/STM32F1/MarlinSerial.cpp
new file mode 100644
index 0000000000..ebf11cb429
--- /dev/null
+++ b/Marlin/src/HAL/STM32F1/MarlinSerial.cpp
@@ -0,0 +1,193 @@
+/**
+ * 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 .
+ *
+ */
+
+#ifdef __STM32F1__
+
+#include "../../inc/MarlinConfig.h"
+#include "MarlinSerial.h"
+#include
+
+// 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) {
+ /* Handle RXNEIE and TXEIE interrupts.
+ * RXNE signifies availability of a byte in DR.
+ *
+ * See table 198 (sec 27.4, p809) in STM document RM0008 rev 15.
+ * We enable RXNEIE.
+ */
+ uint32_t srflags = regs->SR, cr1its = regs->CR1;
+
+ if ((cr1its & USART_CR1_RXNEIE) && (srflags & USART_SR_RXNE)) {
+ if (srflags & USART_SR_FE || srflags & USART_SR_PE ) {
+ // framing error or parity error
+ regs->DR; // Read and throw away the data, which also clears FE and PE
+ }
+ else {
+ uint8_t c = (uint8)regs->DR;
+ #ifdef USART_SAFE_INSERT
+ // If the buffer is full and the user defines USART_SAFE_INSERT,
+ // ignore new bytes.
+ rb_safe_insert(rb, c);
+ #else
+ // By default, push bytes around in the ring buffer.
+ rb_push_insert(rb, c);
+ #endif
+ #if ENABLED(EMERGENCY_PARSER)
+ if (serial.emergency_parser_enabled())
+ emergency_parser.update(serial.emergency_state, c);
+ #endif
+ }
+ }
+ else if (srflags & USART_SR_ORE) {
+ // overrun and empty data, just do a dummy read to clear ORE
+ // and prevent a raise condition where a continous interrupt stream (due to ORE set) occurs
+ // (see chapter "Overrun error" ) in STM32 reference manual
+ regs->DR;
+ }
+
+ // TXE signifies readiness to send a byte to DR.
+ if ((cr1its & USART_CR1_TXEIE) && (srflags & USART_SR_TXE)) {
+ if (!rb_is_empty(wb))
+ regs->DR=rb_remove(wb);
+ else
+ regs->CR1 &= ~((uint32)USART_CR1_TXEIE); // disable TXEIE
+ }
+}
+
+// Not every MarlinSerial port should handle emergency parsing.
+// It would not make sense to parse GCode from TMC responses, for example.
+constexpr bool serial_handles_emergency(int port) {
+ return false
+ #ifdef SERIAL_PORT
+ || (SERIAL_PORT) == port
+ #endif
+ #ifdef SERIAL_PORT_2
+ || (SERIAL_PORT_2) == port
+ #endif
+ #ifdef LCD_SERIAL_PORT
+ || (LCD_SERIAL_PORT) == port
+ #endif
+ ;
+}
+
+#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) { \
+ 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, \
+ BOARD_USART##n##_TX_PIN, \
+ BOARD_USART##n##_RX_PIN, \
+ serial_handles_emergency(n)); \
+ extern "C" void __irq_usart##n(void) { \
+ my_usart_irq(UART##n->rb, UART##n->wb, UART##n##_BASE, MSerial##n); \
+ }
+
+// Instantiate all UARTs even if they are not needed
+// This avoids a bunch of logic to figure out every serial
+// port which may be in use on the system.
+DEFINE_HWSERIAL_MARLIN(MSerial1, 1);
+DEFINE_HWSERIAL_MARLIN(MSerial2, 2);
+DEFINE_HWSERIAL_MARLIN(MSerial3, 3);
+#if EITHER(STM32_HIGH_DENSITY, STM32_XL_DENSITY)
+ DEFINE_HWSERIAL_UART_MARLIN(MSerial4, 4);
+ DEFINE_HWSERIAL_UART_MARLIN(MSerial5, 5);
+#endif
+
+// Check the type of each serial port by passing it to a template function.
+// HardwareSerial is known to sometimes hang the controller when an error occurs,
+// so this case will fail the static assert. All other classes are assumed to be ok.
+template