diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h
index 0d9e9ce90f..d6c17f4df1 100644
--- a/Marlin/Configuration.h
+++ b/Marlin/Configuration.h
@@ -4,6 +4,10 @@
// CUSTOMIZE FOR YOUR MACHINE BELOW
// CUSTOMIZE FOR YOUR MACHINE BELOW
+// Enable this is you have a raptor 2.
+// Selects pin file, runout sensor and stock TMC Drivers automatically
+//#define RAPTOR2
+
/**
* Enable if you replace the stepper drivers with TMC 2208. Be sure to remove MS3 jumper
* underneath the stepper driver! Plug and Play will result in Stealth Chop 2 Mode enabled
@@ -14,7 +18,9 @@
//#define X_2208
//#define X_SpreadCycle
//#define Y_2208
-//#define Y_SpreadCyclebed
+//#define Y_SpreadCycle
+//#define Z_2208
+//#define Z_SpreadCycle
//#define E_2208
//#define E_SpreadCycle
@@ -41,7 +47,13 @@
//ONLY MAKE CHANGES ABOVE FOR RELIABLE FUNCTION
//ONLY MAKE CHANGES ABOVE FOR RELIABLE FUNCTION
-
+#if ENABLED(RAPTOR2)
+ #define X_2208
+ #define Y_2208
+ #define Z_2208
+ #define E_2208
+ #define RunoutSensor
+#endif
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
@@ -177,7 +189,11 @@
// The following define selects which electronics board you have.
// Please choose the name from boards.h that matches your setup
#ifndef MOTHERBOARD
- #define MOTHERBOARD BOARD_FORMBOT_RAPTOR
+ #if ENABLED(RAPTOR2)
+ #define MOTHERBOARD BOARD_FORMBOT_RAPTOR2
+ #else
+ #define MOTHERBOARD BOARD_FORMBOT_RAPTOR
+ #endif
#endif
// Optional custom name for your RepStrap or other custom machine
@@ -490,9 +506,15 @@
//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 100.0
- #define DEFAULT_bedKi 15.0
- #define DEFAULT_bedKd 200.0
+ #if(ENABLED(BED_AC))
+ #define DEFAULT_bedKp 100.0
+ #define DEFAULT_bedKi 15.0
+ #define DEFAULT_bedKd 200.0
+ #else
+ #define DEFAULT_bedKp 10.00
+ #define DEFAULT_bedKi .023
+ #define DEFAULT_bedKd 305.4
+ #endif
//120V 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)
//from pidautotune
@@ -681,16 +703,25 @@
* X, Y, Z, E0 [, E1[, E2[, E3[, E4]]]]
*/
#if(ENABLED(Y_2208))
-#define DEFAULT_AXIS_STEPS_PER_UNIT { 80, 80, 1600, 96 }
+ #define Y_STEPSMM 80
#else
-#define DEFAULT_AXIS_STEPS_PER_UNIT { 80, 160, 1600, 96 }
+ #define Y_STEPSMM 160
#endif
+
+ #if(ENABLED(Z_2208))
+ #define Z_STEPSMM 800
+#else
+ #define Z_STEPSMM 1600
+#endif
+
+ #define DEFAULT_AXIS_STEPS_PER_UNIT { 80,Y_STEPSMM , Z_STEPSMM, 96 }
+
/**
* Default Max Feed Rate (mm/s)
* Override with M203
* X, Y, Z, E0 [, E1[, E2[, E3[, E4]]]]
*/
-#define DEFAULT_MAX_FEEDRATE { 250, 150, 5, 25 }
+#define DEFAULT_MAX_FEEDRATE { 250, 120, 5, 25 }
/**
* Default Max Acceleration (change/s) change = mm/s
@@ -950,27 +981,31 @@
// Invert the stepper direction. Change (or reverse the motor connector) if an axis goes the wrong way.
#if(ENABLED(X_2208))
-#define INVERT_X_DIR true
+ #define INVERT_X_DIR true
#else
-#define INVERT_X_DIR false
+ #define INVERT_X_DIR false
#endif
- #if(ENABLED(Y_2208))
-#define INVERT_Y_DIR true
+#if(ENABLED(Y_2208))
+ #define INVERT_Y_DIR true
#else
-#define INVERT_Y_DIR false
+ #define INVERT_Y_DIR false
+#endif
+#if(ENABLED(Z_2208))
+ #define INVERT_Z_DIR false
+#else
+ #define INVERT_Z_DIR true
#endif
-#define INVERT_Z_DIR true
// @section extruder
// For direct drive extruder v9 set to true, for geared extruder set to false.
#if(ENABLED(E_2208))
-#define INVERT_E0_DIR false
-#define INVERT_E1_DIR false
+ #define INVERT_E0_DIR false
+ #define INVERT_E1_DIR true
#else
-#define INVERT_E0_DIR true
-#define INVERT_E1_DIR true
+ #define INVERT_E0_DIR true
+ #define INVERT_E1_DIR false
#endif
#define INVERT_E2_DIR false
#define INVERT_E3_DIR false
@@ -1047,8 +1082,12 @@
#endif
#if ENABLED(FILAMENT_RUNOUT_SENSOR)
#define NUM_RUNOUT_SENSORS 1 // Number of sensors, up to one per extruder. Define a FIL_RUNOUT#_PIN for each.
- #define FIL_RUNOUT_PIN 57
- #define FIL_RUNOUT_INVERTING true // set to true to invert the logic of the sensor.
+ #if DISABLED(RAPTOR2)
+ #define FIL_RUNOUT_PIN 57
+ #define FIL_RUNOUT_INVERTING true // set to true to invert the logic of the sensor.
+ #else
+ #define FIL_RUNOUT_INVERTING false // set to true to invert the logic of the sensor.
+ #endif
#define FIL_RUNOUT_PULLUP // Use internal pullup for filament runout pins.
//#define FIL_RUNOUT_PULLDOWN // Use internal pulldown for filament runout pins.
#define FILAMENT_RUNOUT_SCRIPT "M600"
@@ -1188,13 +1227,6 @@
#define GRID_MAX_POINTS_X 10 // Don't use more than 15 points per axis, implementation limited.
#define GRID_MAX_POINTS_Y GRID_MAX_POINTS_X
- #define PROBE_PT_1_X 50 // Probing points for 3-Point leveling of the mesh
- #define PROBE_PT_1_Y 350
- #define PROBE_PT_2_X 50
- #define PROBE_PT_2_Y 50
- #define PROBE_PT_3_X 350
- #define PROBE_PT_3_Y 50
-
#define UBL_MESH_EDIT_MOVES_Z // Sophisticated users prefer no movement of nozzle
#define UBL_SAVE_ACTIVE_ON_M500 // Save the currently active mesh in the current slot on M500
@@ -1220,12 +1252,12 @@
* Override if the automatically selected points are inadequate.
*/
#if ENABLED(AUTO_BED_LEVELING_3POINT) || ENABLED(AUTO_BED_LEVELING_UBL)
- //#define PROBE_PT_1_X 15
- //#define PROBE_PT_1_Y 180
- //#define PROBE_PT_2_X 15
- //#define PROBE_PT_2_Y 20
- //#define PROBE_PT_3_X 170
- //#define PROBE_PT_3_Y 20
+ #define PROBE_PT_1_X 50 // Probing points for 3-Point leveling of the mesh
+ #define PROBE_PT_1_Y 350
+ #define PROBE_PT_2_X 50
+ #define PROBE_PT_2_Y 50
+ #define PROBE_PT_3_X 350
+ #define PROBE_PT_3_Y 50
#endif
/**
@@ -1273,6 +1305,7 @@
// - If stepper drivers time out, it will need X and Y homing again before Z homing.
// - Move the Z probe (or nozzle) to a defined XY point before Z Homing when homing all axes (G28).
// - Prevent Z homing when the Z probe is outside bed area.
+//
#define Z_SAFE_HOMING
#if ENABLED(Z_SAFE_HOMING)
@@ -1506,7 +1539,7 @@
*
* View the current statistics with M78.
*/
-//#define PRINTCOUNTER
+#define PRINTCOUNTER
//=============================================================================
//============================= LCD and SD support ============================
@@ -2056,7 +2089,7 @@
* Set this manually if there are extra servos needing manual control.
* Leave undefined or set to 0 to entirely disable the servo subsystem.
*/
-//#define NUM_SERVOS 3 // Servo index starts with 0 for M280 command
+#define NUM_SERVOS 1 // Servo index starts with 0 for M280 command
// Delay (in milliseconds) before the next move will start, to give the servo time to reach its target angle.
// 300ms is a good value but you can try less delay.
diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h
index e7aa85e8c5..58f3fbc60b 100644
--- a/Marlin/Configuration_adv.h
+++ b/Marlin/Configuration_adv.h
@@ -237,7 +237,11 @@
* Multiple extruders can be assigned to the same pin in which case
* the fan will turn on when any selected extruder is above the threshold.
*/
-#define E0_AUTO_FAN_PIN -1
+#if ENABLED(RAPTOR2)
+ #define E0_AUTO_FAN_PIN 9
+#else
+ #define E0_AUTO_FAN_PIN -1
+#endif
#define E1_AUTO_FAN_PIN -1
#define E2_AUTO_FAN_PIN -1
#define E3_AUTO_FAN_PIN -1
@@ -776,7 +780,7 @@
* Mention @Sebastianv650 on GitHub to alert the author of any issues.
*/
#if(DISABLED(E_2208))
-#define LIN_ADVANCE
+ #define LIN_ADVANCE
#endif
#if ENABLED(LIN_ADVANCE)
#define LIN_ADVANCE_K 0.22 // Unit: mm compression per 1mm/s extruder speed
@@ -787,10 +791,29 @@
#if ENABLED(MESH_BED_LEVELING) || ENABLED(AUTO_BED_LEVELING_UBL)
// Override the mesh area if the automatic (max) area is too large
- //#define MESH_MIN_X MESH_INSET
- //#define MESH_MIN_Y MESH_INSET
- //#define MESH_MAX_X X_BED_SIZE - (MESH_INSET)
- //#define MESH_MAX_Y Y_BED_SIZE - (MESH_INSET)
+ #if( (X_PROBE_OFFSET_FROM_EXTRUDER + 15) > 0 )
+ #define MESH_MIN_X (X_PROBE_OFFSET_FROM_EXTRUDER + 5)
+ #else
+ #define MESH_MIN_X 5
+ #endif
+
+ #if( (X_BED_SIZE + X_PROBE_OFFSET_FROM_EXTRUDER - 10) < X_BED_SIZE)
+ #define MESH_MAX_X (X_BED_SIZE + X_PROBE_OFFSET_FROM_EXTRUDER - 5)
+ #else
+ #define MESH_MAX_X (X_BED_SIZE - 10)
+ #endif
+
+ #if ( (Y_PROBE_OFFSET_FROM_EXTRUDER + 10) > 10 )
+ #define MESH_MIN_Y (Y_PROBE_OFFSET_FROM_EXTRUDER + 10)
+ #else
+ #define MESH_MIN_Y 20
+ #endif
+
+ #if( (Y_BED_SIZE + Y_PROBE_OFFSET_FROM_EXTRUDER - 10) < Y_BED_SIZE)
+ #define MESH_MAX_Y (Y_BED_SIZE + Y_PROBE_OFFSET_FROM_EXTRUDER - 10)
+ #else
+ #define MESH_MAX_Y (Y_BED_SIZE - 25)
+ #endif
#endif
/**
@@ -979,7 +1002,7 @@
#define RETRACT_LENGTH 3 // Default retract length (positive mm)
#define RETRACT_LENGTH_SWAP 13 // Default swap retract length (positive mm), for extruder change
#define RETRACT_FEEDRATE 45 // Default feedrate for retracting (mm/s)
- #define RETRACT_ZLIFT 0 // Default retract Z-lift
+ #define RETRACT_ZRAISE 0 // Default retract Z-lift
#define RETRACT_RECOVER_LENGTH 0 // Default additional recover length (mm, added to retract length when recovering)
#define RETRACT_RECOVER_LENGTH_SWAP 0 // Default additional swap recover length (mm, added to retract length when recovering from extruder change)
#define RETRACT_RECOVER_FEEDRATE 8 // Default feedrate for recovering from retraction (mm/s)
@@ -1021,7 +1044,7 @@
// 0 to disable start loading and skip to fast load only
#define FILAMENT_CHANGE_FAST_LOAD_FEEDRATE 6 // (mm/s) Load filament feedrate. This can be pretty fast.
#define FILAMENT_CHANGE_FAST_LOAD_ACCEL 25 // (mm/s^2) Lower acceleration may allow a faster feedrate.
- #define FILAMENT_CHANGE_FAST_LOAD_LENGTH 5 // (mm) Load length of filament, from extruder gear to nozzle.
+ #define FILAMENT_CHANGE_FAST_LOAD_LENGTH 2 // (mm) Load length of filament, from extruder gear to nozzle.
// For Bowden, the full length of the tube and nozzle.
// For direct drive, the full length of the nozzle.
//#define ADVANCED_PAUSE_CONTINUOUS_PURGE // Purge continuously up to the purge length until interrupted.
@@ -1381,17 +1404,19 @@
*
* See http://marlinfw.org/docs/configuration/laser_spindle.html for more config details.
*/
-//#define SPINDLE_LASER_ENABLE
+#if ENABLED(RAPTOR2)
+ #define SPINDLE_LASER_ENABLE
+#endif
#if ENABLED(SPINDLE_LASER_ENABLE)
- #define SPINDLE_LASER_ENABLE_INVERT false // set to "true" if the on/off function is reversed
- #define SPINDLE_LASER_PWM true // set to true if your controller supports setting the speed/power
+ #define SPINDLE_LASER_ENABLE_INVERT true // set to "true" if the on/off function is reversed
+ #define SPINDLE_LASER_PWM false // set to true if your controller supports setting the speed/power
#define SPINDLE_LASER_PWM_INVERT true // set to "true" if the speed/power goes up when you want it to go slower
- #define SPINDLE_LASER_POWERUP_DELAY 5000 // delay in milliseconds to allow the spindle/laser to come up to speed/power
- #define SPINDLE_LASER_POWERDOWN_DELAY 5000 // delay in milliseconds to allow the spindle to stop
- #define SPINDLE_DIR_CHANGE true // set to true if your spindle controller supports changing spindle direction
+ #define SPINDLE_LASER_POWERUP_DELAY 1 // delay in milliseconds to allow the spindle/laser to come up to speed/power
+ #define SPINDLE_LASER_POWERDOWN_DELAY 1 // delay in milliseconds to allow the spindle to stop
+ #define SPINDLE_DIR_CHANGE false // set to true if your spindle controller supports changing spindle direction
#define SPINDLE_INVERT_DIR false
- #define SPINDLE_STOP_ON_DIR_CHANGE true // set to true if Marlin should stop the spindle before changing rotation direction
+ #define SPINDLE_STOP_ON_DIR_CHANGE false // set to true if Marlin should stop the spindle before changing rotation direction
/**
* The M3 & M4 commands use the following equation to convert PWM duty cycle to speed/power
diff --git a/Marlin/Makefile b/Marlin/Makefile
index da3897e807..349574c875 100644
--- a/Marlin/Makefile
+++ b/Marlin/Makefile
@@ -89,8 +89,8 @@ WIRE ?= 0
# this defines if U8GLIB is needed (may require RELOC_WORKAROUND)
U8GLIB ?= 1
-# this defines whether to include the Trinamic TMC2630Stepper
-TMC2630 ?= 1
+# this defines whether to include the Trinamic TMCStepper library
+TMC ?= 1
############
# Try to automatically determine whether RELOC_WORKAROUND is needed based
@@ -103,7 +103,7 @@ CC_PATCHLEVEL:=$(shell $(CC) -dM -E - < /dev/null | grep __GNUC_PATCHLEVEL__ | c
CC_VER:=$(shell echo $$(( $(CC_MAJ) * 10000 + $(CC_MIN) * 100 + $(CC_PATCHLEVEL) )))
ifeq ($(shell test $(CC_VER) -lt 40901 && echo 1),1)
@echo This version of GCC is likely broken. Enabling relocation workaround.
- RELOC_WORKAROUND = 1
+ RELOC_WORKAROUND = 1
endif
############################################################################
@@ -195,7 +195,7 @@ else ifeq ($(HARDWARE_MOTHERBOARD),49)
else ifeq ($(HARDWARE_MOTHERBOARD),7)
# Ultimaker (Older electronics. Pre 1.5.4. This is rare)
else ifeq ($(HARDWARE_MOTHERBOARD),71)
-MCU ?= atmega1280
+ MCU ?= atmega1280
# Azteeg X3
else ifeq ($(HARDWARE_MOTHERBOARD),67)
# Azteeg X3 Pro
@@ -265,9 +265,9 @@ else ifeq ($(HARDWARE_MOTHERBOARD),75)
#
else ifeq ($(HARDWARE_MOTHERBOARD),702)
-MCU ?= atmega1281
+ MCU ?= atmega1281
else ifeq ($(HARDWARE_MOTHERBOARD),25)
-MCU ?= atmega1281
+ MCU ?= atmega1281
#
# Sanguinololu and Derivatives - ATmega644P, ATmega1284P
@@ -275,44 +275,44 @@ MCU ?= atmega1281
# Sanguinololu < 1.2
else ifeq ($(HARDWARE_MOTHERBOARD),6)
-HARDWARE_VARIANT ?= Sanguino
-MCU ?= atmega644p
+ HARDWARE_VARIANT ?= Sanguino
+ MCU ?= atmega644p
# Sanguinololu 1.2 and above
else ifeq ($(HARDWARE_MOTHERBOARD),62)
-HARDWARE_VARIANT ?= Sanguino
-MCU ?= atmega644p
+ HARDWARE_VARIANT ?= Sanguino
+ MCU ?= atmega644p
# Melzi
else ifeq ($(HARDWARE_MOTHERBOARD),63)
-HARDWARE_VARIANT ?= Sanguino
-MCU ?= atmega644p
+ HARDWARE_VARIANT ?= Sanguino
+ MCU ?= atmega644p
# Melzi with ATmega1284 (MaKr3d version)
else ifeq ($(HARDWARE_MOTHERBOARD),66)
-HARDWARE_VARIANT ?= Sanguino
-MCU ?= atmega1284p
+ HARDWARE_VARIANT ?= Sanguino
+ MCU ?= atmega1284p
# Melzi Creality3D board (for CR-10 etc)
else ifeq ($(HARDWARE_MOTHERBOARD),89)
-HARDWARE_VARIANT ?= Sanguino
-MCU ?= atmega1284p
+ HARDWARE_VARIANT ?= Sanguino
+ MCU ?= atmega1284p
# Melzi Malyan M150 board
else ifeq ($(HARDWARE_MOTHERBOARD),92)
-HARDWARE_VARIANT ?= Sanguino
-MCU ?= atmega1284p
+ HARDWARE_VARIANT ?= Sanguino
+ MCU ?= atmega1284p
# Tronxy X5S
else ifeq ($(HARDWARE_MOTHERBOARD),505)
-HARDWARE_VARIANT ?= Sanguino
-MCU ?= atmega1284p
+ HARDWARE_VARIANT ?= Sanguino
+ MCU ?= atmega1284p
# STB V1.1
else ifeq ($(HARDWARE_MOTHERBOARD),64)
-HARDWARE_VARIANT ?= Sanguino
-MCU ?= atmega1284p
+ HARDWARE_VARIANT ?= Sanguino
+ MCU ?= atmega1284p
# Azteeg X1
else ifeq ($(HARDWARE_MOTHERBOARD),65)
-HARDWARE_VARIANT ?= Sanguino
-MCU ?= atmega1284p
+ HARDWARE_VARIANT ?= Sanguino
+ MCU ?= atmega1284p
# Anet 1.0 (Melzi clone)
else ifeq ($(HARDWARE_MOTHERBOARD),69)
-HARDWARE_VARIANT ?= Sanguino
-MCU ?= atmega1284p
+ HARDWARE_VARIANT ?= Sanguino
+ MCU ?= atmega1284p
#
# Other ATmega644P, ATmega644, ATmega1284P
@@ -320,52 +320,52 @@ MCU ?= atmega1284p
# Gen3 Monolithic Electronics
else ifeq ($(HARDWARE_MOTHERBOARD),22)
-HARDWARE_VARIANT ?= Sanguino
-MCU ?= atmega644p
+ HARDWARE_VARIANT ?= Sanguino
+ MCU ?= atmega644p
# Gen3+
else ifeq ($(HARDWARE_MOTHERBOARD),9)
-HARDWARE_VARIANT ?= Sanguino
-MCU ?= atmega644p
+ HARDWARE_VARIANT ?= Sanguino
+ MCU ?= atmega644p
# Gen6
else ifeq ($(HARDWARE_MOTHERBOARD),5)
-HARDWARE_VARIANT ?= Gen6
-MCU ?= atmega644p
+ HARDWARE_VARIANT ?= Gen6
+ MCU ?= atmega644p
# Gen6 deluxe
else ifeq ($(HARDWARE_MOTHERBOARD),51)
-HARDWARE_VARIANT ?= Gen6
-MCU ?= atmega644p
+ HARDWARE_VARIANT ?= Gen6
+ MCU ?= atmega644p
# Gen7 custom (Alfons3 Version)
else ifeq ($(HARDWARE_MOTHERBOARD),10)
-HARDWARE_VARIANT ?= Gen7
-MCU ?= atmega644
-F_CPU ?= 20000000
+ HARDWARE_VARIANT ?= Gen7
+ MCU ?= atmega644
+ F_CPU ?= 20000000
# Gen7 v1.1, v1.2
else ifeq ($(HARDWARE_MOTHERBOARD),11)
-HARDWARE_VARIANT ?= Gen7
-MCU ?= atmega644p
-F_CPU ?= 20000000
+ HARDWARE_VARIANT ?= Gen7
+ MCU ?= atmega644p
+ F_CPU ?= 20000000
# Gen7 v1.3
else ifeq ($(HARDWARE_MOTHERBOARD),12)
-HARDWARE_VARIANT ?= Gen7
-MCU ?= atmega644p
-F_CPU ?= 20000000
+ HARDWARE_VARIANT ?= Gen7
+ MCU ?= atmega644p
+ F_CPU ?= 20000000
# Gen7 v1.4
else ifeq ($(HARDWARE_MOTHERBOARD),13)
-HARDWARE_VARIANT ?= Gen7
-MCU ?= atmega1284p
-F_CPU ?= 20000000
+ HARDWARE_VARIANT ?= Gen7
+ MCU ?= atmega1284p
+ F_CPU ?= 20000000
# Alpha OMCA board
else ifeq ($(HARDWARE_MOTHERBOARD),90)
-HARDWARE_VARIANT ?= SanguinoA
-MCU ?= atmega644
+ HARDWARE_VARIANT ?= SanguinoA
+ MCU ?= atmega644
# Final OMCA board
else ifeq ($(HARDWARE_MOTHERBOARD),91)
-HARDWARE_VARIANT ?= Sanguino
-MCU ?= atmega644p
+ HARDWARE_VARIANT ?= Sanguino
+ MCU ?= atmega644p
# Sethi 3D_1
else ifeq ($(HARDWARE_MOTHERBOARD),20)
-HARDWARE_VARIANT ?= Sanguino
-MCU ?= atmega644p
+ HARDWARE_VARIANT ?= Sanguino
+ MCU ?= atmega644p
#
# Teensyduino - AT90USB1286, AT90USB1286P
@@ -373,37 +373,49 @@ MCU ?= atmega644p
# Teensylu
else ifeq ($(HARDWARE_MOTHERBOARD),8)
-HARDWARE_VARIANT ?= Teensy
-MCU ?= at90usb1286
+ HARDWARE_VARIANT ?= Teensy
+ MCU ?= at90usb1286
# Printrboard (AT90USB1286)
else ifeq ($(HARDWARE_MOTHERBOARD),81)
-HARDWARE_VARIANT ?= Teensy
-MCU ?= at90usb1286
+ HARDWARE_VARIANT ?= Teensy
+ MCU ?= at90usb1286
# Printrboard Revision F (AT90USB1286)
else ifeq ($(HARDWARE_MOTHERBOARD),811)
-HARDWARE_VARIANT ?= Teensy
-MCU ?= at90usb1286
+ HARDWARE_VARIANT ?= Teensy
+ MCU ?= at90usb1286
# Brainwave (AT90USB646)
else ifeq ($(HARDWARE_MOTHERBOARD),82)
-HARDWARE_VARIANT ?= Teensy
-MCU ?= at90usb646
+ HARDWARE_VARIANT ?= Teensy
+ MCU ?= at90usb646
# Brainwave Pro (AT90USB1286)
else ifeq ($(HARDWARE_MOTHERBOARD),83)
-HARDWARE_VARIANT ?= Teensy
-MCU ?= at90usb1286
+ HARDWARE_VARIANT ?= Teensy
+ MCU ?= at90usb1286
# SAV Mk-I (AT90USB1286)
else ifeq ($(HARDWARE_MOTHERBOARD),84)
-HARDWARE_VARIANT ?= Teensy
-MCU ?= at90usb1286
+ HARDWARE_VARIANT ?= Teensy
+ MCU ?= at90usb1286
# Teensy++2.0 (AT90USB1286)
else ifeq ($(HARDWARE_MOTHERBOARD),85)
-HARDWARE_VARIANT ?= Teensy
-MCU ?= at90usb1286
+ HARDWARE_VARIANT ?= Teensy
+ MCU ?= at90usb1286
# 5DPrint D8 Driver Board
else ifeq ($(HARDWARE_MOTHERBOARD),88)
-HARDWARE_VARIANT ?= Teensy
-MCU ?= at90usb1286
+ HARDWARE_VARIANT ?= Teensy
+ MCU ?= at90usb1286
+# UltiMachine Archim1 (with DRV8825 drivers)
+else ifeq ($(HARDWARE_MOTHERBOARD),1591)
+ HARDWARE_VARIANT ?= archim
+ MCPU = cortex-m3
+ F_CPU = 84000000L
+ IS_MCU = 0
+# UltiMachine Archim2 (with TMC2130 drivers)
+else ifeq ($(HARDWARE_MOTHERBOARD),1592)
+ HARDWARE_VARIANT ?= archim
+ MCPU = cortex-m3
+ F_CPU = 84000000L
+ IS_MCU = 0
endif
# Be sure to regenerate speed_lookuptable.h with create_speed_lookuptable.py
@@ -411,9 +423,22 @@ endif
# Set to 16Mhz if not yet set.
F_CPU ?= 16000000
-# Set to arduino, ATmega2560 if not yet set.
-HARDWARE_VARIANT ?= arduino
-MCU ?= atmega2560
+# Set to microcontroller if IS_MCU not yet set
+IS_MCU ?= 1
+
+ifeq ($(IS_MCU),1)
+ # Set to arduino, ATmega2560 if not yet set.
+ HARDWARE_VARIANT ?= arduino
+ MCU ?= atmega2560
+
+ TOOL_PREFIX = avr
+ MCU_FLAGS = -mmcu=$(MCU)
+ SIZE_FLAGS = --mcu=$(MCU) -C
+else
+ TOOL_PREFIX = arm-none-eabi
+ CPU_FLAGS = -mthumb -mcpu=$(MCPU)
+ SIZE_FLAGS = -A
+endif
# Arduino contained the main source code for the Arduino
# Libraries, the "hardware variant" are for boards
@@ -434,19 +459,19 @@ VPATH = .
VPATH += $(BUILD_DIR)
VPATH += $(HARDWARE_SRC)
-# U8glib
-VPATH += $(ARDUINO_USER_DIR)/libraries/U8glib
-VPATH += $(ARDUINO_USER_DIR)/libraries/U8glib/clib
-
ifeq ($(HARDWARE_VARIANT), $(filter $(HARDWARE_VARIANT),arduino Teensy Sanguino))
VPATH += $(ARDUINO_INSTALL_DIR)/hardware/marlin/avr/libraries/LiquidCrystal/src
VPATH += $(ARDUINO_INSTALL_DIR)/hardware/marlin/avr/libraries/SPI
endif
-VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/cores/arduino
+ifeq ($(IS_MCU),1)
+ VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/cores/arduino
+
+ VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/libraries/SPI
+ VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/libraries/SPI/src
+ VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/libraries/SoftwareSerial/src
+endif
-VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/libraries/SPI
-VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/libraries/SPI/src
VPATH += $(ARDUINO_INSTALL_DIR)/libraries/LiquidCrystal/src
ifeq ($(LIQUID_TWI2), 1)
VPATH += $(ARDUINO_INSTALL_DIR)/libraries/Wire
@@ -462,71 +487,90 @@ VPATH += $(ARDUINO_INSTALL_DIR)/libraries/Adafruit_NeoPixel
endif
ifeq ($(U8GLIB), 1)
VPATH += $(ARDUINO_INSTALL_DIR)/libraries/U8glib
-VPATH += $(ARDUINO_INSTALL_DIR)/libraries/U8glib/clib
+VPATH += $(ARDUINO_INSTALL_DIR)/libraries/U8glib/csrc
+VPATH += $(ARDUINO_INSTALL_DIR)/libraries/U8glib/cppsrc
+VPATH += $(ARDUINO_INSTALL_DIR)/libraries/U8glib/fntsrc
endif
-ifeq ($(TMC2630), 1)
-VPATH += $(ARDUINO_INSTALL_DIR)/libraries/TMC2130Stepper/src
-VPATH += $(ARDUINO_INSTALL_DIR)/libraries/TMC2130Stepper/src/source
+ifeq ($(TMC), 1)
+VPATH += $(ARDUINO_INSTALL_DIR)/libraries/TMCStepper/src
+VPATH += $(ARDUINO_INSTALL_DIR)/libraries/TMCStepper/src/source
endif
ifeq ($(HARDWARE_VARIANT), arduino)
-HARDWARE_SUB_VARIANT ?= mega
-VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/variants/$(HARDWARE_SUB_VARIANT)
+ HARDWARE_SUB_VARIANT ?= mega
+ VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/variants/$(HARDWARE_SUB_VARIANT)
+else ifeq ($(HARDWARE_VARIANT), Sanguino)
+ VPATH += $(ARDUINO_INSTALL_DIR)/hardware/marlin/avr/variants/sanguino
+else ifeq ($(HARDWARE_VARIANT), archim)
+ VPATH += $(ARDUINO_INSTALL_DIR)/packages/ultimachine/hardware/sam/1.6.9-b/system/libsam
+ VPATH += $(ARDUINO_INSTALL_DIR)/packages/ultimachine/hardware/sam/1.6.9-b/system/CMSIS/CMSIS/Include/
+ VPATH += $(ARDUINO_INSTALL_DIR)/packages/ultimachine/hardware/sam/1.6.9-b/system/CMSIS/Device/ATMEL/
+ VPATH += $(ARDUINO_INSTALL_DIR)/packages/ultimachine/hardware/sam/1.6.9-b/cores/arduino
+ VPATH += $(ARDUINO_INSTALL_DIR)/packages/ultimachine/hardware/sam/1.6.9-b/cores/arduino/avr
+ VPATH += $(ARDUINO_INSTALL_DIR)/packages/ultimachine/hardware/sam/1.6.9-b/cores/arduino/USB
+ VPATH += $(ARDUINO_INSTALL_DIR)/packages/ultimachine/hardware/sam/1.6.9-b/libraries/Wire/src
+ VPATH += $(ARDUINO_INSTALL_DIR)/packages/ultimachine/hardware/sam/1.6.9-b/libraries/SPI/src
+ VPATH += $(ARDUINO_INSTALL_DIR)/packages/ultimachine/hardware/sam/1.6.9-b/libraries/U8glib/src/clib
+ VPATH += $(ARDUINO_INSTALL_DIR)/packages/ultimachine/hardware/sam/1.6.9-b/variants/archim
+ LDSCRIPT = $(ARDUINO_INSTALL_DIR)/packages/ultimachine/hardware/sam/1.6.9-b/variants/archim/linker_scripts/gcc/flash.ld
+ LDLIBS = $(ARDUINO_INSTALL_DIR)/packages/ultimachine/hardware/sam/1.6.9-b/variants/archim/libsam_sam3x8e_gcc_rel.a
else
-ifeq ($(HARDWARE_VARIANT), Sanguino)
-VPATH += $(ARDUINO_INSTALL_DIR)/hardware/marlin/avr/variants/sanguino
-else
-HARDWARE_SUB_VARIANT ?= standard
-VPATH += $(ARDUINO_INSTALL_DIR)/hardware/$(HARDWARE_VARIANT)/variants/$(HARDWARE_SUB_VARIANT)
-endif
+ HARDWARE_SUB_VARIANT ?= standard
+ VPATH += $(ARDUINO_INSTALL_DIR)/hardware/$(HARDWARE_VARIANT)/variants/$(HARDWARE_SUB_VARIANT)
endif
+
LIB_SRC = wiring.c \
- wiring_analog.c wiring_digital.c \
- wiring_pulse.c \
- wiring_shift.c WInterrupts.c hooks.c
+ wiring_analog.c wiring_digital.c \
+ wiring_shift.c WInterrupts.c hooks.c
+
+ifeq ($(HARDWARE_VARIANT), archim)
+ LIB_ASRC += wiring_pulse_asm.S
+else
+ LIB_SRC += wiring_pulse.c
+endif
ifeq ($(HARDWARE_VARIANT), Teensy)
-LIB_SRC = wiring.c
-VPATH += $(ARDUINO_INSTALL_DIR)/hardware/teensy/cores/teensy
+ LIB_SRC = wiring.c
+ VPATH += $(ARDUINO_INSTALL_DIR)/hardware/teensy/cores/teensy
endif
-LIB_CXXSRC = WMath.cpp WString.cpp Print.cpp SPI.cpp Tone.cpp
+LIB_CXXSRC = WMath.cpp WString.cpp Print.cpp SPI.cpp
ifeq ($(NEOPIXEL), 1)
-LIB_CXXSRC += Adafruit_NeoPixel.cpp
+ LIB_CXXSRC += Adafruit_NeoPixel.cpp
endif
ifeq ($(LIQUID_TWI2), 0)
-LIB_CXXSRC += LiquidCrystal.cpp
+ LIB_CXXSRC += LiquidCrystal.cpp
else
-LIB_SRC += twi.c
-LIB_CXXSRC += Wire.cpp LiquidTWI2.cpp
+ LIB_SRC += twi.c
+ LIB_CXXSRC += Wire.cpp LiquidTWI2.cpp
endif
ifeq ($(WIRE), 1)
-LIB_SRC += twi.c
-LIB_CXXSRC += Wire.cpp
+ LIB_SRC += twi.c
+ LIB_CXXSRC += Wire.cpp
endif
ifeq ($(U8GLIB), 1)
-LIB_CXXSRC += U8glib.cpp
-LIB_SRC += u8g_ll_api.c u8g_bitmap.c u8g_clip.c u8g_com_null.c u8g_delay.c u8g_page.c u8g_pb.c u8g_pb16h1.c u8g_rect.c u8g_state.c u8g_font.c u8g_font_data.c
+ LIB_CXXSRC += U8glib.cpp
+ LIB_SRC += u8g_ll_api.c u8g_bitmap.c u8g_clip.c u8g_com_null.c u8g_delay.c u8g_page.c u8g_pb.c u8g_pb16h1.c u8g_rect.c u8g_state.c u8g_font.c u8g_font_6x13.c u8g_font_04b_03.c u8g_font_5x8.c
endif
-ifeq ($(TMC2630), 1)
-LIB_CXXSRC += TMC2130Stepper.cpp TMC2130Stepper_COOLCONF.cpp TMC2130Stepper_DRV_STATUS.cpp TMC2130Stepper_IHOLD_IRUN.cpp TMC2130Stepper_CHOPCONF.cpp TMC2130Stepper_GCONF.cpp TMC2130Stepper_PWMCONF.cpp SW_SPI.cpp
+ifeq ($(TMC), 1)
+ LIB_CXXSRC += TMCStepper.cpp COOLCONF.cpp DRV_STATUS.cpp IHOLD_IRUN.cpp CHOPCONF.cpp GCONF.cpp PWMCONF.cpp DRV_CONF.cpp DRVCONF.cpp DRVCTRL.cpp DRVSTATUS.cpp ENCMODE.cpp RAMP_STAT.cpp SGCSCONF.cpp SHORT_CONF.cpp SMARTEN.cpp SW_MODE.cpp SW_SPI.cpp TMC2130Stepper.cpp TMC2208Stepper.cpp TMC2660Stepper.cpp TMC5130Stepper.cpp TMC5160Stepper.cpp
endif
ifeq ($(RELOC_WORKAROUND), 1)
-LD_PREFIX=-nodefaultlibs
-LD_SUFFIX=-lm -lgcc -lc -lgcc
+ LD_PREFIX=-nodefaultlibs
+ LD_SUFFIX=-lm -lgcc -lc -lgcc
endif
#Check for Arduino 1.0.0 or higher and use the correct source files for that version
ifeq ($(shell [ $(ARDUINO_VERSION) -ge 100 ] && echo true), true)
-LIB_CXXSRC += main.cpp
+ LIB_CXXSRC += main.cpp
else
-LIB_SRC += pins_arduino.c main.c
+ LIB_SRC += pins_arduino.c main.c
endif
FORMAT = ihex
@@ -544,62 +588,81 @@ OPT = s
DEFINES ?=
# Program settings
-CC = $(AVR_TOOLS_PATH)avr-gcc
-CXX = $(AVR_TOOLS_PATH)avr-g++
-OBJCOPY = $(AVR_TOOLS_PATH)avr-objcopy
-OBJDUMP = $(AVR_TOOLS_PATH)avr-objdump
-AR = $(AVR_TOOLS_PATH)avr-ar
-SIZE = $(AVR_TOOLS_PATH)avr-size
-NM = $(AVR_TOOLS_PATH)avr-nm
+CC = $(AVR_TOOLS_PATH)$(TOOL_PREFIX)-gcc
+CXX = $(AVR_TOOLS_PATH)$(TOOL_PREFIX)-g++
+OBJCOPY = $(AVR_TOOLS_PATH)$(TOOL_PREFIX)-objcopy
+OBJDUMP = $(AVR_TOOLS_PATH)$(TOOL_PREFIX)-objdump
+AR = $(AVR_TOOLS_PATH)$(TOOL_PREFIX)-ar
+SIZE = $(AVR_TOOLS_PATH)$(TOOL_PREFIX)-size
+NM = $(AVR_TOOLS_PATH)$(TOOL_PREFIX)-nm
AVRDUDE = avrdude
REMOVE = rm -f
MV = mv -f
# Place -D or -U options here
-CDEFS = -DF_CPU=$(F_CPU) ${addprefix -D , $(DEFINES)}
+CDEFS = -DF_CPU=$(F_CPU) ${addprefix -D , $(DEFINES)} -DARDUINO=$(ARDUINO_VERSION)
CXXDEFS = $(CDEFS)
ifeq ($(HARDWARE_VARIANT), Teensy)
-CDEFS += -DUSB_SERIAL
-LIB_SRC += usb.c pins_teensy.c
-LIB_CXXSRC += usb_api.cpp
+ CDEFS += -DUSB_SERIAL
+ LIB_SRC += usb.c pins_teensy.c
+ 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"'
+ 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
+
+ ifeq ($(U8GLIB), 1)
+ LIB_SRC += u8g_com_api.c u8g_pb32h1.c
+ endif
endif
# Add all the source directories as include directories too
CINCS = ${addprefix -I ,${VPATH}}
CXXINCS = ${addprefix -I ,${VPATH}}
+# Silence warnings for library code (won't work for .h files, unfortunately)
+LIBWARN = -w -Wno-packed-bitfield-compat
+
# Compiler flag to set the C/CPP Standard level.
CSTANDARD = -std=gnu99
CXXSTANDARD = -std=gnu++11
CDEBUG = -g$(DEBUG)
-CWARN = -Wall -Wstrict-prototypes
-CTUNING = -w -fsigned-char -funsigned-bitfields -fpack-struct \
- -fshort-enums -ffunction-sections -fdata-sections -flto \
- -DARDUINO=$(ARDUINO_VERSION)
+CWARN = -Wall -Wstrict-prototypes -Wno-packed-bitfield-compat -Wno-pragmas
+CXXWARN = -Wall -Wno-packed-bitfield-compat -Wno-pragmas
+CTUNING = -fsigned-char -funsigned-bitfields -fpack-struct -fno-exceptions \
+ -fshort-enums -ffunction-sections -fdata-sections
ifneq ($(HARDWARE_MOTHERBOARD),)
-CTUNING += -DMOTHERBOARD=${HARDWARE_MOTHERBOARD}
+ CTUNING += -DMOTHERBOARD=${HARDWARE_MOTHERBOARD}
endif
#CEXTRA = -Wa,-adhlns=$(<:.c=.lst)
-CEXTRA = -fno-use-cxa-atexit -fno-threadsafe-statics
-
-CFLAGS := $(CDEBUG) $(CDEFS) $(CINCS) -O$(OPT) $(CWARN) $(CEXTRA) $(CTUNING) $(CSTANDARD)
-CXXFLAGS := $(CDEFS) $(CINCS) -O$(OPT) -Wall $(CEXTRA) $(CTUNING) $(CXXSTANDARD)
+CXXEXTRA = -fno-use-cxa-atexit -fno-threadsafe-statics -fno-rtti
+CFLAGS := $(CDEBUG) $(CDEFS) $(CINCS) -O$(OPT) $(CEXTRA) $(CTUNING) $(CSTANDARD)
+CXXFLAGS := $(CDEFS) $(CINCS) -O$(OPT) $(CXXEXTRA) $(CTUNING) $(CXXSTANDARD)
+ASFLAGS := $(CDEFS)
#ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
-LDFLAGS = -lm
-
+ifeq ($(HARDWARE_VARIANT), archim)
+ LD_PREFIX = -Wl,--gc-sections,-Map,Marlin.ino.map,--cref,--check-sections,--entry=Reset_Handler,--unresolved-symbols=report-all,--warn-common,--warn-section-align
+ LD_SUFFIX = $(LDLIBS)
+ LDFLAGS = -lm -gcc -T$(LDSCRIPT) -u _sbrk -u link -u _close -u _fstat -u _isatty -u _lseek -u _read -u _write -u _exit -u kill -u _getpid
+else
+ LD_PREFIX = -Wl,--gc-sections,--relax
+ LDFLAGS = -lm
+ CTUNING += -flto
+endif
# Programming support using avrdude. Settings and variables.
AVRDUDE_PORT = $(UPLOAD_PORT)
AVRDUDE_WRITE_FLASH = -Uflash:w:$(BUILD_DIR)/$(TARGET).hex:i
ifeq ($(shell uname -s), Linux)
-AVRDUDE_CONF = /etc/avrdude/avrdude.conf
+ AVRDUDE_CONF = /etc/avrdude/avrdude.conf
else
-AVRDUDE_CONF = $(ARDUINO_INSTALL_DIR)/hardware/tools/avr/etc/avrdude.conf
+ AVRDUDE_CONF = $(ARDUINO_INSTALL_DIR)/hardware/tools/avr/etc/avrdude.conf
endif
AVRDUDE_FLAGS = -D -C$(AVRDUDE_CONF) \
- -p$(MCU) -P$(AVRDUDE_PORT) -c$(AVRDUDE_PROGRAMMER) \
- -b$(UPLOAD_RATE)
+ -p$(MCU) -P$(AVRDUDE_PORT) -c$(AVRDUDE_PROGRAMMER) \
+ -b$(UPLOAD_RATE)
# Since Marlin 2.0, the source files may be distributed into several
# different directories, so it is necessary to find them recursively
@@ -619,17 +682,17 @@ LST = $(LIB_ASRC:.S=.lst) $(LIB_CXXSRC:.cpp=.lst) $(LIB_SRC:.c=.lst)
# Combine all necessary flags and optional flags.
# Add target processor to flags.
-ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS)
-ALL_CXXFLAGS = -mmcu=$(MCU) $(CXXFLAGS)
-ALL_ASFLAGS = -mmcu=$(MCU) -x assembler-with-cpp $(ASFLAGS)
+ALL_CFLAGS = $(MCU_FLAGS) $(CPU_FLAGS) $(CFLAGS) -I.
+ALL_CXXFLAGS = $(MCU_FLAGS) $(CPU_FLAGS) $(CXXFLAGS)
+ALL_ASFLAGS = $(MCU_FLAGS) $(CPU_FLAGS) $(ASFLAGS) -x assembler-with-cpp
# set V=1 (eg, "make V=1") to print the full commands etc.
ifneq ($V,1)
- Pecho=@echo
- P=@
+ Pecho=@echo
+ P=@
else
- Pecho=@:
- P=
+ Pecho=@:
+ P=
endif
# Create required build hierarchy if it does not exist
@@ -639,9 +702,10 @@ $(shell mkdir -p $(dir $(OBJ)))
# Default target.
all: sizeafter
-build: elf hex
+build: elf hex bin
elf: $(BUILD_DIR)/$(TARGET).elf
+bin: $(BUILD_DIR)/$(TARGET).bin
hex: $(BUILD_DIR)/$(TARGET).hex
eep: $(BUILD_DIR)/$(TARGET).eep
lss: $(BUILD_DIR)/$(TARGET).lss
@@ -658,9 +722,9 @@ ifeq (${AVRDUDE_PROGRAMMER}, arduino)
stty -hup < $(UPLOAD_PORT); true
endif
- # Display size of file.
+ # Display size of file.
HEXSIZE = $(SIZE) --target=$(FORMAT) $(BUILD_DIR)/$(TARGET).hex
-ELFSIZE = $(SIZE) --mcu=$(MCU) -C $(BUILD_DIR)/$(TARGET).elf; \
+ELFSIZE = $(SIZE) $(SIZE_FLAGS) $(BUILD_DIR)/$(TARGET).elf; \
$(SIZE) $(BUILD_DIR)/$(TARGET).elf
sizebefore:
$P if [ -f $(BUILD_DIR)/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(HEXSIZE); echo; fi
@@ -671,10 +735,10 @@ sizeafter: build
# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
COFFCONVERT=$(OBJCOPY) --debugging \
- --change-section-address .data-0x800000 \
- --change-section-address .bss-0x800000 \
- --change-section-address .noinit-0x800000 \
- --change-section-address .eeprom-0x810000
+ --change-section-address .data-0x800000 \
+ --change-section-address .bss-0x800000 \
+ --change-section-address .noinit-0x800000 \
+ --change-section-address .eeprom-0x810000
coff: $(BUILD_DIR)/$(TARGET).elf
@@ -685,16 +749,20 @@ extcoff: $(TARGET).elf
$(COFFCONVERT) -O coff-ext-avr $(BUILD_DIR)/$(TARGET).elf $(TARGET).cof
-.SUFFIXES: .elf .hex .eep .lss .sym
+.SUFFIXES: .elf .hex .eep .lss .sym .bin
.PRECIOUS: .o
.elf.hex:
$(Pecho) " COPY $@"
$P $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
+.elf.bin:
+ $(Pecho) " COPY $@"
+ $P $(OBJCOPY) -O binary -R .eeprom $< $@
+
.elf.eep:
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
- --change-section-lma .eeprom=0 -O $(FORMAT) $< $@
+ --change-section-lma .eeprom=0 -O $(FORMAT) $< $@
# Create extended listing file from ELF output file.
.elf.lss:
@@ -704,32 +772,36 @@ extcoff: $(TARGET).elf
.elf.sym:
$(NM) -n $< > $@
- # Link: create ELF output file from library.
+ # Link: create ELF output file from library.
$(BUILD_DIR)/$(TARGET).elf: $(OBJ) Configuration.h
$(Pecho) " CXX $@"
- $P $(CC) $(LD_PREFIX) $(ALL_CXXFLAGS) -Wl,--gc-sections,--relax -o $@ -L. $(OBJ) $(LDFLAGS) $(LD_SUFFIX)
+ $P $(CC) $(LD_PREFIX) $(ALL_CXXFLAGS) -o $@ -L. $(OBJ) $(LDFLAGS) $(LD_SUFFIX)
# Object files that were found in "src" will be stored in $(BUILD_DIR)
# in directories that mirror the structure of "src"
$(BUILD_DIR)/%.o: %.c Configuration.h Configuration_adv.h $(MAKEFILE)
$(Pecho) " CC $<"
- $P $(CC) -MMD -c $(ALL_CFLAGS) $< -o $@
+ $P $(CC) -MMD -c $(ALL_CFLAGS) $(CWARN) $< -o $@
$(BUILD_DIR)/%.o: %.cpp Configuration.h Configuration_adv.h $(MAKEFILE)
$(Pecho) " CXX $<"
- $P $(CXX) -MMD -c $(ALL_CXXFLAGS) $< -o $@
+ $P $(CXX) -MMD -c $(ALL_CXXFLAGS) $(CXXWARN) $< -o $@
# Object files for Arduino libs will be created in $(BUILD_DIR)/arduino
$(BUILD_DIR)/arduino/%.o: %.c Configuration.h Configuration_adv.h $(MAKEFILE)
$(Pecho) " CC $<"
- $P $(CC) -MMD -c $(ALL_CFLAGS) $< -o $@
+ $P $(CC) -MMD -c $(ALL_CFLAGS) $(LIBWARN) $< -o $@
$(BUILD_DIR)/arduino/%.o: %.cpp Configuration.h Configuration_adv.h $(MAKEFILE)
$(Pecho) " CXX $<"
- $P $(CXX) -MMD -c $(ALL_CXXFLAGS) $< -o $@
+ $P $(CXX) -MMD -c $(ALL_CXXFLAGS) $(LIBWARN) $< -o $@
+
+$(BUILD_DIR)/arduino/%.o: %.S $(MAKEFILE)
+ $(Pecho) " CXX $<"
+ $P $(CXX) -MMD -c $(ALL_ASFLAGS) $< -o $@
# Target: clean project.
clean:
@@ -737,7 +809,7 @@ clean:
$P rm -rf $(BUILD_DIR)
-.PHONY: all build elf hex eep lss sym program coff extcoff clean depend sizebefore sizeafter
+.PHONY: all build elf hex eep lss sym program coff extcoff clean depend sizebefore sizeafter
# Automaticaly include the dependency files created by gcc
-include ${patsubst %.o, %.d, ${OBJ}}
diff --git a/Marlin/_Statusscreen.h b/Marlin/_Statusscreen.h
index 6a06a49016..d0450837ab 100644
--- a/Marlin/_Statusscreen.h
+++ b/Marlin/_Statusscreen.h
@@ -30,431 +30,45 @@
* http://marlinfw.org/tools/u8glib/converter.html
*/
+//
+// Status Screen Logo bitmap
+//
+#define STATUS_LOGO_Y 3
+#define STATUS_LOGO_WIDTH 24
-//============================================
-
-#define STATUS_SCREENWIDTH 128
-
-#define STATUS_SCREEN_HOTEND_TEXT_X(E) (41 + (E) * 20)
-
-#define STATUS_SCREEN_BED_TEXT_X (HOTENDS > 1 ? 81 : 73)
-
-#define FAN_ANIM_FRAMES 3
-#define STATUS_SCREEN_FAN_TEXT_X (FAN_ANIM_FRAMES == 3 ? 103 : 105)
-#define STATUS_SCREEN_FAN_TEXT_Y (FAN_ANIM_FRAMES > 2 ? 28 : 27)
-
-//============================================
+const unsigned char status_logo_bmp[] PROGMEM = {
+ B11111111,B11111111,B11111111,
+ B10000000,B00000000,B00000001,
+ B10001110,B00000000,B11100001,
+ B10011111,B00000001,B11110001,
+ B10010011,B10000001,B00111001,
+ B10011111,B10000001,B11111001,
+ B10011111,B10000001,B11111001,
+ B10011111,B10111001,B11111001,
+ B10001111,B00101000,B11110001,
+ B10000000,B00111000,B00000001,
+ B10000000,B00000000,B00000001,
+ B10011111,B11111111,B11111001,
+ B10010001,B01110100,B10011001,
+ B10011011,B00000110,B10101001,
+ B10011011,B01010100,B10101001,
+ B10011011,B01010110,B10101001,
+ B10011011,B01010100,B10011001,
+ B10011111,B11111111,B11111001,
+ B11111111,B11111111,B11111111
+};
+//
+// Use default bitmaps
+//
+#define STATUS_HOTEND_ANIM
+#define STATUS_BED_ANIM
#if HOTENDS < 2
-
- #if FAN_ANIM_FRAMES <= 2
-
- const unsigned char status_screen0_bmp[] PROGMEM = {
- B11111111,B11111111,B11111111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111,B11111000,
- B10000000,B00000000,B00000001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111110,B00000000,B11111000,
- B10001110,B00000000,B11100001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111000,B00111111,B00111000,
- B10011111,B00000000,B11110001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110000,B01111110,B00011000,
- B10010011,B10000001,B00111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110000,B01111100,B00011000,
- B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101000,B01111100,B00001000,
- B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101100,B00111000,B00001000,
- B10011111,B10111001,B11110001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00101111,B00111001,B11001000,
- B10001111,B00101000,B11110001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00101111,B11111111,B11101000,
- B10000000,B00111000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00101111,B11000111,B11101000,
- B10000000,B00000000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00101111,B11111111,B11101000,
- B10011111,B11111111,B11111001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00100111,B00111001,B11101000,
- B10010001,B01110100,B10011001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00100000,B00111000,B01101000,
- B10011011,B00000110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00100000,B01111100,B00101000,
- B10011011,B01010100,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00110000,B01111100,B00011000,
- B10011011,B01010110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00110000,B11111100,B00011000,
- B10011011,B01010100,B10011001,B00000000,B00000000,B00001111,B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111001,B11111000,B00111000,
- B10011111,B11111111,B11111001,B00000000,B00000000,B00000111,B10000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111110,B00000000,B11111000,
- B11111111,B11111111,B11111111,B00000000,B00000000,B00000011,B00000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111111,B11111111,B11111000
-};
- const unsigned char status_screen1_bmp[] PROGMEM = {
- B11111111,B11111111,B11111111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111,B11111000,
- B10000000,B00000000,B00000001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111110,B10000000,B11111000,
- B10001110,B00000000,B11100001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111001,B10000000,B00111000,
- B10011111,B00000000,B11110001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110111,B10000001,B11011000,
- B10010011,B10000001,B00111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110111,B11000011,B11011000,
- B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00100111,B11000111,B11101000,
- B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00100011,B11000111,B11111000,
- B10011111,B10111001,B11110001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00100001,B11111111,B10001000,
- B10001111,B00101000,B11110001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00100000,B01101100,B00001000,
- B10000000,B00111000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00100000,B01101100,B00001000,
- B10000000,B00000000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00100000,B01101100,B00001000,
- B10011111,B11111111,B11111001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00100011,B11111111,B00001000,
- B10010001,B01110100,B10011001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00111111,B11000111,B10001000,
- B10011011,B00000110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00101111,B11000111,B11001000,
- B10011011,B01010100,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00110111,B10000111,B11011000,
- B10011011,B01010110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00110111,B00000011,B11011000,
- B10011011,B01010100,B10011001,B00000000,B00000000,B00001111,B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111000,B00000011,B00111000,
- B10011111,B11111111,B11111001,B00000000,B00000000,B00000111,B10000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111110,B00000010,B11111000,
- B11111111,B11111111,B11111111,B00000000,B00000000,B00000011,B00000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111111,B11111111,B11111000
-};
-
- #elif FAN_ANIM_FRAMES == 3
-
-
-const unsigned char status_screen0_bmp[] PROGMEM = {
- B11111111,B11111111,B11111111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111,B11111000,
- B10000000,B00000000,B00000001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111110,B00000000,B11111000,
- B10001110,B00000000,B11100001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111000,B00111111,B00111000,
- B10011111,B00000000,B11110001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110000,B01111110,B00011000,
- B10010011,B10000001,B00111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110000,B01111100,B00011000,
- B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101000,B01111100,B00001000,
- B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101100,B00111000,B00001000,
- B10011111,B10111001,B11110001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00101111,B00111001,B11001000,
- B10001111,B00101000,B11110001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00101111,B11111111,B11101000,
- B10000000,B00111000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00101111,B11000111,B11101000,
- B10000000,B00000000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00101111,B11111111,B11101000,
- B10011111,B11111111,B11111001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00100111,B00111001,B11101000,
- B10010001,B01110100,B10011001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00100000,B00111000,B01101000,
- B10011011,B00000110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00100000,B01111100,B00101000,
- B10011011,B01010100,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00110000,B01111100,B00011000,
- B10011011,B01010110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00110000,B11111100,B00011000,
- B10011011,B01010100,B10011001,B00000000,B00000000,B00001111,B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111001,B11111000,B00111000,
- B10011111,B11111111,B11111001,B00000000,B00000000,B00000111,B10000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111110,B00000000,B11111000,
- B11111111,B11111111,B11111111,B00000000,B00000000,B00000011,B00000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111111,B11111111,B11111000
-};
-
-
- const unsigned char status_screen1_bmp[] PROGMEM = {
- B11111111,B11111111,B11111111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111,B11111000,
- B10000000,B00000000,B00000001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111110,B00000000,B11111000,
- B10001110,B00000000,B11100001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111000,B00001111,B00111000,
- B10011111,B00000000,B11110001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110100,B00011111,B11011000,
- B10010011,B10000001,B00111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110110,B00011111,B10011000,
- B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101111,B00011111,B00001000,
- B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101111,B10011110,B00001000,
- B10011111,B10111001,B11110001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00101111,B11111100,B00001000,
- B10001111,B00101000,B11110001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00101111,B11011100,B00001000,
- B10000000,B00111000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00100111,B11101111,B11001000,
- B10000000,B00000000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00100000,B01110111,B11101000,
- B10011111,B11111111,B11111001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00100000,B01111111,B11101000,
- B10010001,B01110100,B10011001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00100000,B11110011,B11101000,
- B10011011,B00000110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00100001,B11110001,B11101000,
- B10011011,B01010100,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00110011,B11110000,B11011000,
- B10011011,B01010110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00110111,B11110000,B01011000,
- B10011011,B01010100,B10011001,B00000000,B00000000,B00001111,B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111001,B11100000,B00111000,
- B10011111,B11111111,B11111001,B00000000,B00000000,B00000111,B10000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111110,B00000000,B11111000,
- B11111111,B11111111,B11111111,B00000000,B00000000,B00000011,B00000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111111,B11111111,B11111000
-};
- const unsigned char status_screen2_bmp[] PROGMEM = {
- B11111111,B11111111,B11111111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111,B11111000,
- B10000000,B00000000,B00000001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111110,B10000000,B11111000,
- B10001110,B00000000,B11100001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111001,B10000000,B00111000,
- B10011111,B00000000,B11110001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110111,B10000001,B11011000,
- B10010011,B10000001,B00111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110111,B11000011,B11011000,
- B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00100111,B11000111,B11101000,
- B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00100011,B11000111,B11111000,
- B10011111,B10111001,B11110001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00100001,B11111111,B10001000,
- B10001111,B00101000,B11110001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00100000,B01101100,B00001000,
- B10000000,B00111000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00100000,B01101100,B00001000,
- B10000000,B00000000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00100000,B01101100,B00001000,
- B10011111,B11111111,B11111001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00100011,B11111111,B00001000,
- B10010001,B01110100,B10011001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00111111,B11000111,B10001000,
- B10011011,B00000110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00101111,B11000111,B11001000,
- B10011011,B01010100,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00110111,B10000111,B11011000,
- B10011011,B01010110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00110111,B00000011,B11011000,
- B10011011,B01010100,B10011001,B00000000,B00000000,B00001111,B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111000,B00000011,B00111000,
- B10011111,B11111111,B11111001,B00000000,B00000000,B00000111,B10000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111110,B00000010,B11111000,
- B11111111,B11111111,B11111111,B00000000,B00000000,B00000011,B00000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111111,B11111111,B11111000
-};
-
- #elif FAN_ANIM_FRAMES == 4
-
-const unsigned char status_screen0_bmp[] PROGMEM = {
- B11111111,B11111111,B11111111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111,B11111000,
- B10000000,B00000000,B00000001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111110,B00000000,B11111000,
- B10001110,B00000000,B11100001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111000,B00111111,B00111000,
- B10011111,B00000000,B11110001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110000,B01111110,B00011000,
- B10010011,B10000001,B00111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110000,B01111100,B00011000,
- B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101000,B01111100,B00001000,
- B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101100,B00111000,B00001000,
- B10011111,B10111001,B11110001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00101111,B00111001,B11001000,
- B10001111,B00101000,B11110001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00101111,B11111111,B11101000,
- B10000000,B00111000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00101111,B11000111,B11101000,
- B10000000,B00000000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00101111,B11111111,B11101000,
- B10011111,B11111111,B11111001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00100111,B00111001,B11101000,
- B10010001,B01110100,B10011001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00100000,B00111000,B01101000,
- B10011011,B00000110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00100000,B01111100,B00101000,
- B10011011,B01010100,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00110000,B01111100,B00011000,
- B10011011,B01010110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00110000,B11111100,B00011000,
- B10011011,B01010100,B10011001,B00000000,B00000000,B00001111,B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111001,B11111000,B00111000,
- B10011111,B11111111,B11111001,B00000000,B00000000,B00000111,B10000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111110,B00000000,B11111000,
- B11111111,B11111111,B11111111,B00000000,B00000000,B00000011,B00000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111111,B11111111,B11111000
-};
-
-const unsigned char status_screen1_bmp[] PROGMEM = {
- B11111111,B11111111,B11111111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111,B11111000,
- B10000000,B00000000,B00000001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111110,B00000000,B11111000,
- B10001110,B00000000,B11100001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111000,B00001111,B00111000,
- B10011111,B00000000,B11110001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110100,B00011111,B11011000,
- B10010011,B10000001,B00111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110110,B00011111,B10011000,
- B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101111,B00011111,B00001000,
- B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101111,B10011110,B00001000,
- B10011111,B10111001,B11110001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00101111,B11111100,B00001000,
- B10001111,B00101000,B11110001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00101111,B11011100,B00001000,
- B10000000,B00111000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00100111,B11101111,B11001000,
- B10000000,B00000000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00100000,B01110111,B11101000,
- B10011111,B11111111,B11111001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00100000,B01111111,B11101000,
- B10010001,B01110100,B10011001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00100000,B11110011,B11101000,
- B10011011,B00000110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00100001,B11110001,B11101000,
- B10011011,B01010100,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00110011,B11110000,B11011000,
- B10011011,B01010110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00110111,B11110000,B01011000,
- B10011011,B01010100,B10011001,B00000000,B00000000,B00001111,B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111001,B11100000,B00111000,
- B10011111,B11111111,B11111001,B00000000,B00000000,B00000111,B10000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111110,B00000000,B11111000,
- B11111111,B11111111,B11111111,B00000000,B00000000,B00000011,B00000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111111,B11111111,B11111000
-};
-
-const unsigned char status_screen2_bmp[] PROGMEM = {
- B11111111,B11111111,B11111111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111,B11111000,
- B10000000,B00000000,B00000001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111110,B10000000,B11111000,
- B10001110,B00000000,B11100001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111001,B10000000,B00111000,
- B10011111,B00000000,B11110001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110111,B10000001,B11011000,
- B10010011,B10000001,B00111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110111,B11000011,B11011000,
- B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00100111,B11000111,B11101000,
- B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00100011,B11000111,B11111000,
- B10011111,B10111001,B11110001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00100001,B11111111,B10001000,
- B10001111,B00101000,B11110001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00100000,B01101100,B00001000,
- B10000000,B00111000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00100000,B01101100,B00001000,
- B10000000,B00000000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00100000,B01101100,B00001000,
- B10011111,B11111111,B11111001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00100011,B11111111,B00001000,
- B10010001,B01110100,B10011001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00111111,B11000111,B10001000,
- B10011011,B00000110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00101111,B11000111,B11001000,
- B10011011,B01010100,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00110111,B10000111,B11011000,
- B10011011,B01010110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00110111,B00000011,B11011000,
- B10011011,B01010100,B10011001,B00000000,B00000000,B00001111,B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111000,B00000011,B00111000,
- B10011111,B11111111,B11111001,B00000000,B00000000,B00000111,B10000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111110,B00000010,B11111000,
- B11111111,B11111111,B11111111,B00000000,B00000000,B00000011,B00000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111111,B11111111,B11111000
-};
-
-
-const unsigned char status_screen3_bmp[] PROGMEM = {
- B11111111,B11111111,B11111111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111,B11111000,
- B10000000,B00000000,B00000001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111110,B00000000,B11111000,
- B10001110,B00000000,B11100001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111001,B11110000,B00111000,
- B10011111,B00000000,B11110001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110001,B11100000,B00011000,
- B10010011,B10000001,B00111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110001,B11100000,B00011000,
- B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00100001,B11100001,B11101000,
- B10011111,B10000001,B11111001,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00100000,B11110011,B11101000,
- B10011111,B10111001,B11110001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00100000,B01111111,B11101000,
- B10001111,B00101000,B11110001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00100000,B01110111,B11101000,
- B10000000,B00111000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00000100,B00010000,B01000000,B00000000,B00101000,B11101110,B00101000,
- B10000000,B00000000,B00000001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00101111,B11011100,B00001000,
- B10011111,B11111111,B11111001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00101111,B11111100,B00001000,
- B10010001,B01110100,B10011001,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00101111,B10011110,B00001000,
- B10011011,B00000110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00100000,B10000010,B00000000,B00000000,B00101111,B00001111,B00001000,
- B10011011,B01010100,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00010000,B01000001,B00000000,B00000000,B00110000,B00001111,B00011000,
- B10011011,B01010110,B10101001,B00000000,B00000000,B00111111,B11110000,B00000000,B00000000,B00001000,B00100000,B10000000,B00000000,B00110000,B00001111,B00011000,
- B10011011,B01010100,B10011001,B00000000,B00000000,B00001111,B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111000,B00011111,B00111000,
- B10011111,B11111111,B11111001,B00000000,B00000000,B00000111,B10000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111110,B00000000,B11111000,
- B11111111,B11111111,B11111111,B00000000,B00000000,B00000011,B00000000,B00000000,B00000000,B11111111,B11111111,B11000000,B00000000,B00111111,B11111111,B11111000
-};
-
-
- #endif
-
-#else // HOTENDS >= 2
-
- #if FAN_ANIM_FRAMES <= 2
-
- const unsigned char status_screen0_bmp[] PROGMEM = {
- B00111101,B11110000,B00000010,B00111000,B11110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111,B11110000,
- B01000100,B10001000,B00000110,B01000101,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111000,B00000000,B01110000,
- B10000000,B10001000,B00000010,B01000101,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110000,B11111100,B00110000,
- B10000000,B11110000,B00000010,B01000100,B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00100000,B11111100,B00010000,
- B10000000,B10100011,B11110010,B01000100,B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00100000,B01111000,B00010000,
- B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00100000,B00110000,B00010000,
- B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101100,B00000000,B11010000,
- B01000100,B10001000,B00000010,B01000101,B00010000,B00011111,B11100000,B00000001,B11111110,B00000000,B00001000,B00100000,B10000000,B00101110,B00110001,B11010000,
- B00111001,B11001100,B00000111,B00111001,B11100000,B00111110,B11110000,B00000011,B11001111,B00000000,B00000100,B00010000,B01000000,B00101111,B01111011,B11010000,
- B00000000,B00000000,B00000000,B00000000,B00000000,B00111100,B11110000,B00000011,B10110111,B00000000,B00000100,B00010000,B01000000,B00101111,B01111011,B11010000,
- B00000000,B00111000,B01110000,B11100000,B00000000,B00111010,B11110000,B00000011,B11110111,B00000000,B00001000,B00100000,B10000000,B00101110,B00110001,B11010000,
- B00000000,B01000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11101110,B00000000,B00010000,B01000001,B00000000,B00101100,B00000000,B11010000,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11011110,B00000000,B00100000,B10000010,B00000000,B00100000,B00110000,B00010000,
- B00000000,B00011000,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10111111,B00000000,B00100000,B10000010,B00000000,B00100000,B01111000,B00010000,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10000111,B00000000,B00010000,B01000001,B00000000,B00100000,B11111100,B00010000,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00111111,B11110000,B00000011,B11111111,B00000000,B00001000,B00100000,B10000000,B00110000,B11111100,B00110000,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00001111,B11000000,B00000000,B11111100,B00000000,B00000000,B00000000,B00000000,B00111000,B00000000,B01110000,
- B00000000,B01000100,B10001001,B00010000,B00000000,B00000111,B10000000,B00000000,B01111000,B00000000,B11111111,B11111111,B11000000,B00111111,B11111111,B11110000,
- B00000000,B00111000,B01110000,B11100000,B00000000,B00000011,B00000000,B00000000,B00110000,B00000000,B11111111,B11111111,B11000000,B00000000,B00000000,B00000000
- };
- const unsigned char status_screen1_bmp[] PROGMEM = {
- B00111101,B11110000,B00000010,B00111000,B11110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111,B11110000,
- B01000100,B10001000,B00000110,B01000101,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111000,B00000000,B01110000,
- B10000000,B10001000,B00000010,B01000101,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110011,B10000111,B00110000,
- B10000000,B11110000,B00000010,B01000100,B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00100111,B10000111,B10010000,
- B10000000,B10100011,B11110010,B01000100,B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101111,B10000111,B11010000,
- B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101111,B10000111,B11010000,
- B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101111,B00000011,B11010000,
- B01000100,B10001000,B00000010,B01000101,B00010000,B00011111,B11100000,B00000001,B11111110,B00000000,B00001000,B00100000,B10000000,B00100000,B00110000,B00010000,
- B00111001,B11001100,B00000111,B00111001,B11100000,B00111110,B11110000,B00000011,B11001111,B00000000,B00000100,B00010000,B01000000,B00100000,B01111000,B00010000,
- B00000000,B00000000,B00000000,B00000000,B00000000,B00111100,B11110000,B00000011,B10110111,B00000000,B00000100,B00010000,B01000000,B00100000,B01111000,B00010000,
- B00000000,B00111000,B01110000,B11100000,B00000000,B00111010,B11110000,B00000011,B11110111,B00000000,B00001000,B00100000,B10000000,B00100000,B00110000,B00010000,
- B00000000,B01000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11101110,B00000000,B00010000,B01000001,B00000000,B00101111,B00000011,B11010000,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11011110,B00000000,B00100000,B10000010,B00000000,B00101111,B10000111,B11010000,
- B00000000,B00011000,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10111111,B00000000,B00100000,B10000010,B00000000,B00101111,B10000111,B11010000,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10000111,B00000000,B00010000,B01000001,B00000000,B00100111,B10000111,B10010000,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00111111,B11110000,B00000011,B11111111,B00000000,B00001000,B00100000,B10000000,B00110011,B10000111,B00110000,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00001111,B11000000,B00000000,B11111100,B00000000,B00000000,B00000000,B00000000,B00111000,B00000000,B01110000,
- B00000000,B01000100,B10001001,B00010000,B00000000,B00000111,B10000000,B00000000,B01111000,B00000000,B11111111,B11111111,B11000000,B00111111,B11111111,B11110000,
- B00000000,B00111000,B01110000,B11100000,B00000000,B00000011,B00000000,B00000000,B00110000,B00000000,B11111111,B11111111,B11000000,B00000000,B00000000,B00000000
- };
-
- #elif FAN_ANIM_FRAMES == 3
-
- const unsigned char status_screen0_bmp[] PROGMEM = {
- B00111101,B11110000,B00000010,B00111000,B11110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11111111,B11111111,
- B01000100,B10001000,B00000110,B01000101,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11000000,B00011111,
- B10000000,B10001000,B00000010,B01000101,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B00100000,B00100111,
- B10000000,B11110000,B00000010,B01000100,B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110,B11110000,B01111011,
- B10000000,B10100011,B11110010,B01000100,B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110,B11110000,B01111011,
- B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000101,B11111000,B11111101,
- B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000100,B11111000,B11111001,
- B01000100,B10001000,B00000010,B01000101,B00010000,B00011111,B11100000,B00000001,B11111110,B00000000,B00001000,B00100000,B10000000,B00000100,B00111111,B11100001,
- B00111001,B11001100,B00000111,B00111001,B11100000,B00111110,B11110000,B00000011,B11001111,B00000000,B00000100,B00010000,B01000000,B00000100,B00001111,B10000001,
- B00000000,B00000000,B00000000,B00000000,B00000000,B00111100,B11110000,B00000011,B10110111,B00000000,B00000100,B00010000,B01000000,B00000100,B00001111,B10000001,
- B00000000,B00111000,B01110000,B11100000,B00000000,B00111010,B11110000,B00000011,B11110111,B00000000,B00001000,B00100000,B10000000,B00000100,B00001111,B10000001,
- B00000000,B01000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11101110,B00000000,B00010000,B01000001,B00000000,B00000100,B00111111,B11100001,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11011110,B00000000,B00100000,B10000010,B00000000,B00000100,B11111000,B11111001,
- B00000000,B00011000,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10111111,B00000000,B00100000,B10000010,B00000000,B00000101,B11111000,B11111101,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10000111,B00000000,B00010000,B01000001,B00000000,B00000110,B11110000,B01111011,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00111111,B11110000,B00000011,B11111111,B00000000,B00001000,B00100000,B10000000,B00000110,B11110000,B01111011,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00001111,B11000000,B00000000,B11111100,B00000000,B00000000,B00000000,B00000000,B00000111,B00100000,B00100111,
- B00000000,B01000100,B10001001,B00010000,B00000000,B00000111,B10000000,B00000000,B01111000,B00000000,B11111111,B11111111,B11000000,B00000111,B11000000,B00011111,
- B00000000,B00111000,B01110000,B11100000,B00000000,B00000011,B00000000,B00000000,B00110000,B00000000,B11111111,B11111111,B11000000,B00000111,B11111111,B11111111
- };
- const unsigned char status_screen1_bmp[] PROGMEM = {
- B00111101,B11110000,B00000010,B00111000,B11110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11111111,B11111111,
- B01000100,B10001000,B00000110,B01000101,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11000110,B00011111,
- B10000000,B10001000,B00000010,B01000101,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B00111110,B00000111,
- B10000000,B11110000,B00000010,B01000100,B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110,B00111110,B00000011,
- B10000000,B10100011,B11110010,B01000100,B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110,B00011110,B00000011,
- B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000100,B00011110,B00001101,
- B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000100,B00000110,B00111101,
- B01000100,B10001000,B00000010,B01000101,B00010000,B00011111,B11100000,B00000001,B11111110,B00000000,B00001000,B00100000,B10000000,B00000100,B00000111,B00111101,
- B00111001,B11001100,B00000111,B00111001,B11100000,B00111110,B11110000,B00000011,B11001111,B00000000,B00000100,B00010000,B01000000,B00000100,B00001111,B11111111,
- B00000000,B00000000,B00000000,B00000000,B00000000,B00111100,B11110000,B00000011,B10110111,B00000000,B00000100,B00010000,B01000000,B00000111,B11111111,B11111111,
- B00000000,B00111000,B01110000,B11100000,B00000000,B00111010,B11110000,B00000011,B11110111,B00000000,B00001000,B00100000,B10000000,B00000111,B11111111,B10000001,
- B00000000,B01000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11101110,B00000000,B00010000,B01000001,B00000000,B00000101,B11100111,B00000001,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11011110,B00000000,B00100000,B10000010,B00000000,B00000101,B11000011,B00000001,
- B00000000,B00011000,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10111111,B00000000,B00100000,B10000010,B00000000,B00000101,B10000011,B11000001,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10000111,B00000000,B00010000,B01000001,B00000000,B00000110,B00000011,B11000011,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00111111,B11110000,B00000011,B11111111,B00000000,B00001000,B00100000,B10000000,B00000110,B00000011,B11100011,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00001111,B11000000,B00000000,B11111100,B00000000,B00000000,B00000000,B00000000,B00000111,B00000011,B11100111,
- B00000000,B01000100,B10001001,B00010000,B00000000,B00000111,B10000000,B00000000,B01111000,B00000000,B11111111,B11111111,B11000000,B00000111,B11000011,B00011111,
- B00000000,B00111000,B01110000,B11100000,B00000000,B00000011,B00000000,B00000000,B00110000,B00000000,B11111111,B11111111,B11000000,B00000111,B11111111,B11111111
- };
- const unsigned char status_screen2_bmp[] PROGMEM = {
- B00111101,B11110000,B00000010,B00111000,B11110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11111111,B11111111,
- B01000100,B10001000,B00000110,B01000101,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11000011,B00011111,
- B10000000,B10001000,B00000010,B01000101,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B00000011,B11100111,
- B10000000,B11110000,B00000010,B01000100,B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110,B00000011,B11110011,
- B10000000,B10100011,B11110010,B01000100,B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000110,B10000011,B11100011,
- B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000101,B11000011,B11000001,
- B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000101,B11100011,B10000001,
- B01000100,B10001000,B00000010,B01000101,B00010000,B00011111,B11100000,B00000001,B11111110,B00000000,B00001000,B00100000,B10000000,B00000101,B11110111,B00000001,
- B00111001,B11001100,B00000111,B00111001,B11100000,B00111110,B11110000,B00000011,B11001111,B00000000,B00000100,B00010000,B01000000,B00000111,B11111111,B10000001,
- B00000000,B00000000,B00000000,B00000000,B00000000,B00111100,B11110000,B00000011,B10110111,B00000000,B00000100,B00010000,B01000000,B00000111,B11111111,B11111111,
- B00000000,B00111000,B01110000,B11100000,B00000000,B00111010,B11110000,B00000011,B11110111,B00000000,B00001000,B00100000,B10000000,B00000100,B00001111,B11111111,
- B00000000,B01000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11101110,B00000000,B00010000,B01000001,B00000000,B00000100,B00000111,B01111101,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11011110,B00000000,B00100000,B10000010,B00000000,B00000100,B00001110,B00111101,
- B00000000,B00011000,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10111111,B00000000,B00100000,B10000010,B00000000,B00000100,B00011110,B00011101,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10000111,B00000000,B00010000,B01000001,B00000000,B00000110,B00111110,B00001011,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00111111,B11110000,B00000011,B11111111,B00000000,B00001000,B00100000,B10000000,B00000110,B01111110,B00000011,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00001111,B11000000,B00000000,B11111100,B00000000,B00000000,B00000000,B00000000,B00000111,B00111110,B00000111,
- B00000000,B01000100,B10001001,B00010000,B00000000,B00000111,B10000000,B00000000,B01111000,B00000000,B11111111,B11111111,B11000000,B00000111,B11000110,B00011111,
- B00000000,B00111000,B01110000,B11100000,B00000000,B00000011,B00000000,B00000000,B00110000,B00000000,B11111111,B11111111,B11000000,B00000111,B11111111,B11111111
- };
-
- #elif FAN_ANIM_FRAMES == 4
-
- const unsigned char status_screen0_bmp[] PROGMEM = {
- B00111101,B11110000,B00000010,B00111000,B11110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111,B11111000,
- B01000100,B10001000,B00000110,B01000101,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111110,B00000000,B11111000,
- B10000000,B10001000,B00000010,B01000101,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111000,B00111111,B00111000,
- B10000000,B11110000,B00000010,B01000100,B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110000,B01111110,B00011000,
- B10000000,B10100011,B11110010,B01000100,B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110000,B01111100,B00011000,
- B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101000,B01111100,B00001000,
- B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101100,B00111000,B00001000,
- B01000100,B10001000,B00000010,B01000101,B00010000,B00011111,B11100000,B00000001,B11111110,B00000000,B00001000,B00100000,B10000000,B00101111,B00111001,B11001000,
- B00111001,B11001100,B00000111,B00111001,B11100000,B00111110,B11110000,B00000011,B11001111,B00000000,B00000100,B00010000,B01000000,B00101111,B11111111,B11101000,
- B00000000,B00000000,B00000000,B00000000,B00000000,B00111100,B11110000,B00000011,B10110111,B00000000,B00000100,B00010000,B01000000,B00101111,B11000111,B11101000,
- B00000000,B00111000,B01110000,B11100000,B00000000,B00111010,B11110000,B00000011,B11110111,B00000000,B00001000,B00100000,B10000000,B00101111,B11111111,B11101000,
- B00000000,B01000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11101110,B00000000,B00010000,B01000001,B00000000,B00100111,B00111001,B11101000,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11011110,B00000000,B00100000,B10000010,B00000000,B00100000,B00111000,B01101000,
- B00000000,B00011000,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10111111,B00000000,B00100000,B10000010,B00000000,B00100000,B01111100,B00101000,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10000111,B00000000,B00010000,B01000001,B00000000,B00110000,B01111100,B00011000,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00111111,B11110000,B00000011,B11111111,B00000000,B00001000,B00100000,B10000000,B00110000,B11111100,B00011000,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00001111,B11000000,B00000000,B11111100,B00000000,B00000000,B00000000,B00000000,B00111001,B11111000,B00111000,
- B00000000,B01000100,B10001001,B00010000,B00000000,B00000111,B10000000,B00000000,B01111000,B00000000,B11111111,B11111111,B11000000,B00111110,B00000000,B11111000,
- B00000000,B00111000,B01110000,B11100000,B00000000,B00000011,B00000000,B00000000,B00110000,B00000000,B11111111,B11111111,B11000000,B00111111,B11111111,B11111000
- };
- const unsigned char status_screen1_bmp[] PROGMEM = {
- B00111101,B11110000,B00000010,B00111000,B11110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111,B11111000,
- B01000100,B10001000,B00000110,B01000101,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111110,B00000000,B11111000,
- B10000000,B10001000,B00000010,B01000101,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111000,B00001111,B00111000,
- B10000000,B11110000,B00000010,B01000100,B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110100,B00011111,B11011000,
- B10000000,B10100011,B11110010,B01000100,B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110110,B00011111,B10011000,
- B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101111,B00011111,B00001000,
- B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00101111,B10011110,B00001000,
- B01000100,B10001000,B00000010,B01000101,B00010000,B00011111,B11100000,B00000001,B11111110,B00000000,B00001000,B00100000,B10000000,B00101111,B11111100,B00001000,
- B00111001,B11001100,B00000111,B00111001,B11100000,B00111110,B11110000,B00000011,B11001111,B00000000,B00000100,B00010000,B01000000,B00101111,B11011100,B00001000,
- B00000000,B00000000,B00000000,B00000000,B00000000,B00111100,B11110000,B00000011,B10110111,B00000000,B00000100,B00010000,B01000000,B00100111,B11101111,B11001000,
- B00000000,B00111000,B01110000,B11100000,B00000000,B00111010,B11110000,B00000011,B11110111,B00000000,B00001000,B00100000,B10000000,B00100000,B01110111,B11101000,
- B00000000,B01000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11101110,B00000000,B00010000,B01000001,B00000000,B00100000,B01111111,B11101000,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11011110,B00000000,B00100000,B10000010,B00000000,B00100000,B11110011,B11101000,
- B00000000,B00011000,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10111111,B00000000,B00100000,B10000010,B00000000,B00100001,B11110001,B11101000,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10000111,B00000000,B00010000,B01000001,B00000000,B00110011,B11110000,B11011000,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00111111,B11110000,B00000011,B11111111,B00000000,B00001000,B00100000,B10000000,B00110111,B11110000,B01011000,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00001111,B11000000,B00000000,B11111100,B00000000,B00000000,B00000000,B00000000,B00111001,B11100000,B00111000,
- B00000000,B01000100,B10001001,B00010000,B00000000,B00000111,B10000000,B00000000,B01111000,B00000000,B11111111,B11111111,B11000000,B00111110,B00000000,B11111000,
- B00000000,B00111000,B01110000,B11100000,B00000000,B00000011,B00000000,B00000000,B00110000,B00000000,B11111111,B11111111,B11000000,B00111111,B11111111,B11111000
- };
- const unsigned char status_screen2_bmp[] PROGMEM = {
- B00111101,B11110000,B00000010,B00111000,B11110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111,B11111000,
- B01000100,B10001000,B00000110,B01000101,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111110,B10000000,B11111000,
- B10000000,B10001000,B00000010,B01000101,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111001,B10000000,B00111000,
- B10000000,B11110000,B00000010,B01000100,B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110111,B10000001,B11011000,
- B10000000,B10100011,B11110010,B01000100,B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110111,B11000011,B11011000,
- B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00100111,B11000111,B11101000,
- B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00100011,B11000111,B11111000,
- B01000100,B10001000,B00000010,B01000101,B00010000,B00011111,B11100000,B00000001,B11111110,B00000000,B00001000,B00100000,B10000000,B00100001,B11111111,B10001000,
- B00111001,B11001100,B00000111,B00111001,B11100000,B00111110,B11110000,B00000011,B11001111,B00000000,B00000100,B00010000,B01000000,B00100000,B01101100,B00001000,
- B00000000,B00000000,B00000000,B00000000,B00000000,B00111100,B11110000,B00000011,B10110111,B00000000,B00000100,B00010000,B01000000,B00100000,B01101100,B00001000,
- B00000000,B00111000,B01110000,B11100000,B00000000,B00111010,B11110000,B00000011,B11110111,B00000000,B00001000,B00100000,B10000000,B00100000,B01101100,B00001000,
- B00000000,B01000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11101110,B00000000,B00010000,B01000001,B00000000,B00100011,B11111111,B00001000,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11011110,B00000000,B00100000,B10000010,B00000000,B00111111,B11000111,B10001000,
- B00000000,B00011000,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10111111,B00000000,B00100000,B10000010,B00000000,B00101111,B11000111,B11001000,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10000111,B00000000,B00010000,B01000001,B00000000,B00110111,B10000111,B11011000,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00111111,B11110000,B00000011,B11111111,B00000000,B00001000,B00100000,B10000000,B00110111,B00000011,B11011000,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00001111,B11000000,B00000000,B11111100,B00000000,B00000000,B00000000,B00000000,B00111000,B00000011,B00111000,
- B00000000,B01000100,B10001001,B00010000,B00000000,B00000111,B10000000,B00000000,B01111000,B00000000,B11111111,B11111111,B11000000,B00111110,B00000010,B11111000,
- B00000000,B00111000,B01110000,B11100000,B00000000,B00000011,B00000000,B00000000,B00110000,B00000000,B11111111,B11111111,B11000000,B00111111,B11111111,B11111000
- };
- const unsigned char status_screen3_bmp[] PROGMEM = {
- B00111101,B11110000,B00000010,B00111000,B11110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111,B11111000,
- B01000100,B10001000,B00000110,B01000101,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111110,B00000000,B11111000,
- B10000000,B10001000,B00000010,B01000101,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111001,B11110000,B00111000,
- B10000000,B11110000,B00000010,B01000100,B10000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110001,B11100000,B00011000,
- B10000000,B10100011,B11110010,B01000100,B01100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110001,B11100000,B00011000,
- B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00100001,B11100001,B11101000,
- B10000000,B10010000,B00000010,B01000100,B00010000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00100000,B11110011,B11101000,
- B01000100,B10001000,B00000010,B01000101,B00010000,B00011111,B11100000,B00000001,B11111110,B00000000,B00001000,B00100000,B10000000,B00100000,B01111111,B11101000,
- B00111001,B11001100,B00000111,B00111001,B11100000,B00111110,B11110000,B00000011,B11001111,B00000000,B00000100,B00010000,B01000000,B00100000,B01110111,B11101000,
- B00000000,B00000000,B00000000,B00000000,B00000000,B00111100,B11110000,B00000011,B10110111,B00000000,B00000100,B00010000,B01000000,B00101000,B11101110,B00101000,
- B00000000,B00111000,B01110000,B11100000,B00000000,B00111010,B11110000,B00000011,B11110111,B00000000,B00001000,B00100000,B10000000,B00101111,B11011100,B00001000,
- B00000000,B01000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11101110,B00000000,B00010000,B01000001,B00000000,B00101111,B11111100,B00001000,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00011110,B11100000,B00000001,B11011110,B00000000,B00100000,B10000010,B00000000,B00101111,B10011110,B00001000,
- B00000000,B00011000,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10111111,B00000000,B00100000,B10000010,B00000000,B00101111,B00001111,B00001000,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00111110,B11110000,B00000011,B10000111,B00000000,B00010000,B01000001,B00000000,B00110000,B00001111,B00011000,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00111111,B11110000,B00000011,B11111111,B00000000,B00001000,B00100000,B10000000,B00110000,B00001111,B00011000,
- B00000000,B00000100,B10001001,B00010000,B00000000,B00001111,B11000000,B00000000,B11111100,B00000000,B00000000,B00000000,B00000000,B00111000,B00011111,B00111000,
- B00000000,B01000100,B10001001,B00010000,B00000000,B00000111,B10000000,B00000000,B01111000,B00000000,B11111111,B11111111,B11000000,B00111110,B00000000,B11111000,
- B00000000,B00111000,B01110000,B11100000,B00000000,B00000011,B00000000,B00000000,B00110000,B00000000,B11111111,B11111111,B11000000,B00111111,B11111111,B11111000
- };
-
- #endif
-
-#endif // HOTENDS >= 2
+ #define STATUS_LOGO_X 8
+ #define STATUS_HEATERS_X 40
+ #define STATUS_BED_X 72
+#else
+ #define STATUS_LOGO_X 0
+ #define STATUS_HEATERS_X 32
+ #define STATUS_BED_X 80
+#endif
diff --git a/Marlin/src/HAL/HAL_AVR/HAL.h b/Marlin/src/HAL/HAL_AVR/HAL.h
index 5a7f41ed2d..2992ebe0e3 100644
--- a/Marlin/src/HAL/HAL_AVR/HAL.h
+++ b/Marlin/src/HAL/HAL_AVR/HAL.h
@@ -16,9 +16,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-
-#ifndef _HAL_AVR_H_
-#define _HAL_AVR_H_
+#pragma once
// --------------------------------------------------------------------------
// Includes
@@ -79,16 +77,32 @@ typedef int8_t pin_t;
//extern uint8_t MCUSR;
-#define NUM_SERIAL 1
-
+// Serial ports
#ifdef USBCON
#if ENABLED(BLUETOOTH)
#define MYSERIAL0 bluetoothSerial
#else
#define MYSERIAL0 Serial
#endif
+ #define NUM_SERIAL 1
#else
- #define MYSERIAL0 customizedSerial
+ #if !WITHIN(SERIAL_PORT, -1, 3)
+ #error "SERIAL_PORT must be from -1 to 3"
+ #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"
+ #elif SERIAL_PORT_2 == SERIAL_PORT
+ #error "SERIAL_PORT_2 must be different than SERIAL_PORT"
+ #endif
+ #define NUM_SERIAL 2
+ #define MYSERIAL1 customizedSerial2
+ #else
+ #define NUM_SERIAL 1
+ #endif
#endif
// --------------------------------------------------------------------------
@@ -358,5 +372,3 @@ inline void HAL_adc_init(void) {
// AVR compatibility
#define strtof strtod
-
-#endif // _HAL_AVR_H_
diff --git a/Marlin/src/HAL/HAL_AVR/MarlinSerial.cpp b/Marlin/src/HAL/HAL_AVR/MarlinSerial.cpp
index ece2497766..36134f7b89 100644
--- a/Marlin/src/HAL/HAL_AVR/MarlinSerial.cpp
+++ b/Marlin/src/HAL/HAL_AVR/MarlinSerial.cpp
@@ -29,6 +29,7 @@
* Modified 14 February 2016 by Andreas Hardtung (added tx buffer)
* Modified 01 October 2017 by Eduardo José Tagle (added XON/XOFF)
* Modified 10 June 2018 by Eduardo José Tagle (See #10991)
+ * Templatized 01 October 2018 by Eduardo José Tagle to allow multiple instances
*/
#ifdef __AVR__
@@ -42,62 +43,26 @@
#include "MarlinSerial.h"
#include "../../Marlin.h"
- struct ring_buffer_r {
- unsigned char buffer[RX_BUFFER_SIZE];
- volatile ring_buffer_pos_t head, tail;
- };
-
- #if TX_BUFFER_SIZE > 0
- struct ring_buffer_t {
- unsigned char buffer[TX_BUFFER_SIZE];
- volatile uint8_t head, tail;
- };
- #endif
-
- #if UART_PRESENT(SERIAL_PORT)
- ring_buffer_r rx_buffer = { { 0 }, 0, 0 };
- #if TX_BUFFER_SIZE > 0
- ring_buffer_t tx_buffer = { { 0 }, 0, 0 };
- #endif
- static bool _written;
- #endif
-
- #if ENABLED(SERIAL_XON_XOFF)
- constexpr uint8_t XON_XOFF_CHAR_SENT = 0x80, // XON / XOFF Character was sent
- XON_XOFF_CHAR_MASK = 0x1F; // XON / XOFF character to send
- // XON / XOFF character definitions
- constexpr uint8_t XON_CHAR = 17, XOFF_CHAR = 19;
- uint8_t xon_xoff_state = XON_XOFF_CHAR_SENT | XON_CHAR;
- #endif
-
- #if ENABLED(SERIAL_STATS_DROPPED_RX)
- uint8_t rx_dropped_bytes = 0;
- #endif
-
- #if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
- uint8_t rx_buffer_overruns = 0;
- #endif
-
- #if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
- uint8_t rx_framing_errors = 0;
- #endif
-
- #if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
- ring_buffer_pos_t rx_max_enqueued = 0;
- #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");
- #if ENABLED(EMERGENCY_PARSER)
- #include "../../feature/emergency_parser.h"
- #endif
+ #include "../../feature/emergency_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!
- FORCE_INLINE ring_buffer_pos_t atomic_read_rx_head() {
- #if RX_BUFFER_SIZE > 256
+ 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
@@ -111,23 +76,25 @@
sw_barrier();
} while (vold != vnew);
return vnew;
- #else
+ }
+ else {
// With an 8bit index, reads are always atomic. No need for special handling
return rx_buffer.head;
- #endif
+ }
}
- #if RX_BUFFER_SIZE > 256
- static volatile bool rx_tail_value_not_stable = false;
- static volatile uint16_t rx_tail_value_backup = 0;
- #endif
+ 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 -
- FORCE_INLINE void atomic_set_rx_tail(ring_buffer_pos_t value) {
- #if RX_BUFFER_SIZE > 256
+ 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();
@@ -140,29 +107,29 @@
// Signal the new value is completely stored into the value
rx_tail_value_not_stable = false;
sw_barrier();
- #else
+ }
+ else
rx_buffer.tail = value;
- #endif
}
// 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 -
- FORCE_INLINE ring_buffer_pos_t atomic_read_rx_tail() {
- #if RX_BUFFER_SIZE > 256
+ 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;
- #endif
+ }
// The true index is stable, return it
return rx_buffer.tail;
}
// (called with RX interrupts disabled)
- FORCE_INLINE void store_rxd_char() {
+ template
+ FORCE_INLINE void MarlinSerial::store_rxd_char() {
- #if ENABLED(EMERGENCY_PARSER)
- static EmergencyParser::State emergency_state; // = EP_RESET
- #endif
+ static EmergencyParser::State emergency_state; // = EP_RESET
// 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.
@@ -173,27 +140,17 @@
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)(RX_BUFFER_SIZE - 1);
+ ring_buffer_pos_t i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
- // This must read the M_UCSRxA register before reading the received byte to detect error causes
- #if ENABLED(SERIAL_STATS_DROPPED_RX)
- if (TEST(M_UCSRxA, M_DORx) && !++rx_dropped_bytes) --rx_dropped_bytes;
- #endif
-
- #if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
- if (TEST(M_UCSRxA, M_DORx) && !++rx_buffer_overruns) --rx_buffer_overruns;
- #endif
-
- #if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
- if (TEST(M_UCSRxA, M_FEx) && !++rx_framing_errors) --rx_framing_errors;
- #endif
+ // 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 = M_UDRx;
+ uint8_t c = R_UDR;
- #if ENABLED(EMERGENCY_PARSER)
- emergency_parser.update(emergency_state, c);
- #endif
+ 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
@@ -202,29 +159,28 @@
rx_buffer.buffer[h] = c;
h = i;
}
- #if ENABLED(SERIAL_STATS_DROPPED_RX)
- else if (!++rx_dropped_bytes) --rx_dropped_bytes;
- #endif
+ else if (Cfg::DROPPED_RX && !++rx_dropped_bytes)
+ --rx_dropped_bytes;
- #if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
+ 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)(RX_BUFFER_SIZE - 1);
+ 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);
- #endif
+ }
- #if ENABLED(SERIAL_XON_XOFF)
+ if (Cfg::XONOFF) {
// If the last char that was sent was an XON
if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XON_CHAR) {
// Bytes stored into the RX buffer
- const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
+ const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
// 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 >= (RX_BUFFER_SIZE) / 8) {
+ if (rx_count >= (Cfg::RX_SIZE) / 8) {
// 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
@@ -238,19 +194,17 @@
// 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 (!TEST(M_UCSRxA, M_UDREx)) {
+ while (!B_UDRE) {
- if (TEST(M_UCSRxA,M_RXCx)) {
+ 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)(RX_BUFFER_SIZE - 1);
+ i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
// Read the character from the USART
- c = M_UDRx;
+ c = R_UDR;
- #if ENABLED(EMERGENCY_PARSER)
- emergency_parser.update(emergency_state, c);
- #endif
+ 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
@@ -259,19 +213,18 @@
rx_buffer.buffer[h] = c;
h = i;
}
- #if ENABLED(SERIAL_STATS_DROPPED_RX)
- else if (!++rx_dropped_bytes) --rx_dropped_bytes;
- #endif
+ else if (Cfg::DROPPED_RX && !++rx_dropped_bytes)
+ --rx_dropped_bytes;
}
sw_barrier();
}
- M_UDRx = XOFF_CHAR;
+ 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
- SBI(M_UCSRxA, M_TXCx);
+ 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
@@ -280,19 +233,18 @@
// 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 (!TEST(M_UCSRxA, M_UDREx)) {
+ while (!B_UDRE) {
- if (TEST(M_UCSRxA,M_RXCx)) {
+ 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)(RX_BUFFER_SIZE - 1);
+ i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
// Read the character from the USART
- c = M_UDRx;
+ c = R_UDR;
- #if ENABLED(EMERGENCY_PARSER)
+ if (Cfg::EMERGENCYPARSER)
emergency_parser.update(emergency_state, c);
- #endif
// 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
@@ -301,9 +253,8 @@
rx_buffer.buffer[h] = c;
h = i;
}
- #if ENABLED(SERIAL_STATS_DROPPED_RX)
- else if (!++rx_dropped_bytes) --rx_dropped_bytes;
- #endif
+ else if (Cfg::DROPPED_RX && !++rx_dropped_bytes)
+ --rx_dropped_bytes;
}
sw_barrier();
}
@@ -312,78 +263,68 @@
// have any issues writing to the UART TX register if it needs to!
}
}
- #endif // SERIAL_XON_XOFF
+ }
// Store the new head value - The main loop will retry until the value is stable
rx_buffer.head = h;
}
- #if TX_BUFFER_SIZE > 0
-
- // (called with TX irqs disabled)
- FORCE_INLINE void _tx_udr_empty_irq(void) {
-
+ // (called with TX irqs disabled)
+ template
+ FORCE_INLINE void MarlinSerial::_tx_udr_empty_irq(void) {
+ if (Cfg::TX_SIZE > 0) {
// Read positions
uint8_t t = tx_buffer.tail;
const uint8_t h = tx_buffer.head;
- #if ENABLED(SERIAL_XON_XOFF)
+ if (Cfg::XONOFF) {
// If an XON char is pending to be sent, do it now
if (xon_xoff_state == XON_CHAR) {
// Send the character
- M_UDRx = XON_CHAR;
+ R_UDR = 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
- SBI(M_UCSRxA, M_TXCx);
+ B_TXC = 1;
// Remember we sent it.
xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
// If nothing else to transmit, just disable TX interrupts.
- if (h == t) CBI(M_UCSRxB, M_UDRIEx); // (Non-atomic, could be reenabled by the main program, but eventually this will succeed)
+ if (h == t) B_UDRIE = 0; // (Non-atomic, could be reenabled by the main program, but eventually this will succeed)
return;
}
- #endif
+ }
// 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) {
- CBI(M_UCSRxB, M_UDRIEx); // (Non-atomic, could be reenabled by the main program, but eventually this will succeed)
+ 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) & (TX_BUFFER_SIZE - 1);
- M_UDRx = c;
+ 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/
- SBI(M_UCSRxA, M_TXCx);
+ B_TXC = 1;
// Disable interrupts if there is nothing to transmit following this byte
- if (h == t) CBI(M_UCSRxB, M_UDRIEx); // (Non-atomic, could be reenabled by the main program, but eventually this will succeed)
+ if (h == t) B_UDRIE = 0; // (Non-atomic, could be reenabled by the main program, but eventually this will succeed)
}
-
- #ifdef M_USARTx_UDRE_vect
- ISR(M_USARTx_UDRE_vect) { _tx_udr_empty_irq(); }
- #endif
-
- #endif // TX_BUFFER_SIZE
-
- #ifdef M_USARTx_RX_vect
- ISR(M_USARTx_RX_vect) { store_rxd_char(); }
- #endif
+ }
// Public Methods
-
- void MarlinSerial::begin(const long baud) {
+ template
+ void MarlinSerial::begin(const long baud) {
uint16_t baud_setting;
bool useU2X = true;
@@ -394,41 +335,41 @@
if (baud == 57600) useU2X = false;
#endif
+ R_UCSRA = 0;
if (useU2X) {
- M_UCSRxA = _BV(M_U2Xx);
+ B_U2X = 1;
baud_setting = (F_CPU / 4 / baud - 1) / 2;
}
- else {
- M_UCSRxA = 0;
+ else
baud_setting = (F_CPU / 8 / baud - 1) / 2;
- }
// assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register)
- M_UBRRxH = baud_setting >> 8;
- M_UBRRxL = baud_setting;
+ R_UBRRH = baud_setting >> 8;
+ R_UBRRL = baud_setting;
- SBI(M_UCSRxB, M_RXENx);
- SBI(M_UCSRxB, M_TXENx);
- SBI(M_UCSRxB, M_RXCIEx);
- #if TX_BUFFER_SIZE > 0
- CBI(M_UCSRxB, M_UDRIEx);
- #endif
+ B_RXEN = 1;
+ B_TXEN = 1;
+ B_RXCIE = 1;
+ if (Cfg::TX_SIZE > 0) B_UDRIE = 0;
_written = false;
}
- void MarlinSerial::end() {
- CBI(M_UCSRxB, M_RXENx);
- CBI(M_UCSRxB, M_TXENx);
- CBI(M_UCSRxB, M_RXCIEx);
- CBI(M_UCSRxB, M_UDRIEx);
+ template
+ void MarlinSerial::end() {
+ B_RXEN = 0;
+ B_TXEN = 0;
+ B_RXCIE = 0;
+ B_UDRIE = 0;
}
- int MarlinSerial::peek(void) {
+ template
+ int MarlinSerial::peek(void) {
const ring_buffer_pos_t h = atomic_read_rx_head(), t = rx_buffer.tail;
return h == t ? -1 : rx_buffer.buffer[t];
}
- int MarlinSerial::read(void) {
+ template
+ int MarlinSerial::read(void) {
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
@@ -439,42 +380,45 @@
// Get the next char
const int v = rx_buffer.buffer[t];
- t = (ring_buffer_pos_t)(t + 1) & (RX_BUFFER_SIZE - 1);
+ 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 ENABLED(SERIAL_XON_XOFF)
+ 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)(RX_BUFFER_SIZE - 1);
- if (rx_count < (RX_BUFFER_SIZE) / 10) {
- #if TX_BUFFER_SIZE > 0
+ 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
- SBI(M_UCSRxB, M_UDRIEx);
- #else
+ 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 (!TEST(M_UCSRxA, M_UDREx)) sw_barrier();
- M_UDRx = XON_CHAR;
- #endif
+ while (!B_UDRE) sw_barrier();
+ R_UDR = XON_CHAR;
+ }
}
}
- #endif
+ }
return v;
}
- ring_buffer_pos_t MarlinSerial::available(void) {
+ template
+ typename MarlinSerial::ring_buffer_pos_t MarlinSerial::available(void) {
const ring_buffer_pos_t h = atomic_read_rx_head(), t = rx_buffer.tail;
- return (ring_buffer_pos_t)(RX_BUFFER_SIZE + h - t) & (RX_BUFFER_SIZE - 1);
+ return (ring_buffer_pos_t)(Cfg::RX_SIZE + h - t) & (Cfg::RX_SIZE - 1);
}
- void MarlinSerial::flush(void) {
+ template
+ void MarlinSerial::flush(void) {
// Set the tail to the head:
// - Read the RX head index in a safe way. (See atomic_read_rx_head.)
@@ -482,26 +426,36 @@
// if it interrupts the writing of the value of that variable in the middle.
atomic_set_rx_tail(atomic_read_rx_head());
- #if ENABLED(SERIAL_XON_XOFF)
+ 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 TX_BUFFER_SIZE > 0
+ 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.
- SBI(M_UCSRxB, M_UDRIEx);
- #else
+ 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 (!TEST(M_UCSRxA, M_UDREx)) sw_barrier();
- M_UDRx = XON_CHAR;
- #endif
+ while (!B_UDRE) sw_barrier();
+ R_UDR = XON_CHAR;
+ }
}
- #endif
+ }
}
- #if TX_BUFFER_SIZE > 0
- void MarlinSerial::write(const uint8_t c) {
+ 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
@@ -511,17 +465,17 @@
// 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 (!TEST(M_UCSRxB, M_UDRIEx) && TEST(M_UCSRxA, M_UDREx)) {
- M_UDRx = c;
+ 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
- SBI(M_UCSRxA, M_TXCx);
+ B_TXC = 1;
return;
}
- const uint8_t i = (tx_buffer.head + 1) & (TX_BUFFER_SIZE - 1);
+ 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()) {
@@ -530,7 +484,7 @@
while (i == tx_buffer.tail) {
// If we can transmit another byte, do it.
- if (TEST(M_UCSRxA, M_UDREx)) _tx_udr_empty_irq();
+ if (B_UDRE) _tx_udr_empty_irq();
// Make sure compiler rereads tx_buffer.tail
sw_barrier();
@@ -538,7 +492,7 @@
}
else {
// Interrupts are enabled, just wait until there is space
- while (i == tx_buffer.tail) { sw_barrier(); }
+ while (i == tx_buffer.tail) sw_barrier();
}
// Store new char. head is always safe to move
@@ -546,10 +500,27 @@
tx_buffer.head = i;
// Enable TX ISR - Non atomic, but it will eventually enable TX ISR
- SBI(M_UCSRxB, M_UDRIEx);
+ B_UDRIE = 1;
}
+ }
+
+ template
+ void MarlinSerial::flushTX(void) {
+
+ 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 {
- void MarlinSerial::flushTX(void) {
// 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;
@@ -558,11 +529,10 @@
if (!ISRS_ENABLED()) {
// Wait until everything was transmitted - We must do polling, as interrupts are disabled
- while (tx_buffer.head != tx_buffer.tail || !TEST(M_UCSRxA, M_TXCx)) {
+ while (tx_buffer.head != tx_buffer.tail || !B_TXC) {
// If there is more space, send an extra character
- if (TEST(M_UCSRxA, M_UDREx))
- _tx_udr_empty_irq();
+ if (B_UDRE) _tx_udr_empty_irq();
sw_barrier();
}
@@ -570,55 +540,40 @@
}
else {
// Wait until everything was transmitted
- while (tx_buffer.head != tx_buffer.tail || !TEST(M_UCSRxA, M_TXCx)) sw_barrier();
+ 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).
}
-
- #else // TX_BUFFER_SIZE == 0
-
- void MarlinSerial::write(const uint8_t c) {
- _written = true;
- while (!TEST(M_UCSRxA, M_UDREx)) sw_barrier();
- M_UDRx = c;
- }
-
- void MarlinSerial::flushTX(void) {
- // 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 (!TEST(M_UCSRxA, M_TXCx)) sw_barrier();
-
- // At this point nothing is queued anymore (DRIE is disabled) and
- // the hardware finished transmission (TXC is set).
- }
- #endif // TX_BUFFER_SIZE == 0
+ }
/**
* Imports from print.h
*/
- void MarlinSerial::print(char c, int base) {
+ template
+ void MarlinSerial::print(char c, int base) {
print((long)c, base);
}
- void MarlinSerial::print(unsigned char b, int base) {
+ template
+ void MarlinSerial::print(unsigned char b, int base) {
print((unsigned long)b, base);
}
- void MarlinSerial::print(int n, int base) {
+ template
+ void MarlinSerial::print(int n, int base) {
print((long)n, base);
}
- void MarlinSerial::print(unsigned int n, int base) {
+ template
+ void MarlinSerial::print(unsigned int n, int base) {
print((unsigned long)n, base);
}
- void MarlinSerial::print(long n, int base) {
+ template
+ void MarlinSerial::print(long n, int base) {
if (base == 0) write(n);
else if (base == 10) {
if (n < 0) { print('-'); n = -n; }
@@ -628,68 +583,81 @@
printNumber(n, base);
}
- void MarlinSerial::print(unsigned long n, int base) {
+ template
+ void MarlinSerial::print(unsigned long n, int base) {
if (base == 0) write(n);
else printNumber(n, base);
}
- void MarlinSerial::print(double n, int digits) {
+ template
+ void MarlinSerial::print(double n, int digits) {
printFloat(n, digits);
}
- void MarlinSerial::println(void) {
+ template
+ void MarlinSerial::println(void) {
print('\r');
print('\n');
}
- void MarlinSerial::println(const String& s) {
+ template
+ void MarlinSerial::println(const String& s) {
print(s);
println();
}
- void MarlinSerial::println(const char c[]) {
+ template
+ void MarlinSerial::println(const char c[]) {
print(c);
println();
}
- void MarlinSerial::println(char c, int base) {
+ template
+ void MarlinSerial::println(char c, int base) {
print(c, base);
println();
}
- void MarlinSerial::println(unsigned char b, int base) {
+ template
+ void MarlinSerial::println(unsigned char b, int base) {
print(b, base);
println();
}
- void MarlinSerial::println(int n, int base) {
+ template
+ void MarlinSerial::println(int n, int base) {
print(n, base);
println();
}
- void MarlinSerial::println(unsigned int n, int base) {
+ template
+ void MarlinSerial::println(unsigned int n, int base) {
print(n, base);
println();
}
- void MarlinSerial::println(long n, int base) {
+ template
+ void MarlinSerial::println(long n, int base) {
print(n, base);
println();
}
- void MarlinSerial::println(unsigned long n, int base) {
+ template
+ void MarlinSerial::println(unsigned long n, int base) {
print(n, base);
println();
}
- void MarlinSerial::println(double n, int digits) {
+ template
+ void MarlinSerial::println(double n, int digits) {
print(n, digits);
println();
}
// Private Methods
- void MarlinSerial::printNumber(unsigned long n, uint8_t base) {
+ 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;
@@ -704,7 +672,8 @@
print('0');
}
- void MarlinSerial::printFloat(double number, uint8_t digits) {
+ template
+ void MarlinSerial::printFloat(double number, uint8_t digits) {
// Handle negative numbers
if (number < 0.0) {
print('-');
@@ -713,9 +682,7 @@
// Round correctly so that print(1.999, 2) prints as "2.00"
double rounding = 0.5;
- for (uint8_t i = 0; i < digits; ++i)
- rounding *= 0.1;
-
+ for (uint8_t i = 0; i < digits; ++i) rounding *= 0.1;
number += rounding;
// Extract the integer part of the number and print it
@@ -736,8 +703,39 @@
}
}
+ // 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
- MarlinSerial customizedSerial;
+ template class MarlinSerial>;
+
+ // Instantiate
+ MarlinSerial> customizedSerial1;
+
+ #ifdef SERIAL_PORT_2
+
+ // Hookup ISR handlers
+ ISR(SERIAL_REGNAME(USART,SERIAL_PORT_2,_RX_vect)) {
+ MarlinSerial>::store_rxd_char();
+ }
+
+ ISR(SERIAL_REGNAME(USART,SERIAL_PORT_2,_UDRE_vect)) {
+ MarlinSerial>::_tx_udr_empty_irq();
+ }
+
+ // Preinstantiate
+ template class MarlinSerial>;
+
+ // Instantiate
+ MarlinSerial> customizedSerial2;
+
+ #endif
#endif // !USBCON && (UBRRH || UBRR0H || UBRR1H || UBRR2H || UBRR3H)
diff --git a/Marlin/src/HAL/HAL_AVR/MarlinSerial.h b/Marlin/src/HAL/HAL_AVR/MarlinSerial.h
index 8c2b3f3186..132097eb49 100644
--- a/Marlin/src/HAL/HAL_AVR/MarlinSerial.h
+++ b/Marlin/src/HAL/HAL_AVR/MarlinSerial.h
@@ -19,6 +19,7 @@
* along with this program. If not, see .
*
*/
+#pragma once
/**
* MarlinSerial.h - Hardware serial library for Wiring
@@ -27,12 +28,10 @@
* Modified 28 September 2010 by Mark Sproul
* Modified 14 February 2016 by Andreas Hardtung (added tx buffer)
* Modified 01 October 2017 by Eduardo José Tagle (added XON/XOFF)
+ * Templatized 01 October 2018 by Eduardo José Tagle to allow multiple instances
*/
-#ifndef _MARLINSERIAL_H_
-#define _MARLINSERIAL_H_
-
-#include "../../inc/MarlinConfigPre.h"
+#include "../shared/MarlinSerial.h"
#include
@@ -40,73 +39,173 @@
#define SERIAL_PORT 0
#endif
-// The presence of the UBRRH register is used to detect a UART.
-#define UART_PRESENT(port) ((port == 0 && (defined(UBRRH) || defined(UBRR0H))) || \
- (port == 1 && defined(UBRR1H)) || (port == 2 && defined(UBRR2H)) || \
- (port == 3 && defined(UBRR3H)))
-
-// 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)
-#if SERIAL_PORT == 0 && (!defined(UBRR0H) || !defined(UDR0)) // use un-numbered registers if necessary
- #define SERIAL_REGNAME_INTERNAL(registerbase,number,suffix) registerbase##suffix
-#else
- #define SERIAL_REGNAME_INTERNAL(registerbase,number,suffix) registerbase##number##suffix
-#endif
-
-// Registers used by MarlinSerial class (expanded depending on selected serial port)
-#define M_UCSRxA SERIAL_REGNAME(UCSR,SERIAL_PORT,A) // defines M_UCSRxA to be UCSRnA where n is the serial port number
-#define M_UCSRxB SERIAL_REGNAME(UCSR,SERIAL_PORT,B)
-#define M_RXENx SERIAL_REGNAME(RXEN,SERIAL_PORT,)
-#define M_TXENx SERIAL_REGNAME(TXEN,SERIAL_PORT,)
-#define M_TXCx SERIAL_REGNAME(TXC,SERIAL_PORT,)
-#define M_RXCIEx SERIAL_REGNAME(RXCIE,SERIAL_PORT,)
-#define M_UDREx SERIAL_REGNAME(UDRE,SERIAL_PORT,)
-#define M_FEx SERIAL_REGNAME(FE,SERIAL_PORT,)
-#define M_DORx SERIAL_REGNAME(DOR,SERIAL_PORT,)
-#define M_UPEx SERIAL_REGNAME(UPE,SERIAL_PORT,)
-#define M_UDRIEx SERIAL_REGNAME(UDRIE,SERIAL_PORT,)
-#define M_UDRx SERIAL_REGNAME(UDR,SERIAL_PORT,)
-#define M_UBRRxH SERIAL_REGNAME(UBRR,SERIAL_PORT,H)
-#define M_UBRRxL SERIAL_REGNAME(UBRR,SERIAL_PORT,L)
-#define M_RXCx SERIAL_REGNAME(RXC,SERIAL_PORT,)
-#define M_USARTx_RX_vect SERIAL_REGNAME(USART,SERIAL_PORT,_RX_vect)
-#define M_U2Xx SERIAL_REGNAME(U2X,SERIAL_PORT,)
-#define M_USARTx_UDRE_vect SERIAL_REGNAME(USART,SERIAL_PORT,_UDRE_vect)
-
-#define DEC 10
-#define HEX 16
-#define OCT 8
-#define BIN 2
-#define BYTE 0
-
#ifndef USBCON
- // We're using a ring buffer (I think), in which rx_buffer_head is the index of the
- // location to which to write the next incoming character and rx_buffer_tail is the
- // index of the location from which to read.
- #if RX_BUFFER_SIZE > 256
- typedef uint16_t ring_buffer_pos_t;
+
+ // The presence of the UBRRH register is used to detect a UART.
+ #define UART_PRESENT(port) ((port == 0 && (defined(UBRRH) || defined(UBRR0H))) || \
+ (port == 1 && defined(UBRR1H)) || (port == 2 && defined(UBRR2H)) || \
+ (port == 3 && defined(UBRR3H)))
+
+ // 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)
+ #if SERIAL_PORT == 0 && (!defined(UBRR0H) || !defined(UDR0)) // use un-numbered registers if necessary
+ #define SERIAL_REGNAME_INTERNAL(registerbase,number,suffix) registerbase##suffix
#else
- typedef uint8_t ring_buffer_pos_t;
+ #define SERIAL_REGNAME_INTERNAL(registerbase,number,suffix) registerbase##number##suffix
#endif
- #if ENABLED(SERIAL_STATS_DROPPED_RX)
- extern uint8_t rx_dropped_bytes;
+ // Registers used by MarlinSerial class (expanded depending on selected serial port)
+
+ // Templated 8bit register (generic)
+ #define UART_REGISTER_DECL_BASE(registerbase, suffix) \
+ template struct R_##registerbase##x##suffix {}
+
+ // Templated 8bit register (specialization for each port)
+ #define UART_REGISTER_DECL(port, registerbase, suffix) \
+ template<> struct R_##registerbase##x##suffix { \
+ constexpr R_##registerbase##x##suffix(int) {} \
+ FORCE_INLINE void operator=(uint8_t newVal) const { SERIAL_REGNAME(registerbase,port,suffix) = newVal; } \
+ FORCE_INLINE operator uint8_t() const { return SERIAL_REGNAME(registerbase,port,suffix); } \
+ }
+
+ // Templated 1bit register (generic)
+ #define UART_BIT_DECL_BASE(registerbase, suffix, bit) \
+ templatestruct B_##bit##x {}
+
+ // Templated 1bit register (specialization for each port)
+ #define UART_BIT_DECL(port, registerbase, suffix, bit) \
+ template<> struct B_##bit##x { \
+ constexpr B_##bit##x(int) {} \
+ FORCE_INLINE void operator=(int newVal) const { \
+ if (newVal) \
+ SBI(SERIAL_REGNAME(registerbase,port,suffix),SERIAL_REGNAME(bit,port,)); \
+ else \
+ CBI(SERIAL_REGNAME(registerbase,port,suffix),SERIAL_REGNAME(bit,port,)); \
+ } \
+ FORCE_INLINE operator bool() const { return TEST(SERIAL_REGNAME(registerbase,port,suffix),SERIAL_REGNAME(bit,port,)); } \
+ }
+
+ #define UART_DECL_BASE() \
+ UART_REGISTER_DECL_BASE(UCSR,A);\
+ UART_REGISTER_DECL_BASE(UDR,);\
+ UART_REGISTER_DECL_BASE(UBRR,H);\
+ UART_REGISTER_DECL_BASE(UBRR,L);\
+ UART_BIT_DECL_BASE(UCSR,B,RXEN);\
+ UART_BIT_DECL_BASE(UCSR,B,TXEN);\
+ UART_BIT_DECL_BASE(UCSR,A,TXC);\
+ UART_BIT_DECL_BASE(UCSR,B,RXCIE);\
+ UART_BIT_DECL_BASE(UCSR,A,UDRE);\
+ UART_BIT_DECL_BASE(UCSR,A,FE);\
+ UART_BIT_DECL_BASE(UCSR,A,DOR);\
+ UART_BIT_DECL_BASE(UCSR,B,UDRIE);\
+ UART_BIT_DECL_BASE(UCSR,A,RXC);\
+ UART_BIT_DECL_BASE(UCSR,A,U2X)
+
+ #define UART_DECL(port) \
+ UART_REGISTER_DECL(port,UCSR,A);\
+ UART_REGISTER_DECL(port,UDR,);\
+ UART_REGISTER_DECL(port,UBRR,H);\
+ UART_REGISTER_DECL(port,UBRR,L);\
+ UART_BIT_DECL(port,UCSR,B,RXEN);\
+ UART_BIT_DECL(port,UCSR,B,TXEN);\
+ UART_BIT_DECL(port,UCSR,A,TXC);\
+ UART_BIT_DECL(port,UCSR,B,RXCIE);\
+ UART_BIT_DECL(port,UCSR,A,UDRE);\
+ UART_BIT_DECL(port,UCSR,A,FE);\
+ UART_BIT_DECL(port,UCSR,A,DOR);\
+ UART_BIT_DECL(port,UCSR,B,UDRIE);\
+ UART_BIT_DECL(port,UCSR,A,RXC);\
+ UART_BIT_DECL(port,UCSR,A,U2X)
+
+ // Declare empty templates
+ UART_DECL_BASE();
+
+ // And all the specializations for each possible serial port
+ #if UART_PRESENT(0)
+ UART_DECL(0);
+ #endif
+ #if UART_PRESENT(1)
+ UART_DECL(1);
+ #endif
+ #if UART_PRESENT(2)
+ UART_DECL(2);
+ #endif
+ #if UART_PRESENT(3)
+ UART_DECL(3);
#endif
- #if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
- extern uint8_t rx_buffer_overruns;
- #endif
+ #define DEC 10
+ #define HEX 16
+ #define OCT 8
+ #define BIN 2
+ #define BYTE 0
- #if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
- extern uint8_t rx_framing_errors;
- #endif
-
- #if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
- extern ring_buffer_pos_t rx_max_enqueued;
- #endif
+ // Templated type selector
+ template struct TypeSelector { typedef T type;} ;
+ template struct TypeSelector { typedef F type; };
+ template
class MarlinSerial {
+ protected:
+ // Registers
+ static constexpr R_UCSRxA R_UCSRA = 0;
+ static constexpr R_UDRx R_UDR = 0;
+ static constexpr R_UBRRxH R_UBRRH = 0;
+ static constexpr R_UBRRxL R_UBRRL = 0;
+
+ // Bits
+ static constexpr B_RXENx B_RXEN = 0;
+ static constexpr B_TXENx B_TXEN = 0;
+ static constexpr B_TXCx B_TXC = 0;
+ static constexpr B_RXCIEx B_RXCIE = 0;
+ static constexpr B_UDREx B_UDRE = 0;
+ static constexpr B_FEx B_FE = 0;
+ static constexpr B_DORx B_DOR = 0;
+ static constexpr B_UDRIEx B_UDRIE = 0;
+ static constexpr B_RXCx B_RXC = 0;
+ static constexpr B_U2Xx B_U2X = 0;
+
+ // Base size of type on buffer size
+ typedef typename TypeSelector<(Cfg::RX_SIZE>256), uint16_t, uint8_t>::type ring_buffer_pos_t;
+
+ struct ring_buffer_r {
+ volatile ring_buffer_pos_t head, tail;
+ unsigned char buffer[Cfg::RX_SIZE];
+ };
+
+ struct ring_buffer_t {
+ volatile uint8_t head, tail;
+ unsigned char buffer[Cfg::TX_SIZE];
+ };
+
+ static ring_buffer_r rx_buffer;
+ static ring_buffer_t tx_buffer;
+ static bool _written;
+
+ static constexpr uint8_t XON_XOFF_CHAR_SENT = 0x80, // XON / XOFF Character was sent
+ XON_XOFF_CHAR_MASK = 0x1F; // XON / XOFF character to send
+
+ // XON / XOFF character definitions
+ static constexpr uint8_t XON_CHAR = 17, XOFF_CHAR = 19;
+ static uint8_t xon_xoff_state,
+ rx_dropped_bytes,
+ rx_buffer_overruns,
+ rx_framing_errors;
+ static ring_buffer_pos_t rx_max_enqueued;
+
+ static FORCE_INLINE ring_buffer_pos_t atomic_read_rx_head();
+
+ static volatile bool rx_tail_value_not_stable;
+ static volatile uint16_t rx_tail_value_backup;
+
+ static FORCE_INLINE void atomic_set_rx_tail(ring_buffer_pos_t value);
+ static FORCE_INLINE ring_buffer_pos_t atomic_read_rx_tail();
+
+ public:
+
+ FORCE_INLINE static void store_rxd_char();
+ FORCE_INLINE static void _tx_udr_empty_irq(void);
public:
MarlinSerial() {};
@@ -119,21 +218,10 @@
static void write(const uint8_t c);
static void flushTX(void);
- #if ENABLED(SERIAL_STATS_DROPPED_RX)
- FORCE_INLINE static uint32_t dropped() { return rx_dropped_bytes; }
- #endif
-
- #if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
- FORCE_INLINE static uint32_t buffer_overruns() { return rx_buffer_overruns; }
- #endif
-
- #if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
- FORCE_INLINE static uint32_t framing_errors() { return rx_framing_errors; }
- #endif
-
- #if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
- FORCE_INLINE static ring_buffer_pos_t rxMaxEnqueued() { return rx_max_enqueued; }
- #endif
+ FORCE_INLINE static uint8_t dropped() { return Cfg::DROPPED_RX ? rx_dropped_bytes : 0; }
+ FORCE_INLINE static uint8_t buffer_overruns() { return Cfg::RX_OVERRUNS ? rx_buffer_overruns : 0; }
+ FORCE_INLINE static uint8_t framing_errors() { return Cfg::RX_FRAMING_ERRORS ? rx_framing_errors : 0; }
+ FORCE_INLINE static ring_buffer_pos_t rxMaxEnqueued() { return Cfg::MAX_RX_QUEUED ? rx_max_enqueued : 0; }
FORCE_INLINE static void write(const char* str) { while (*str) write(*str++); }
FORCE_INLINE static void write(const uint8_t* buffer, size_t size) { while (size--) write(*buffer++); }
@@ -165,7 +253,25 @@
static void printFloat(double, uint8_t);
};
- extern MarlinSerial customizedSerial;
+ template
+ struct MarlinSerialCfg {
+ static constexpr int PORT = serial;
+ static constexpr unsigned int RX_SIZE = RX_BUFFER_SIZE;
+ static constexpr unsigned int TX_SIZE = TX_BUFFER_SIZE;
+ static constexpr bool XONOFF = bSERIAL_XON_XOFF;
+ static constexpr bool EMERGENCYPARSER = bEMERGENCY_PARSER;
+ static constexpr bool DROPPED_RX = bSERIAL_STATS_DROPPED_RX;
+ static constexpr bool RX_OVERRUNS = bSERIAL_STATS_RX_BUFFER_OVERRUNS;
+ static constexpr bool RX_FRAMING_ERRORS = bSERIAL_STATS_RX_FRAMING_ERRORS;
+ static constexpr bool MAX_RX_QUEUED = bSERIAL_STATS_MAX_RX_QUEUED;
+ };
+ extern MarlinSerial> customizedSerial1;
+
+ #ifdef SERIAL_PORT_2
+
+ extern MarlinSerial> customizedSerial2;
+
+ #endif
#endif // !USBCON
@@ -173,5 +279,3 @@
#if defined(USBCON) && ENABLED(BLUETOOTH)
extern HardwareSerial bluetoothSerial;
#endif
-
-#endif // _MARLINSERIAL_H_
diff --git a/Marlin/src/HAL/HAL_AVR/SanityCheck.h b/Marlin/src/HAL/HAL_AVR/SanityCheck.h
index a61472cc44..4485b8f39b 100644
--- a/Marlin/src/HAL/HAL_AVR/SanityCheck.h
+++ b/Marlin/src/HAL/HAL_AVR/SanityCheck.h
@@ -19,9 +19,7 @@
* along with this program. If not, see .
*
*/
-
-#ifndef _SANITYCHECK_AVR_8_BIT_H_
-#define _SANITYCHECK_AVR_8_BIT_H_
+#pragma once
/**
* Test AVR specific configuration values for errors at compile-time.
@@ -81,11 +79,11 @@
#elif PIN_EXISTS(E5_AUTO_FAN) && SPINDLE_LASER_PWM_PIN == E5_AUTO_FAN_PIN
#error "SPINDLE_LASER_PWM_PIN is used by E5_AUTO_FAN_PIN."
#elif PIN_EXISTS(FAN) && SPINDLE_LASER_PWM_PIN == FAN_PIN
- #error "SPINDLE_LASER_PWM_PIN is used FAN_PIN."
+ #error "SPINDLE_LASER_PWM_PIN is used by FAN_PIN."
#elif PIN_EXISTS(FAN1) && SPINDLE_LASER_PWM_PIN == FAN1_PIN
- #error "SPINDLE_LASER_PWM_PIN is used FAN1_PIN."
+ #error "SPINDLE_LASER_PWM_PIN is used by FAN1_PIN."
#elif PIN_EXISTS(FAN2) && SPINDLE_LASER_PWM_PIN == FAN2_PIN
- #error "SPINDLE_LASER_PWM_PIN is used FAN2_PIN."
+ #error "SPINDLE_LASER_PWM_PIN is used by FAN2_PIN."
#elif PIN_EXISTS(CONTROLLERFAN) && SPINDLE_LASER_PWM_PIN == CONTROLLERFAN_PIN
#error "SPINDLE_LASER_PWM_PIN is used by CONTROLLERFAN_PIN."
#elif PIN_EXISTS(MOTOR_CURRENT_PWM_XY) && SPINDLE_LASER_PWM_PIN == MOTOR_CURRENT_PWM_XY_PIN
@@ -116,5 +114,3 @@
|| defined(E4_HARDWARE_SERIAL) )
#error "Select hardware UART for TMC2208 to use both TMC2208 and ENDSTOP_INTERRUPTS_FEATURE."
#endif
-
-#endif // _SANITYCHECK_AVR_8_BIT_H_
diff --git a/Marlin/src/HAL/HAL_AVR/ServoTimers.h b/Marlin/src/HAL/HAL_AVR/ServoTimers.h
index 4af997f1ef..c7c4587adc 100644
--- a/Marlin/src/HAL/HAL_AVR/ServoTimers.h
+++ b/Marlin/src/HAL/HAL_AVR/ServoTimers.h
@@ -19,6 +19,7 @@
* along with this program. If not, see .
*
*/
+#pragma once
/**
* ServoTimers.h - Interrupt driven Servo library for Arduino using 16 bit timers- Version 2
@@ -39,9 +40,6 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef _SERVOTIMERS_H_
-#define _SERVOTIMERS_H_
-
/**
* Defines for 16 bit timers used with Servo library
*
@@ -91,5 +89,3 @@ typedef enum {
#endif
_Nbr_16timers
} timer16_Sequence_t;
-
-#endif // _SERVOTIMERS_H_
diff --git a/Marlin/src/HAL/HAL_AVR/endstop_interrupts.h b/Marlin/src/HAL/HAL_AVR/endstop_interrupts.h
index 13b3f16e3b..791c9812af 100644
--- a/Marlin/src/HAL/HAL_AVR/endstop_interrupts.h
+++ b/Marlin/src/HAL/HAL_AVR/endstop_interrupts.h
@@ -19,6 +19,7 @@
* along with this program. If not, see .
*
*/
+#pragma once
/**
* Endstop Interrupts
@@ -35,9 +36,6 @@
* (Located in Marlin/buildroot/share/pin_interrupt_test/pin_interrupt_test.ino)
*/
-#ifndef _ENDSTOP_INTERRUPTS_H_
-#define _ENDSTOP_INTERRUPTS_H_
-
#include "../../core/macros.h"
#include
#include "../../module/endstops.h"
@@ -85,22 +83,21 @@ void pciSetup(const int8_t pin) {
SBI(PCICR, digitalPinToPCICRbit(pin)); // enable interrupt for the group
}
-
// Handlers for pin change interrupts
#ifdef PCINT0_vect
ISR(PCINT0_vect) { endstop_ISR(); }
#endif
#ifdef PCINT1_vect
- ISR(PCINT1_vect) { endstop_ISR(); }
+ ISR(PCINT1_vect, ISR_ALIASOF(PCINT0_vect));
#endif
#ifdef PCINT2_vect
- ISR(PCINT2_vect) { endstop_ISR(); }
+ ISR(PCINT2_vect, ISR_ALIASOF(PCINT0_vect));
#endif
#ifdef PCINT3_vect
- ISR(PCINT3_vect) { endstop_ISR(); }
+ ISR(PCINT3_vect, ISR_ALIASOF(PCINT0_vect));
#endif
void setup_endstop_interrupts( void ) {
@@ -257,5 +254,3 @@ void setup_endstop_interrupts( void ) {
// If we arrive here without raising an assertion, each pin has either an EXT-interrupt or a PCI.
}
-
-#endif // _ENDSTOP_INTERRUPTS_H_
diff --git a/Marlin/src/HAL/HAL_AVR/fastio_1280.h b/Marlin/src/HAL/HAL_AVR/fastio_1280.h
index 1c65f2bde7..601c515f7f 100644
--- a/Marlin/src/HAL/HAL_AVR/fastio_1280.h
+++ b/Marlin/src/HAL/HAL_AVR/fastio_1280.h
@@ -19,6 +19,7 @@
* along with this program. If not, see .
*
*/
+#pragma once
/**
* Pin mapping for the 1280 and 2560
@@ -28,9 +29,6 @@
* Logical Pin : 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
*/
-#ifndef _FASTIO_1280_H_
-#define _FASTIO_1280_H_
-
#include "fastio_AVR.h"
// change for your board
@@ -1111,5 +1109,3 @@
#define PL7_WPORT PORTL
#define PL7_DDR DDRL
#define PL7_PWM NULL
-
-#endif // _FASTIO_1280_H_
diff --git a/Marlin/src/HAL/HAL_AVR/fastio_1281.h b/Marlin/src/HAL/HAL_AVR/fastio_1281.h
index 94ab6b7553..274bc6285b 100644
--- a/Marlin/src/HAL/HAL_AVR/fastio_1281.h
+++ b/Marlin/src/HAL/HAL_AVR/fastio_1281.h
@@ -19,6 +19,7 @@
* along with this program. If not, see .
*
*/
+#pragma once
/**
* Pin mapping for the 1281 and 2561
@@ -27,9 +28,6 @@
* Port: A0 A1 A2 A3 A4 A5 A6 A7 B0 B1 B2 B3 B4 B5 B6 B7 C0 C1 C2 C3 C4 C5 C6 C7 D0 D1 D2 D3 D4 D5 D6 D7 E0 E1 E2 E3 E4 E5 E6 E7 F0 F1 F2 F3 F4 F5 F6 F7 G0 G1 G2 G3 G4 G5
*/
-#ifndef _FASTIO_1281_H_
-#define _FASTIO_1281_H_
-
#include "fastio_AVR.h"
// change for your board
@@ -715,5 +713,3 @@
#define PG5_WPORT PORTG
#define PG5_DDR DDRG
#define PG5_PWM &OCR0B
-
-#endif // _FASTIO_1281_H_
diff --git a/Marlin/src/HAL/HAL_AVR/fastio_168.h b/Marlin/src/HAL/HAL_AVR/fastio_168.h
index 33492d15dc..36187bc698 100644
--- a/Marlin/src/HAL/HAL_AVR/fastio_168.h
+++ b/Marlin/src/HAL/HAL_AVR/fastio_168.h
@@ -19,6 +19,7 @@
* along with this program. If not, see .
*
*/
+#pragma once
/**
* Pin mapping for the 168, 328, and 328P
@@ -27,9 +28,6 @@
* Port: B0 B1 B2 B3 B4 B5 C0 C1 C2 C3 C4 C5 C6 C7 D0 D1 D2 D3 D4 D5 D6 D7
*/
-#ifndef _FASTIO_168_H_
-#define _FASTIO_168_H_
-
#include "fastio_AVR.h"
#define DEBUG_LED AIO5
@@ -357,5 +355,3 @@
#define PD7_WPORT PORTD
#define PD7_DDR DDRD
#define PD7_PWM NULL
-
-#endif // _FASTIO_168_H_
diff --git a/Marlin/src/HAL/HAL_AVR/fastio_644.h b/Marlin/src/HAL/HAL_AVR/fastio_644.h
index 171172023b..1ad7573801 100644
--- a/Marlin/src/HAL/HAL_AVR/fastio_644.h
+++ b/Marlin/src/HAL/HAL_AVR/fastio_644.h
@@ -19,6 +19,7 @@
* along with this program. If not, see .
*
*/
+#pragma once
/**
* Pin mapping for the 644, 644p, 644pa, and 1284p
@@ -53,9 +54,6 @@
* +--------+
*/
-#ifndef _FASTIO_644_H_
-#define _FASTIO_644_H_
-
#include "fastio_AVR.h"
#define DEBUG_LED DIO0
@@ -552,5 +550,3 @@
#define PD7_WPORT PORTD
#define PD7_DDR DDRD
#define PD7_PWM OCR2A
-
-#endif // _FASTIO_644_H_
diff --git a/Marlin/src/HAL/HAL_AVR/fastio_AT90USB.h b/Marlin/src/HAL/HAL_AVR/fastio_AT90USB.h
index 6043292960..70cfcf39b7 100644
--- a/Marlin/src/HAL/HAL_AVR/fastio_AT90USB.h
+++ b/Marlin/src/HAL/HAL_AVR/fastio_AT90USB.h
@@ -19,6 +19,7 @@
* along with this program. If not, see .
*
*/
+#pragma once
/**
* Pin mapping (Teensy) for AT90USB646, 647, 1286, and 1287
@@ -28,9 +29,6 @@
* The logical pins 46 and 47 are not supported by Teensyduino, but are supported below as E2 and E3
*/
-#ifndef _FASTIO_AT90USB_H_
-#define _FASTIO_AT90USB_H_
-
#include "fastio_AVR.h"
// change for your board
@@ -697,5 +695,3 @@
#define TIMER3A 5
#define TIMER3B 4
#define TIMER3C 3
-
-#endif // _FASTIO_AT90USB_H_
diff --git a/Marlin/src/HAL/HAL_AVR/fastio_AVR.h b/Marlin/src/HAL/HAL_AVR/fastio_AVR.h
index a4e3c5d74d..448438c87e 100644
--- a/Marlin/src/HAL/HAL_AVR/fastio_AVR.h
+++ b/Marlin/src/HAL/HAL_AVR/fastio_AVR.h
@@ -19,6 +19,7 @@
* along with this program. If not, see .
*
*/
+#pragma once
/**
* Fast I/O Routines for AVR
@@ -26,9 +27,6 @@
* Contributed by Triffid_Hunter and modified by Kliment, thinkyhead, Bob-the-Kuhn, et.al.
*/
-#ifndef _FASTIO_ARDUINO_H_
-#define _FASTIO_ARDUINO_H_
-
#include
#include "../../core/macros.h"
@@ -312,5 +310,3 @@ enum ClockSource2 : char {
// finally - the macro that tells us if a pin is an available hardware PWM
#define USEABLE_HARDWARE_PWM(p) (PWM_PINS(p) && !PWM_CHK(p))
-
-#endif // _FASTIO_ARDUINO_H_
diff --git a/Marlin/src/HAL/HAL_AVR/math_AVR.h b/Marlin/src/HAL/HAL_AVR/math_AVR.h
index 6348ed8bbf..64c9c7998e 100644
--- a/Marlin/src/HAL/HAL_AVR/math_AVR.h
+++ b/Marlin/src/HAL/HAL_AVR/math_AVR.h
@@ -19,9 +19,7 @@
* along with this program. If not, see .
*
*/
-
-#ifndef _MATH_AVR_H_
-#define _MATH_AVR_H_
+#pragma once
/**
* Optimized math functions for AVR
@@ -38,9 +36,9 @@
// D C B A is longIn2
//
static FORCE_INLINE uint16_t MultiU24X32toH16(uint32_t longIn1, uint32_t longIn2) {
- register uint8_t tmp1;
- register uint8_t tmp2;
- register uint16_t intRes;
+ uint8_t tmp1;
+ uint8_t tmp2;
+ uint16_t intRes;
__asm__ __volatile__(
A("clr %[tmp1]")
A("mul %A[longIn1], %B[longIn2]")
@@ -92,8 +90,8 @@ static FORCE_INLINE uint16_t MultiU24X32toH16(uint32_t longIn1, uint32_t longIn2
// r26 to store 0
// r27 to store the byte 1 of the 24 bit result
static FORCE_INLINE uint16_t MultiU16X8toH16(uint8_t charIn1, uint16_t intIn2) {
- register uint8_t tmp;
- register uint16_t intRes;
+ uint8_t tmp;
+ uint16_t intRes;
__asm__ __volatile__ (
A("clr %[tmp]")
A("mul %[charIn1], %B[intIn2]")
@@ -113,5 +111,3 @@ static FORCE_INLINE uint16_t MultiU16X8toH16(uint8_t charIn1, uint16_t intIn2) {
);
return intRes;
}
-
-#endif // _MATH_AVR_H_
diff --git a/Marlin/src/HAL/HAL_AVR/persistent_store_eeprom.cpp b/Marlin/src/HAL/HAL_AVR/persistent_store_eeprom.cpp
index 1593b1829c..99b18001ad 100644
--- a/Marlin/src/HAL/HAL_AVR/persistent_store_eeprom.cpp
+++ b/Marlin/src/HAL/HAL_AVR/persistent_store_eeprom.cpp
@@ -23,7 +23,7 @@
#include "../../inc/MarlinConfig.h"
-#if ENABLED(EEPROM_SETTINGS)
+#if ENABLED(EEPROM_SETTINGS) || ENABLED(SD_FIRMWARE_UPDATE)
#include "../shared/persistent_store_api.h"
@@ -53,7 +53,7 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
bool PersistentStore::read_data(int &pos, uint8_t* value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
do {
- uint8_t c = eeprom_read_byte((unsigned char*)pos);
+ uint8_t c = eeprom_read_byte((uint8_t*)pos);
if (writing) *value = c;
crc16(crc, &c, 1);
pos++;
@@ -64,5 +64,5 @@ bool PersistentStore::read_data(int &pos, uint8_t* value, size_t size, uint16_t
size_t PersistentStore::capacity() { return E2END + 1; }
-#endif // EEPROM_SETTINGS
+#endif // EEPROM_SETTINGS || SD_FIRMWARE_UPDATE
#endif // __AVR__
diff --git a/Marlin/src/HAL/HAL_AVR/pinsDebug.h b/Marlin/src/HAL/HAL_AVR/pinsDebug.h
index ea35f881e5..9c0bebbdd4 100644
--- a/Marlin/src/HAL/HAL_AVR/pinsDebug.h
+++ b/Marlin/src/HAL/HAL_AVR/pinsDebug.h
@@ -19,14 +19,12 @@
* along with this program. If not, see .
*
*/
+#pragma once
/**
* PWM print routines for Atmel 8 bit AVR CPUs
*/
-#ifndef _PINSDEBUG_AVR_8_BIT_
-#define _PINSDEBUG_AVR_8_BIT_
-
#include "../../inc/MarlinConfig.h"
#define NUMBER_PINS_TOTAL NUM_DIGITAL_PINS
@@ -406,5 +404,3 @@ static void pwm_details(uint8_t pin) {
#endif
#define PRINT_PIN(p) do {sprintf_P(buffer, PSTR("%3d "), p); SERIAL_ECHO(buffer);} while (0)
-
-#endif // _PINSDEBUG_AVR_8_BIT_
diff --git a/Marlin/src/HAL/HAL_AVR/pinsDebug_Teensyduino.h b/Marlin/src/HAL/HAL_AVR/pinsDebug_Teensyduino.h
index 840e2a22e9..8da9570743 100644
--- a/Marlin/src/HAL/HAL_AVR/pinsDebug_Teensyduino.h
+++ b/Marlin/src/HAL/HAL_AVR/pinsDebug_Teensyduino.h
@@ -19,9 +19,7 @@
* along with this program. If not, see .
*
*/
-
-#ifndef _PINSDEBUG_TEENSYSUINO_H_
-#define _PINSDEBUG_TEENSYSUINO_H_
+#pragma once
//
// some of the pin mapping functions of the Teensduino extension to the Arduino IDE
@@ -111,5 +109,3 @@ const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
// disable the PWMs so we can use it as is
// portModeRegister(pin) is OK
-
-#endif // _PINSDEBUG_TEENSYSUINO_H_
diff --git a/Marlin/src/HAL/HAL_AVR/pinsDebug_plus_70.h b/Marlin/src/HAL/HAL_AVR/pinsDebug_plus_70.h
index 5a0f840140..99f83a03a4 100644
--- a/Marlin/src/HAL/HAL_AVR/pinsDebug_plus_70.h
+++ b/Marlin/src/HAL/HAL_AVR/pinsDebug_plus_70.h
@@ -20,14 +20,12 @@
* along with this program. If not, see .
*
*/
+#pragma once
/**
* Structures for 2560 family boards that use more than 70 pins
*/
-#ifndef _PINSDEBUG_PLUS_70_H_
-#define _PINSDEBUG_PLUS_70_H_
-
#undef NUM_DIGITAL_PINS
#if MB(BQ_ZUM_MEGA_3D)
#define NUM_DIGITAL_PINS 85
@@ -336,6 +334,3 @@ const uint8_t PROGMEM digital_pin_to_timer_PGM_plus_70[] = {
* PCINT14 J5 76
* PCINT15 J6 77
*/
-
-
-#endif // _PINSDEBUG_PLUS_70_H_
diff --git a/Marlin/src/HAL/HAL_AVR/spi_pins.h b/Marlin/src/HAL/HAL_AVR/spi_pins.h
index d4838956e7..d3d2412416 100644
--- a/Marlin/src/HAL/HAL_AVR/spi_pins.h
+++ b/Marlin/src/HAL/HAL_AVR/spi_pins.h
@@ -19,9 +19,7 @@
* along with this program. If not, see .
*
*/
-
-#ifndef _SPI_PINS_H_
-#define _SPI_PINS_H_
+#pragma once
/**
* Define SPI Pins: SCK, MISO, MOSI, SS
@@ -65,6 +63,3 @@
#ifndef SS_PIN
#define SS_PIN AVR_SS_PIN
#endif
-
-
-#endif // _SPI_PINS_H_
diff --git a/Marlin/src/HAL/HAL_AVR/watchdog_AVR.cpp b/Marlin/src/HAL/HAL_AVR/watchdog_AVR.cpp
index 6af106439a..8845fa04ac 100644
--- a/Marlin/src/HAL/HAL_AVR/watchdog_AVR.cpp
+++ b/Marlin/src/HAL/HAL_AVR/watchdog_AVR.cpp
@@ -63,9 +63,8 @@ void watchdog_init() {
ISR(WDT_vect) {
sei(); // With the interrupt driven serial we need to allow interrupts.
SERIAL_ERROR_START();
- SERIAL_ERRORLNPGM("Watchdog barked, please turn off the printer.");
- kill(PSTR("ERR:Watchdog")); //kill blocks //up to 16 characters so it fits on a 16x2 display
- while (1); //wait for user or serial reset
+ SERIAL_ERRORLNPGM(MSG_WATCHDOG_FIRED);
+ minkill(); // interrupt-safe final kill and infinite loop
}
#endif // WATCHDOG_RESET_MANUAL
diff --git a/Marlin/src/HAL/HAL_AVR/watchdog_AVR.h b/Marlin/src/HAL/HAL_AVR/watchdog_AVR.h
index 90c6185cb6..ac55c9aebd 100644
--- a/Marlin/src/HAL/HAL_AVR/watchdog_AVR.h
+++ b/Marlin/src/HAL/HAL_AVR/watchdog_AVR.h
@@ -19,9 +19,7 @@
* along with this program. If not, see .
*
*/
-
-#ifndef _WATCHDOG_AVR_H_
-#define _WATCHDOG_AVR_H_
+#pragma once
#include
@@ -31,5 +29,3 @@ void watchdog_init();
// Reset watchdog. MUST be called at least every 4 seconds after the
// first watchdog_init or AVR will go into emergency procedures.
inline void watchdog_reset() { wdt_reset(); }
-
-#endif // _WATCHDOG_AVR_H_
diff --git a/Marlin/src/HAL/HAL_DUE/DebugMonitor_Due.cpp b/Marlin/src/HAL/HAL_DUE/DebugMonitor_Due.cpp
index f12f0df7fb..40407f7f5d 100644
--- a/Marlin/src/HAL/HAL_DUE/DebugMonitor_Due.cpp
+++ b/Marlin/src/HAL/HAL_DUE/DebugMonitor_Due.cpp
@@ -145,8 +145,8 @@ static const UnwindCallbacks UnwCallbacks = {
UnwReadW,
UnwReadH,
UnwReadB
- #if defined(UNW_DEBUG)
- ,UnwPrintf
+ #ifdef UNW_DEBUG
+ , UnwPrintf
#endif
};
diff --git a/Marlin/src/HAL/HAL_DUE/HAL.cpp b/Marlin/src/HAL/HAL_DUE/HAL.cpp
index 9d932d94db..cc2db0eb26 100644
--- a/Marlin/src/HAL/HAL_DUE/HAL.cpp
+++ b/Marlin/src/HAL/HAL_DUE/HAL.cpp
@@ -29,6 +29,7 @@
// Includes
// --------------------------------------------------------------------------
+#include "../../inc/MarlinConfig.h"
#include "HAL.h"
#include
diff --git a/Marlin/src/HAL/HAL_DUE/HAL.h b/Marlin/src/HAL/HAL_DUE/HAL.h
index b5d1d4580f..57d3160ca4 100644
--- a/Marlin/src/HAL/HAL_DUE/HAL.h
+++ b/Marlin/src/HAL/HAL_DUE/HAL.h
@@ -19,6 +19,7 @@
* along with this program. If not, see .
*
*/
+#pragma once
/**
* Description: HAL for Arduino Due and compatible (SAM3X8E)
@@ -26,9 +27,6 @@
* For ARDUINO_ARCH_SAM
*/
-#ifndef _HAL_DUE_H
-#define _HAL_DUE_H
-
#define CPU_32_BIT
#include
@@ -41,9 +39,25 @@
#include "watchdog_Due.h"
#include "HAL_timers_Due.h"
-#define NUM_SERIAL 1
-// Required before the include or compilation fails
-#define MYSERIAL0 customizedSerial
+// Serial ports
+#if !WITHIN(SERIAL_PORT, -1, 3)
+ #error "SERIAL_PORT must be from -1 to 3"
+#endif
+
+// MYSERIAL0 required before MarlinSerial includes!
+#define MYSERIAL0 customizedSerial1
+
+#ifdef SERIAL_PORT_2
+ #if !WITHIN(SERIAL_PORT_2, -1, 3)
+ #error "SERIAL_PORT_2 must be from -1 to 3"
+ #elif SERIAL_PORT_2 == SERIAL_PORT
+ #error "SERIAL_PORT_2 must be different than SERIAL_PORT"
+ #endif
+ #define NUM_SERIAL 2
+ #define MYSERIAL1 customizedSerial2
+#else
+ #define NUM_SERIAL 1
+#endif
#include "MarlinSerial_Due.h"
#include "MarlinSerialUSB_Due.h"
@@ -108,8 +122,8 @@ uint8_t spiRec(uint32_t chan);
//
// EEPROM
//
-void eeprom_write_byte(unsigned char *pos, unsigned char value);
-unsigned char eeprom_read_byte(unsigned char *pos);
+void eeprom_write_byte(uint8_t *pos, unsigned char value);
+uint8_t eeprom_read_byte(uint8_t *pos);
void eeprom_read_block (void *__dst, const void *__src, size_t __n);
void eeprom_update_block (const void *__src, void *__dst, size_t __n);
@@ -173,5 +187,3 @@ char *dtostrf (double __val, signed char __width, unsigned char __prec, char *__
#ifdef __cplusplus
}
#endif
-
-#endif // _HAL_DUE_H
diff --git a/Marlin/src/HAL/HAL_DUE/HAL_spi_Due.cpp b/Marlin/src/HAL/HAL_DUE/HAL_spi_Due.cpp
index a45306e316..b127f1a990 100644
--- a/Marlin/src/HAL/HAL_DUE/HAL_spi_Due.cpp
+++ b/Marlin/src/HAL/HAL_DUE/HAL_spi_Due.cpp
@@ -78,11 +78,11 @@
// run at ~8 .. ~10Mhz - Tx version (Rx data discarded)
static uint8_t spiTransferTx0(uint8_t bout) { // using Mode 0
- register uint32_t MOSI_PORT_PLUS30 = ((uint32_t) PORT(MOSI_PIN)) + 0x30; /* SODR of port */
- register uint32_t MOSI_MASK = PIN_MASK(MOSI_PIN);
- register uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
- register uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
- register uint32_t idx = 0;
+ uint32_t MOSI_PORT_PLUS30 = ((uint32_t) PORT(MOSI_PIN)) + 0x30; /* SODR of port */
+ uint32_t MOSI_MASK = PIN_MASK(MOSI_PIN);
+ uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
+ uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
+ uint32_t idx = 0;
/* Negate bout, as the assembler requires a negated value */
bout = ~bout;
@@ -161,11 +161,11 @@
// run at ~8 .. ~10Mhz - Rx version (Tx line not altered)
static uint8_t spiTransferRx0(uint8_t bout) { // using Mode 0
- register uint32_t bin = 0;
- register uint32_t work = 0;
- register uint32_t BITBAND_MISO_PORT = BITBAND_ADDRESS( ((uint32_t)PORT(MISO_PIN))+0x3C, PIN_SHIFT(MISO_PIN)); /* PDSR of port in bitband area */
- register uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
- register uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
+ uint32_t bin = 0;
+ uint32_t work = 0;
+ uint32_t BITBAND_MISO_PORT = BITBAND_ADDRESS( ((uint32_t)PORT(MISO_PIN))+0x3C, PIN_SHIFT(MISO_PIN)); /* PDSR of port in bitband area */
+ uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
+ uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
UNUSED(bout);
/* The software SPI routine */
@@ -281,12 +281,12 @@
// Block transfers run at ~8 .. ~10Mhz - Tx version (Rx data discarded)
static void spiTxBlock0(const uint8_t* ptr, uint32_t todo) {
- register uint32_t MOSI_PORT_PLUS30 = ((uint32_t) PORT(MOSI_PIN)) + 0x30; /* SODR of port */
- register uint32_t MOSI_MASK = PIN_MASK(MOSI_PIN);
- register uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
- register uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
- register uint32_t work = 0;
- register uint32_t txval = 0;
+ uint32_t MOSI_PORT_PLUS30 = ((uint32_t) PORT(MOSI_PIN)) + 0x30; /* SODR of port */
+ uint32_t MOSI_MASK = PIN_MASK(MOSI_PIN);
+ uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
+ uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
+ uint32_t work = 0;
+ uint32_t txval = 0;
/* The software SPI routine */
__asm__ __volatile__(
@@ -360,11 +360,11 @@
}
static void spiRxBlock0(uint8_t* ptr, uint32_t todo) {
- register uint32_t bin = 0;
- register uint32_t work = 0;
- register uint32_t BITBAND_MISO_PORT = BITBAND_ADDRESS( ((uint32_t)PORT(MISO_PIN))+0x3C, PIN_SHIFT(MISO_PIN)); /* PDSR of port in bitband area */
- register uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
- register uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
+ uint32_t bin = 0;
+ uint32_t work = 0;
+ uint32_t BITBAND_MISO_PORT = BITBAND_ADDRESS( ((uint32_t)PORT(MISO_PIN))+0x3C, PIN_SHIFT(MISO_PIN)); /* PDSR of port in bitband area */
+ uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
+ uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
/* The software SPI routine */
__asm__ __volatile__(
@@ -581,84 +581,124 @@
// --------------------------------------------------------------------------
// hardware SPI
// --------------------------------------------------------------------------
- // 8.4 MHz, 4 MHz, 2 MHz, 1 MHz, 0.5 MHz, 0.329 MHz, 0.329 MHz
- int spiDueDividors[] = { 10, 21, 42, 84, 168, 255, 255 };
- bool spiInitMaded = false;
-
- void spiBegin() {
- if (spiInitMaded == false) {
- // Configure SPI pins
- PIO_Configure(
- g_APinDescription[SCK_PIN].pPort,
- g_APinDescription[SCK_PIN].ulPinType,
- g_APinDescription[SCK_PIN].ulPin,
- g_APinDescription[SCK_PIN].ulPinConfiguration);
- PIO_Configure(
- g_APinDescription[MOSI_PIN].pPort,
- g_APinDescription[MOSI_PIN].ulPinType,
- g_APinDescription[MOSI_PIN].ulPin,
- g_APinDescription[MOSI_PIN].ulPinConfiguration);
- PIO_Configure(
- g_APinDescription[MISO_PIN].pPort,
- g_APinDescription[MISO_PIN].ulPinType,
- g_APinDescription[MISO_PIN].ulPin,
- g_APinDescription[MISO_PIN].ulPinConfiguration);
-
- // set master mode, peripheral select, fault detection
- SPI_Configure(SPI0, ID_SPI0, SPI_MR_MSTR | SPI_MR_MODFDIS | SPI_MR_PS);
- SPI_Enable(SPI0);
-
- #if MB(ALLIGATOR)
- SET_OUTPUT(DAC0_SYNC);
- #if EXTRUDERS > 1
- SET_OUTPUT(DAC1_SYNC);
- WRITE(DAC1_SYNC, HIGH);
- #endif
- SET_OUTPUT(SPI_EEPROM1_CS);
- SET_OUTPUT(SPI_EEPROM2_CS);
- SET_OUTPUT(SPI_FLASH_CS);
- WRITE(DAC0_SYNC, HIGH);
- WRITE(SPI_EEPROM1_CS, HIGH );
- WRITE(SPI_EEPROM2_CS, HIGH );
- WRITE(SPI_FLASH_CS, HIGH );
- WRITE(SS_PIN, HIGH );
- #endif // MB(ALLIGATOR)
-
- OUT_WRITE(SDSS,0);
-
- PIO_Configure(
- g_APinDescription[SPI_PIN].pPort,
- g_APinDescription[SPI_PIN].ulPinType,
- g_APinDescription[SPI_PIN].ulPin,
- g_APinDescription[SPI_PIN].ulPinConfiguration);
-
- spiInit(1);
- spiInitMaded = true;
- }
- }
+ static bool spiInitialized = false;
void spiInit(uint8_t spiRate) {
- if (spiInitMaded == false) {
- if (spiRate > 6) spiRate = 1;
+ if (spiInitialized) return;
- #if MB(ALLIGATOR)
- // Set SPI mode 1, clock, select not active after transfer, with delay between transfers
- SPI_ConfigureNPCS(SPI0, SPI_CHAN_DAC,
- SPI_CSR_CSAAT | SPI_CSR_SCBR(spiDueDividors[spiRate]) |
- SPI_CSR_DLYBCT(1));
- // Set SPI mode 0, clock, select not active after transfer, with delay between transfers
- SPI_ConfigureNPCS(SPI0, SPI_CHAN_EEPROM1, SPI_CSR_NCPHA |
- SPI_CSR_CSAAT | SPI_CSR_SCBR(spiDueDividors[spiRate]) |
- SPI_CSR_DLYBCT(1));
- #endif//MB(ALLIGATOR)
+ // 8.4 MHz, 4 MHz, 2 MHz, 1 MHz, 0.5 MHz, 0.329 MHz, 0.329 MHz
+ constexpr int spiDivider[] = { 10, 21, 42, 84, 168, 255, 255 };
+ if (spiRate > 6) spiRate = 1;
- // Set SPI mode 0, clock, select not active after transfer, with delay between transfers
- SPI_ConfigureNPCS(SPI0, SPI_CHAN, SPI_CSR_NCPHA |
- SPI_CSR_CSAAT | SPI_CSR_SCBR(spiDueDividors[spiRate]) |
- SPI_CSR_DLYBCT(1));
- SPI_Enable(SPI0);
- spiInitMaded = true;
+ // Set SPI mode 1, clock, select not active after transfer, with delay between transfers
+ SPI_ConfigureNPCS(SPI0, SPI_CHAN_DAC,
+ SPI_CSR_CSAAT | SPI_CSR_SCBR(spiDivider[spiRate]) |
+ SPI_CSR_DLYBCT(1));
+ // Set SPI mode 0, clock, select not active after transfer, with delay between transfers
+ SPI_ConfigureNPCS(SPI0, SPI_CHAN_EEPROM1, SPI_CSR_NCPHA |
+ SPI_CSR_CSAAT | SPI_CSR_SCBR(spiDivider[spiRate]) |
+ SPI_CSR_DLYBCT(1));
+
+ // Set SPI mode 0, clock, select not active after transfer, with delay between transfers
+ SPI_ConfigureNPCS(SPI0, SPI_CHAN, SPI_CSR_NCPHA |
+ SPI_CSR_CSAAT | SPI_CSR_SCBR(spiDivider[spiRate]) |
+ SPI_CSR_DLYBCT(1));
+ SPI_Enable(SPI0);
+ spiInitialized = true;
+ }
+
+ void spiBegin() {
+ if (spiInitialized) return;
+
+ // Configure SPI pins
+ PIO_Configure(
+ g_APinDescription[SCK_PIN].pPort,
+ g_APinDescription[SCK_PIN].ulPinType,
+ g_APinDescription[SCK_PIN].ulPin,
+ g_APinDescription[SCK_PIN].ulPinConfiguration);
+ PIO_Configure(
+ g_APinDescription[MOSI_PIN].pPort,
+ g_APinDescription[MOSI_PIN].ulPinType,
+ g_APinDescription[MOSI_PIN].ulPin,
+ g_APinDescription[MOSI_PIN].ulPinConfiguration);
+ PIO_Configure(
+ g_APinDescription[MISO_PIN].pPort,
+ g_APinDescription[MISO_PIN].ulPinType,
+ g_APinDescription[MISO_PIN].ulPin,
+ g_APinDescription[MISO_PIN].ulPinConfiguration);
+
+ // set master mode, peripheral select, fault detection
+ SPI_Configure(SPI0, ID_SPI0, SPI_MR_MSTR | SPI_MR_MODFDIS | SPI_MR_PS);
+ SPI_Enable(SPI0);
+
+ SET_OUTPUT(DAC0_SYNC);
+ #if EXTRUDERS > 1
+ SET_OUTPUT(DAC1_SYNC);
+ WRITE(DAC1_SYNC, HIGH);
+ #endif
+ SET_OUTPUT(SPI_EEPROM1_CS);
+ SET_OUTPUT(SPI_EEPROM2_CS);
+ SET_OUTPUT(SPI_FLASH_CS);
+ WRITE(DAC0_SYNC, HIGH);
+ WRITE(SPI_EEPROM1_CS, HIGH );
+ WRITE(SPI_EEPROM2_CS, HIGH );
+ WRITE(SPI_FLASH_CS, HIGH );
+ WRITE(SS_PIN, HIGH );
+
+ OUT_WRITE(SDSS,0);
+
+ PIO_Configure(
+ g_APinDescription[SPI_PIN].pPort,
+ g_APinDescription[SPI_PIN].ulPinType,
+ g_APinDescription[SPI_PIN].ulPin,
+ g_APinDescription[SPI_PIN].ulPinConfiguration);
+
+ spiInit(1);
+ }
+
+ // Read single byte from SPI
+ uint8_t spiRec() {
+ // write dummy byte with address and end transmission flag
+ SPI0->SPI_TDR = 0x000000FF | SPI_PCS(SPI_CHAN) | SPI_TDR_LASTXFER;
+ // wait for transmit register empty
+ while ((SPI0->SPI_SR & SPI_SR_TDRE) == 0);
+
+ // wait for receive register
+ while ((SPI0->SPI_SR & SPI_SR_RDRF) == 0);
+ // get byte from receive register
+ //DELAY_US(1U);
+ return SPI0->SPI_RDR;
+ }
+
+ uint8_t spiRec(uint32_t chan) {
+ uint8_t spirec_tmp;
+ // wait for transmit register empty
+ while ((SPI0->SPI_SR & SPI_SR_TDRE) == 0);
+ while ((SPI0->SPI_SR & SPI_SR_RDRF) == 1)
+ spirec_tmp = SPI0->SPI_RDR;
+ UNUSED(spirec_tmp);
+
+ // write dummy byte with address and end transmission flag
+ SPI0->SPI_TDR = 0x000000FF | SPI_PCS(chan) | SPI_TDR_LASTXFER;
+
+ // wait for receive register
+ while ((SPI0->SPI_SR & SPI_SR_RDRF) == 0);
+ // get byte from receive register
+ return SPI0->SPI_RDR;
+ }
+
+ // Read from SPI into buffer
+ void spiRead(uint8_t* buf, uint16_t nbyte) {
+ if (nbyte-- == 0) return;
+
+ for (int i = 0; i < nbyte; i++) {
+ //while ((SPI0->SPI_SR & SPI_SR_TDRE) == 0);
+ SPI0->SPI_TDR = 0x000000FF | SPI_PCS(SPI_CHAN);
+ while ((SPI0->SPI_SR & SPI_SR_RDRF) == 0);
+ buf[i] = SPI0->SPI_RDR;
+ //DELAY_US(1U);
}
+ buf[nbyte] = spiRec();
}
// Write single byte to SPI
@@ -714,51 +754,6 @@
spiSend(chan, buf[n - 1]);
}
- // Read single byte from SPI
- uint8_t spiRec() {
- // write dummy byte with address and end transmission flag
- SPI0->SPI_TDR = 0x000000FF | SPI_PCS(SPI_CHAN) | SPI_TDR_LASTXFER;
- // wait for transmit register empty
- while ((SPI0->SPI_SR & SPI_SR_TDRE) == 0);
-
- // wait for receive register
- while ((SPI0->SPI_SR & SPI_SR_RDRF) == 0);
- // get byte from receive register
- //DELAY_US(1U);
- return SPI0->SPI_RDR;
- }
-
- uint8_t spiRec(uint32_t chan) {
- uint8_t spirec_tmp;
- // wait for transmit register empty
- while ((SPI0->SPI_SR & SPI_SR_TDRE) == 0);
- while ((SPI0->SPI_SR & SPI_SR_RDRF) == 1)
- spirec_tmp = SPI0->SPI_RDR;
- UNUSED(spirec_tmp);
-
- // write dummy byte with address and end transmission flag
- SPI0->SPI_TDR = 0x000000FF | SPI_PCS(chan) | SPI_TDR_LASTXFER;
-
- // wait for receive register
- while ((SPI0->SPI_SR & SPI_SR_RDRF) == 0);
- // get byte from receive register
- return SPI0->SPI_RDR;
- }
-
- // Read from SPI into buffer
- void spiRead(uint8_t* buf, uint16_t nbyte) {
- if (nbyte-- == 0) return;
-
- for (int i = 0; i < nbyte; i++) {
- //while ((SPI0->SPI_SR & SPI_SR_TDRE) == 0);
- SPI0->SPI_TDR = 0x000000FF | SPI_PCS(SPI_CHAN);
- while ((SPI0->SPI_SR & SPI_SR_RDRF) == 0);
- buf[i] = SPI0->SPI_RDR;
- //DELAY_US(1U);
- }
- buf[nbyte] = spiRec();
- }
-
// Write from buffer to SPI
void spiSendBlock(uint8_t token, const uint8_t* buf) {
SPI0->SPI_TDR = (uint32_t)token | SPI_PCS(SPI_CHAN);
@@ -780,7 +775,7 @@
// TODO: to be implemented
}
- #else // U8G compatible hardware SPI
+ #else // U8G compatible hardware SPI
#define SPI_MODE_0_DUE_HW 2 // DUE CPHA control bit is inverted
#define SPI_MODE_1_DUE_HW 3
@@ -789,7 +784,7 @@
void spiInit(uint8_t spiRate=6) { // Default to slowest rate if not specified)
// 8.4 MHz, 4 MHz, 2 MHz, 1 MHz, 0.5 MHz, 0.329 MHz, 0.329 MHz
- int spiDueDividors[] = { 10, 21, 42, 84, 168, 255, 255 };
+ constexpr int spiDivider[] = { 10, 21, 42, 84, 168, 255, 255 };
if (spiRate > 6) spiRate = 1;
// Enable PIOA and SPI0
@@ -809,7 +804,11 @@
// Master mode, no fault detection, PCS bits in data written to TDR select CSR register
SPI0->SPI_MR = SPI_MR_MSTR | SPI_MR_PS | SPI_MR_MODFDIS;
// SPI mode 0, 8 Bit data transfer, baud rate
- SPI0->SPI_CSR[3] = SPI_CSR_SCBR(spiDueDividors[spiRate]) | SPI_CSR_CSAAT | SPI_MODE_0_DUE_HW; // use same CSR as TMC2130
+ SPI0->SPI_CSR[3] = SPI_CSR_SCBR(spiDivider[spiRate]) | SPI_CSR_CSAAT | SPI_MODE_0_DUE_HW; // use same CSR as TMC2130
+ }
+
+ void spiBegin() {
+ spiInit();
}
static uint8_t spiTransfer(uint8_t data) {
@@ -828,10 +827,6 @@
return SPI0->SPI_RDR;
}
- void spiBegin() {
- spiInit();
- }
-
uint8_t spiRec() {
uint8_t data = spiTransfer(0xFF);
return data;
diff --git a/Marlin/src/HAL/HAL_DUE/HAL_timers_Due.cpp b/Marlin/src/HAL/HAL_DUE/HAL_timers_Due.cpp
index eb23692b44..f5f74c0ce2 100644
--- a/Marlin/src/HAL/HAL_DUE/HAL_timers_Due.cpp
+++ b/Marlin/src/HAL/HAL_DUE/HAL_timers_Due.cpp
@@ -31,7 +31,7 @@
// --------------------------------------------------------------------------
// Includes
// --------------------------------------------------------------------------
-
+#include "../../inc/MarlinConfig.h"
#include "HAL.h"
#include "HAL_timers_Due.h"
diff --git a/Marlin/src/HAL/HAL_DUE/HAL_timers_Due.h b/Marlin/src/HAL/HAL_DUE/HAL_timers_Due.h
index dd342f5471..46b7aaf5a4 100644
--- a/Marlin/src/HAL/HAL_DUE/HAL_timers_Due.h
+++ b/Marlin/src/HAL/HAL_DUE/HAL_timers_Due.h
@@ -18,6 +18,7 @@
* along with this program. If not, see .
*
*/
+#pragma once
/**
* HAL for Arduino Due and compatible (SAM3X8E)
@@ -25,9 +26,6 @@
* For ARDUINO_ARCH_SAM
*/
-#ifndef _HAL_TIMERS_DUE_H
-#define _HAL_TIMERS_DUE_H
-
// --------------------------------------------------------------------------
// Includes
// --------------------------------------------------------------------------
@@ -120,5 +118,3 @@ FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) {
}
#define HAL_timer_isr_epilogue(TIMER_NUM)
-
-#endif // _HAL_TIMERS_DUE_H
diff --git a/Marlin/src/HAL/HAL_DUE/InterruptVectors_Due.cpp b/Marlin/src/HAL/HAL_DUE/InterruptVectors_Due.cpp
index 9b226a60da..97aefc98d1 100644
--- a/Marlin/src/HAL/HAL_DUE/InterruptVectors_Due.cpp
+++ b/Marlin/src/HAL/HAL_DUE/InterruptVectors_Due.cpp
@@ -32,6 +32,7 @@
*/
#ifdef ARDUINO_ARCH_SAM
+#include "../../inc/MarlinConfig.h"
#include "HAL.h"
#include "InterruptVectors_Due.h"
diff --git a/Marlin/src/HAL/HAL_DUE/InterruptVectors_Due.h b/Marlin/src/HAL/HAL_DUE/InterruptVectors_Due.h
index efc63de25d..a9be8e0b31 100644
--- a/Marlin/src/HAL/HAL_DUE/InterruptVectors_Due.h
+++ b/Marlin/src/HAL/HAL_DUE/InterruptVectors_Due.h
@@ -19,6 +19,7 @@
* along with this program. If not, see .
*
*/
+#pragma once
/**
* InterruptVectors_Due.h
@@ -35,11 +36,6 @@
* Copyright (c) 2017 Eduardo José Tagle. All right reserved
*/
-#ifndef INTERRUPTVECTORS_DUE_H
-#define INTERRUPTVECTORS_DUE_H
-
-#include "../../inc/MarlinConfig.h"
-
#ifdef ARDUINO_ARCH_SAM
// ISR handler type
@@ -49,4 +45,3 @@ typedef void (*pfnISR_Handler)(void);
pfnISR_Handler install_isr(IRQn_Type irq, pfnISR_Handler newHandler);
#endif // ARDUINO_ARCH_SAM
-#endif // INTERRUPTVECTORS_DUE_H
diff --git a/Marlin/src/HAL/HAL_DUE/MarlinSerialUSB_Due.cpp b/Marlin/src/HAL/HAL_DUE/MarlinSerialUSB_Due.cpp
index eed4c73999..b176f9d0d9 100644
--- a/Marlin/src/HAL/HAL_DUE/MarlinSerialUSB_Due.cpp
+++ b/Marlin/src/HAL/HAL_DUE/MarlinSerialUSB_Due.cpp
@@ -143,8 +143,8 @@ void MarlinSerialUSB::write(const uint8_t c) {
}
/**
-* Imports from print.h
-*/
+ * Imports from print.h
+ */
void MarlinSerialUSB::print(char c, int base) {
print((long)c, base);
@@ -285,7 +285,7 @@ void MarlinSerialUSB::printFloat(double number, uint8_t digits) {
}
// Preinstantiate
-MarlinSerialUSB customizedSerial;
+MarlinSerialUSB customizedSerial1;
#endif // SERIAL_PORT == -1
diff --git a/Marlin/src/HAL/HAL_DUE/MarlinSerialUSB_Due.h b/Marlin/src/HAL/HAL_DUE/MarlinSerialUSB_Due.h
index bfa2ccedc0..fbba508506 100644
--- a/Marlin/src/HAL/HAL_DUE/MarlinSerialUSB_Due.h
+++ b/Marlin/src/HAL/HAL_DUE/MarlinSerialUSB_Due.h
@@ -19,15 +19,13 @@
* along with this program. If not, see .
*
*/
+#pragma once
/**
* MarlinSerialUSB_Due.h - Hardware Serial over USB (CDC) library for Arduino DUE
* Copyright (c) 2017 Eduardo José Tagle. All right reserved
*/
-#ifndef MARLINSERIALUSB_DUE_H
-#define MARLINSERIALUSB_DUE_H
-
#include "../../inc/MarlinConfig.h"
#if SERIAL_PORT == -1
@@ -52,11 +50,11 @@ public:
static void write(const uint8_t c);
#if ENABLED(SERIAL_STATS_DROPPED_RX)
- FORCE_INLINE static uint32_t dropped() { return 0; }
+ FORCE_INLINE static uint32_t dropped() { return 0; }
#endif
#if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
- FORCE_INLINE static int rxMaxEnqueued() { return 0; }
+ FORCE_INLINE static int rxMaxEnqueued() { return 0; }
#endif
FORCE_INLINE static void write(const char* str) { while (*str) write(*str++); }
@@ -89,7 +87,6 @@ private:
static void printFloat(double, uint8_t);
};
-extern MarlinSerialUSB customizedSerial;
+extern MarlinSerialUSB customizedSerial1;
#endif // SERIAL_PORT == -1
-#endif // MARLINSERIAL_DUE_H
diff --git a/Marlin/src/HAL/HAL_DUE/MarlinSerial_Due.cpp b/Marlin/src/HAL/HAL_DUE/MarlinSerial_Due.cpp
index 0ff98e62ff..ef72c38270 100644
--- a/Marlin/src/HAL/HAL_DUE/MarlinSerial_Due.cpp
+++ b/Marlin/src/HAL/HAL_DUE/MarlinSerial_Due.cpp
@@ -33,671 +33,619 @@
#include "InterruptVectors_Due.h"
#include "../../Marlin.h"
-// If not using the USB port as serial port
-#if SERIAL_PORT >= 0
+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;
- // Based on selected port, use the proper configuration
- #if SERIAL_PORT == 0
- #define HWUART UART
- #define HWUART_IRQ UART_IRQn
- #define HWUART_IRQ_ID ID_UART
- #elif SERIAL_PORT == 1
- #define HWUART ((Uart*)USART0)
- #define HWUART_IRQ USART0_IRQn
- #define HWUART_IRQ_ID ID_USART0
- #elif SERIAL_PORT == 2
- #define HWUART ((Uart*)USART1)
- #define HWUART_IRQ USART1_IRQn
- #define HWUART_IRQ_ID ID_USART1
- #elif SERIAL_PORT == 3
- #define HWUART ((Uart*)USART2)
- #define HWUART_IRQ USART2_IRQn
- #define HWUART_IRQ_ID ID_USART2
- #elif SERIAL_PORT == 4
- #define HWUART ((Uart*)USART3)
- #define HWUART_IRQ USART3_IRQn
- #define HWUART_IRQ_ID ID_USART3
- #endif
+// A SW memory barrier, to ensure GCC does not overoptimize loops
+#define sw_barrier() asm volatile("": : :"memory");
- struct ring_buffer_r {
- unsigned char buffer[RX_BUFFER_SIZE];
- volatile ring_buffer_pos_t head, tail;
- };
+#include "../../feature/emergency_parser.h"
- #if TX_BUFFER_SIZE > 0
- struct ring_buffer_t {
- unsigned char buffer[TX_BUFFER_SIZE];
- volatile uint8_t head, tail;
- };
- #endif
+// (called with RX interrupts disabled)
+template
+FORCE_INLINE void MarlinSerial::store_rxd_char() {
- ring_buffer_r rx_buffer = { { 0 }, 0, 0 };
- #if TX_BUFFER_SIZE > 0
- ring_buffer_t tx_buffer = { { 0 }, 0, 0 };
- #endif
- static bool _written;
+ static EmergencyParser::State emergency_state; // = EP_RESET
- #if ENABLED(SERIAL_XON_XOFF)
- constexpr uint8_t XON_XOFF_CHAR_SENT = 0x80, // XON / XOFF Character was sent
- XON_XOFF_CHAR_MASK = 0x1F; // XON / XOFF character to send
- // XON / XOFF character definitions
- constexpr uint8_t XON_CHAR = 17, XOFF_CHAR = 19;
- uint8_t xon_xoff_state = XON_XOFF_CHAR_SENT | XON_CHAR;
+ // Get the tail - Nothing can alter its value while we are at this ISR
+ const ring_buffer_pos_t t = rx_buffer.tail;
- // Validate that RX buffer size is at least 4096 bytes- According to several experiments, on
- // the original Arduino Due that uses a ATmega16U2 as USB to serial bridge, due to the introduced
- // latencies, at least 2959 bytes of RX buffering (when transmitting at 250kbits/s) are required
- // to avoid overflows.
+ // Get the head pointer
+ ring_buffer_pos_t h = rx_buffer.head;
- #if RX_BUFFER_SIZE < 4096
- #error Arduino DUE requires at least 4096 bytes of RX buffer to avoid buffer overflows when using XON/XOFF handshake
- #endif
- #endif
+ // Get the next element
+ ring_buffer_pos_t i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
- #if ENABLED(SERIAL_STATS_DROPPED_RX)
- uint8_t rx_dropped_bytes = 0;
- #endif
+ // Read the character from the USART
+ uint8_t c = HWUART->UART_RHR;
- #if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
- uint8_t rx_buffer_overruns = 0;
- #endif
+ if (Cfg::EMERGENCYPARSER) emergency_parser.update(emergency_state, c);
- #if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
- uint8_t rx_framing_errors = 0;
- #endif
+ // 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 ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
- ring_buffer_pos_t rx_max_enqueued = 0;
- #endif
+ const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
+ // Calculate count of bytes stored into the RX buffer
- // A SW memory barrier, to ensure GCC does not overoptimize loops
- #define sw_barrier() asm volatile("": : :"memory");
+ // Keep track of the maximum count of enqueued bytes
+ if (Cfg::MAX_RX_QUEUED) NOLESS(rx_max_enqueued, rx_count);
- #if ENABLED(EMERGENCY_PARSER)
- #include "../../feature/emergency_parser.h"
- #endif
+ if (Cfg::XONOFF) {
+ // If the last char that was sent was an XON
+ if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XON_CHAR) {
- // (called with RX interrupts disabled)
- FORCE_INLINE void store_rxd_char() {
+ // 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);
- #if ENABLED(EMERGENCY_PARSER)
- static EmergencyParser::State emergency_state; // = EP_RESET
- #endif
+ // 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) {
- // Get the tail - Nothing can alter its value while we are at this ISR
- const ring_buffer_pos_t t = rx_buffer.tail;
+ // 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.
- // Get the head pointer
- ring_buffer_pos_t h = rx_buffer.head;
+ // About to send the XOFF char
+ xon_xoff_state = XOFF_CHAR | XON_XOFF_CHAR_SENT;
- // Get the next element
- ring_buffer_pos_t i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(RX_BUFFER_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!
+ uint32_t status;
+ while (!((status = HWUART->UART_SR) & UART_SR_TXRDY)) {
- // Read the character from the USART
- uint8_t c = HWUART->UART_RHR;
+ if (status & UART_SR_RXRDY) {
+ // We received a char while waiting for the TX buffer to be empty - Receive and process it!
- #if ENABLED(EMERGENCY_PARSER)
- emergency_parser.update(emergency_state, c);
- #endif
+ i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
- // 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;
- }
- #if ENABLED(SERIAL_STATS_DROPPED_RX)
- else if (!++rx_dropped_bytes) --rx_dropped_bytes;
- #endif
+ // Read the character from the USART
+ c = HWUART->UART_RHR;
- #if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
- const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
- // Calculate count of bytes stored into the RX buffer
+ if (Cfg::EMERGENCYPARSER) emergency_parser.update(emergency_state, c);
- // Keep track of the maximum count of enqueued bytes
- NOLESS(rx_max_enqueued, rx_count);
- #endif
-
- #if ENABLED(SERIAL_XON_XOFF)
- // If the last char that was sent was an XON
- if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XON_CHAR) {
-
- // Bytes stored into the RX buffer
- const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
-
- // 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 >= (RX_BUFFER_SIZE) / 8) {
-
- // 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.
-
- // About to send the XOFF char
- xon_xoff_state = XOFF_CHAR | XON_XOFF_CHAR_SENT;
-
- // 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!
- uint32_t status;
- while (!((status = HWUART->UART_SR) & UART_SR_TXRDY)) {
-
- if (status & UART_SR_RXRDY) {
- // We received a char while waiting for the TX buffer to be empty - Receive and process it!
-
- i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
-
- // Read the character from the USART
- c = HWUART->UART_RHR;
-
- #if ENABLED(EMERGENCY_PARSER)
- emergency_parser.update(emergency_state, c);
- #endif
-
- // 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;
- }
- #if ENABLED(SERIAL_STATS_DROPPED_RX)
- else if (!++rx_dropped_bytes) --rx_dropped_bytes;
- #endif
+ // 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;
}
-
- HWUART->UART_THR = XOFF_CHAR;
-
- // 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 (!((status = HWUART->UART_SR) & UART_SR_TXRDY)) {
-
- if (status & UART_SR_RXRDY) {
- // 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)(RX_BUFFER_SIZE - 1);
-
- // Read the character from the USART
- c = HWUART->UART_RHR;
-
- #if ENABLED(EMERGENCY_PARSER)
- emergency_parser.update(emergency_state, c);
- #endif
-
- // 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;
- }
- #if ENABLED(SERIAL_STATS_DROPPED_RX)
- else if (!++rx_dropped_bytes) --rx_dropped_bytes;
- #endif
- }
- 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();
}
- }
- #endif // SERIAL_XON_XOFF
- // Store the new head value
- rx_buffer.head = h;
+ HWUART->UART_THR = XOFF_CHAR;
+
+ // 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 (!((status = HWUART->UART_SR) & UART_SR_TXRDY)) {
+
+ if (status & UART_SR_RXRDY) {
+ // 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 = HWUART->UART_RHR;
+
+ 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!
+ }
+ }
}
- #if TX_BUFFER_SIZE > 0
+ // Store the new head value
+ rx_buffer.head = h;
+}
- FORCE_INLINE void _tx_thr_empty_irq(void) {
- // Read positions
- uint8_t t = tx_buffer.tail;
- const uint8_t h = tx_buffer.head;
+template
+FORCE_INLINE void MarlinSerial::_tx_thr_empty_irq(void) {
+ if (Cfg::TX_SIZE > 0) {
+ // Read positions
+ uint8_t t = tx_buffer.tail;
+ const uint8_t h = tx_buffer.head;
- #if ENABLED(SERIAL_XON_XOFF)
- // If an XON char is pending to be sent, do it now
- if (xon_xoff_state == XON_CHAR) {
+ if (Cfg::XONOFF) {
+ // If an XON char is pending to be sent, do it now
+ if (xon_xoff_state == XON_CHAR) {
- // Send the character
- HWUART->UART_THR = XON_CHAR;
+ // Send the character
+ HWUART->UART_THR = XON_CHAR;
- // Remember we sent it.
- xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
+ // Remember we sent it.
+ xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
- // If nothing else to transmit, just disable TX interrupts.
- if (h == t) HWUART->UART_IDR = UART_IDR_TXRDY;
+ // If nothing else to transmit, just disable TX interrupts.
+ if (h == t) HWUART->UART_IDR = UART_IDR_TXRDY;
- return;
- }
- #endif
-
- // 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) {
- HWUART->UART_IDR = UART_IDR_TXRDY;
return;
}
-
- // There is something to TX, Send the next byte
- const uint8_t c = tx_buffer.buffer[t];
- t = (t + 1) & (TX_BUFFER_SIZE - 1);
- HWUART->UART_THR = c;
- tx_buffer.tail = t;
-
- // Disable interrupts if there is nothing to transmit following this byte
- if (h == t) HWUART->UART_IDR = UART_IDR_TXRDY;
}
- #endif // TX_BUFFER_SIZE > 0
-
- static void UART_ISR(void) {
- const uint32_t status = HWUART->UART_SR;
-
- // Data received?
- if (status & UART_SR_RXRDY) store_rxd_char();
-
- #if TX_BUFFER_SIZE > 0
- // Something to send, and TX interrupts are enabled (meaning something to send)?
- if ((status & UART_SR_TXRDY) && (HWUART->UART_IMR & UART_IMR_TXRDY)) _tx_thr_empty_irq();
- #endif
-
- // Acknowledge errors
- if ((status & UART_SR_OVRE) || (status & UART_SR_FRAME)) {
-
- #if ENABLED(SERIAL_STATS_DROPPED_RX)
- if (status & UART_SR_OVRE && !++rx_dropped_bytes) --rx_dropped_bytes;
- #endif
-
- #if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
- if (status & UART_SR_OVRE && !++rx_buffer_overruns) --rx_buffer_overruns;
- #endif
-
- #if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
- if (status & UART_SR_FRAME && !++rx_framing_errors) --rx_framing_errors;
- #endif
-
- // TODO: error reporting outside ISR
- HWUART->UART_CR = UART_CR_RSTSTA;
+ // 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) {
+ HWUART->UART_IDR = UART_IDR_TXRDY;
+ 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);
+ HWUART->UART_THR = c;
+ tx_buffer.tail = t;
+
+ // Disable interrupts if there is nothing to transmit following this byte
+ if (h == t) HWUART->UART_IDR = UART_IDR_TXRDY;
+ }
+}
+
+template
+void MarlinSerial::UART_ISR(void) {
+ const uint32_t status = HWUART->UART_SR;
+
+ // Data received?
+ if (status & UART_SR_RXRDY) store_rxd_char();
+
+ if (Cfg::TX_SIZE > 0) {
+ // Something to send, and TX interrupts are enabled (meaning something to send)?
+ if ((status & UART_SR_TXRDY) && (HWUART->UART_IMR & UART_IMR_TXRDY)) _tx_thr_empty_irq();
}
- // Public Methods
+ // Acknowledge errors
+ if ((status & UART_SR_OVRE) || (status & UART_SR_FRAME)) {
+ if (Cfg::DROPPED_RX && (status & UART_SR_OVRE) && !++rx_dropped_bytes) --rx_dropped_bytes;
+ if (Cfg::RX_OVERRUNS && (status & UART_SR_OVRE) && !++rx_buffer_overruns) --rx_buffer_overruns;
+ if (Cfg::RX_FRAMING_ERRORS && (status & UART_SR_FRAME) && !++rx_framing_errors) --rx_framing_errors;
- void MarlinSerial::begin(const long baud_setting) {
-
- // Disable UART interrupt in NVIC
- NVIC_DisableIRQ( HWUART_IRQ );
-
- // We NEED memory barriers to ensure Interrupts are actually disabled!
- // ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
- __DSB();
- __ISB();
-
- // Disable clock
- pmc_disable_periph_clk( HWUART_IRQ_ID );
-
- // Configure PMC
- pmc_enable_periph_clk( HWUART_IRQ_ID );
-
- // Disable PDC channel
- HWUART->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS;
-
- // Reset and disable receiver and transmitter
- HWUART->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS;
-
- // Configure mode: 8bit, No parity, 1 bit stop
- HWUART->UART_MR = UART_MR_CHMODE_NORMAL | US_MR_CHRL_8_BIT | US_MR_NBSTOP_1_BIT | UART_MR_PAR_NO;
-
- // Configure baudrate (asynchronous, no oversampling)
- HWUART->UART_BRGR = (SystemCoreClock / (baud_setting << 4));
-
- // Configure interrupts
- HWUART->UART_IDR = 0xFFFFFFFF;
- HWUART->UART_IER = UART_IER_RXRDY | UART_IER_OVRE | UART_IER_FRAME;
-
- // Install interrupt handler
- install_isr(HWUART_IRQ, UART_ISR);
-
- // Configure priority. We need a very high priority to avoid losing characters
- // and we need to be able to preempt the Stepper ISR and everything else!
- // (this could probably be fixed by using DMA with the Serial port)
- NVIC_SetPriority(HWUART_IRQ, 1);
-
- // Enable UART interrupt in NVIC
- NVIC_EnableIRQ(HWUART_IRQ);
-
- // Enable receiver and transmitter
- HWUART->UART_CR = UART_CR_RXEN | UART_CR_TXEN;
-
- #if TX_BUFFER_SIZE > 0
- _written = false;
- #endif
+ // TODO: error reporting outside ISR
+ HWUART->UART_CR = UART_CR_RSTSTA;
}
+}
- void MarlinSerial::end() {
- // Disable UART interrupt in NVIC
- NVIC_DisableIRQ( HWUART_IRQ );
+// Public Methods
+template
+void MarlinSerial::begin(const long baud_setting) {
- // We NEED memory barriers to ensure Interrupts are actually disabled!
- // ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
- __DSB();
- __ISB();
+ // Disable UART interrupt in NVIC
+ NVIC_DisableIRQ( HWUART_IRQ );
- pmc_disable_periph_clk( HWUART_IRQ_ID );
- }
+ // We NEED memory barriers to ensure Interrupts are actually disabled!
+ // ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
+ __DSB();
+ __ISB();
- int MarlinSerial::peek(void) {
- const int v = rx_buffer.head == rx_buffer.tail ? -1 : rx_buffer.buffer[rx_buffer.tail];
- return v;
- }
+ // Disable clock
+ pmc_disable_periph_clk( HWUART_IRQ_ID );
- int MarlinSerial::read(void) {
+ // Configure PMC
+ pmc_enable_periph_clk( HWUART_IRQ_ID );
- const ring_buffer_pos_t h = rx_buffer.head;
- ring_buffer_pos_t t = rx_buffer.tail;
+ // Disable PDC channel
+ HWUART->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS;
- if (h == t) return -1;
+ // Reset and disable receiver and transmitter
+ HWUART->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS;
- int v = rx_buffer.buffer[t];
- t = (ring_buffer_pos_t)(t + 1) & (RX_BUFFER_SIZE - 1);
+ // Configure mode: 8bit, No parity, 1 bit stop
+ HWUART->UART_MR = UART_MR_CHMODE_NORMAL | US_MR_CHRL_8_BIT | US_MR_NBSTOP_1_BIT | UART_MR_PAR_NO;
- // Advance tail
- rx_buffer.tail = t;
+ // Configure baudrate (asynchronous, no oversampling)
+ HWUART->UART_BRGR = (SystemCoreClock / (baud_setting << 4));
- #if ENABLED(SERIAL_XON_XOFF)
- // 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)(RX_BUFFER_SIZE - 1);
- // When below 10% of RX buffer capacity, send XON before running out of RX buffer bytes
- if (rx_count < (RX_BUFFER_SIZE) / 10) {
- #if TX_BUFFER_SIZE > 0
- // Signal we want an XON character to be sent.
- xon_xoff_state = XON_CHAR;
- // Enable TX isr.
- HWUART->UART_IER = UART_IER_TXRDY;
- #else
- // If not using TX interrupts, we must send the XON char now
- xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
- while (!(HWUART->UART_SR & UART_SR_TXRDY)) sw_barrier();
- HWUART->UART_THR = XON_CHAR;
- #endif
- }
- }
- #endif
+ // Configure interrupts
+ HWUART->UART_IDR = 0xFFFFFFFF;
+ HWUART->UART_IER = UART_IER_RXRDY | UART_IER_OVRE | UART_IER_FRAME;
- return v;
- }
+ // Install interrupt handler
+ install_isr(HWUART_IRQ, UART_ISR);
- ring_buffer_pos_t MarlinSerial::available(void) {
- const ring_buffer_pos_t h = rx_buffer.head, t = rx_buffer.tail;
- return (ring_buffer_pos_t)(RX_BUFFER_SIZE + h - t) & (RX_BUFFER_SIZE - 1);
- }
+ // Configure priority. We need a very high priority to avoid losing characters
+ // and we need to be able to preempt the Stepper ISR and everything else!
+ // (this could probably be fixed by using DMA with the Serial port)
+ NVIC_SetPriority(HWUART_IRQ, 1);
- void MarlinSerial::flush(void) {
- rx_buffer.tail = rx_buffer.head;
+ // Enable UART interrupt in NVIC
+ NVIC_EnableIRQ(HWUART_IRQ);
- #if ENABLED(SERIAL_XON_XOFF)
- if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XOFF_CHAR) {
- #if TX_BUFFER_SIZE > 0
+ // Enable receiver and transmitter
+ HWUART->UART_CR = UART_CR_RXEN | UART_CR_TXEN;
+
+ if (Cfg::TX_SIZE > 0) _written = false;
+}
+
+template
+void MarlinSerial::end() {
+ // Disable UART interrupt in NVIC
+ NVIC_DisableIRQ( HWUART_IRQ );
+
+ // We NEED memory barriers to ensure Interrupts are actually disabled!
+ // ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
+ __DSB();
+ __ISB();
+
+ pmc_disable_periph_clk( HWUART_IRQ_ID );
+}
+
+template
+int MarlinSerial::peek(void) {
+ const int v = rx_buffer.head == rx_buffer.tail ? -1 : rx_buffer.buffer[rx_buffer.tail];
+ return v;
+}
+
+template
+int MarlinSerial::read(void) {
+
+ const ring_buffer_pos_t h = rx_buffer.head;
+ ring_buffer_pos_t t = rx_buffer.tail;
+
+ if (h == t) return -1;
+
+ int v = rx_buffer.buffer[t];
+ t = (ring_buffer_pos_t)(t + 1) & (Cfg::RX_SIZE - 1);
+
+ // Advance tail
+ rx_buffer.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);
+ // When below 10% of RX buffer capacity, send XON before running out of RX buffer bytes
+ 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.
HWUART->UART_IER = UART_IER_TXRDY;
- #else
+ }
+ else {
// If not using TX interrupts, we must send the XON char now
xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
while (!(HWUART->UART_SR & UART_SR_TXRDY)) sw_barrier();
HWUART->UART_THR = XON_CHAR;
- #endif
+ }
}
- #endif
+ }
}
- #if TX_BUFFER_SIZE > 0
- void MarlinSerial::write(const uint8_t c) {
- _written = true;
+ return v;
+}
- // 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 (!(HWUART->UART_IMR & UART_IMR_TXRDY) && (HWUART->UART_SR & UART_SR_TXRDY)) {
- HWUART->UART_THR = c;
- return;
- }
+template
+typename MarlinSerial::ring_buffer_pos_t MarlinSerial::available(void) {
+ const ring_buffer_pos_t h = rx_buffer.head, t = rx_buffer.tail;
+ return (ring_buffer_pos_t)(Cfg::RX_SIZE + h - t) & (Cfg::RX_SIZE - 1);
+}
- const uint8_t i = (tx_buffer.head + 1) & (TX_BUFFER_SIZE - 1);
+template
+void MarlinSerial::flush(void) {
+ rx_buffer.tail = rx_buffer.head;
- // 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 (HWUART->UART_SR & UART_SR_TXRDY) _tx_thr_empty_irq();
- // Make sure compiler rereads tx_buffer.tail
- sw_barrier();
- }
+ if (Cfg::XONOFF) {
+ 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.
+ HWUART->UART_IER = UART_IER_TXRDY;
}
else {
- // Interrupts are enabled, just wait until there is space
- while (i == tx_buffer.tail) sw_barrier();
+ // If not using TX interrupts, we must send the XON char now
+ xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
+ while (!(HWUART->UART_SR & UART_SR_TXRDY)) sw_barrier();
+ HWUART->UART_THR = XON_CHAR;
}
-
- // 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
- HWUART->UART_IER = UART_IER_TXRDY;
}
+ }
+}
- void MarlinSerial::flushTX(void) {
- // TX
+template
+void MarlinSerial::write(const uint8_t c) {
+ _written = true;
- // If we have never written a byte, no need to flush. This special
- // case is needed since there is no way to force the TXC (transmit
- // complete) bit to 1 during initialization
- if (!_written) return;
+ if (Cfg::TX_SIZE == 0) {
+ while (!(HWUART->UART_SR & UART_SR_TXRDY)) sw_barrier();
+ HWUART->UART_THR = c;
+ }
+ else {
- // 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 || !(HWUART->UART_SR & UART_SR_TXEMPTY)) {
- // If there is more space, send an extra character
- if (HWUART->UART_SR & UART_SR_TXRDY) _tx_thr_empty_irq();
- sw_barrier();
- }
-
- }
- else {
- // Wait until everything was transmitted
- while (tx_buffer.head != tx_buffer.tail || !(HWUART->UART_SR & UART_SR_TXEMPTY)) sw_barrier();
- }
-
- // At this point nothing is queued anymore (DRIE is disabled) and
- // the hardware finished transmission (TXC is set).
- }
-
- #else // TX_BUFFER_SIZE == 0
-
- void MarlinSerial::write(const uint8_t c) {
- _written = true;
- while (!(HWUART->UART_SR & UART_SR_TXRDY)) sw_barrier();
+ // 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 (!(HWUART->UART_IMR & UART_IMR_TXRDY) && (HWUART->UART_SR & UART_SR_TXRDY)) {
HWUART->UART_THR = c;
+ return;
}
- void MarlinSerial::flushTX(void) {
- // TX
+ const uint8_t i = (tx_buffer.head + 1) & (Cfg::TX_SIZE - 1);
- // 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()) {
+ // 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 (HWUART->UART_SR & UART_SR_TXRDY) _tx_thr_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
+ HWUART->UART_IER = UART_IER_TXRDY;
+ }
+}
+
+template
+void MarlinSerial::flushTX(void) {
+ // TX
+
+ 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 (!(HWUART->UART_SR & UART_SR_TXEMPTY)) sw_barrier();
+
+ // At this point nothing is queued anymore (DRIE is disabled) and
+ // the hardware finished transmission (TXC is set).
+
+ }
+ else {
+ // If we have never written a byte, no need to flush. This special
+ // case is needed since there is 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 || !(HWUART->UART_SR & UART_SR_TXEMPTY)) {
+ // If there is more space, send an extra character
+ if (HWUART->UART_SR & UART_SR_TXRDY) _tx_thr_empty_irq();
+ sw_barrier();
+ }
+
+ }
+ else {
// Wait until everything was transmitted
- while (!(HWUART->UART_SR & UART_SR_TXEMPTY)) sw_barrier();
-
- // At this point nothing is queued anymore (DRIE is disabled) and
- // the hardware finished transmission (TXC is set).
- }
- #endif // TX_BUFFER_SIZE == 0
-
- /**
- * Imports from print.h
- */
-
- void MarlinSerial::print(char c, int base) {
- print((long)c, base);
- }
-
- void MarlinSerial::print(unsigned char b, int base) {
- print((unsigned long)b, base);
- }
-
- void MarlinSerial::print(int n, int base) {
- print((long)n, base);
- }
-
- void MarlinSerial::print(unsigned int n, int base) {
- print((unsigned long)n, base);
- }
-
- 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);
- }
-
- void MarlinSerial::print(unsigned long n, int base) {
- if (base == 0) write(n);
- else printNumber(n, base);
- }
-
- void MarlinSerial::print(double n, int digits) {
- printFloat(n, digits);
- }
-
- void MarlinSerial::println(void) {
- print('\r');
- print('\n');
- }
-
- void MarlinSerial::println(const String& s) {
- print(s);
- println();
- }
-
- void MarlinSerial::println(const char c[]) {
- print(c);
- println();
- }
-
- void MarlinSerial::println(char c, int base) {
- print(c, base);
- println();
- }
-
- void MarlinSerial::println(unsigned char b, int base) {
- print(b, base);
- println();
- }
-
- void MarlinSerial::println(int n, int base) {
- print(n, base);
- println();
- }
-
- void MarlinSerial::println(unsigned int n, int base) {
- print(n, base);
- println();
- }
-
- void MarlinSerial::println(long n, int base) {
- print(n, base);
- println();
- }
-
- void MarlinSerial::println(unsigned long n, int base) {
- print(n, base);
- println();
- }
-
- void MarlinSerial::println(double n, int digits) {
- print(n, digits);
- println();
- }
-
- // Private Methods
-
- 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');
- }
-
- 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 || !(HWUART->UART_SR & UART_SR_TXEMPTY)) sw_barrier();
}
- // Round correctly so that print(1.999, 2) prints as "2.00"
- double rounding = 0.5;
- for (uint8_t i = 0; i < digits; ++i) 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(void) {
+ 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;
+ for (uint8_t i = 0; i < digits; ++i) rounding *= 0.1;
+ number += rounding;
+
+ // Extract the integer part of the number and print it
+ unsigned long int_part = (unsigned long)number;
+ double remainder = number - (double)int_part;
+ print(int_part);
+
+ // Print the decimal point, but only if there are digits beyond
+ if (digits) {
+ print('.');
+ // Extract digits from the remainder one at a time
+ while (digits--) {
+ remainder *= 10.0;
+ int toPrint = int(remainder);
+ print(toPrint);
+ remainder -= toPrint;
}
}
+}
+
+// If not using the USB port as serial port
+#if SERIAL_PORT >= 0
// Preinstantiate
- MarlinSerial customizedSerial;
+ template class MarlinSerial>;
+
+ // Instantiate
+ MarlinSerial> customizedSerial1;
+
+#endif
+
+#ifdef SERIAL_PORT_2
+
+ // Preinstantiate
+ template class MarlinSerial>;
+
+ // Instantiate
+ MarlinSerial> customizedSerial2;
+
#endif
#endif // ARDUINO_ARCH_SAM
diff --git a/Marlin/src/HAL/HAL_DUE/MarlinSerial_Due.h b/Marlin/src/HAL/HAL_DUE/MarlinSerial_Due.h
index 2f5a07f515..1fe0d236ee 100644
--- a/Marlin/src/HAL/HAL_DUE/MarlinSerial_Due.h
+++ b/Marlin/src/HAL/HAL_DUE/MarlinSerial_Due.h
@@ -19,6 +19,7 @@
* along with this program. If not, see .
*
*/
+#pragma once
/**
* MarlinSerial_Due.h - Hardware serial library for Arduino DUE
@@ -26,12 +27,7 @@
* Based on MarlinSerial for AVR, copyright (c) 2006 Nicholas Zambetti. All right reserved.
*/
-#ifndef MARLINSERIAL_DUE_H
-#define MARLINSERIAL_DUE_H
-
-#include "../../inc/MarlinConfig.h"
-
-#if SERIAL_PORT >= 0
+#include "../shared/MarlinSerial.h"
#include
@@ -60,29 +56,60 @@
// #error "TX_BUFFER_SIZE must be 0, a power of 2 greater than 1, and no greater than 256."
//#endif
-#if RX_BUFFER_SIZE > 256
- typedef uint16_t ring_buffer_pos_t;
-#else
- typedef uint8_t ring_buffer_pos_t;
-#endif
+// Templated type selector
+template struct TypeSelector { typedef T type;} ;
+template struct TypeSelector { typedef F type; };
-#if ENABLED(SERIAL_STATS_DROPPED_RX)
- extern uint8_t rx_dropped_bytes;
-#endif
-
-#if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
- extern uint8_t rx_buffer_overruns;
-#endif
-
-#if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
- extern uint8_t rx_framing_errors;
-#endif
-
-#if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
- extern ring_buffer_pos_t rx_max_enqueued;
-#endif
+// Templated structure wrapper
+template struct StructWrapper {
+ constexpr StructWrapper(int) {}
+ FORCE_INLINE S* operator->() const { return (S*)addr; }
+};
+template
class MarlinSerial {
+protected:
+ // Information for all supported UARTs
+ static constexpr uint32_t BASES[] = {0x400E0800U, 0x40098000U, 0x4009C000U, 0x400A0000U, 0x400A4000U};
+ static constexpr IRQn_Type IRQS[] = { UART_IRQn, USART0_IRQn, USART1_IRQn, USART2_IRQn, USART3_IRQn};
+ static constexpr int IRQ_IDS[] = { ID_UART, ID_USART0, ID_USART1, ID_USART2, ID_USART3};
+
+ // Alias for shorter code
+ static constexpr StructWrapper HWUART = 0;
+ static constexpr IRQn_Type HWUART_IRQ = IRQS[Cfg::PORT];
+ static constexpr int HWUART_IRQ_ID = IRQ_IDS[Cfg::PORT];
+
+ // Base size of type on buffer size
+ typedef typename TypeSelector<(Cfg::RX_SIZE>256), uint16_t, uint8_t>::type ring_buffer_pos_t;
+
+ struct ring_buffer_r {
+ volatile ring_buffer_pos_t head, tail;
+ unsigned char buffer[Cfg::RX_SIZE];
+ };
+
+ struct ring_buffer_t {
+ volatile uint8_t head, tail;
+ unsigned char buffer[Cfg::TX_SIZE];
+ };
+
+ static ring_buffer_r rx_buffer;
+ static ring_buffer_t tx_buffer;
+ static bool _written;
+
+ static constexpr uint8_t XON_XOFF_CHAR_SENT = 0x80, // XON / XOFF Character was sent
+ XON_XOFF_CHAR_MASK = 0x1F; // XON / XOFF character to send
+
+ // XON / XOFF character definitions
+ static constexpr uint8_t XON_CHAR = 17, XOFF_CHAR = 19;
+ static uint8_t xon_xoff_state,
+ rx_dropped_bytes,
+ rx_buffer_overruns,
+ rx_framing_errors;
+ static ring_buffer_pos_t rx_max_enqueued;
+
+ FORCE_INLINE static void store_rxd_char();
+ FORCE_INLINE static void _tx_thr_empty_irq(void);
+ static void UART_ISR(void);
public:
MarlinSerial() {};
@@ -95,21 +122,10 @@ public:
static void write(const uint8_t c);
static void flushTX(void);
- #if ENABLED(SERIAL_STATS_DROPPED_RX)
- FORCE_INLINE static uint32_t dropped() { return rx_dropped_bytes; }
- #endif
-
- #if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
- FORCE_INLINE static uint32_t buffer_overruns() { return rx_buffer_overruns; }
- #endif
-
- #if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
- FORCE_INLINE static uint32_t framing_errors() { return rx_framing_errors; }
- #endif
-
- #if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
- FORCE_INLINE static ring_buffer_pos_t rxMaxEnqueued() { return rx_max_enqueued; }
- #endif
+ FORCE_INLINE static uint8_t dropped() { return Cfg::DROPPED_RX ? rx_dropped_bytes : 0; }
+ FORCE_INLINE static uint8_t buffer_overruns() { return Cfg::RX_OVERRUNS ? rx_buffer_overruns : 0; }
+ FORCE_INLINE static uint8_t framing_errors() { return Cfg::RX_FRAMING_ERRORS ? rx_framing_errors : 0; }
+ FORCE_INLINE static ring_buffer_pos_t rxMaxEnqueued() { return Cfg::MAX_RX_QUEUED ? rx_max_enqueued : 0; }
FORCE_INLINE static void write(const char* str) { while (*str) write(*str++); }
FORCE_INLINE static void write(const uint8_t* buffer, size_t size) { while (size--) write(*buffer++); }
@@ -141,8 +157,28 @@ private:
static void printFloat(double, uint8_t);
};
-extern MarlinSerial customizedSerial;
+// Serial port configuration
+template
+struct MarlinSerialCfg {
+ static constexpr int PORT = serial;
+ static constexpr unsigned int RX_SIZE = RX_BUFFER_SIZE;
+ static constexpr unsigned int TX_SIZE = TX_BUFFER_SIZE;
+ static constexpr bool XONOFF = bSERIAL_XON_XOFF;
+ static constexpr bool EMERGENCYPARSER = bEMERGENCY_PARSER;
+ static constexpr bool DROPPED_RX = bSERIAL_STATS_DROPPED_RX;
+ static constexpr bool RX_OVERRUNS = bSERIAL_STATS_RX_BUFFER_OVERRUNS;
+ static constexpr bool RX_FRAMING_ERRORS = bSERIAL_STATS_RX_FRAMING_ERRORS;
+ static constexpr bool MAX_RX_QUEUED = bSERIAL_STATS_MAX_RX_QUEUED;
+};
+
+#if SERIAL_PORT >= 0
+
+ extern MarlinSerial> customizedSerial1;
#endif // SERIAL_PORT >= 0
-#endif // MARLINSERIAL_DUE_H
+#ifdef SERIAL_PORT_2
+
+ extern MarlinSerial> customizedSerial2;
+
+#endif
diff --git a/Marlin/src/HAL/HAL_DUE/Servo_Due.cpp b/Marlin/src/HAL/HAL_DUE/Servo_Due.cpp
index d2207d91aa..db1b3e39ba 100644
--- a/Marlin/src/HAL/HAL_DUE/Servo_Due.cpp
+++ b/Marlin/src/HAL/HAL_DUE/Servo_Due.cpp
@@ -76,14 +76,14 @@ void Servo_Handler(timer16_Sequence_t timer, Tc *tc, uint8_t channel) {
tc->TC_CHANNEL[channel].TC_SR;
if (Channel[timer] < 0)
tc->TC_CHANNEL[channel].TC_CCR |= TC_CCR_SWTRG; // channel set to -1 indicated that refresh interval completed so reset the timer
- else if (SERVO_INDEX(timer,Channel[timer]) < ServoCount && SERVO(timer,Channel[timer]).Pin.isActive)
- digitalWrite(SERVO(timer,Channel[timer]).Pin.nbr, LOW); // pulse this channel low if activated
+ else if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && SERVO(timer, Channel[timer]).Pin.isActive)
+ digitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, LOW); // pulse this channel low if activated
Channel[timer]++; // increment to the next channel
if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) {
tc->TC_CHANNEL[channel].TC_RA = tc->TC_CHANNEL[channel].TC_CV + SERVO(timer,Channel[timer]).ticks;
if (SERVO(timer,Channel[timer]).Pin.isActive) // check if activated
- digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,HIGH); // its an active channel so pulse it high
+ digitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, HIGH); // its an active channel so pulse it high
}
else {
// finished all channels so wait for the refresh period to expire before starting over
diff --git a/Marlin/src/HAL/HAL_DUE/Tone.cpp b/Marlin/src/HAL/HAL_DUE/Tone.cpp
index 55c03f5e58..ff522fa3ab 100644
--- a/Marlin/src/HAL/HAL_DUE/Tone.cpp
+++ b/Marlin/src/HAL/HAL_DUE/Tone.cpp
@@ -27,6 +27,7 @@
#ifdef ARDUINO_ARCH_SAM
+#include "../../inc/MarlinConfig.h"
#include "HAL.h"
#include "HAL_timers_Due.h"
diff --git a/Marlin/src/HAL/HAL_DUE/endstop_interrupts.h b/Marlin/src/HAL/HAL_DUE/endstop_interrupts.h
index a5c0df61bf..d026abfea6 100644
--- a/Marlin/src/HAL/HAL_DUE/endstop_interrupts.h
+++ b/Marlin/src/HAL/HAL_DUE/endstop_interrupts.h
@@ -19,6 +19,7 @@
* along with this program. If not, see .
*
*/
+#pragma once
/**
* Endstop Interrupts
@@ -34,9 +35,6 @@
* (Located in Marlin/buildroot/share/pin_interrupt_test/pin_interrupt_test.ino)
*/
-#ifndef _ENDSTOP_INTERRUPTS_H_
-#define _ENDSTOP_INTERRUPTS_H_
-
#include "../../module/endstops.h"
// One ISR for all EXT-Interrupts
@@ -82,5 +80,3 @@ void setup_endstop_interrupts(void) {
attachInterrupt(digitalPinToInterrupt(Z_MIN_PROBE_PIN), endstop_ISR, CHANGE);
#endif
}
-
-#endif //_ENDSTOP_INTERRUPTS_H_
diff --git a/Marlin/src/HAL/HAL_DUE/fastio_Due.h b/Marlin/src/HAL/HAL_DUE/fastio_Due.h
index bb25f45174..cb713122e7 100644
--- a/Marlin/src/HAL/HAL_DUE/fastio_Due.h
+++ b/Marlin/src/HAL/HAL_DUE/fastio_Due.h
@@ -19,6 +19,7 @@
* along with this program. If not, see .
*
*/
+#pragma once
/**
* Fast I/O Routines for SAM3X8E
@@ -36,9 +37,6 @@
* leads to less efficient compiled code!!
*/
-#ifndef _FASTIO_DUE_H
-#define _FASTIO_DUE_H
-
#include
/**
@@ -47,7 +45,7 @@
// Due has 12 PWMs assigned to logical pins 2-13.
// 6, 7, 8 & 9 come from the PWM controller. The others come from the timers.
-#define USEABLE_HARDWARE_PWM(p) ((2 <= p) && (p <= 13))
+#define USEABLE_HARDWARE_PWM(p) WITHIN(p, 2, 13)
#ifndef MASK
#define MASK(PIN) (1 << PIN)
@@ -467,6 +465,9 @@
#define DIO107_PIN 10
#define DIO107_WPORT PIOB
+
+ #define DIO108_PIN 9
+ #define DIO108_WPORT PIOB
#else
#define DIO92_PIN 5
#define DIO92_WPORT PIOA
@@ -495,5 +496,3 @@
#define DIO100_PIN 11
#define DIO100_WPORT PIOC
#endif
-
-#endif // _FASTIO_DUE_H
diff --git a/Marlin/src/HAL/HAL_DUE/persistent_store_eeprom.cpp b/Marlin/src/HAL/HAL_DUE/persistent_store_eeprom.cpp
index fa611111d0..e7ff4f9c81 100644
--- a/Marlin/src/HAL/HAL_DUE/persistent_store_eeprom.cpp
+++ b/Marlin/src/HAL/HAL_DUE/persistent_store_eeprom.cpp
@@ -67,7 +67,7 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
bool PersistentStore::read_data(int &pos, uint8_t* value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
do {
- uint8_t c = eeprom_read_byte((unsigned char*)pos);
+ uint8_t c = eeprom_read_byte((uint8_t*)pos);
if (writing) *value = c;
crc16(crc, &c, 1);
pos++;
diff --git a/Marlin/src/HAL/HAL_DUE/spi_pins.h b/Marlin/src/HAL/HAL_DUE/spi_pins.h
index d0eb711df2..8f4f987155 100644
--- a/Marlin/src/HAL/HAL_DUE/spi_pins.h
+++ b/Marlin/src/HAL/HAL_DUE/spi_pins.h
@@ -19,9 +19,7 @@
* along with this program. If not, see .
*
*/
-
-#ifndef SPI_PINS_H_
-#define SPI_PINS_H_
+#pragma once
/**
* Define SPI Pins: SCK, MISO, MOSI, SS
@@ -48,12 +46,16 @@
#else
// defaults
#define DUE_SOFTWARE_SPI
- #define SCK_PIN 52
- #define MISO_PIN 50
- #define MOSI_PIN 51
+ #ifndef SCK_PIN
+ #define SCK_PIN 52
+ #endif
+ #ifndef MISO_PIN
+ #define MISO_PIN 50
+ #endif
+ #ifndef MOSI_PIN
+ #define MOSI_PIN 51
+ #endif
#endif
/* A.28, A.29, B.21, C.26, C.29 */
#define SS_PIN SDSS
-
-#endif /* SPI_PINS_H_ */
diff --git a/Marlin/src/HAL/HAL_DUE/u8g_com_HAL_DUE_shared_hw_spi.cpp b/Marlin/src/HAL/HAL_DUE/u8g_com_HAL_DUE_shared_hw_spi.cpp
index 0dab3bb412..c62f6a06ec 100644
--- a/Marlin/src/HAL/HAL_DUE/u8g_com_HAL_DUE_shared_hw_spi.cpp
+++ b/Marlin/src/HAL/HAL_DUE/u8g_com_HAL_DUE_shared_hw_spi.cpp
@@ -60,7 +60,7 @@
#include "../../inc/MarlinConfigPre.h"
-#if ENABLED(DOGLCD)
+#if HAS_GRAPHICAL_LCD
#include
@@ -94,10 +94,8 @@ void u8g_SetPILevel_DUE_hw_spi(u8g_t *u8g, uint8_t pin_index, uint8_t level) {
else port->PIO_CODR = mask;
}
-uint8_t u8g_com_HAL_DUE_shared_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr)
-{
- switch(msg)
- {
+uint8_t u8g_com_HAL_DUE_shared_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
+ switch(msg) {
case U8G_COM_MSG_STOP:
break;
@@ -156,6 +154,6 @@ uint8_t u8g_com_HAL_DUE_shared_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_va
return 1;
}
-#endif // DOGLCD
+#endif // HAS_GRAPHICAL_LCD
-#endif //__SAM3X8E__
+#endif //__SAM3X8E__
diff --git a/Marlin/src/HAL/HAL_DUE/u8g_com_HAL_DUE_st7920_sw_spi.cpp b/Marlin/src/HAL/HAL_DUE/u8g_com_HAL_DUE_st7920_sw_spi.cpp
index 243033e68b..968f63241c 100644
--- a/Marlin/src/HAL/HAL_DUE/u8g_com_HAL_DUE_st7920_sw_spi.cpp
+++ b/Marlin/src/HAL/HAL_DUE/u8g_com_HAL_DUE_st7920_sw_spi.cpp
@@ -57,7 +57,7 @@
#include "../../inc/MarlinConfigPre.h"
-#if ENABLED(DOGLCD)
+#if HAS_GRAPHICAL_LCD
#include
#include
@@ -180,6 +180,6 @@ uint8_t u8g_com_HAL_DUE_ST7920_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_va
return 1;
}
-#endif // DOGLCD
+#endif // HAS_GRAPHICAL_LCD
#endif // ARDUINO_ARCH_SAM
diff --git a/Marlin/src/HAL/HAL_DUE/usb/arduino_due_x.h b/Marlin/src/HAL/HAL_DUE/usb/arduino_due_x.h
index c1434228cd..7355f74f6d 100644
--- a/Marlin/src/HAL/HAL_DUE/usb/arduino_due_x.h
+++ b/Marlin/src/HAL/HAL_DUE/usb/arduino_due_x.h
@@ -40,15 +40,12 @@
* \asf_license_stop
*
*/
-/*
+#pragma once
+
+/**
* Support and FAQ: visit Atmel Support
*/
-#ifndef ARDUINO_DUE_X_H_INCLUDED
-#define ARDUINO_DUE_X_H_INCLUDED
-
-/* ------------------------------------------------------------------------ */
-
/**
* \page arduino_due_x_opfreq "Arduino Due/X - Operating frequencies"
* This page lists several definition related to the board operating frequency
@@ -98,6 +95,3 @@
/*! Active level of the USB_VBOF output pin. */
#define USB_VBOF_ACTIVE_LEVEL LOW
/* ------------------------------------------------------------------------ */
-
-
-#endif /* ARDUINO_DUE_X_H_INCLUDED */
diff --git a/Marlin/src/HAL/HAL_DUE/usb/compiler.h b/Marlin/src/HAL/HAL_DUE/usb/compiler.h
index 43895381a2..d9ecd3f0fe 100644
--- a/Marlin/src/HAL/HAL_DUE/usb/compiler.h
+++ b/Marlin/src/HAL/HAL_DUE/usb/compiler.h
@@ -105,7 +105,7 @@
* \brief Marking \a v as a unused parameter or value.
*/
#ifndef UNUSED
-#define UNUSED(x) (void) (x)
+ #define UNUSED(x) ((void)(x))
#endif
/**
diff --git a/Marlin/src/HAL/HAL_DUE/usb/conf_usb.h b/Marlin/src/HAL/HAL_DUE/usb/conf_usb.h
index 604fd2019b..6934494e57 100644
--- a/Marlin/src/HAL/HAL_DUE/usb/conf_usb.h
+++ b/Marlin/src/HAL/HAL_DUE/usb/conf_usb.h
@@ -49,10 +49,10 @@
#undef UNUSED /* To avoid a macro clash as macros.h already defines it */
#include "../../../core/macros.h" /* For ENABLED()/DISABLED() */
+#include "../../../core/boards.h" /* For MB() */
#include "../../../../Configuration.h" /* For CUSTOM_MACHINE_NAME definition - We just need the name, no C++ allowed! */
#include "compiler.h"
-
/**
* USB Device Configuration
* @{
@@ -89,7 +89,11 @@
//#define USB_DEVICE_LOW_SPEED
//! To define a Full speed device
-//#define USB_DEVICE_FULL_SPEED
+//#define USB_DEVICE_FULL_SPEED
+
+#if MB(ARCHIM1)
+ #define USB_DEVICE_FULL_SPEED
+#endif
//! To authorize the High speed
#ifndef USB_DEVICE_FULL_SPEED
diff --git a/Marlin/src/HAL/HAL_DUE/usb/sd_mmc_spi_mem.cpp b/Marlin/src/HAL/HAL_DUE/usb/sd_mmc_spi_mem.cpp
index 4de46104e2..cdb81b2489 100644
--- a/Marlin/src/HAL/HAL_DUE/usb/sd_mmc_spi_mem.cpp
+++ b/Marlin/src/HAL/HAL_DUE/usb/sd_mmc_spi_mem.cpp
@@ -19,15 +19,17 @@ void sd_mmc_spi_mem_init(void) {
}
Ctrl_status sd_mmc_spi_test_unit_ready(void) {
- if (!IS_SD_INSERTED || IS_SD_PRINTING || IS_SD_FILE_OPEN || !card.cardOK)
+ if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.flag.cardOK)
return CTRL_NO_PRESENT;
return CTRL_GOOD;
}
+// NOTE: This function is defined as returning the address of the last block
+// in the card, which is cardSize() - 1
Ctrl_status sd_mmc_spi_read_capacity(uint32_t *nb_sector) {
- if (!IS_SD_INSERTED || IS_SD_PRINTING || IS_SD_FILE_OPEN || !card.cardOK)
+ if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.flag.cardOK)
return CTRL_NO_PRESENT;
- *nb_sector = card.getSd2Card().cardSize();
+ *nb_sector = card.getSd2Card().cardSize() - 1;
return CTRL_GOOD;
}
@@ -40,7 +42,7 @@ bool sd_mmc_spi_wr_protect(void) {
}
bool sd_mmc_spi_removal(void) {
- if (!IS_SD_INSERTED || IS_SD_PRINTING || IS_SD_FILE_OPEN || !card.cardOK)
+ if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.flag.cardOK)
return true;
return false;
}
@@ -59,7 +61,7 @@ uint8_t sector_buf[SD_MMC_BLOCK_SIZE];
// #define DEBUG_MMC
Ctrl_status sd_mmc_spi_usb_read_10(uint32_t addr, uint16_t nb_sector) {
- if (!IS_SD_INSERTED || IS_SD_PRINTING || IS_SD_FILE_OPEN || !card.cardOK)
+ if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.flag.cardOK)
return CTRL_NO_PRESENT;
#ifdef DEBUG_MMC
@@ -93,7 +95,7 @@ Ctrl_status sd_mmc_spi_usb_read_10(uint32_t addr, uint16_t nb_sector) {
}
Ctrl_status sd_mmc_spi_usb_write_10(uint32_t addr, uint16_t nb_sector) {
- if (!IS_SD_INSERTED || IS_SD_PRINTING || IS_SD_FILE_OPEN || !card.cardOK)
+ if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.flag.cardOK)
return CTRL_NO_PRESENT;
#ifdef DEBUG_MMC
diff --git a/Marlin/src/HAL/HAL_DUE/watchdog_Due.h b/Marlin/src/HAL/HAL_DUE/watchdog_Due.h
index 57120309a3..c75875e2ea 100644
--- a/Marlin/src/HAL/HAL_DUE/watchdog_Due.h
+++ b/Marlin/src/HAL/HAL_DUE/watchdog_Due.h
@@ -19,9 +19,7 @@
* along with this program. If not, see .
*
*/
-
-#ifndef WATCHDOG_DUE_H
-#define WATCHDOG_DUE_H
+#pragma once
// Arduino Due core now has watchdog support
@@ -33,5 +31,3 @@ void watchdog_init();
// Reset watchdog. MUST be called at least every 4 seconds after the
// first watchdog_init or AVR will go into emergency procedures.
inline void watchdog_reset() { watchdogReset(); }
-
-#endif // WATCHDOG_DUE_H
diff --git a/Marlin/src/HAL/HAL_ESP32/HAL.h b/Marlin/src/HAL/HAL_ESP32/HAL.h
index 106299295a..a9f9afbffc 100644
--- a/Marlin/src/HAL/HAL_ESP32/HAL.h
+++ b/Marlin/src/HAL/HAL_ESP32/HAL.h
@@ -16,14 +16,12 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
+#pragma once
/**
* Description: HAL for Espressif ESP32 WiFi
*/
-#ifndef _HAL_ESP32_H
-#define _HAL_ESP32_H
-
#define CPU_32_BIT
// --------------------------------------------------------------------------
@@ -98,8 +96,8 @@ int freeMemory(void);
void analogWrite(int pin, int value);
// EEPROM
-void eeprom_write_byte(unsigned char *pos, unsigned char value);
-unsigned char eeprom_read_byte(unsigned char *pos);
+void eeprom_write_byte(uint8_t *pos, unsigned char value);
+uint8_t eeprom_read_byte(uint8_t *pos);
void eeprom_read_block (void *__dst, const void *__src, size_t __n);
void eeprom_update_block (const void *__src, void *__dst, size_t __n);
@@ -123,5 +121,3 @@ void HAL_adc_start_conversion (uint8_t adc_pin);
#define HAL_INIT 1
void HAL_idletask(void);
void HAL_init(void);
-
-#endif // _HAL_ESP32_H
diff --git a/Marlin/src/HAL/HAL_ESP32/HAL_timers_ESP32.h b/Marlin/src/HAL/HAL_ESP32/HAL_timers_ESP32.h
index a2d0c0b6db..e8afd83bb8 100644
--- a/Marlin/src/HAL/HAL_ESP32/HAL_timers_ESP32.h
+++ b/Marlin/src/HAL/HAL_ESP32/HAL_timers_ESP32.h
@@ -19,9 +19,7 @@
* along with this program. If not, see .
*
*/
-
-#ifndef _HAL_TIMERS_ESP32_H
-#define _HAL_TIMERS_ESP32_H
+#pragma once
// --------------------------------------------------------------------------
// Includes
@@ -104,5 +102,3 @@ bool HAL_timer_interrupt_enabled(const uint8_t timer_num);
#define HAL_timer_isr_prologue(TIMER_NUM)
#define HAL_timer_isr_epilogue(TIMER_NUM)
-
-#endif // _HAL_TIMERS_ESP32_H
diff --git a/Marlin/src/HAL/HAL_ESP32/endstop_interrupts.h b/Marlin/src/HAL/HAL_ESP32/endstop_interrupts.h
index bcc32db19a..9a325f30a7 100644
--- a/Marlin/src/HAL/HAL_ESP32/endstop_interrupts.h
+++ b/Marlin/src/HAL/HAL_ESP32/endstop_interrupts.h
@@ -19,6 +19,7 @@
* along with this program. If not, see .
*
*/
+#pragma once
/**
* Endstop Interrupts
@@ -34,9 +35,6 @@
* (Located in Marlin/buildroot/share/pin_interrupt_test/pin_interrupt_test.ino)
*/
-#ifndef _ENDSTOP_INTERRUPTS_H_
-#define _ENDSTOP_INTERRUPTS_H_
-
#include "../../module/endstops.h"
// One ISR for all EXT-Interrupts
@@ -77,5 +75,3 @@ void setup_endstop_interrupts(void) {
attachInterrupt(digitalPinToInterrupt(Z_MIN_PROBE_PIN), endstop_ISR, CHANGE);
#endif
}
-
-#endif //_ENDSTOP_INTERRUPTS_H_
diff --git a/Marlin/src/HAL/HAL_ESP32/fastio_ESP32.h b/Marlin/src/HAL/HAL_ESP32/fastio_ESP32.h
index 5f609c4f0c..8459a151cc 100644
--- a/Marlin/src/HAL/HAL_ESP32/fastio_ESP32.h
+++ b/Marlin/src/HAL/HAL_ESP32/fastio_ESP32.h
@@ -19,9 +19,7 @@
* along with this program. If not, see .
*
*/
-
-#ifndef _FASTIO_ESP32_H
-#define _FASTIO_ESP32_H
+#pragma once
/**
* Utility functions
@@ -64,9 +62,3 @@
// TWI (I2C)
#define SCL 5
#define SDA 4
-
-//
-// pins
-//
-
-#endif // _FASTIO_ESP32_H
diff --git a/Marlin/src/HAL/HAL_ESP32/ota.h b/Marlin/src/HAL/HAL_ESP32/ota.h
index 4af2a74cab..0fa33b532e 100644
--- a/Marlin/src/HAL/HAL_ESP32/ota.h
+++ b/Marlin/src/HAL/HAL_ESP32/ota.h
@@ -16,11 +16,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-
-#ifndef _HAL_OTA_H
-#define _HAL_OTA_H
+#pragma once
void OTA_init();
void OTA_handle();
-
-#endif
diff --git a/Marlin/src/HAL/HAL_ESP32/spi_pins.h b/Marlin/src/HAL/HAL_ESP32/spi_pins.h
index ecd58b9100..48e20a0442 100644
--- a/Marlin/src/HAL/HAL_ESP32/spi_pins.h
+++ b/Marlin/src/HAL/HAL_ESP32/spi_pins.h
@@ -16,13 +16,9 @@
* along with this program. If not, see .
*
*/
-
-#ifndef SPI_PINS_H_
-#define SPI_PINS_H_
+#pragma once
#define SS_PIN 5
#define SCK_PIN 18
#define MISO_PIN 19
#define MOSI_PIN 23
-
-#endif // SPI_PINS_H_
diff --git a/Marlin/src/HAL/HAL_ESP32/watchdog_ESP32.h b/Marlin/src/HAL/HAL_ESP32/watchdog_ESP32.h
index 39f0287275..df80ebc84c 100644
--- a/Marlin/src/HAL/HAL_ESP32/watchdog_ESP32.h
+++ b/Marlin/src/HAL/HAL_ESP32/watchdog_ESP32.h
@@ -19,14 +19,10 @@
* along with this program. If not, see .
*
*/
-
-#ifndef WATCHDOG_ESP32_H
-#define WATCHDOG_ESP32_H
+#pragma once
// Initialize watchdog with a 4 second interrupt time
void watchdog_init();
// Reset watchdog.
-inline void watchdog_reset() {};
-
-#endif // WATCHDOG_ESP32_H
+inline void watchdog_reset() { }
diff --git a/Marlin/src/HAL/HAL_LPC1768/DebugMonitor_LPC1768.cpp b/Marlin/src/HAL/HAL_LPC1768/DebugMonitor_LPC1768.cpp
new file mode 100644
index 0000000000..c992925bf0
--- /dev/null
+++ b/Marlin/src/HAL/HAL_LPC1768/DebugMonitor_LPC1768.cpp
@@ -0,0 +1,318 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 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 TARGET_LPC1768
+
+#include "../../core/macros.h"
+#include "../../core/serial.h"
+#include
+
+#include "../shared/backtrace/unwinder.h"
+#include "../shared/backtrace/unwmemaccess.h"
+#include "watchdog.h"
+#include
+
+
+// Debug monitor that dumps to the Programming port all status when
+// an exception or WDT timeout happens - And then resets the board
+
+// All the Monitor routines must run with interrupts disabled and
+// under an ISR execution context. That is why we cannot reuse the
+// Serial interrupt routines or any C runtime, as we don't know the
+// state we are when running them
+
+// A SW memory barrier, to ensure GCC does not overoptimize loops
+#define sw_barrier() __asm__ volatile("": : :"memory");
+
+// (re)initialize UART0 as a monitor output to 250000,n,8,1
+static void TXBegin(void) {
+}
+
+// Send character through UART with no interrupts
+static void TX(char c) {
+ _DBC(c);
+}
+
+// Send String through UART
+static void TX(const char* s) {
+ while (*s) TX(*s++);
+}
+
+static void TXDigit(uint32_t d) {
+ if (d < 10) TX((char)(d+'0'));
+ else if (d < 16) TX((char)(d+'A'-10));
+ else TX('?');
+}
+
+// Send Hex number thru UART
+static void TXHex(uint32_t v) {
+ TX("0x");
+ for (uint8_t i = 0; i < 8; i++, v <<= 4)
+ TXDigit((v >> 28) & 0xF);
+}
+
+// Send Decimal number thru UART
+static void TXDec(uint32_t v) {
+ if (!v) {
+ TX('0');
+ return;
+ }
+
+ char nbrs[14];
+ char *p = &nbrs[0];
+ while (v != 0) {
+ *p++ = '0' + (v % 10);
+ v /= 10;
+ }
+ do {
+ p--;
+ TX(*p);
+ } while (p != &nbrs[0]);
+}
+
+// Dump a backtrace entry
+static bool UnwReportOut(void* ctx, const UnwReport* bte) {
+ int* p = (int*)ctx;
+
+ (*p)++;
+ TX('#'); TXDec(*p); TX(" : ");
+ TX(bte->name?bte->name:"unknown"); TX('@'); TXHex(bte->function);
+ TX('+'); TXDec(bte->address - bte->function);
+ TX(" PC:");TXHex(bte->address); TX('\n');
+ return true;
+}
+
+#ifdef UNW_DEBUG
+ void UnwPrintf(const char* format, ...) {
+ char dest[256];
+ va_list argptr;
+ va_start(argptr, format);
+ vsprintf(dest, format, argptr);
+ va_end(argptr);
+ TX(&dest[0]);
+ }
+#endif
+
+/* Table of function pointers for passing to the unwinder */
+static const UnwindCallbacks UnwCallbacks = {
+ UnwReportOut,
+ UnwReadW,
+ UnwReadH,
+ UnwReadB
+ #ifdef UNW_DEBUG
+ ,UnwPrintf
+ #endif
+};
+
+
+/**
+ * HardFaultHandler_C:
+ * This is called from the HardFault_HandlerAsm with a pointer the Fault stack
+ * as the parameter. We can then read the values from the stack and place them
+ * into local variables for ease of reading.
+ * We then read the various Fault Status and Address Registers to help decode
+ * cause of the fault.
+ * The function ends with a BKPT instruction to force control back into the debugger
+ */
+extern "C"
+void HardFault_HandlerC(unsigned long *sp, unsigned long lr, unsigned long cause) {
+
+ static const char* causestr[] = {
+ "NMI","Hard","Mem","Bus","Usage","Debug","WDT","RSTC"
+ };
+
+ UnwindFrame btf;
+
+ // Dump report to the Programming port (interrupts are DISABLED)
+ TXBegin();
+ TX("\n\n## Software Fault detected ##\n");
+ TX("Cause: "); TX(causestr[cause]); TX('\n');
+
+ TX("R0 : "); TXHex(((unsigned long)sp[0])); TX('\n');
+ TX("R1 : "); TXHex(((unsigned long)sp[1])); TX('\n');
+ TX("R2 : "); TXHex(((unsigned long)sp[2])); TX('\n');
+ TX("R3 : "); TXHex(((unsigned long)sp[3])); TX('\n');
+ TX("R12 : "); TXHex(((unsigned long)sp[4])); TX('\n');
+ TX("LR : "); TXHex(((unsigned long)sp[5])); TX('\n');
+ TX("PC : "); TXHex(((unsigned long)sp[6])); TX('\n');
+ TX("PSR : "); TXHex(((unsigned long)sp[7])); TX('\n');
+
+ // Configurable Fault Status Register
+ // Consists of MMSR, BFSR and UFSR
+ TX("CFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED28)))); TX('\n');
+
+ // Hard Fault Status Register
+ TX("HFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED2C)))); TX('\n');
+
+ // Debug Fault Status Register
+ TX("DFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED30)))); TX('\n');
+
+ // Auxiliary Fault Status Register
+ TX("AFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED3C)))); TX('\n');
+
+ // Read the Fault Address Registers. These may not contain valid values.
+ // Check BFARVALID/MMARVALID to see if they are valid values
+ // MemManage Fault Address Register
+ TX("MMAR : "); TXHex((*((volatile unsigned long *)(0xE000ED34)))); TX('\n');
+
+ // Bus Fault Address Register
+ TX("BFAR : "); TXHex((*((volatile unsigned long *)(0xE000ED38)))); TX('\n');
+
+ TX("ExcLR: "); TXHex(lr); TX('\n');
+ TX("ExcSP: "); TXHex((unsigned long)sp); TX('\n');
+
+ btf.sp = ((unsigned long)sp) + 8*4; // The original stack pointer
+ btf.fp = btf.sp;
+ btf.lr = ((unsigned long)sp[5]);
+ btf.pc = ((unsigned long)sp[6]) | 1; // Force Thumb, as CORTEX only support it
+
+ // Perform a backtrace
+ TX("\nBacktrace:\n\n");
+ int ctr = 0;
+ UnwindStart(&btf, &UnwCallbacks, &ctr);
+
+ // Disable all NVIC interrupts
+ NVIC->ICER[0] = 0xFFFFFFFF;
+ NVIC->ICER[1] = 0xFFFFFFFF;
+
+ // Relocate VTOR table to default position
+ SCB->VTOR = 0;
+
+ // Clear cause of reset to prevent entering smoothie bootstrap
+ HAL_clear_reset_source();
+ // Restart watchdog
+ //WDT_Restart(WDT);
+ watchdog_init();
+
+ // Reset controller
+ NVIC_SystemReset();
+
+ while(1) { watchdog_init(); }
+}
+
+extern "C" {
+__attribute__((naked)) void NMI_Handler(void) {
+ __asm__ __volatile__ (
+ ".syntax unified" "\n\t"
+ A("tst lr, #4")
+ A("ite eq")
+ A("mrseq r0, msp")
+ A("mrsne r0, psp")
+ A("mov r1,lr")
+ A("mov r2,#0")
+ A("b HardFault_HandlerC")
+ );
+}
+
+__attribute__((naked)) void HardFault_Handler(void) {
+ __asm__ __volatile__ (
+ ".syntax unified" "\n\t"
+ A("tst lr, #4")
+ A("ite eq")
+ A("mrseq r0, msp")
+ A("mrsne r0, psp")
+ A("mov r1,lr")
+ A("mov r2,#1")
+ A("b HardFault_HandlerC")
+ );
+}
+
+__attribute__((naked)) void MemManage_Handler(void) {
+ __asm__ __volatile__ (
+ ".syntax unified" "\n\t"
+ A("tst lr, #4")
+ A("ite eq")
+ A("mrseq r0, msp")
+ A("mrsne r0, psp")
+ A("mov r1,lr")
+ A("mov r2,#2")
+ A("b HardFault_HandlerC")
+ );
+}
+
+__attribute__((naked)) void BusFault_Handler(void) {
+ __asm__ __volatile__ (
+ ".syntax unified" "\n\t"
+ A("tst lr, #4")
+ A("ite eq")
+ A("mrseq r0, msp")
+ A("mrsne r0, psp")
+ A("mov r1,lr")
+ A("mov r2,#3")
+ A("b HardFault_HandlerC")
+ );
+}
+
+__attribute__((naked)) void UsageFault_Handler(void) {
+ __asm__ __volatile__ (
+ ".syntax unified" "\n\t"
+ A("tst lr, #4")
+ A("ite eq")
+ A("mrseq r0, msp")
+ A("mrsne r0, psp")
+ A("mov r1,lr")
+ A("mov r2,#4")
+ A("b HardFault_HandlerC")
+ );
+}
+
+__attribute__((naked)) void DebugMon_Handler(void) {
+ __asm__ __volatile__ (
+ ".syntax unified" "\n\t"
+ A("tst lr, #4")
+ A("ite eq")
+ A("mrseq r0, msp")
+ A("mrsne r0, psp")
+ A("mov r1,lr")
+ A("mov r2,#5")
+ A("b HardFault_HandlerC")
+ );
+}
+
+/* This is NOT an exception, it is an interrupt handler - Nevertheless, the framing is the same */
+__attribute__((naked)) void WDT_IRQHandler(void) {
+ __asm__ __volatile__ (
+ ".syntax unified" "\n\t"
+ A("tst lr, #4")
+ A("ite eq")
+ A("mrseq r0, msp")
+ A("mrsne r0, psp")
+ A("mov r1,lr")
+ A("mov r2,#6")
+ A("b HardFault_HandlerC")
+ );
+}
+
+__attribute__((naked)) void RSTC_Handler(void) {
+ __asm__ __volatile__ (
+ ".syntax unified" "\n\t"
+ A("tst lr, #4")
+ A("ite eq")
+ A("mrseq r0, msp")
+ A("mrsne r0, psp")
+ A("mov r1,lr")
+ A("mov r2,#7")
+ A("b HardFault_HandlerC")
+ );
+}
+}
+#endif // TARGET_LPC1768
diff --git a/Marlin/src/HAL/HAL_LPC1768/HAL.cpp b/Marlin/src/HAL/HAL_LPC1768/HAL.cpp
index aec9b4ce73..020a1660b3 100644
--- a/Marlin/src/HAL/HAL_LPC1768/HAL.cpp
+++ b/Marlin/src/HAL/HAL_LPC1768/HAL.cpp
@@ -22,8 +22,7 @@
#include "../../inc/MarlinConfig.h"
#include "../shared/Delay.h"
-
-HalSerial usb_serial;
+#include "../../../gcode/parser.h"
// U8glib required functions
extern "C" void u8g_xMicroDelay(uint16_t val) {
@@ -51,231 +50,11 @@ int freeMemory() {
return result;
}
-// --------------------------------------------------------------------------
-// ADC
-// --------------------------------------------------------------------------
-
-#define ADC_DONE 0x80000000
-#define ADC_OVERRUN 0x40000000
-
-void HAL_adc_init(void) {
- LPC_SC->PCONP |= (1 << 12); // Enable CLOCK for internal ADC controller
- LPC_SC->PCLKSEL0 &= ~(0x3 << 24);
- LPC_SC->PCLKSEL0 |= (0x1 << 24); // 0: 25MHz, 1: 100MHz, 2: 50MHz, 3: 12.5MHZ to ADC clock divider
- LPC_ADC->ADCR = (0 << 0) // SEL: 0 = no channels selected
- | (0xFF << 8) // select slowest clock for A/D conversion 150 - 190 uS for a complete conversion
- | (0 << 16) // BURST: 0 = software control
- | (0 << 17) // CLKS: not applicable
- | (1 << 21) // PDN: 1 = operational
- | (0 << 24) // START: 0 = no start
- | (0 << 27); // EDGE: not applicable
-}
-
-// externals need to make the call to KILL compile
-#include "../../core/language.h"
-
-extern void kill(const char*);
-extern const char errormagic[];
-
-void HAL_adc_enable_channel(int ch) {
- pin_t pin = analogInputToDigitalPin(ch);
-
- if (pin == -1) {
- SERIAL_PRINTF("%sINVALID ANALOG PORT:%d\n", errormagic, ch);
- kill(MSG_KILLED);
- }
-
- int8_t pin_port = LPC1768_PIN_PORT(pin),
- pin_port_pin = LPC1768_PIN_PIN(pin),
- pinsel_start_bit = pin_port_pin > 15 ? 2 * (pin_port_pin - 16) : 2 * pin_port_pin;
- uint8_t pin_sel_register = (pin_port == 0 && pin_port_pin <= 15) ? 0 :
- pin_port == 0 ? 1 :
- pin_port == 1 ? 3 : 10;
-
- switch (pin_sel_register) {
- case 1:
- LPC_PINCON->PINSEL1 &= ~(0x3 << pinsel_start_bit);
- LPC_PINCON->PINSEL1 |= (0x1 << pinsel_start_bit);
- break;
- case 3:
- LPC_PINCON->PINSEL3 &= ~(0x3 << pinsel_start_bit);
- LPC_PINCON->PINSEL3 |= (0x3 << pinsel_start_bit);
- break;
- case 0:
- LPC_PINCON->PINSEL0 &= ~(0x3 << pinsel_start_bit);
- LPC_PINCON->PINSEL0 |= (0x2 << pinsel_start_bit);
- break;
- };
-}
-
-void HAL_adc_start_conversion(const uint8_t ch) {
- if (analogInputToDigitalPin(ch) == -1) {
- SERIAL_PRINTF("HAL: HAL_adc_start_conversion: invalid channel %d\n", ch);
- return;
- }
-
- LPC_ADC->ADCR &= ~0xFF; // Reset
- SBI(LPC_ADC->ADCR, ch); // Select Channel
- SBI(LPC_ADC->ADCR, 24); // Start conversion
-}
-
-bool HAL_adc_finished(void) {
- return LPC_ADC->ADGDR & ADC_DONE;
-}
-
-// possible config options if something similar is extended to more platforms.
-#define ADC_USE_MEDIAN_FILTER // Filter out erroneous readings
-#define ADC_MEDIAN_FILTER_SIZE 23 // Higher values increase step delay (phase shift),
- // (ADC_MEDIAN_FILTER_SIZE + 1) / 2 sample step delay (12 samples @ 500Hz: 24ms phase shift)
- // Memory usage per ADC channel (bytes): (6 * ADC_MEDIAN_FILTER_SIZE) + 16
- // 8 * ((6 * 23) + 16 ) = 1232 Bytes for 8 channels
-
-#define ADC_USE_LOWPASS_FILTER // Filter out high frequency noise
-#define ADC_LOWPASS_K_VALUE 6 // Higher values increase rise time
- // Rise time sample delays for 100% signal convergence on full range step
- // (1 : 13, 2 : 32, 3 : 67, 4 : 139, 5 : 281, 6 : 565, 7 : 1135, 8 : 2273)
- // K = 6, 565 samples, 500Hz sample rate, 1.13s convergence on full range step
- // Memory usage per ADC channel (bytes): 4 (32 Bytes for 8 channels)
-
-
-// Sourced from https://embeddedgurus.com/stack-overflow/tag/median-filter/
-struct MedianFilter {
- #define STOPPER 0 // Smaller than any datum
- struct Pair {
- Pair *point; // Pointers forming list linked in sorted order
- uint16_t value; // Values to sort
- };
-
- Pair buffer[ADC_MEDIAN_FILTER_SIZE] = {}; // Buffer of nwidth pairs
- Pair *datpoint = buffer; // Pointer into circular buffer of data
- Pair small = {NULL, STOPPER}; // Chain stopper
- Pair big = {&small, 0}; // Pointer to head (largest) of linked list.
-
- uint16_t update(uint16_t datum) {
- Pair *successor; // Pointer to successor of replaced data item
- Pair *scan; // Pointer used to scan down the sorted list
- Pair *scanold; // Previous value of scan
- Pair *median; // Pointer to median
- uint16_t i;
-
- if (datum == STOPPER) {
- datum = STOPPER + 1; // No stoppers allowed.
- }
-
- if ( (++datpoint - buffer) >= (ADC_MEDIAN_FILTER_SIZE)) {
- datpoint = buffer; // Increment and wrap data in pointer.
- }
-
- datpoint->value = datum; // Copy in new datum
- successor = datpoint->point; // Save pointer to old value's successor
- median = &big; // Median initially to first in chain
- scanold = NULL; // Scanold initially null.
- scan = &big; // Points to pointer to first (largest) datum in chain
-
- // Handle chain-out of first item in chain as special case
- if (scan->point == datpoint) {
- scan->point = successor;
- }
- scanold = scan; // Save this pointer and
- scan = scan->point ; // step down chain
-
- // Loop through the chain, normal loop exit via break.
- for (i = 0 ; i < ADC_MEDIAN_FILTER_SIZE; ++i) {
- // Handle odd-numbered item in chain
- if (scan->point == datpoint) {
- scan->point = successor; // Chain out the old datum
- }
-
- if (scan->value < datum) { // If datum is larger than scanned value
- datpoint->point = scanold->point; // Chain it in here
- scanold->point = datpoint; // Mark it chained in
- datum = STOPPER;
- }
-
- // Step median pointer down chain after doing odd-numbered element
- median = median->point; // Step median pointer
- if (scan == &small) {
- break; // Break at end of chain
- }
- scanold = scan; // Save this pointer and
- scan = scan->point; // step down chain
-
- // Handle even-numbered item in chain.
- if (scan->point == datpoint) {
- scan->point = successor;
- }
-
- if (scan->value < datum) {
- datpoint->point = scanold->point;
- scanold->point = datpoint;
- datum = STOPPER;
- }
-
- if (scan == &small) {
- break;
- }
-
- scanold = scan;
- scan = scan->point;
- }
- return median->value;
- }
-};
-
-struct LowpassFilter {
- uint32_t data_delay = 0;
- uint16_t update(const uint16_t value) {
- data_delay -= (data_delay >> (ADC_LOWPASS_K_VALUE)) - value;
- return (uint16_t)(data_delay >> (ADC_LOWPASS_K_VALUE));
- }
-};
-
-uint16_t HAL_adc_get_result(void) {
- uint32_t adgdr = LPC_ADC->ADGDR;
- CBI(LPC_ADC->ADCR, 24); // Stop conversion
-
- if (adgdr & ADC_OVERRUN) return 0;
- uint16_t data = (adgdr >> 4) & 0xFFF; // copy the 12bit data value
- uint8_t adc_channel = (adgdr >> 24) & 0x7; // copy the 3bit used channel
-
- #ifdef ADC_USE_MEDIAN_FILTER
- static MedianFilter median_filter[NUM_ANALOG_INPUTS];
- data = median_filter[adc_channel].update(data);
- #endif
-
- #ifdef ADC_USE_LOWPASS_FILTER
- static LowpassFilter lowpass_filter[NUM_ANALOG_INPUTS];
- data = lowpass_filter[adc_channel].update(data);
- #endif
-
- return ((data >> 2) & 0x3FF); // return 10bit value as Marlin expects
-}
-
-#define SBIT_CNTEN 0
-#define SBIT_PWMEN 2
-#define SBIT_PWMMR0R 1
-
-#define PWM_1 0 //P2_00 (0-1 Bits of PINSEL4)
-#define PWM_2 2 //P2_01 (2-3 Bits of PINSEL4)
-#define PWM_3 4 //P2_02 (4-5 Bits of PINSEL4)
-#define PWM_4 6 //P2_03 (6-7 Bits of PINSEL4)
-#define PWM_5 8 //P2_04 (8-9 Bits of PINSEL4)
-#define PWM_6 10 //P2_05 (10-11 Bits of PINSEL4)
-
-void HAL_pwm_init(void) {
- LPC_PINCON->PINSEL4 = _BV(PWM_5) | _BV(PWM_6);
-
- LPC_PWM1->TCR = _BV(SBIT_CNTEN) | _BV(SBIT_PWMEN);
- LPC_PWM1->PR = 0x0; // No prescalar
- LPC_PWM1->MCR = _BV(SBIT_PWMMR0R); // Reset on PWMMR0, reset TC if it matches MR0
- LPC_PWM1->MR0 = 255; // set PWM cycle(Ton+Toff)=255)
- LPC_PWM1->MR5 = 0; // Set 50% Duty Cycle for the channels
- LPC_PWM1->MR6 = 0;
-
- // Trigger the latch Enable Bits to load the new Match Values MR0, MR5, MR6
- LPC_PWM1->LER = _BV(0) | _BV(5) | _BV(6);
- // Enable the PWM output pins for PWM_5-PWM_6(P2_04 - P2_05)
- LPC_PWM1->PCR = _BV(13) | _BV(14);
+int16_t PARSED_PIN_INDEX(const char code, const int16_t dval) {
+ const uint16_t val = (uint16_t)parser.intval(code), port = val / 100, pin = val % 100;
+ const int16_t ind = (port < (NUM_DIGITAL_PINS >> 5) && (pin < 32))
+ ? GET_PIN_MAP_INDEX(port << 5 | pin) : -2;
+ return ind > -2 ? ind : dval;
}
#endif // TARGET_LPC1768
diff --git a/Marlin/src/HAL/HAL_LPC1768/HAL.h b/Marlin/src/HAL/HAL_LPC1768/HAL.h
index 1447b45d6e..689105f109 100644
--- a/Marlin/src/HAL/HAL_LPC1768/HAL.h
+++ b/Marlin/src/HAL/HAL_LPC1768/HAL.h
@@ -19,52 +19,35 @@
* along with this program. If not, see .
*
*/
+#pragma once
/**
* HAL_LPC1768/HAL.h
* Hardware Abstraction Layer for NXP LPC1768
*/
-#ifndef _HAL_LPC1768_H_
-#define _HAL_LPC1768_H_
-
#define CPU_32_BIT
+#define HAL_INIT
-// --------------------------------------------------------------------------
-// Includes
-// --------------------------------------------------------------------------
+void HAL_init();
#include
#include
-
-#undef min
-#undef max
-
#include
-void _printf (const char *format, ...);
-void _putc(uint8_t c);
-uint8_t _getc();
-
-extern "C" volatile uint32_t _millis;
-
-//arduino: Print.h
-#define DEC 10
-#define HEX 16
-#define OCT 8
-#define BIN 2
-//arduino: binary.h (weird defines)
-#define B01 1
-#define B10 2
+extern "C" volatile millis_t _millis;
#include
#include
+#include
#include "../shared/math_32bit.h"
#include "../shared/HAL_SPI.h"
#include "fastio.h"
+#include
#include "watchdog.h"
#include "HAL_timers.h"
+#include "MarlinSerial.h"
//
// Default graphical display delays
@@ -79,32 +62,20 @@ extern "C" volatile uint32_t _millis;
#define ST7920_DELAY_3 DELAY_NS(750)
#endif
-//
-// Arduino-style serial ports
-//
-#include "serial.h"
-#include "HardwareSerial.h"
-
-extern HalSerial usb_serial;
-
#if !WITHIN(SERIAL_PORT, -1, 3)
#error "SERIAL_PORT must be from -1 to 3"
#endif
#if SERIAL_PORT == -1
- #define MYSERIAL0 usb_serial
+ #define MYSERIAL0 UsbSerial
#elif SERIAL_PORT == 0
- extern HardwareSerial Serial;
- #define MYSERIAL0 Serial
+ #define MYSERIAL0 MSerial
#elif SERIAL_PORT == 1
- extern HardwareSerial Serial1;
- #define MYSERIAL0 Serial1
+ #define MYSERIAL0 MSerial1
#elif SERIAL_PORT == 2
- extern HardwareSerial Serial2;
- #define MYSERIAL0 Serial2
+ #define MYSERIAL0 MSerial2
#elif SERIAL_PORT == 3
- #define MYSERIAL0 Serial3
- extern HardwareSerial Serial3;
+ #define MYSERIAL0 MSerial3
#endif
#ifdef SERIAL_PORT_2
@@ -115,19 +86,15 @@ extern HalSerial usb_serial;
#endif
#define NUM_SERIAL 2
#if SERIAL_PORT_2 == -1
- #define MYSERIAL1 usb_serial
+ #define MYSERIAL1 UsbSerial
#elif SERIAL_PORT_2 == 0
- extern HardwareSerial Serial;
- #define MYSERIAL1 Serial
+ #define MYSERIAL1 MSerial
#elif SERIAL_PORT_2 == 1
- extern HardwareSerial Serial1;
- #define MYSERIAL1 Serial1
+ #define MYSERIAL1 MSerial1
#elif SERIAL_PORT_2 == 2
- extern HardwareSerial Serial2;
- #define MYSERIAL1 Serial2
+ #define MYSERIAL1 MSerial2
#elif SERIAL_PORT_2 == 3
- extern HardwareSerial Serial3;
- #define MYSERIAL1 Serial3
+ #define MYSERIAL1 MSerial3
#endif
#else
#define NUM_SERIAL 1
@@ -159,17 +126,31 @@ void spiSend(uint32_t chan, const uint8_t* buf, size_t n);
uint8_t spiRec(uint32_t chan);
//
-// ADC
+// ADC API
//
-#define HAL_ANALOG_SELECT(pin) HAL_adc_enable_channel(pin)
-#define HAL_START_ADC(pin) HAL_adc_start_conversion(pin)
-#define HAL_READ_ADC() HAL_adc_get_result()
-#define HAL_ADC_READY() HAL_adc_finished()
-void HAL_adc_init(void);
-void HAL_adc_enable_channel(int pin);
-void HAL_adc_start_conversion(const uint8_t adc_pin);
-uint16_t HAL_adc_get_result(void);
-bool HAL_adc_finished(void);
+#define ADC_MEDIAN_FILTER_SIZE (23) // Higher values increase step delay (phase shift),
+ // (ADC_MEDIAN_FILTER_SIZE + 1) / 2 sample step delay (12 samples @ 500Hz: 24ms phase shift)
+ // Memory usage per ADC channel (bytes): (6 * ADC_MEDIAN_FILTER_SIZE) + 16
+ // 8 * ((6 * 23) + 16 ) = 1232 Bytes for 8 channels
-#endif // _HAL_LPC1768_H_
+#define ADC_LOWPASS_K_VALUE (6) // Higher values increase rise time
+ // Rise time sample delays for 100% signal convergence on full range step
+ // (1 : 13, 2 : 32, 3 : 67, 4 : 139, 5 : 281, 6 : 565, 7 : 1135, 8 : 2273)
+ // K = 6, 565 samples, 500Hz sample rate, 1.13s convergence on full range step
+ // Memory usage per ADC channel (bytes): 4 (32 Bytes for 8 channels)
+
+using FilteredADC = LPC176x::ADC;
+#define HAL_adc_init() FilteredADC::init()
+#define HAL_ANALOG_SELECT(pin) FilteredADC::enable_channel(pin)
+#define HAL_START_ADC(pin) FilteredADC::start_conversion(pin)
+#define HAL_READ_ADC() FilteredADC::get_result()
+#define HAL_ADC_READY() FilteredADC::finished_conversion()
+
+// Parse a G-code word into a pin index
+int16_t PARSED_PIN_INDEX(const char code, const int16_t dval);
+// P0.6 thru P0.9 are for the onboard SD card
+#define HAL_SENSITIVE_PINS P0_06, P0_07, P0_08, P0_09
+
+#define HAL_IDLETASK 1
+void HAL_idletask(void);
diff --git a/Marlin/src/HAL/HAL_LPC1768/HAL_spi.cpp b/Marlin/src/HAL/HAL_LPC1768/HAL_spi.cpp
index c8fe029d39..2765bb553a 100644
--- a/Marlin/src/HAL/HAL_LPC1768/HAL_spi.cpp
+++ b/Marlin/src/HAL/HAL_LPC1768/HAL_spi.cpp
@@ -49,7 +49,6 @@
#ifdef TARGET_LPC1768
#include "../../inc/MarlinConfig.h"
-
// --------------------------------------------------------------------------
// Includes
// --------------------------------------------------------------------------
@@ -59,7 +58,6 @@
// --------------------------------------------------------------------------
// Public functions
// --------------------------------------------------------------------------
-
#if ENABLED(LPC_SOFTWARE_SPI)
#include "SoftwareSPI.h"
@@ -127,8 +125,25 @@
#include
#include
- void spiBegin() { // setup SCK, MOSI & MISO pins for SSP0
+ // 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;
@@ -147,10 +162,13 @@
PinCfg.Portnum = LPC1768_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
}
void spiInit(uint8_t spiRate) {
- SSP_Cmd(LPC_SSP0, DISABLE); // Disable SSP0 before changing rate
// 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
@@ -160,33 +178,32 @@
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
-
- // divide PCLK by 2 for SSP0
- CLKPWR_SetPCLKDiv(CLKPWR_PCLKSEL_SSP0, CLKPWR_PCLKSEL_CCLK_DIV_2);
-
// 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
- SSP_Init(LPC_SSP0, &HW_SPI_init); // puts the values into the proper bits in the SSP0 registers
+ 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
+ }
- SSP_Cmd(LPC_SSP0, ENABLE); // start SSP0 running
+
+ 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;
}
void spiSend(uint8_t b) {
- while (!SSP_GetStatus(LPC_SSP0, SSP_STAT_TXFIFO_NOTFULL)); // wait for room in the buffer
- SSP_SendData(LPC_SSP0, b & 0x00FF);
- while (SSP_GetStatus(LPC_SSP0, SSP_STAT_BUSY)); // wait for it to finish
+ doio(b);
}
void spiSend(const uint8_t* buf, size_t n) {
if (n == 0) return;
for (uint16_t i = 0; i < n; i++) {
- while (!SSP_GetStatus(LPC_SSP0, SSP_STAT_TXFIFO_NOTFULL)); // wait for room in the buffer
- SSP_SendData(LPC_SSP0, buf[i] & 0x00FF);
+ doio(buf[i]);
}
- while (SSP_GetStatus(LPC_SSP0, SSP_STAT_BUSY)); // wait for it to finish
}
void spiSend(uint32_t chan, byte b) {
@@ -195,17 +212,9 @@
void spiSend(uint32_t chan, const uint8_t* buf, size_t n) {
}
- static uint8_t get_one_byte() {
- // send a dummy byte so can clock in receive data
- SSP_SendData(LPC_SSP0,0x00FF);
- while (SSP_GetStatus(LPC_SSP0, SSP_STAT_BUSY)); // wait for it to finish
- return SSP_ReceiveData(LPC_SSP0) & 0x00FF;
- }
-
// Read single byte from SPI
uint8_t spiRec() {
- while (SSP_GetStatus(LPC_SSP0, SSP_STAT_RXFIFO_NOTEMPTY) || SSP_GetStatus(LPC_SSP0, SSP_STAT_BUSY)) SSP_ReceiveData(LPC_SSP0); //flush the receive buffer
- return get_one_byte();
+ return doio(0xff);
}
uint8_t spiRec(uint32_t chan) {
@@ -214,22 +223,25 @@
// Read from SPI into buffer
void spiRead(uint8_t*buf, uint16_t nbyte) {
- while (SSP_GetStatus(LPC_SSP0, SSP_STAT_RXFIFO_NOTEMPTY) || SSP_GetStatus(LPC_SSP0, SSP_STAT_BUSY)) SSP_ReceiveData(LPC_SSP0); //flush the receive buffer
if (nbyte == 0) return;
for (int i = 0; i < nbyte; i++) {
- buf[i] = get_one_byte();
+ buf[i] = doio(0xff);
}
}
static uint8_t spiTransfer(uint8_t b) {
- while (SSP_GetStatus(LPC_SSP0, SSP_STAT_RXFIFO_NOTEMPTY) || SSP_GetStatus(LPC_SSP0, SSP_STAT_BUSY)) SSP_ReceiveData(LPC_SSP0); //flush the receive buffer
- SSP_SendData(LPC_SSP0, b); // send the byte
- while (SSP_GetStatus(LPC_SSP0, SSP_STAT_BUSY)); // wait for it to finish
- return SSP_ReceiveData(LPC_SSP0) & 0x00FF;
+ return doio(b);
}
// Write from buffer to SPI
void spiSendBlock(uint8_t token, const uint8_t* buf) {
+ uint8_t response;
+ response = spiTransfer(token);
+
+ for (uint16_t i = 0; i < 512; i++) {
+ response = spiTransfer(buf[i]);
+ }
+ UNUSED(response);
}
/** Begin SPI transaction, set clock, bit order, data mode */
@@ -270,4 +282,3 @@ uint16_t SPIClass::transfer16(uint16_t data) {
SPIClass SPI;
#endif // TARGET_LPC1768
-
diff --git a/Marlin/src/HAL/HAL_LPC1768/HAL_temp.h b/Marlin/src/HAL/HAL_LPC1768/HAL_temp.h
deleted file mode 100644
index 20d2cf8d05..0000000000
--- a/Marlin/src/HAL/HAL_LPC1768/HAL_temp.h
+++ /dev/null
@@ -1 +0,0 @@
-// blank file needed until I get platformio to update it's copy of U8Glib-HAL
\ No newline at end of file
diff --git a/Marlin/src/HAL/HAL_LPC1768/HAL_timers.h b/Marlin/src/HAL/HAL_LPC1768/HAL_timers.h
index 4257028fc6..360a0f5c21 100644
--- a/Marlin/src/HAL/HAL_LPC1768/HAL_timers.h
+++ b/Marlin/src/HAL/HAL_LPC1768/HAL_timers.h
@@ -18,16 +18,13 @@
* along with this program. If not, see .
*
*/
+#pragma once
/**
- * HAL for Arduino Due and compatible (SAM3X8E)
*
- * For ARDUINO_ARCH_SAM
+ * HAL For LPC1768
*/
-#ifndef _HAL_TIMERS_H
-#define _HAL_TIMERS_H
-
// --------------------------------------------------------------------------
// Includes
// --------------------------------------------------------------------------
@@ -167,5 +164,3 @@ FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) {
}
#define HAL_timer_isr_epilogue(TIMER_NUM)
-
-#endif // _HAL_TIMERS_H
diff --git a/Marlin/src/HAL/HAL_LPC1768/LPC1768_PWM.cpp b/Marlin/src/HAL/HAL_LPC1768/LPC1768_PWM.cpp
deleted file mode 100644
index b27d8e1f31..0000000000
--- a/Marlin/src/HAL/HAL_LPC1768/LPC1768_PWM.cpp
+++ /dev/null
@@ -1,576 +0,0 @@
-/**
- * Marlin 3D Printer Firmware
- * Copyright (C) 2017 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 .
- *
- */
-
-/**
- * The class Servo uses the PWM class to implement its functions
- *
- * All PWMs use the same repetition rate - 20mS because that's the normal servo rate
- */
-
-/**
- * This is a hybrid system.
- *
- * The PWM1 module is used to directly control the Servo 0, 1 & 3 pins and D9 & D10 pins. This keeps
- * the pulse width jitter to under a microsecond.
- *
- * For all other pins a timer is used to generate interrupts. The ISR
- * routine does the actual setting/clearing of pins. The upside is that any pin can
- * have a PWM channel assigned to it. The downside is that there is more pulse width
- * jitter. The jitter depends on what else is happening in the system and what ISRs
- * pre-empt the PWM ISR.
- */
-
-/**
- * The data structures are set up to minimize the computation done by the ISR which
- * minimizes ISR execution time. Execution times are 5-14µs depending on how full the
- * ISR table is. 14uS is for a 20 element ISR table.
- *
- * Two tables are used. One table contains the data used by the ISR to update/control
- * the PWM pins. The other is used as an aid when updating the ISR table.
- *
- * See the end of this file for details on the hardware/firmware interaction
- */
-
-/**
- * Directly controlled PWM pins (
- * NA means not being used as a directly controlled PWM pin
- *
- * Re-ARM MKS Sbase
- * PWM1.1 P1_18 SERVO3_PIN NA(no connection)
- * PWM1.1 P2_00 NA(E0_STEP_PIN) NA(X stepper)
- * PWM1.2 P1_20 SERVO0_PIN NA(no connection)
- * PWM1.2 P2_01 NA(X_STEP_PIN) NA(Y stepper)
- * PWM1.3 P1_21 SERVO1_PIN NA(no connection)
- * PWM1.3 P2_02 NA(Y_STEP_PIN) NA(Z stepper)
- * PWM1.4 P1_23 NA(SDSS(SSEL0)) SERVO0_PIN
- * PWM1.4 P2_03 NA(Z_STEP_PIN) NA(E0 stepper)
- * PWM1.5 P1_24 NA(X_MIN_PIN) NA(X_MIN_pin)
- * PWM1.5 P2_04 RAMPS_D9_PIN FAN_PIN
- * PWM1.6 P1_26 NA(Y_MIN_PIN) NA(Y_MIN_pin)
- * PWM1.6 P2_05 RAMPS_D10_PIN HEATER_BED_PIN
- */
-
-#ifdef TARGET_LPC1768
-
-#include "../../inc/MarlinConfig.h"
-#include
-#include "LPC1768_PWM.h"
-#include
-
-#define NUM_ISR_PWMS 20
-
-#define HAL_PWM_TIMER LPC_TIM3
-#define HAL_PWM_TIMER_ISR extern "C" void TIMER3_IRQHandler(void)
-#define HAL_PWM_TIMER_IRQn TIMER3_IRQn
-
-#define LPC_PORT_OFFSET (0x0020)
-#define LPC_PIN(pin) (1UL << pin)
-#define LPC_GPIO(port) ((volatile LPC_GPIO_TypeDef *)(LPC_GPIO0_BASE + LPC_PORT_OFFSET * port))
-
-typedef struct { // holds all data needed to control/init one of the PWM channels
- bool active_flag; // THIS TABLE ENTRY IS ACTIVELY TOGGLING A PIN
- pin_t pin;
- volatile uint32_t* set_register;
- volatile uint32_t* clr_register;
- uint32_t write_mask; // USED BY SET/CLEAR COMMANDS
- uint32_t microseconds; // value written to MR register
- uint32_t min; // lower value limit checked by WRITE routine before writing to the MR register
- uint32_t max; // upper value limit checked by WRITE routine before writing to the MR register
- uint8_t servo_index; // 0 - MAX_SERVO -1 : servo index, 0xFF : PWM channel
-} PWM_map;
-
-PWM_map PWM1_map_A[NUM_ISR_PWMS]; // compiler will initialize to all zeros
-PWM_map PWM1_map_B[NUM_ISR_PWMS]; // compiler will initialize to all zeros
-
-PWM_map *active_table = PWM1_map_A;
-PWM_map *work_table = PWM1_map_B;
-PWM_map *temp_table;
-
-#define P1_18_PWM_channel 1 // servo 3
-#define P1_20_PWM_channel 2 // servo 0
-#define P1_21_PWM_channel 3 // servo 1
-#define P1_23_PWM_channel 4 // servo 0 for MKS Sbase
-#define P2_04_PWM_channel 5 // D9
-#define P2_05_PWM_channel 6 // D10
-
-typedef struct {
- uint32_t min;
- uint32_t max;
- bool assigned;
-} table_direct;
-
-table_direct direct_table[6]; // compiler will initialize to all zeros
-
-/**
- * Prescale register and MR0 register values
- *
- * 100MHz PCLK 50MHz PCLK 25MHz PCLK 12.5MHz PCLK
- * ----------------- ----------------- ----------------- -----------------
- * desired prescale MR0 prescale MR0 prescale MR0 prescale MR0 resolution
- * prescale register register register register register register register register in degrees
- * freq value value value value value value value value
- *
- * 8 11.5 159,999 5.25 159,999 2.13 159,999 0.5625 159,999 0.023
- * 4 24 79,999 11.5 79,999 5.25 79,999 2.125 79,999 0.045
- * 2 49 39,999 24 39,999 11.5 39,999 5.25 39,999 0.090
- * 1 99 19,999 49 19,999 24 19,999 11.5 19,999 0.180
- * 0.5 199 9,999 99 9,999 49 9,999 24 9,999 0.360
- * 0.25 399 4,999 199 4,999 99 4,999 49 4,999 0.720
- * 0.125 799 2,499 399 2,499 199 2,499 99 2,499 1.440
- *
- * The desired prescale frequency column comes from an input in the range of 544 - 2400 microseconds
- * and the desire to just shift the input left or right as needed.
- *
- * A resolution of 0.2 degrees seems reasonable so a prescale frequency output of 1MHz is being used.
- * It also means we don't need to scale the input.
- *
- * The PCLK is set to 25MHz because that's the slowest one that gives whole numbers for prescale and
- * MR0 registers.
- *
- * Final settings:
- * PCLKSEL0: 0x0
- * PWM1PR: 0x018 (24)
- * PWM1MR0: 0x04E1F (19,999)
- *
- */
-
-void LPC1768_PWM_init(void) {
-
- ///// directly controlled PWM pins (interrupts not used for these)
-
- #define SBIT_CNTEN 0 // PWM1 counter & pre-scaler enable/disable
- #define SBIT_CNTRST 1 // reset counters to known state
- #define SBIT_PWMEN 3 // 1 - PWM, 0 - timer
- #define SBIT_PWMMR0R 1
- #define PCPWM1 6
- #define PCLK_PWM1 12
-
- SBI(LPC_SC->PCONP, PCPWM1); // Enable PWM1 controller (enabled on power up)
- LPC_SC->PCLKSEL0 &= ~(0x3 << PCLK_PWM1);
- LPC_SC->PCLKSEL0 |= (LPC_PWM1_PCLKSEL0 << PCLK_PWM1);
-
- uint32_t PR = (CLKPWR_GetPCLK(CLKPWR_PCLKSEL_PWM1) / 1000000) - 1; // Prescalar to create 1 MHz output
-
- LPC_PWM1->MR0 = LPC_PWM1_MR0; // TC resets every 19,999 + 1 cycles - sets PWM cycle(Ton+Toff) to 20 mS
- // MR0 must be set before TCR enables the PWM
- LPC_PWM1->TCR = _BV(SBIT_CNTEN) | _BV(SBIT_CNTRST) | _BV(SBIT_PWMEN); // Enable counters, reset counters, set mode to PWM
- CBI(LPC_PWM1->TCR, SBIT_CNTRST); // Take counters out of reset
- LPC_PWM1->PR = PR;
- LPC_PWM1->MCR = _BV(SBIT_PWMMR0R) | _BV(0); // Reset TC if it matches MR0, disable all interrupts except for MR0
- LPC_PWM1->CTCR = 0; // Disable counter mode (enable PWM mode)
- LPC_PWM1->LER = 0x07F; // Set the latch Enable Bits to load the new Match Values for MR0 - MR6
- LPC_PWM1->PCR = 0; // Single edge mode for all channels, PWM1 control of outputs off
-
- //// interrupt controlled PWM setup
-
- LPC_SC->PCONP |= 1 << 23; // power on timer3
- HAL_PWM_TIMER->PR = PR;
- HAL_PWM_TIMER->MCR = 0x0B; // Interrupt on MR0 & MR1, reset on MR0
- HAL_PWM_TIMER->MR0 = LPC_PWM1_MR0;
- HAL_PWM_TIMER->MR1 = 0;
- HAL_PWM_TIMER->TCR = _BV(0); // enable
- NVIC_EnableIRQ(HAL_PWM_TIMER_IRQn);
- NVIC_SetPriority(HAL_PWM_TIMER_IRQn, NVIC_EncodePriority(0, 4, 0));
-}
-
-
-bool ISR_table_update = false; // flag to tell the ISR that the tables need to be updated & swapped
-uint8_t ISR_index = 0; // index used by ISR to skip already actioned entries
-#define COPY_ACTIVE_TABLE for (uint8_t i = 0; i < NUM_ISR_PWMS ; i++) work_table[i] = active_table[i]
-uint32_t first_MR1_value = LPC_PWM1_MR0 + 1;
-
-void LPC1768_PWM_sort(void) {
-
- for (uint8_t i = NUM_ISR_PWMS; --i;) { // (bubble) sort table by microseconds
- bool didSwap = false;
- PWM_map temp;
- for (uint16_t j = 0; j < i; ++j) {
- if (work_table[j].microseconds > work_table[j + 1].microseconds) {
- temp = work_table[j + 1];
- work_table[j + 1] = work_table[j];
- work_table[j] = temp;
- didSwap = true;
- }
- }
- if (!didSwap) break;
- }
-}
-
-bool LPC1768_PWM_attach_pin(pin_t pin, uint32_t min /* = 1 */, uint32_t max /* = (LPC_PWM1_MR0 - 1) */, uint8_t servo_index /* = 0xFF */) {
-
- pin = GET_PIN_MAP_PIN(GET_PIN_MAP_INDEX(pin & 0xFF)); // Sometimes the upper byte is garbled
-
-//// direct control PWM code
- switch (pin) {
- case P1_23: // MKS Sbase Servo 0, PWM1 channel 4 (J3-8 PWM1.4)
- direct_table[P1_23_PWM_channel - 1].min = min;
- direct_table[P1_23_PWM_channel - 1].max = MIN(max, LPC_PWM1_MR0 - MR0_MARGIN);
- direct_table[P1_23_PWM_channel - 1].assigned = true;
- return true;
- case P1_20: // Servo 0, PWM1 channel 2 (Pin 11 P1.20 PWM1.2)
- direct_table[P1_20_PWM_channel - 1].min = min;
- direct_table[P1_20_PWM_channel - 1].max = MIN(max, LPC_PWM1_MR0 - MR0_MARGIN);
- direct_table[P1_20_PWM_channel - 1].assigned = true;
- return true;
- case P1_21: // Servo 1, PWM1 channel 3 (Pin 6 P1.21 PWM1.3)
- direct_table[P1_21_PWM_channel - 1].min = min;
- direct_table[P1_21_PWM_channel - 1].max = MIN(max, LPC_PWM1_MR0 - MR0_MARGIN);
- direct_table[P1_21_PWM_channel - 1].assigned = true;
- return true;
- case P1_18: // Servo 3, PWM1 channel 1 (Pin 4 P1.18 PWM1.1)
- direct_table[P1_18_PWM_channel - 1].min = min;
- direct_table[P1_18_PWM_channel - 1].max = MIN(max, LPC_PWM1_MR0 - MR0_MARGIN);
- direct_table[P1_18_PWM_channel - 1].assigned = true;
- return true;
- case P2_04: // D9 FET, PWM1 channel 5 (Pin 9 P2_04 PWM1.5)
- direct_table[P2_04_PWM_channel - 1].min = min;
- direct_table[P2_04_PWM_channel - 1].max = MIN(max, LPC_PWM1_MR0 - MR0_MARGIN);
- direct_table[P2_04_PWM_channel - 1].assigned = true;
- return true;
- case P2_05: // D10 FET, PWM1 channel 6 (Pin 10 P2_05 PWM1.6)
- direct_table[P2_05_PWM_channel - 1].min = min;
- direct_table[P2_05_PWM_channel - 1].max = MIN(max, LPC_PWM1_MR0 - MR0_MARGIN);
- direct_table[P2_05_PWM_channel - 1].assigned = true;
- return true;
- }
-
-//// interrupt controlled PWM code
- NVIC_DisableIRQ(HAL_PWM_TIMER_IRQn); // make it safe to update the active table
- // OK to update the active table because the
- // ISR doesn't use any of the changed items
-
- // We NEED memory barriers to ensure Interrupts are actually disabled!
- // ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
- __DSB();
- __ISB();
-
- if (ISR_table_update) //use work table if that's the newest
- temp_table = work_table;
- else
- temp_table = active_table;
-
- uint8_t slot = 0;
- for (uint8_t i = 0; i < NUM_ISR_PWMS; i++) // see if already in table
- if (temp_table[i].pin == pin) {
- NVIC_EnableIRQ(HAL_PWM_TIMER_IRQn); // re-enable PWM interrupts
- return 1;
- }
-
- for (uint8_t i = 1; (i < NUM_ISR_PWMS + 1) && !slot; i++) // find empty slot
- if ( !(temp_table[i - 1].set_register)) { slot = i; break; } // any item that can't be zero when active or just attached is OK
-
- if (!slot) {
- NVIC_EnableIRQ(HAL_PWM_TIMER_IRQn); // re-enable PWM interrupts
- return 0;
- }
-
- slot--; // turn it into array index
-
- temp_table[slot].pin = pin; // init slot
- temp_table[slot].set_register = &LPC_GPIO(LPC1768_PIN_PORT(pin))->FIOSET;
- temp_table[slot].clr_register = &LPC_GPIO(LPC1768_PIN_PORT(pin))->FIOCLR;
- temp_table[slot].write_mask = LPC_PIN(LPC1768_PIN_PIN(pin));
- temp_table[slot].min = min;
- temp_table[slot].max = max; // different max for ISR PWMs than for direct PWMs
- temp_table[slot].servo_index = servo_index;
- temp_table[slot].active_flag = false;
-
- NVIC_EnableIRQ(HAL_PWM_TIMER_IRQn); // re-enable PWM interrupts
-
- return 1;
-}
-
-
-bool LPC1768_PWM_detach_pin(pin_t pin) {
-
- pin = GET_PIN_MAP_PIN(GET_PIN_MAP_INDEX(pin & 0xFF));
-
-//// direct control PWM code
- switch (pin) {
- case P1_23: // MKS Sbase Servo 0, PWM1 channel 4 (J3-8 PWM1.4)
- if (!direct_table[P1_23_PWM_channel - 1].assigned) return false;
- CBI(LPC_PWM1->PCR, 8 + P1_23_PWM_channel); // disable PWM1 module control of this pin
- LPC_PINCON->PINSEL3 &= ~(0x3 << 14); // return pin to general purpose I/O
- direct_table[P1_23_PWM_channel - 1].assigned = false;
- return true;
- case P1_20: // Servo 0, PWM1 channel 2 (Pin 11 P1.20 PWM1.2)
- if (!direct_table[P1_20_PWM_channel - 1].assigned) return false;
- CBI(LPC_PWM1->PCR, 8 + P1_20_PWM_channel); // disable PWM1 module control of this pin
- LPC_PINCON->PINSEL3 &= ~(0x3 << 8); // return pin to general purpose I/O
- direct_table[P1_20_PWM_channel - 1].assigned = false;
- return true;
- case P1_21: // Servo 1, PWM1 channel 3 (Pin 6 P1.21 PWM1.3)
- if (!direct_table[P1_21_PWM_channel - 1].assigned) return false;
- CBI(LPC_PWM1->PCR, 8 + P1_21_PWM_channel); // disable PWM1 module control of this pin
- LPC_PINCON->PINSEL3 &= ~(0x3 << 10); // return pin to general purpose I/O
- direct_table[P1_21_PWM_channel - 1].assigned = false;
- return true;
- case P1_18: // Servo 3, PWM1 channel 1 (Pin 4 P1.18 PWM1.1)
- if (!direct_table[P1_18_PWM_channel - 1].assigned) return false;
- CBI(LPC_PWM1->PCR, 8 + P1_18_PWM_channel); // disable PWM1 module control of this pin
- LPC_PINCON->PINSEL3 &= ~(0x3 << 4); // return pin to general purpose I/O
- direct_table[P1_18_PWM_channel - 1].assigned = false;
- return true;
- case P2_04: // D9 FET, PWM1 channel 5 (Pin 9 P2_04 PWM1.5)
- if (!direct_table[P2_04_PWM_channel - 1].assigned) return false;
- CBI(LPC_PWM1->PCR, 8 + P2_04_PWM_channel); // disable PWM1 module control of this pin
- LPC_PINCON->PINSEL4 &= ~(0x3 << 10); // return pin to general purpose I/O
- direct_table[P2_04_PWM_channel - 1].assigned = false;
- return true;
- case P2_05: // D10 FET, PWM1 channel 6 (Pin 10 P2_05 PWM1.6)
- if (!direct_table[P2_05_PWM_channel - 1].assigned) return false;
- CBI(LPC_PWM1->PCR, 8 + P2_05_PWM_channel); // disable PWM1 module control of this pin
- LPC_PINCON->PINSEL4 &= ~(0x3 << 4); // return pin to general purpose I/O
- direct_table[P2_05_PWM_channel - 1].assigned = false;
- return true;
- }
-
-//// interrupt controlled PWM code
- NVIC_DisableIRQ(HAL_PWM_TIMER_IRQn);
-
- // We NEED memory barriers to ensure Interrupts are actually disabled!
- // ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
- __DSB();
- __ISB();
-
- if (ISR_table_update) {
- ISR_table_update = false; // don't update yet - have another update to do
- NVIC_EnableIRQ(HAL_PWM_TIMER_IRQn); // re-enable PWM interrupts
- }
- else {
- NVIC_EnableIRQ(HAL_PWM_TIMER_IRQn); // re-enable PWM interrupts
- COPY_ACTIVE_TABLE; // copy active table into work table
- }
-
- uint8_t slot = 0xFF;
- for (uint8_t i = 0; i < NUM_ISR_PWMS; i++) { // find slot
- if (work_table[i].pin == pin) {
- slot = i;
- break;
- }
- }
- if (slot == 0xFF) // return error if pin not found
- return false;
-
- work_table[slot] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
-
- LPC1768_PWM_sort(); // sort table by microseconds
- ISR_table_update = true;
- return true;
-}
-
-// value is 0-20,000 microseconds (0% to 100% duty cycle)
-// servo routine provides values in the 544 - 2400 range
-bool LPC1768_PWM_write(pin_t pin, uint32_t value) {
-
- pin = GET_PIN_MAP_PIN(GET_PIN_MAP_INDEX(pin & 0xFF));
-
-//// direct control PWM code
- switch (pin) {
- case P1_23: // MKS Sbase Servo 0, PWM1 channel 4 (J3-8 PWM1.4)
- if (!direct_table[P1_23_PWM_channel - 1].assigned) return false;
- LPC_PWM1->PCR |= _BV(8 + P1_23_PWM_channel); // enable PWM1 module control of this pin
- LPC_PINCON->PINSEL3 = 0x2 << 14; // must set pin function AFTER setting PCR
- // load the new time value
- LPC_PWM1->MR4 = MAX(MIN(value, direct_table[P1_23_PWM_channel - 1].max), direct_table[P1_23_PWM_channel - 1].min);
- LPC_PWM1->LER = 0x1 << P1_23_PWM_channel; // Set the latch Enable Bit to load the new Match Value on the next MR0
- return true;
- case P1_20: // Servo 0, PWM1 channel 2 (Pin 11 P1.20 PWM1.2)
- if (!direct_table[P1_20_PWM_channel - 1].assigned) return false;
- LPC_PWM1->PCR |= _BV(8 + P1_20_PWM_channel); // enable PWM1 module control of this pin
- LPC_PINCON->PINSEL3 |= 0x2 << 8; // must set pin function AFTER setting PCR
- // load the new time value
- LPC_PWM1->MR2 = MAX(MIN(value, direct_table[P1_20_PWM_channel - 1].max), direct_table[P1_20_PWM_channel - 1].min);
- LPC_PWM1->LER = 0x1 << P1_20_PWM_channel; // Set the latch Enable Bit to load the new Match Value on the next MR0
- return true;
- case P1_21: // Servo 1, PWM1 channel 3 (Pin 6 P1.21 PWM1.3)
- if (!direct_table[P1_21_PWM_channel - 1].assigned) return false;
- LPC_PWM1->PCR |= _BV(8 + P1_21_PWM_channel); // enable PWM1 module control of this pin
- LPC_PINCON->PINSEL3 |= 0x2 << 10; // must set pin function AFTER setting PCR
- // load the new time value
- LPC_PWM1->MR3 = MAX(MIN(value, direct_table[P1_21_PWM_channel - 1].max), direct_table[P1_21_PWM_channel - 1].min);
- LPC_PWM1->LER = 0x1 << P1_21_PWM_channel; // Set the latch Enable Bit to load the new Match Value on the next MR0
- return true;
- case P1_18: // Servo 3, PWM1 channel 1 (Pin 4 P1.18 PWM1.1)
- if (!direct_table[P1_18_PWM_channel - 1].assigned) return false;
- LPC_PWM1->PCR |= _BV(8 + P1_18_PWM_channel); // enable PWM1 module control of this pin
- LPC_PINCON->PINSEL3 |= 0x2 << 4; // must set pin function AFTER setting PCR
- // load the new time value
- LPC_PWM1->MR1 = MAX(MIN(value, direct_table[P1_18_PWM_channel - 1].max), direct_table[P1_18_PWM_channel - 1].min);
- LPC_PWM1->LER = 0x1 << P1_18_PWM_channel; // Set the latch Enable Bit to load the new Match Value on the next MR0
- return true;
- case P2_04: // D9 FET, PWM1 channel 5 (Pin 9 P2_04 PWM1.5)
- if (!direct_table[P2_04_PWM_channel - 1].assigned) return false;
- LPC_PWM1->PCR |= _BV(8 + P2_04_PWM_channel); // enable PWM1 module control of this pin
- LPC_PINCON->PINSEL4 |= 0x1 << 8; // must set pin function AFTER setting PCR
- // load the new time value
- LPC_PWM1->MR5 = MAX(MIN(value, direct_table[P2_04_PWM_channel - 1].max), direct_table[P2_04_PWM_channel - 1].min);
- LPC_PWM1->LER = 0x1 << P2_04_PWM_channel; // Set the latch Enable Bit to load the new Match Value on the next MR0
- return true;
- case P2_05: // D10 FET, PWM1 channel 6 (Pin 10 P2_05 PWM1.6)
- if (!direct_table[P2_05_PWM_channel - 1].assigned) return false;
- LPC_PWM1->PCR |= _BV(8 + P2_05_PWM_channel); // enable PWM1 module control of this pin
- LPC_PINCON->PINSEL4 |= 0x1 << 10; // must set pin function AFTER setting PCR
- // load the new time value
- LPC_PWM1->MR6 = MAX(MIN(value, direct_table[P2_05_PWM_channel - 1].max), direct_table[P2_05_PWM_channel - 1].min);
- LPC_PWM1->LER = 0x1 << P2_05_PWM_channel; // Set the latch Enable Bit to load the new Match Value on the next MR0
- return true;
- }
-
-//// interrupt controlled PWM code
- NVIC_DisableIRQ(HAL_PWM_TIMER_IRQn);
-
- // We NEED memory barriers to ensure Interrupts are actually disabled!
- // ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
- __DSB();
- __ISB();
-
- if (!ISR_table_update) // use the most up to date table
- COPY_ACTIVE_TABLE; // copy active table into work table
-
- uint8_t slot = 0xFF;
- for (uint8_t i = 0; i < NUM_ISR_PWMS; i++) // find slot
- if (work_table[i].pin == pin) { slot = i; break; }
- if (slot == 0xFF) { // return error if pin not found
- NVIC_EnableIRQ(HAL_PWM_TIMER_IRQn);
- return false;
- }
-
- work_table[slot].microseconds = MAX(MIN(value, work_table[slot].max), work_table[slot].min);;
- work_table[slot].active_flag = true;
-
- LPC1768_PWM_sort(); // sort table by microseconds
- ISR_table_update = true;
-
- NVIC_EnableIRQ(HAL_PWM_TIMER_IRQn); // re-enable PWM interrupts
- return 1;
-}
-
-
-bool useable_hardware_PWM(pin_t pin) {
-
- pin = GET_PIN_MAP_PIN(GET_PIN_MAP_INDEX(pin & 0xFF));
-
- NVIC_DisableIRQ(HAL_PWM_TIMER_IRQn);
-
- // We NEED memory barriers to ensure Interrupts are actually disabled!
- // ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
- __DSB();
- __ISB();
-
- bool return_flag = false;
- for (uint8_t i = 0; i < NUM_ISR_PWMS; i++) // see if it's already setup
- if (active_table[i].pin == pin) return_flag = true;
- for (uint8_t i = 0; i < NUM_ISR_PWMS; i++) // see if there is an empty slot
- if (!active_table[i].set_register) return_flag = true;
- NVIC_EnableIRQ(HAL_PWM_TIMER_IRQn); // re-enable PWM interrupts
- return return_flag;
-}
-
-
-////////////////////////////////////////////////////////////////////////////////
-
-
-#define PWM_LPC1768_ISR_SAFETY_FACTOR 5 // amount of time needed to guarantee MR1 count will be above TC
-volatile bool in_PWM_isr = false;
-
-HAL_PWM_TIMER_ISR {
- bool first_active_entry = true;
- uint32_t next_MR1_val;
-
- if (in_PWM_isr) goto exit_PWM_ISR; // prevent re-entering this ISR
- in_PWM_isr = true;
-
- if (HAL_PWM_TIMER->IR & 0x01) { // MR0 interrupt
- next_MR1_val = first_MR1_value; // only used if have a blank ISR table
- if (ISR_table_update) { // new values have been loaded so swap tables
- temp_table = active_table;
- active_table = work_table;
- work_table = temp_table;
- ISR_table_update = false;
- }
- }
- HAL_PWM_TIMER->IR = 0x3F; // clear all interrupts
-
- for (uint8_t i = 0; i < NUM_ISR_PWMS; i++) {
- if (active_table[i].active_flag) {
- if (first_active_entry) {
- first_active_entry = false;
- next_MR1_val = active_table[i].microseconds;
- }
- if (HAL_PWM_TIMER->TC < active_table[i].microseconds) {
- *active_table[i].set_register = active_table[i].write_mask; // set pin high
- }
- else {
- *active_table[i].clr_register = active_table[i].write_mask; // set pin low
- next_MR1_val = (i == NUM_ISR_PWMS -1)
- ? LPC_PWM1_MR0 + 1 // done with table, wait for MR0
- : active_table[i + 1].microseconds; // set next MR1 interrupt?
- }
- }
- }
- if (first_active_entry) next_MR1_val = LPC_PWM1_MR0 + 1; // empty table so disable MR1 interrupt
- HAL_PWM_TIMER->MR1 = MAX(next_MR1_val, HAL_PWM_TIMER->TC + PWM_LPC1768_ISR_SAFETY_FACTOR); // set next
- in_PWM_isr = false;
-
- exit_PWM_ISR:
- return;
-}
-#endif
-
-
-/////////////////////////////////////////////////////////////////
-///////////////// HARDWARE FIRMWARE INTERACTION ////////////////
-/////////////////////////////////////////////////////////////////
-
-/**
- * There are two distinct systems used for PWMs:
- * directly controlled pins
- * ISR controlled pins.
- *
- * The two systems are independent of each other. The use the same counter frequency so there's no
- * translation needed when setting the time values. The init, attach, detach and write routines all
- * start with the direct pin code which is followed by the ISR pin code.
- *
- * The PMW1 module handles the directly controlled pins. Each directly controlled pin is associated
- * with a match register (MR1 - MR6). When the associated MR equals the module's TIMER/COUNTER (TC)
- * then the pins is set to low. The MR0 register controls the repetition rate. When the TC equals
- * MR0 then the TC is reset and ALL directly controlled pins are set high. The resulting pulse widths
- * are almost immune to system loading and ISRs. No PWM1 interrupts are used.
- *
- * The ISR controlled pins use the TIMER/COUNTER, MR0 and MR1 registers from one timer. MR0 controls
- * period of the controls the repetition rate. When the TC equals MR0 then the TC is reset and an
- * interrupt is generated. When the TC equals MR1 then an interrupt is generated.
- *
- * Each interrupt does the following:
- * 1) Swaps the tables if it's a MR0 interrupt and the swap flag is set. It then clears the swap flag.
- * 2) Scans the entire ISR table (it's been sorted low to high time)
- * a. If its the first active entry then it grabs the time as a tentative time for MR1
- * b. If active and TC is less than the time then it sets the pin high
- * c. If active and TC is more than the time it sets the pin high
- * d. On every entry that sets a pin low it grabs the NEXT entry's time for use as the next MR1.
- * This results in MR1 being set to the time in the first active entry that does NOT set a
- * pin low.
- * e. If it's setting the last entry's pin low then it sets MR1 to a value bigger than MR0
- * f. If no value has been grabbed for the next MR1 then it's an empty table and MR1 is set to a
- * value greater than MR0
- */
diff --git a/Marlin/src/HAL/HAL_LPC1768/LPC1768_PWM.h b/Marlin/src/HAL/HAL_LPC1768/LPC1768_PWM.h
deleted file mode 100644
index 6c1a2480b8..0000000000
--- a/Marlin/src/HAL/HAL_LPC1768/LPC1768_PWM.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * Marlin 3D Printer Firmware
- * Copyright (C) 2017 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 .
- *
- */
-
-/**
- * The class Servo uses the PWM class to implement its functions
- *
- * All PWMs use the same repetition rate - 20mS because that's the normal servo rate
- */
-
-/**
- * This is a hybrid system.
- *
- * The PWM1 module is used to directly control the Servo 0, 1 & 3 pins. This keeps
- * the pulse width jitter to under a microsecond.
- *
- * For all other pins the PWM1 module is used to generate interrupts. The ISR
- * routine does the actual setting/clearing of pins. The upside is that any pin can
- * have a PWM channel assigned to it. The downside is that there is more pulse width
- * jitter. The jitter depends on what else is happening in the system and what ISRs
- * prempt the PWM ISR. Writing to the SD card can add 20 microseconds to the pulse
- * width.
- */
-
-/**
- * The data structures are setup to minimize the computation done by the ISR which
- * minimizes ISR execution time. Execution times are 2.2 - 3.7 microseconds.
- *
- * Two tables are used. active_table is used by the ISR. Changes to the table are
- * are done by copying the active_table into the work_table, updating the work_table
- * and then swapping the two tables. Swapping is done by manipulating pointers.
- *
- * Immediately after the swap the ISR uses the work_table until the start of the
- * next 20mS cycle. During this transition the "work_table" is actually the table
- * that was being used before the swap. The "active_table" contains the data that
- * will start being used at the start of the next 20mS period. This keeps the pins
- * well behaved during the transition.
- *
- * The ISR's priority is set to the maximum otherwise other ISRs can cause considerable
- * jitter in the PWM high time.
- *
- * See the end of this file for details on the hardware/firmware interaction
- */
-
-#ifndef _LPC1768_PWM_H_
-#define _LPC1768_PWM_H_
-
-#include
-#include
-
-#define LPC_PWM1_MR0 19999 // base repetition rate minus one count - 20mS
-#define LPC_PWM1_PCLKSEL0 CLKPWR_PCLKSEL_CCLK_DIV_4 // select clock divider for prescaler - defaults to 4 on power up
-#define MR0_MARGIN 200 // if channel value too close to MR0 the system locks up
-
-void LPC1768_PWM_init(void);
-bool LPC1768_PWM_attach_pin(pin_t pin, uint32_t min=1, uint32_t max=(LPC_PWM1_MR0 - (MR0_MARGIN)), uint8_t servo_index=0xFF);
-bool LPC1768_PWM_write(pin_t pin, uint32_t value);
-bool LPC1768_PWM_detach_pin(pin_t pin);
-bool useable_hardware_PWM(pin_t pin);
-
-#endif // _LPC1768_PWM_H_
diff --git a/Marlin/src/HAL/HAL_LPC1768/LPC1768_Servo.cpp b/Marlin/src/HAL/HAL_LPC1768/LPC1768_Servo.cpp
deleted file mode 100644
index 4997c5e4bc..0000000000
--- a/Marlin/src/HAL/HAL_LPC1768/LPC1768_Servo.cpp
+++ /dev/null
@@ -1,163 +0,0 @@
-/**
- * Marlin 3D Printer Firmware
- * Copyright (C) 2016 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 .
- *
- */
-
-/**
- * Based on servo.cpp - Interrupt driven Servo library for Arduino using 16 bit
- * timers- Version 2 Copyright (c) 2009 Michael Margolis. All right reserved.
- */
-
-/**
- * A servo is activated by creating an instance of the Servo class passing the desired pin to the attach() method.
- * The servos are pulsed in the background using the value most recently written using the write() method
- *
- * Note that analogWrite of PWM on pins associated with the timer are disabled when the first servo is attached.
- * Timers are seized as needed in groups of 12 servos - 24 servos use two timers, 48 servos will use four.
- *
- * The methods are:
- *
- * Servo - Class for manipulating servo motors connected to Arduino pins.
- *
- * attach(pin) - Attach a servo motor to an i/o pin.
- * attach(pin, min, max) - Attach to a pin, setting min and max values in microseconds
- * Default min is 544, max is 2400
- *
- * write() - Set the servo angle in degrees. (Invalid angles —over MIN_PULSE_WIDTH— are treated as µs.)
- * writeMicroseconds() - Set the servo pulse width in microseconds.
- * move(pin, angle) - Sequence of attach(pin), write(angle), safe_delay(servo_delay[servoIndex]).
- * With DEACTIVATE_SERVOS_AFTER_MOVE it detaches after servo_delay[servoIndex].
- * read() - Get the last-written servo pulse width as an angle between 0 and 180.
- * 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.
- *
- */
-
-/**
- * The only time that this library wants physical movement is when a WRITE
- * command is issued. Before that all the attach & detach activity is solely
- * within the data base.
- *
- * The PWM output is inactive until the first WRITE. After that it stays active
- * unless DEACTIVATE_SERVOS_AFTER_MOVE is enabled and a MOVE command was issued.
- */
-
-#ifdef TARGET_LPC1768
-
-#include "../../inc/MarlinConfig.h"
-
-#if HAS_SERVOS
-
- #include "LPC1768_PWM.h"
- #include "LPC1768_Servo.h"
- #include "servo_private.h"
-
- ServoInfo_t servo_info[MAX_SERVOS]; // static array of servo info structures
- uint8_t ServoCount = 0; // the total number of attached servos
-
- #define US_TO_PULSE_WIDTH(p) p
- #define PULSE_WIDTH_TO_US(p) p
- #define TRIM_DURATION 0
- #define SERVO_MIN() MIN_PULSE_WIDTH // minimum value in uS for this servo
- #define SERVO_MAX() MAX_PULSE_WIDTH // maximum value in uS for this servo
-
- Servo::Servo() {
- if (ServoCount < MAX_SERVOS) {
- this->servoIndex = ServoCount++; // assign a servo index to this instance
- servo_info[this->servoIndex].pulse_width = US_TO_PULSE_WIDTH(DEFAULT_PULSE_WIDTH); // store default values - 12 Aug 2009
- }
- else
- this->servoIndex = INVALID_SERVO; // too many servos
- }
-
- int8_t Servo::attach(const int pin) {
- return this->attach(pin, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
- }
-
- int8_t Servo::attach(const int pin, const int min, const int max) {
-
- if (this->servoIndex >= MAX_SERVOS) return -1;
-
- if (pin > 0) servo_info[this->servoIndex].Pin.nbr = pin; // only assign a pin value if the pin info is
- // greater than zero. This way the init routine can
- // assign the pin and the MOVE command only needs the value.
-
- this->min = MIN_PULSE_WIDTH; //resolution of min/max is 1 uS
- this->max = MAX_PULSE_WIDTH;
-
- servo_info[this->servoIndex].Pin.isActive = true;
-
- return this->servoIndex;
- }
-
- void Servo::detach() {
- servo_info[this->servoIndex].Pin.isActive = false;
- }
-
- void Servo::write(int value) {
- if (value < MIN_PULSE_WIDTH) { // treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)
- value = map(constrain(value, 0, 180), 0, 180, SERVO_MIN(), SERVO_MAX());
- // odd - this sets zero degrees to 544 and 180 degrees to 2400 microseconds but the literature says
- // zero degrees should be 500 microseconds and 180 should be 2500
- }
- this->writeMicroseconds(value);
- }
-
- void Servo::writeMicroseconds(int value) {
- // calculate and store the values for the given channel
- byte channel = this->servoIndex;
- if (channel < MAX_SERVOS) { // ensure channel is valid
- // ensure pulse width is valid
- value = constrain(value, SERVO_MIN(), SERVO_MAX()) - (TRIM_DURATION);
- value = US_TO_PULSE_WIDTH(value); // convert to pulse_width after compensating for interrupt overhead - 12 Aug 2009
-
- servo_info[channel].pulse_width = value;
- LPC1768_PWM_attach_pin(servo_info[this->servoIndex].Pin.nbr, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH, this->servoIndex);
- LPC1768_PWM_write(servo_info[this->servoIndex].Pin.nbr, value);
-
- }
- }
-
- // return the value as degrees
- int Servo::read() { return map(this->readMicroseconds() + 1, SERVO_MIN(), SERVO_MAX(), 0, 180); }
-
- int Servo::readMicroseconds() {
- return (this->servoIndex == INVALID_SERVO) ? 0 : PULSE_WIDTH_TO_US(servo_info[this->servoIndex].pulse_width) + TRIM_DURATION;
- }
-
- bool Servo::attached() { return servo_info[this->servoIndex].Pin.isActive; }
-
- void Servo::move(const int value) {
- constexpr uint16_t servo_delay[] = SERVO_DELAY;
- static_assert(COUNT(servo_delay) == NUM_SERVOS, "SERVO_DELAY must be an array NUM_SERVOS long.");
- if (this->attach(0) >= 0) { // notice the pin number is zero here
- this->write(value);
- safe_delay(servo_delay[this->servoIndex]);
- #if ENABLED(DEACTIVATE_SERVOS_AFTER_MOVE)
- this->detach();
- LPC1768_PWM_detach_pin(servo_info[this->servoIndex].Pin.nbr); // shut down the PWM signal
- LPC1768_PWM_attach_pin(servo_info[this->servoIndex].Pin.nbr, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH, this->servoIndex); // make sure no one else steals the slot
- #endif
- }
- }
-
-#endif // HAS_SERVOS
-#endif // TARGET_LPC1768
diff --git a/Marlin/src/HAL/HAL_LPC1768/LPC1768_Servo.h b/Marlin/src/HAL/HAL_LPC1768/LPC1768_Servo.h
deleted file mode 100644
index f0d6f048a5..0000000000
--- a/Marlin/src/HAL/HAL_LPC1768/LPC1768_Servo.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/**
- * Marlin 3D Printer Firmware
- * Copyright (C) 2017 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 .
- *
- */
-
-/**
- * The class Servo uses the PWM class to implement its functions
- *
- * The PWM1 module is only used to generate interrups at specified times. It
- * is NOT used to directly toggle pins. The ISR writes to the pin assigned to
- * that interrupt
- *
- * All PWMs use the same repetition rate - 20mS because that's the normal servo rate
- *
- */
-
-#ifndef LPC1768_SERVO_H
-#define LPC1768_SERVO_H
-
-#include
-
- class Servo {
- public:
- Servo();
- int8_t attach(const int pin); // attach the given pin to the next free channel, set pinMode, return channel number (-1 on fail)
- int8_t attach(const int pin, const int min, const int max); // as above but also sets min and max values for writes.
- void detach();
- void write(int value); // if value is < 200 it is treated as an angle, otherwise as pulse width in microseconds
- void writeMicroseconds(int value); // write pulse width in microseconds
- void move(const int value); // attach the servo, then move to value
- // if value is < 200 it is treated as an angle, otherwise as pulse width in microseconds
- // if DEACTIVATE_SERVOS_AFTER_MOVE wait SERVO_DELAY, then detach
- int read(); // returns current pulse width as an angle between 0 and 180 degrees
- int readMicroseconds(); // returns current pulse width in microseconds for this servo (was read_us() in first release)
- bool attached(); // return true if this servo is attached, otherwise false
-
- private:
- uint8_t servoIndex; // index into the channel data for this servo
- int min;
- int max;
- };
-
- #define HAL_SERVO_LIB Servo
-
-#endif // LPC1768_SERVO_H
diff --git a/Marlin/src/HAL/HAL_LPC1768/MarlinSerial.cpp b/Marlin/src/HAL/HAL_LPC1768/MarlinSerial.cpp
new file mode 100644
index 0000000000..248e9007f1
--- /dev/null
+++ b/Marlin/src/HAL/HAL_LPC1768/MarlinSerial.cpp
@@ -0,0 +1,56 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 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 TARGET_LPC1768
+
+#include "../../inc/MarlinConfigPre.h"
+#include "MarlinSerial.h"
+
+#if (defined(SERIAL_PORT) && SERIAL_PORT == 0) || (defined(SERIAL_PORT_2) && SERIAL_PORT_2 == 0)
+ MarlinSerial MSerial(LPC_UART0);
+ extern "C" void UART0_IRQHandler(void) {
+ MSerial.IRQHandler();
+ }
+#endif
+
+#if (defined(SERIAL_PORT) && SERIAL_PORT == 1) || (defined(SERIAL_PORT_2) && SERIAL_PORT_2 == 1)
+ MarlinSerial MSerial1((LPC_UART_TypeDef *) LPC_UART1);
+ extern "C" void UART1_IRQHandler(void) {
+ MSerial1.IRQHandler();
+ }
+#endif
+
+#if (defined(SERIAL_PORT) && SERIAL_PORT == 2) || (defined(SERIAL_PORT_2) && SERIAL_PORT_2 == 2)
+ MarlinSerial MSerial2(LPC_UART2);
+ extern "C" void UART2_IRQHandler(void) {
+ MSerial2.IRQHandler();
+ }
+#endif
+
+#if (defined(SERIAL_PORT) && SERIAL_PORT == 3) || (defined(SERIAL_PORT_2) && SERIAL_PORT_2 == 3)
+ MarlinSerial MSerial3(LPC_UART3);
+ extern "C" void UART3_IRQHandler(void) {
+ MSerial3.IRQHandler();
+ }
+#endif
+
+#endif // TARGET_LPC1768
diff --git a/Marlin/src/HAL/HAL_LPC1768/MarlinSerial.h b/Marlin/src/HAL/HAL_LPC1768/MarlinSerial.h
new file mode 100644
index 0000000000..7f95be3569
--- /dev/null
+++ b/Marlin/src/HAL/HAL_LPC1768/MarlinSerial.h
@@ -0,0 +1,67 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+#include
+#include
+
+#include "../../inc/MarlinConfigPre.h"
+#if ENABLED(EMERGENCY_PARSER)
+ #include "../../feature/emergency_parser.h"
+#endif
+
+#ifndef SERIAL_PORT
+ #define SERIAL_PORT 0
+#endif
+#ifndef RX_BUFFER_SIZE
+ #define RX_BUFFER_SIZE 128
+#endif
+#ifndef TX_BUFFER_SIZE
+ #define TX_BUFFER_SIZE 32
+#endif
+
+class MarlinSerial : public HardwareSerial {
+public:
+ MarlinSerial(LPC_UART_TypeDef *UARTx) :
+ HardwareSerial(UARTx)
+ #if ENABLED(EMERGENCY_PARSER)
+ , emergency_state(EmergencyParser::State::EP_RESET)
+ #endif
+ {
+ }
+
+ #if ENABLED(EMERGENCY_PARSER)
+ bool recv_callback(const char c) override {
+ emergency_parser.update(emergency_state, c);
+ return true; // do not discard character
+ }
+ #endif
+
+ #if ENABLED(EMERGENCY_PARSER)
+ EmergencyParser::State emergency_state;
+ #endif
+};
+
+extern MarlinSerial MSerial;
+extern MarlinSerial MSerial1;
+extern MarlinSerial MSerial2;
+extern MarlinSerial MSerial3;
diff --git a/Marlin/src/HAL/HAL_LPC1768/servo_private.h b/Marlin/src/HAL/HAL_LPC1768/MarlinServo.h
similarity index 66%
rename from Marlin/src/HAL/HAL_LPC1768/servo_private.h
rename to Marlin/src/HAL/HAL_LPC1768/MarlinServo.h
index 451c487d73..c535ea6ff5 100644
--- a/Marlin/src/HAL/HAL_LPC1768/servo_private.h
+++ b/Marlin/src/HAL/HAL_LPC1768/MarlinServo.h
@@ -38,6 +38,7 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#pragma once
/**
* Based on "servo.h - Interrupt driven Servo library for Arduino using 16 bit timers -
@@ -47,38 +48,23 @@
*
*/
-#ifndef SERVO_PRIVATE_H
-#define SERVO_PRIVATE_H
+#include
-#include