This commit is contained in:
2022-12-14 12:54:23 -05:00
836 changed files with 25627 additions and 12003 deletions

View File

@@ -4,10 +4,10 @@ root = true
[{*.patch,syntax_test_*}]
trim_trailing_whitespace = false
[{*.c,*.cpp,*.h}]
[{*.c,*.cpp,*.h,*.ino}]
charset = utf-8
[{*.c,*.cpp,*.h,Makefile}]
[{*.c,*.cpp,*.h,*.ino,Makefile}]
trim_trailing_whitespace = true
insert_final_newline = true
end_of_line = lf

View File

@@ -89,6 +89,8 @@ jobs:
- mks_robin_nano35_stm32
- NUCLEO_F767ZI
- REMRAM_V1
- BTT_SKR_SE_BX
- chitu_f103
# Put lengthy tests last
@@ -98,6 +100,7 @@ jobs:
# Non-working environment tests
#- at90usb1286_cdc
#- STM32F103CB_malyan
#- STM32F103RE
#- mks_robin_mini
steps:

23
.gitignore vendored
View File

@@ -122,29 +122,6 @@ tags
.gcc-flags.json
/lib/
# Workaround for Deviot+platformio quirks
Marlin/lib
Marlin/platformio.ini
Marlin/*/platformio.ini
Marlin/*/*/platformio.ini
Marlin/*/*/*/platformio.ini
Marlin/*/*/*/*/platformio.ini
Marlin/.travis.yml
Marlin/*/.travis.yml
Marlin/*/*/.travis.yml
Marlin/*/*/*/.travis.yml
Marlin/*/*/*/*/.travis.yml
Marlin/.gitignore
Marlin/*/.gitignore
Marlin/*/*/.gitignore
Marlin/*/*/*/.gitignore
Marlin/*/*/*/*/.gitignore
Marlin/readme.txt
Marlin/*/readme.txt
Marlin/*/*/readme.txt
Marlin/*/*/*/readme.txt
Marlin/*/*/*/*/readme.txt
# Secure Credentials
Configuration_Secure.h

View File

@@ -163,8 +163,8 @@
* PRUSA_MMU1 : Průša MMU1 (The "multiplexer" version)
* PRUSA_MMU2 : Průša MMU2
* PRUSA_MMU2S : Průša MMU2S (Requires MK3S extruder with motion sensor, EXTRUDERS = 5)
* SMUFF_EMU_MMU2 : Technik Gegg SMuFF (Průša MMU2 emulation mode)
* SMUFF_EMU_MMU2S : Technik Gegg SMuFF (Průša MMU2S emulation mode)
* EXTENDABLE_EMU_MMU2 : MMU with configurable number of filaments (ERCF, SMuFF or similar with Průša MMU2 compatible firmware)
* EXTENDABLE_EMU_MMU2S : MMUS with configurable number of filaments (ERCF, SMuFF or similar with Průša MMU2 compatible firmware)
*
* Requires NOZZLE_PARK_FEATURE to park print head in case MMU unit fails.
* See additional options in Configuration_adv.h.
@@ -329,10 +329,13 @@
#define AUTO_POWER_E_FANS
#define AUTO_POWER_CONTROLLERFAN
#define AUTO_POWER_CHAMBER_FAN
#define AUTO_POWER_E_TEMP 50 // (°C) Turn on PSU if any extruder is over this temperature
#define AUTO_POWER_COOLER_FAN
//#define AUTO_POWER_E_TEMP 50 // (°C) Turn on PSU if any extruder is over this temperature
//#define AUTO_POWER_CHAMBER_TEMP 30 // (°C) Turn on PSU if the chamber is over this temperature
// #define POWER_TIMEOUT 30 // (s) Turn off power if the machine is idle for this duration
//#define AUTO_POWER_COOLER_TEMP 26 // (°C) Turn on PSU if the cooler is over this temperature
#define POWER_TIMEOUT 30 // (s) Turn off power if the machine is idle for this duration
//#define POWER_OFF_DELAY 60 // (s) Delay of poweroff after M81 command. Useful to let fans run for extra time.
#endif
#endif
@@ -418,6 +421,7 @@
#define TEMP_SENSOR_BED 1
#define TEMP_SENSOR_PROBE 0
#define TEMP_SENSOR_CHAMBER 0
#define TEMP_SENSOR_COOLER 0
// Dummy thermistor constant temperature readings, for use with 998 and 999
#define DUMMY_THERMISTOR_998_VALUE 25
@@ -473,6 +477,16 @@
#define BED_MAXTEMP 150
#define CHAMBER_MAXTEMP 60
/**
* Thermal Overshoot
* During heatup (and printing) the temperature can often "overshoot" the target by many degrees
* (especially before PID tuning). Setting the target temperature too close to MAXTEMP guarantees
* a MAXTEMP shutdown! Use these values to forbid temperatures being set too close to MAXTEMP.
*/
#define HOTEND_OVERSHOOT 15 // (°C) Forbid temperatures over MAXTEMP - OVERSHOOT
#define BED_OVERSHOOT 10 // (°C) Forbid temperatures over MAXTEMP - OVERSHOOT
#define COOLER_OVERSHOOT 2 // (°C) Forbid temperatures closer than OVERSHOOT
//===========================================================================
//============================= PID Settings ================================
//===========================================================================
@@ -637,6 +651,7 @@
#define THERMAL_PROTECTION_HOTENDS // Enable thermal protection for all extruders
#define THERMAL_PROTECTION_BED // Enable thermal protection for the heated bed
#define THERMAL_PROTECTION_CHAMBER // Enable thermal protection for the heated chamber
#define THERMAL_PROTECTION_COOLER // Enable thermal protection for the laser cooling
//===========================================================================
//============================= Mechanical Settings =========================
@@ -922,7 +937,6 @@
* or (with LCD_BED_LEVELING) the LCD controller.
*/
//#define PROBE_MANUALLY
//#define MANUAL_PROBE_START_Z 0.2
/**
* A Fix-Mounted Probe either doesn't deploy or needs manual deployment.
@@ -1214,10 +1228,12 @@
// @section machine
// The size of the print bed
#define X_BED_SIZE 227
#define Y_BED_SIZE 148
// Travel limits (mm) after homing, corresponding to endstop positions.
#define X_MIN_POS 0
#define Y_MIN_POS 0
@@ -1268,7 +1284,7 @@
* RAMPS-based boards use SERVO3_PIN for the first runout sensor.
* For other boards you may need to define FIL_RUNOUT_PIN, FIL_RUNOUT2_PIN, etc.
*/
//#define FILAMENT_RUNOUT_SENSOR
#define FILAMENT_RUNOUT_SENSOR
#if ENABLED(FILAMENT_RUNOUT_SENSOR)
#define FIL_RUNOUT_ENABLED_DEFAULT true // Enable the sensor on startup. Override with M412 followed by M500.
#define NUM_RUNOUT_SENSORS 1 // Number of sensors, up to one per extruder. Define a FIL_RUNOUT#_PIN for each.
@@ -1279,6 +1295,8 @@
//#define WATCH_ALL_RUNOUT_SENSORS // Execute runout script on any triggering sensor, not only for the active extruder.
// This is automatically enabled for MIXING_EXTRUDERs.
// Override individually if the runout sensors vary
//#define FIL_RUNOUT1_STATE LOW
//#define FIL_RUNOUT1_PULLUP
@@ -1320,13 +1338,13 @@
// After a runout is detected, continue printing this length of filament
// before executing the runout script. Useful for a sensor at the end of
// a feed tube. Requires 4 bytes SRAM per sensor, plus 4 bytes overhead.
//#define FILAMENT_RUNOUT_DISTANCE_MM 25
#define FILAMENT_RUNOUT_DISTANCE_MM 7
#ifdef FILAMENT_RUNOUT_DISTANCE_MM
// Enable this option to use an encoder disc that toggles the runout pin
// as the filament moves. (Be sure to set FILAMENT_RUNOUT_DISTANCE_MM
// large enough to avoid false positives.)
//#define FILAMENT_MOTION_SENSOR
#define FILAMENT_MOTION_SENSOR
#endif
#endif
@@ -1398,6 +1416,11 @@
*/
//#define DEBUG_LEVELING_FEATURE
#if ANY(MESH_BED_LEVELING, AUTO_BED_LEVELING_UBL, PROBE_MANUALLY)
// Set a height for the start of manual adjustment
#define MANUAL_PROBE_START_Z 0.2 // (mm) Comment out to use the last-measured height
#endif
#if ANY(MESH_BED_LEVELING, AUTO_BED_LEVELING_BILINEAR, AUTO_BED_LEVELING_UBL)
// Gradually reduce leveling correction until a set height is reached,
// at which point movement will be level to the machine's XY plane.
@@ -1468,6 +1491,8 @@
#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 UBL_HILBERT_CURVE // Use Hilbert distribution for less travel when probing multiple points
#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
@@ -2171,6 +2196,11 @@
//
//#define REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER
//
// K.3D Full Graphic Smart Controller
//
//#define K3D_FULL_GRAPHIC_SMART_CONTROLLER
//
// ReprapWorld Graphical LCD
// https://reprapworld.com/?products_details&products_id/1218
@@ -2308,7 +2338,7 @@
//#define OLED_PANEL_TINYBOY2
//
// MKS OLED 1.3" 128×64 FULL GRAPHICS CONTROLLER
// MKS OLED 1.3" 128×64 Full Graphics Controller
// https://reprap.org/wiki/MKS_12864OLED
//
// Tiny, but very sharp OLED display
@@ -2317,7 +2347,7 @@
//#define MKS_12864OLED_SSD1306 // Uses the SSD1306 controller
//
// Zonestar OLED 128×64 FULL GRAPHICS CONTROLLER
// Zonestar OLED 128×64 Full Graphics Controller
//
//#define ZONESTAR_12864LCD // Graphical (DOGM) with ST7920 controller
//#define ZONESTAR_12864OLED // 1.3" OLED with SH1106 controller (default)
@@ -2334,10 +2364,15 @@
//#define OVERLORD_OLED
//
// FYSETC OLED 2.42" 128×64 FULL GRAPHICS CONTROLLER with WS2812 RGB
// FYSETC OLED 2.42" 128×64 Full Graphics Controller with WS2812 RGB
// Where to find : https://www.aliexpress.com/item/4000345255731.html
//#define FYSETC_242_OLED_12864 // Uses the SSD1309 controller
//
// K.3D SSD1309 OLED 2.42" 128×64 Full Graphics Controller
//
//#define K3D_242_OLED_CONTROLLER // Software SPI
//=============================================================================
//========================== Extensible UI Displays ===========================
//=============================================================================
@@ -2350,7 +2385,11 @@
//#define DGUS_LCD_UI_ORIGIN
//#define DGUS_LCD_UI_FYSETC
//#define DGUS_LCD_UI_HIPRECY
//#define DGUS_LCD_UI_MKS
#if ENABLED(DGUS_LCD_UI_MKS)
#define USE_MKS_GREEN_UI
#endif
//
// Touch-screen LCD for Malyan M200/M300 printers
@@ -2376,6 +2415,14 @@
//#define ANYCUBIC_LCD_DEBUG
#endif
//
// 320x240 Nextion 2.8" serial TFT Resistive Touch Screen NX3224T028
//
//#define NEXTION_TFT
#if ENABLED(NEXTION_TFT)
#define LCD_SERIAL_PORT 1 // Default is 1 for Nextion
#endif
//
// Third-party or vendor-customized controller interfaces.
// Sources should be installed in 'src/lcd/extui'.
@@ -2461,6 +2508,11 @@
//
//#define ANET_ET5_TFT35
//
// 1024x600, 7", RGB Stock Display from BIQU-BX
//
//#define BIQU_BX_TFT70
//
// Generic TFT with detailed options
//
@@ -2615,7 +2667,7 @@
* more current than the Arduino 5V linear regulator can produce.
* *** CAUTION ***
*
* LED Type. Enable only one of the following two options.
* LED Typ/FYe. Enable only one of the following two options.
*/
//#define RGB_LED
//#define RGBW_LED
@@ -2632,18 +2684,18 @@
#if ENABLED(NEOPIXEL_LED)
#define NEOPIXEL_TYPE NEO_GRB // NEO_GRBW / NEO_GRB - four/three channel driver type (defined in Adafruit_NeoPixel.h)
// #define NEOPIXEL_PIN 4 // LED driving pin
//#define NEOPIXEL2_TYPE NEOPIXEL_TYPE
//#define NEOPIXEL2_PIN 5
#define NEOPIXEL_PIXELS 3 // Number of LEDs in the strip. (Longest strip when NEOPIXEL2_SEPARATE is disabled.)
#define NEOPIXEL2_TYPE NEO_GRB
#define NEOPIXEL2_PIN P1_24
#define NEOPIXEL_PIXELS 30 // Number of LEDs in the strip. (Longest strip when NEOPIXEL2_SEPARATE is disabled.)
#define NEOPIXEL_IS_SEQUENTIAL // Sequential display for temperature change - LED by LED. Disable to change all LEDs at once.
#define NEOPIXEL_BRIGHTNESS 255 // Initial brightness (0-255)
//#define NEOPIXEL_STARTUP_TEST // Cycle through colors at startup
#define NEOPIXEL_STARTUP_TEST // Cycle through colors at startup
// Support for second Adafruit NeoPixel LED driver controlled with M150 S1 ...
//#define NEOPIXEL2_SEPARATE
#define NEOPIXEL2_SEPARATE
#if ENABLED(NEOPIXEL2_SEPARATE)
#define NEOPIXEL2_PIXELS 15 // Number of LEDs in the second strip
#define NEOPIXEL2_BRIGHTNESS 127 // Initial brightness (0-255)
#define NEOPIXEL2_PIXELS 30 // Number of LEDs in the second strip
#define NEOPIXEL2_BRIGHTNESS 255 // Initial brightness (0-255)
#define NEOPIXEL2_STARTUP_TEST // Cycle through colors at startup
#else
//#define NEOPIXEL2_INSERIES // Default behavior is NeoPixel 2 in parallel

View File

@@ -113,6 +113,12 @@
#define CHAMBER_BETA 3950 // Beta value
#endif
#if TEMP_SENSOR_COOLER == 1000
#define COOLER_PULLUP_RESISTOR_OHMS 4700 // Pullup resistor
#define COOLER_RESISTANCE_25C_OHMS 100000 // Resistance at 25C
#define COOLER_BETA 3950 // Beta value
#endif
#if TEMP_SENSOR_PROBE == 1000
#define PROBE_PULLUP_RESISTOR_OHMS 4700 // Pullup resistor
#define PROBE_RESISTANCE_25C_OHMS 100000 // Resistance at 25C
@@ -157,7 +163,7 @@
//#define CHAMBER_FAN // Enable a fan on the chamber
#if ENABLED(CHAMBER_FAN)
#define CHAMBER_FAN_MODE 2 // Fan control mode: 0=Static; 1=Linear increase when temp is higher than target; 2=V-shaped curve.
#define CHAMBER_FAN_MODE 2 // Fan control mode: 0=Static; 1=Linear increase when temp is higher than target; 2=V-shaped curve; 3=similar to 1 but fan is always on.
#if CHAMBER_FAN_MODE == 0
#define CHAMBER_FAN_BASE 255 // Chamber fan PWM (0-255)
#elif CHAMBER_FAN_MODE == 1
@@ -166,6 +172,9 @@
#elif CHAMBER_FAN_MODE == 2
#define CHAMBER_FAN_BASE 128 // Minimum chamber fan PWM (0-255)
#define CHAMBER_FAN_FACTOR 25 // PWM increase per °C difference from target
#elif CHAMBER_FAN_MODE == 3
#define CHAMBER_FAN_BASE 128 // Base chamber fan PWM (0-255)
#define CHAMBER_FAN_FACTOR 25 // PWM increase per °C above target
#endif
#endif
@@ -179,6 +188,39 @@
#endif
#endif
//
// Laser Cooler options
//
#if TEMP_SENSOR_COOLER
#define COOLER_MINTEMP 8 // (°C)
#define COOLER_MAXTEMP 26 // (°C)
#define COOLER_DEFAULT_TEMP 16 // (°C)
#define TEMP_COOLER_HYSTERESIS 1 // (°C) Temperature proximity considered "close enough" to the target
#define COOLER_PIN 8 // Laser cooler on/off pin used to control power to the cooling element e.g. TEC, External chiller via relay
#define COOLER_INVERTING false
#define TEMP_COOLER_PIN 15 // Laser/Cooler temperature sensor pin. ADC is required.
#define COOLER_FAN // Enable a fan on the cooler, Fan# 0,1,2,3 etc.
#define COOLER_FAN_INDEX 0 // FAN number 0, 1, 2 etc. e.g.
#if ENABLED(COOLER_FAN)
#define COOLER_FAN_BASE 100 // Base Cooler fan PWM (0-255); turns on when Cooler temperature is above the target
#define COOLER_FAN_FACTOR 25 // PWM increase per °C above target
#endif
#endif
//
// Laser Coolant Flow Meter
//
//#define LASER_COOLANT_FLOW_METER
#if ENABLED(LASER_COOLANT_FLOW_METER)
#define FLOWMETER_PIN 20 // Requires an external interrupt-enabled pin (e.g., RAMPS 2,3,18,19,20,21)
#define FLOWMETER_PPL 5880 // (pulses/liter) Flow meter pulses-per-liter on the input pin
#define FLOWMETER_INTERVAL 1000 // (ms) Flow rate calculation interval in milliseconds
#define FLOWMETER_SAFETY // Prevent running the laser without the minimum flow rate set below
#if ENABLED(FLOWMETER_SAFETY)
#define FLOWMETER_MIN_LITERS_PER_MINUTE 1.5 // (liters/min) Minimum flow required when enabled
#endif
#endif
/**
* Thermal Protection provides additional protection to your printer from damage
* and fire. Marlin always includes safe min and max temperature ranges which
@@ -248,6 +290,20 @@
#define WATCH_CHAMBER_TEMP_INCREASE 2 // Degrees Celsius
#endif
/**
* Thermal Protection parameters for the laser cooler.
*/
#if ENABLED(THERMAL_PROTECTION_COOLER)
#define THERMAL_PROTECTION_COOLER_PERIOD 10 // Seconds
#define THERMAL_PROTECTION_COOLER_HYSTERESIS 3 // Degrees Celsius
/**
* Laser cooling watch settings (M143/M193).
*/
#define WATCH_COOLER_TEMP_PERIOD 60 // Seconds
#define WATCH_COOLER_TEMP_INCREASE 3 // Degrees Celsius
#endif
#if ENABLED(PIDTEMP)
// Add an experimental additional term to the heater power, proportional to the extrusion speed.
// A well-chosen Kc value should add just enough power to melt the increased material volume.
@@ -493,11 +549,15 @@
#define E6_AUTO_FAN_PIN -1
#define E7_AUTO_FAN_PIN -1
#define CHAMBER_AUTO_FAN_PIN -1
#define COOLER_AUTO_FAN_PIN -1
#define COOLER_FAN_PIN -1
#define EXTRUDER_AUTO_FAN_TEMPERATURE 50
#define EXTRUDER_AUTO_FAN_SPEED 255 // 255 == full speed
#define CHAMBER_AUTO_FAN_TEMPERATURE 30
#define CHAMBER_AUTO_FAN_SPEED 255
#define COOLER_AUTO_FAN_TEMPERATURE 18
#define COOLER_AUTO_FAN_SPEED 255
/**
* Part-Cooling Fan Multiplexer
@@ -912,6 +972,9 @@
#define BACKLASH_DISTANCE_MM { 0, 0, 0 } // (mm)
#define BACKLASH_CORRECTION 0.0 // 0.0 = no correction; 1.0 = full correction
// Add steps for motor direction changes on CORE kinematics
//#define CORE_BACKLASH
// Set BACKLASH_SMOOTHING_MM to spread backlash correction over multiple segments
// to reduce print artifacts. (Enabling this is costly in memory and computation!)
//#define BACKLASH_SMOOTHING_MM 3 // (mm)
@@ -1420,6 +1483,15 @@
// Enable if SD detect is rendered useless (e.g., by using an SD extender)
//#define NO_SD_DETECT
// Multiple volume support - EXPERIMENTAL.
//#define MULTI_VOLUME
#if ENABLED(MULTI_VOLUME)
#define VOLUME_SD_ONBOARD
#define VOLUME_USB_FLASH_DRIVE
#define DEFAULT_VOLUME SD_ONBOARD
#define DEFAULT_SHARED_VOLUME USB_FLASH_DRIVE
#endif
#endif // SDSUPPORT
/**
@@ -1497,6 +1569,8 @@
#define STATUS_BED_ANIM // Use a second bitmap to indicate bed heating
#define STATUS_CHAMBER_ANIM // Use a second bitmap to indicate chamber heating
//#define STATUS_CUTTER_ANIM // Use a second bitmap to indicate spindle / laser active
//#define STATUS_COOLER_ANIM // Use a second bitmap to indicate laser cooling
//#define STATUS_FLOWMETER_ANIM // Use multiple bitmaps to indicate coolant flow
//#define STATUS_ALT_BED_BITMAP // Use the alternative bed bitmap
//#define STATUS_ALT_FAN_BITMAP // Use the alternative fan bitmap
//#define STATUS_FAN_FRAMES 3 // :[0,1,2,3,4] Number of fan animation frames
@@ -1548,6 +1622,31 @@
#endif
#endif // HAS_DGUS_LCD
//
// Additional options for AnyCubic Chiron TFT displays
//
#if ENABLED(ANYCUBIC_LCD_CHIRON)
// By default the type of panel is automatically detected.
// Enable one of these options if you know the panel type.
//#define CHIRON_TFT_STANDARD
//#define CHIRON_TFT_NEW
// Enable the longer Anycubic powerup startup tune
//#define AC_DEFAULT_STARTUP_TUNE
/**
* Display Folders
* By default the file browser lists all G-code files (including those in subfolders) in a flat list.
* Enable this option to display a hierarchical file browser.
*
* NOTES:
* - Without this option it helps to enable SDCARD_SORT_ALPHA so files are sorted before/after folders.
* - When used with the "new" panel, folder names will also have '.gcode' appended to their names.
* This hack is currently required to force the panel to show folders.
*/
#define AC_SD_FOLDER_VIEW
#endif
//
// Specify additional languages for the UI. Default specified by LCD_LANGUAGE.
//
@@ -2046,6 +2145,26 @@
*/
//#define EMERGENCY_PARSER
/**
* Realtime Reporting (requires EMERGENCY_PARSER)
*
* - Report position and state of the machine (like Grbl).
* - Auto-report position during long moves.
* - Useful for CNC/LASER.
*
* Adds support for commands:
* S000 : Report State and Position while moving.
* P000 : Instant Pause / Hold while moving.
* R000 : Resume from Pause / Hold.
*
* - During Hold all Emergency Parser commands are available, as usual.
* - Enable NANODLP_Z_SYNC and NANODLP_ALL_AXIS for move command end-state reports.
*/
//#define REALTIME_REPORTING_COMMANDS
#if ENABLED(REALTIME_REPORTING_COMMANDS)
//#define FULL_REPORT_TO_HOST_FEATURE // Auto-report the machine status like Grbl CNC
#endif
// Bad Serial-connections can miss a received command by sending an 'ok'
// Therefore some clients abort after 30 seconds in a timeout.
// Some other clients start sending commands while receiving a 'wait'.
@@ -2120,6 +2239,12 @@
//#define EVENT_GCODE_AFTER_TOOLCHANGE "G12X" // Extra G-code to run after tool-change
#endif
/**
* Tool Sensors detect when tools have been picked up or dropped.
* Requires the pins TOOL_SENSOR1_PIN, TOOL_SENSOR2_PIN, etc.
*/
//#define TOOL_SENSOR
/**
* Retract and prime filament on tool-change to reduce
* ooze and stringing and to get cleaner transitions.
@@ -2596,6 +2721,7 @@
* Define your own with:
* { <off_time[1..15]>, <hysteresis_end[-3..12]>, hysteresis_start[1..8] }
*/
#define CHOPPER_TIMING CHOPPER_DEFAULT_24V // All axes (override below)
//#define CHOPPER_TIMING_X CHOPPER_DEFAULT_12V // For X Axes (override below)
//#define CHOPPER_TIMING_X2 CHOPPER_DEFAULT_12V
@@ -2614,6 +2740,25 @@
//#define CHOPPER_TIMING_E6 CHOPPER_DEFAULT_12V
//#define CHOPPER_TIMING_E7 CHOPPER_DEFAULT_12V
// #define CHOPPER_TIMING CHOPPER_DEFAULT_12V // All axes (override below)
//#define CHOPPER_TIMING_X CHOPPER_TIMING // For X Axes (override below)
//#define CHOPPER_TIMING_X2 CHOPPER_TIMING_X
//#define CHOPPER_TIMING_Y CHOPPER_TIMING // For Y Axes (override below)
//#define CHOPPER_TIMING_Y2 CHOPPER_TIMING_Y
//#define CHOPPER_TIMING_Z CHOPPER_TIMING // For Z Axes (override below)
//#define CHOPPER_TIMING_Z2 CHOPPER_TIMING_Z
//#define CHOPPER_TIMING_Z3 CHOPPER_TIMING_Z
//#define CHOPPER_TIMING_Z4 CHOPPER_TIMING_Z
//#define CHOPPER_TIMING_E CHOPPER_TIMING // For Extruders (override below)
//#define CHOPPER_TIMING_E1 CHOPPER_TIMING_E
//#define CHOPPER_TIMING_E2 CHOPPER_TIMING_E
//#define CHOPPER_TIMING_E3 CHOPPER_TIMING_E
//#define CHOPPER_TIMING_E4 CHOPPER_TIMING_E
//#define CHOPPER_TIMING_E5 CHOPPER_TIMING_E
//#define CHOPPER_TIMING_E6 CHOPPER_TIMING_E
//#define CHOPPER_TIMING_E7 CHOPPER_TIMING_E
/**
* Monitor Trinamic drivers
* for error conditions like overtemperature and short to ground.
@@ -2685,20 +2830,20 @@
* Comment *_STALL_SENSITIVITY to disable sensorless homing for that axis.
*/
//#define SENSORLESS_HOMING // StallGuard capable drivers only
#define SENSORLESS_HOMING // StallGuard capable drivers only
#if EITHER(SENSORLESS_HOMING, SENSORLESS_PROBING)
// TMC2209: 0...255. TMC2130: -64...63
//#define X_STALL_SENSITIVITY 15
#define X_STALL_SENSITIVITY 15
// #define X2_STALL_SENSITIVITY X_STALL_SENSITIVITY
//#define Y_STALL_SENSITIVITY 15
#define Y_STALL_SENSITIVITY 15
// #define Y2_STALL_SENSITIVITY Y_STALL_SENSITIVITY
// #define Z_STALL_SENSITIVITY 6
//#define Z2_STALL_SENSITIVITY Z_STALL_SENSITIVITY
//#define Z3_STALL_SENSITIVITY Z_STALL_SENSITIVITY
//#define Z4_STALL_SENSITIVITY Z_STALL_SENSITIVITY
//#define SPI_ENDSTOPS // TMC2130 only
//#define IMPROVE_HOMING_RELIABILITY
#define IMPROVE_HOMING_RELIABILITY
#endif
/**
@@ -2721,7 +2866,7 @@
/**
* Enable M122 debugging command for TMC stepper drivers.
* M122 S0/1 will enable continous reporting.
* M122 S0/1 will enable continuous reporting.
*/
#define TMC_DEBUG
@@ -3042,6 +3187,12 @@
#define SPINDLE_LASER_FREQUENCY 2500 // (Hz) Spindle/laser frequency (only on supported HALs: AVR and LPC)
//#define AIR_EVACUATION // Cutter Vacuum / Laser Blower motor control with G-codes M10-M11
#if ENABLED(AIR_EVACUATION)
#define AIR_EVACUATION_ACTIVE LOW // Set to "HIGH" if the on/off function is active HIGH
#define AIR_EVACUATION_PIN 42 // Override the default Cutter Vacuum or Laser Blower pin
#endif
//#define SPINDLE_SERVO // A servo converting an angle to spindle power
#ifdef SPINDLE_SERVO
#define SPINDLE_SERVO_NR 0 // Index of servo used for spindle control
@@ -3177,6 +3328,18 @@
#endif
#endif
/**
* Synchronous Laser Control with M106/M107
*
* Marlin normally applies M106/M107 fan speeds at a time "soon after" processing
* a planner block. This is too inaccurate for a PWM/TTL laser attached to the fan
* header (as with some add-on laser kits). Enable this option to set fan/laser
* speeds with much more exact timing for improved print fidelity.
*
* NOTE: This option sacrifices some cooling fan speed options.
*/
//#define LASER_SYNCHRONOUS_M106_M107
/**
* Coolant Control
*
@@ -3236,13 +3399,27 @@
*/
//#define POWER_MONITOR_CURRENT // Monitor the system current
//#define POWER_MONITOR_VOLTAGE // Monitor the system voltage
#if EITHER(POWER_MONITOR_CURRENT, POWER_MONITOR_VOLTAGE)
#if ENABLED(POWER_MONITOR_CURRENT)
#define POWER_MONITOR_VOLTS_PER_AMP 0.05000 // Input voltage to the MCU analog pin per amp - DO NOT apply more than ADC_VREF!
#define POWER_MONITOR_CURRENT_OFFSET -1 // Offset value for current sensors with linear function output
#define POWER_MONITOR_VOLTS_PER_VOLT 0.11786 // Input voltage to the MCU analog pin per volt - DO NOT apply more than ADC_VREF!
#define POWER_MONITOR_CURRENT_OFFSET 0 // Offset (in amps) applied to the calculated current
#define POWER_MONITOR_FIXED_VOLTAGE 13.6 // Voltage for a current sensor with no voltage sensor (for power display)
#endif
#if ENABLED(POWER_MONITOR_VOLTAGE)
#define POWER_MONITOR_VOLTS_PER_VOLT 0.077933 // Input voltage to the MCU analog pin per volt - DO NOT apply more than ADC_VREF!
#define POWER_MONITOR_VOLTAGE_OFFSET 0 // Offset (in volts) applied to the calculated voltage
#endif
/**
* Stepper Driver Anti-SNAFU Protection
*
* If the SAFE_POWER_PIN is defined for your board, Marlin will check
* that stepper drivers are properly plugged in before applying power.
* Disable protection if your stepper drivers don't support the feature.
*/
//#define DISABLE_DRIVER_SAFE_POWER_PROTECT
/**
* CNC Coordinate Systems
*
@@ -3309,7 +3486,7 @@
//#define NO_WORKSPACE_OFFSETS
// Extra options for the M114 "Current Position" report
//#define M114_DETAIL // Use 'M114` for details to check planner calculations
#define M114_DETAIL // Use 'M114` for details to check planner calculations
//#define M114_REALTIME // Real current position based on forward kinematics
//#define M114_LEGACY // M114 used to synchronize on every call. Enable if needed.
@@ -3333,7 +3510,9 @@
//#define GCODE_QUOTED_STRINGS // Support for quoted string parameters
#endif
//#define MEATPACK // Support for MeatPack G-code compression (https://github.com/scottmudge/OctoPrint-MeatPack)
// Support for MeatPack G-code compression (https://github.com/scottmudge/OctoPrint-MeatPack)
//#define MEATPACK_ON_SERIAL_PORT_1
//#define MEATPACK_ON_SERIAL_PORT_2
//#define GCODE_CASE_INSENSITIVE // Accept G-code sent to the firmware in lowercase
@@ -3373,6 +3552,71 @@
#define GCODE_MACROS_SLOT_SIZE 50 // Maximum length of a single macro
#endif
/**
* User-defined menu items to run custom G-code.
* Up to 25 may be defined, but the actual number is LCD-dependent.
*/
// Custom Menu: Main Menu
#define CUSTOM_MENU_MAIN
#if ENABLED(CUSTOM_MENU_MAIN)
#define CUSTOM_MENU_MAIN_TITLE "Custom Commands"
#define CUSTOM_MENU_MAIN_SCRIPT_DONE "M117 User Script Done"
#define CUSTOM_MENU_MAIN_SCRIPT_AUDIBLE_FEEDBACK
//#define CUSTOM_MENU_MAIN_SCRIPT_RETURN // Return to status screen after a script
#define CUSTOM_MENU_MAIN_ONLY_IDLE // Only show custom menu when the machine is idle
#define MAIN_MENU_ITEM_1_DESC "Home & UBL Info"
#define MAIN_MENU_ITEM_1_GCODE "G28\nG29 W"
//#define MAIN_MENU_ITEM_1_CONFIRM // Show a confirmation dialog before this action
#define MAIN_MENU_ITEM_2_DESC "Preheat for " PREHEAT_1_LABEL
#define MAIN_MENU_ITEM_2_GCODE "M140 S" STRINGIFY(PREHEAT_1_TEMP_BED) "\nM104 S" STRINGIFY(PREHEAT_1_TEMP_HOTEND)
//#define MAIN_MENU_ITEM_2_CONFIRM
//#define MAIN_MENU_ITEM_3_DESC "Preheat for " PREHEAT_2_LABEL
//#define MAIN_MENU_ITEM_3_GCODE "M140 S" STRINGIFY(PREHEAT_2_TEMP_BED) "\nM104 S" STRINGIFY(PREHEAT_2_TEMP_HOTEND)
//#define MAIN_MENU_ITEM_3_CONFIRM
//#define MAIN_MENU_ITEM_4_DESC "Heat Bed/Home/Level"
//#define MAIN_MENU_ITEM_4_GCODE "M140 S" STRINGIFY(PREHEAT_2_TEMP_BED) "\nG28\nG29"
//#define MAIN_MENU_ITEM_4_CONFIRM
//#define MAIN_MENU_ITEM_5_DESC "Home & Info"
//#define MAIN_MENU_ITEM_5_GCODE "G28\nM503"
//#define MAIN_MENU_ITEM_5_CONFIRM
#endif
// Custom Menu: Configuration Menu
//#define CUSTOM_MENU_CONFIG
#if ENABLED(CUSTOM_MENU_CONFIG)
//#define CUSTOM_MENU_CONFIG_TITLE "Custom Commands"
#define CUSTOM_MENU_CONFIG_SCRIPT_DONE "M117 Wireless Script Done"
#define CUSTOM_MENU_CONFIG_SCRIPT_AUDIBLE_FEEDBACK
//#define CUSTOM_MENU_CONFIG_SCRIPT_RETURN // Return to status screen after a script
#define CUSTOM_MENU_CONFIG_ONLY_IDLE // Only show custom menu when the machine is idle
#define CONFIG_MENU_ITEM_1_DESC "Wifi ON"
#define CONFIG_MENU_ITEM_1_GCODE "M118 [ESP110] WIFI-STA pwd=12345678"
//#define CONFIG_MENU_ITEM_1_CONFIRM // Show a confirmation dialog before this action
#define CONFIG_MENU_ITEM_2_DESC "Bluetooth ON"
#define CONFIG_MENU_ITEM_2_GCODE "M118 [ESP110] BT pwd=12345678"
//#define CONFIG_MENU_ITEM_2_CONFIRM
//#define CONFIG_MENU_ITEM_3_DESC "Radio OFF"
//#define CONFIG_MENU_ITEM_3_GCODE "M118 [ESP110] OFF pwd=12345678"
//#define CONFIG_MENU_ITEM_3_CONFIRM
//#define CONFIG_MENU_ITEM_4_DESC "Wifi ????"
//#define CONFIG_MENU_ITEM_4_GCODE "M118 ????"
//#define CONFIG_MENU_ITEM_4_CONFIRM
//#define CONFIG_MENU_ITEM_5_DESC "Wifi ????"
//#define CONFIG_MENU_ITEM_5_GCODE "M118 ????"
//#define CONFIG_MENU_ITEM_5_CONFIRM
#endif
/**
* User-defined buttons to run custom G-code.
* Up to 25 may be defined.
@@ -3380,7 +3624,7 @@
//#define CUSTOM_USER_BUTTONS
#if ENABLED(CUSTOM_USER_BUTTONS)
//#define BUTTON1_PIN -1
#if PIN_EXISTS(BUTTON1_PIN)
#if PIN_EXISTS(BUTTON1)
#define BUTTON1_HIT_STATE LOW // State of the triggered button. NC=LOW. NO=HIGH.
#define BUTTON1_WHEN_PRINTING false // Button allowed to trigger during printing?
#define BUTTON1_GCODE "G28"
@@ -3388,7 +3632,7 @@
#endif
//#define BUTTON2_PIN -1
#if PIN_EXISTS(BUTTON2_PIN)
#if PIN_EXISTS(BUTTON2)
#define BUTTON2_HIT_STATE LOW
#define BUTTON2_WHEN_PRINTING false
#define BUTTON2_GCODE "M140 S" STRINGIFY(PREHEAT_1_TEMP_BED) "\nM104 S" STRINGIFY(PREHEAT_1_TEMP_HOTEND)
@@ -3396,7 +3640,7 @@
#endif
//#define BUTTON3_PIN -1
#if PIN_EXISTS(BUTTON3_PIN)
#if PIN_EXISTS(BUTTON3)
#define BUTTON3_HIT_STATE LOW
#define BUTTON3_WHEN_PRINTING false
#define BUTTON3_GCODE "M140 S" STRINGIFY(PREHEAT_2_TEMP_BED) "\nM104 S" STRINGIFY(PREHEAT_2_TEMP_HOTEND)
@@ -3405,33 +3649,7 @@
#endif
/**
* User-defined menu items to run custom G-code.
* Up to 25 may be defined, but the actual number is LCD-dependent.
*/
#define CUSTOM_USER_MENUS
#if ENABLED(CUSTOM_USER_MENUS)
//#define CUSTOM_USER_MENU_TITLE "Custom Commands"
#define USER_SCRIPT_DONE "M117 User Script Done"
#define USER_SCRIPT_AUDIBLE_FEEDBACK
//#define USER_SCRIPT_RETURN // Return to status screen after a script
#define USER_DESC_1 "Home & UBL Info"
#define USER_GCODE_1 "G28\nG29W"
#define USER_DESC_2 "Preheat for " PREHEAT_1_LABEL
#define USER_GCODE_2 "M140 S" STRINGIFY(PREHEAT_1_TEMP_BED) "\nM104 S" STRINGIFY(PREHEAT_1_TEMP_HOTEND)
#define USER_DESC_3 "Preheat for " PREHEAT_2_LABEL
#define USER_GCODE_3 "M140 S" STRINGIFY(PREHEAT_2_TEMP_BED) "\nM104 S" STRINGIFY(PREHEAT_2_TEMP_HOTEND)
#define USER_DESC_4 "Heat Bed/Home/Level"
#define USER_GCODE_4 "M140 S" STRINGIFY(PREHEAT_2_TEMP_BED) "\nG28\nG29"
#define USER_DESC_5 "Home & Info"
#define USER_GCODE_5 "G28\nM503"
#endif
/**
* Host Action Commands
*
* Define host streamer action commands in compliance with the standard.
@@ -3457,6 +3675,9 @@
* Implement M486 to allow Marlin to skip objects
*/
//#define CANCEL_OBJECTS
#if ENABLED(CANCEL_OBJECTS)
#define CANCEL_OBJECTS_REPORTING // Emit the current object as a status message
#endif
/**
* I2C position encoders for closed loop control.
@@ -3614,14 +3835,13 @@
/**
* NanoDLP Sync support
*
* Add support for Synchronized Z moves when using with NanoDLP. G0/G1 axis moves will output "Z_move_comp"
* string to enable synchronization with DLP projector exposure. This change will allow to use
* [[WaitForDoneMessage]] instead of populating your gcode with M400 commands
* Support for Synchronized Z moves when used with NanoDLP. G0/G1 axis moves will
* output a "Z_move_comp" string to enable synchronization with DLP projector exposure.
* This feature allows you to use [[WaitForDoneMessage]] instead of M400 commands.
*/
//#define NANODLP_Z_SYNC
#if ENABLED(NANODLP_Z_SYNC)
//#define NANODLP_ALL_AXIS // Enables "Z_move_comp" output on any axis move.
// Default behavior is limited to Z axis only.
//#define NANODLP_ALL_AXIS // Send a "Z_move_comp" report for any axis move (not just Z).
#endif
/**
@@ -3796,3 +4016,9 @@
* a crash from a remote location. Requires ~400 bytes of SRAM and 5Kb of flash.
*/
//#define POSTMORTEM_DEBUGGING
/**
* Software Reset options
*/
//#define SOFT_RESET_VIA_SERIAL // 'KILL' and '^X' commands will soft-reset the controller
//#define SOFT_RESET_ON_KILL // Use a digital button to soft-reset the controller after KILL

View File

@@ -219,7 +219,7 @@ else ifeq ($(HARDWARE_MOTHERBOARD),1111)
else ifeq ($(HARDWARE_MOTHERBOARD),1112)
# MKS GEN L
else ifeq ($(HARDWARE_MOTHERBOARD),1113)
# zrib V2.0 control board (Chinese knock off RAMPS replica)
# zrib V2.0 control board (Chinese RAMPS replica)
else ifeq ($(HARDWARE_MOTHERBOARD),1114)
# BigTreeTech or BIQU KFB2.0
else ifeq ($(HARDWARE_MOTHERBOARD),1115)
@@ -993,5 +993,5 @@ clean:
.PHONY: all build elf hex eep lss sym program coff extcoff clean depend sizebefore sizeafter
# Automaticaly include the dependency files created by gcc
# Automatically include the dependency files created by gcc
-include ${patsubst %.o, %.d, ${OBJ}}

View File

@@ -25,7 +25,7 @@
#include "HAL.h"
#ifdef USBCON
DefaultSerial MSerial(false, Serial);
DefaultSerial1 MSerial0(false, Serial);
#ifdef BLUETOOTH
BTSerial btSerial(false, bluetoothSerial);
#endif
@@ -58,6 +58,15 @@ void HAL_init() {
#endif
}
void HAL_reboot() {
#if ENABLED(USE_WATCHDOG)
while (1) { /* run out the watchdog */ }
#else
void (*resetFunc)() = 0; // Declare resetFunc() at address 0
resetFunc(); // Jump to address 0
#endif
}
#if ENABLED(SDSUPPORT)
#include "../../sd/SdFatUtil.h"

View File

@@ -83,38 +83,38 @@ typedef int8_t pin_t;
// Serial ports
#ifdef USBCON
#include "../../core/serial_hook.h"
typedef ForwardSerial0Type< decltype(Serial) > DefaultSerial;
extern DefaultSerial MSerial;
typedef ForwardSerial1Class< decltype(Serial) > DefaultSerial1;
extern DefaultSerial1 MSerial0;
#ifdef BLUETOOTH
typedef ForwardSerial0Type< decltype(bluetoothSerial) > BTSerial;
typedef ForwardSerial1Class< decltype(bluetoothSerial) > BTSerial;
extern BTSerial btSerial;
#endif
#define MYSERIAL0 TERN(BLUETOOTH, btSerial, MSerial)
#define MYSERIAL1 TERN(BLUETOOTH, btSerial, MSerial0)
#else
#if !WITHIN(SERIAL_PORT, -1, 3)
#error "SERIAL_PORT must be from -1 to 3. Please update your configuration."
#error "SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
#endif
#define MYSERIAL0 customizedSerial1
#define MYSERIAL1 customizedSerial1
#ifdef SERIAL_PORT_2
#if !WITHIN(SERIAL_PORT_2, -1, 3)
#error "SERIAL_PORT_2 must be from -1 to 3. Please update your configuration."
#error "SERIAL_PORT_2 must be from 0 to 3. You can also use -1 if the board supports Native USB."
#endif
#define MYSERIAL1 customizedSerial2
#define MYSERIAL2 customizedSerial2
#endif
#endif
#ifdef MMU2_SERIAL_PORT
#if !WITHIN(MMU2_SERIAL_PORT, -1, 3)
#error "MMU2_SERIAL_PORT must be from -1 to 3. Please update your configuration."
#error "MMU2_SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
#endif
#define MMU2_SERIAL mmuSerial
#endif
#ifdef LCD_SERIAL_PORT
#if !WITHIN(LCD_SERIAL_PORT, -1, 3)
#error "LCD_SERIAL_PORT must be from -1 to 3. Please update your configuration."
#error "LCD_SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
#endif
#define LCD_SERIAL lcdSerial
#if HAS_DGUS_LCD
@@ -135,7 +135,7 @@ void HAL_init();
inline void HAL_clear_reset_source() { MCUSR = 0; }
inline uint8_t HAL_get_reset_source() { return MCUSR; }
inline void HAL_reboot() {} // reboot the board or restart the bootloader
void HAL_reboot();
#if GCC_VERSION <= 50000
#pragma GCC diagnostic push

View File

@@ -454,7 +454,7 @@ void MarlinSerial<Cfg>::flush() {
}
template<typename Cfg>
size_t MarlinSerial<Cfg>::write(const uint8_t c) {
void MarlinSerial<Cfg>::write(const uint8_t c) {
if (Cfg::TX_SIZE == 0) {
_written = true;
@@ -480,7 +480,7 @@ size_t MarlinSerial<Cfg>::write(const uint8_t c) {
// location". This makes sure flush() won't return until the bytes
// actually got written
B_TXC = 1;
return 1;
return;
}
const uint8_t i = (tx_buffer.head + 1) & (Cfg::TX_SIZE - 1);
@@ -510,7 +510,6 @@ size_t MarlinSerial<Cfg>::write(const uint8_t c) {
// Enable TX ISR - Non atomic, but it will eventually enable TX ISR
B_UDRIE = 1;
}
return 1;
}
template<typename Cfg>

View File

@@ -210,7 +210,7 @@
static int read();
static void flush();
static ring_buffer_pos_t available();
static size_t write(const uint8_t c);
static void write(const uint8_t c);
static void flushTX();
#if HAS_DGUS_LCD
static ring_buffer_pos_t get_tx_buffer_free();
@@ -238,11 +238,11 @@
static constexpr bool MAX_RX_QUEUED = ENABLED(SERIAL_STATS_MAX_RX_QUEUED);
};
typedef Serial0Type< MarlinSerial< MarlinSerialCfg<SERIAL_PORT> > > MSerialT;
typedef Serial1Class< MarlinSerial< MarlinSerialCfg<SERIAL_PORT> > > MSerialT;
extern MSerialT customizedSerial1;
#ifdef SERIAL_PORT_2
typedef Serial0Type< MarlinSerial< MarlinSerialCfg<SERIAL_PORT_2> > > MSerialT2;
typedef Serial1Class< MarlinSerial< MarlinSerialCfg<SERIAL_PORT_2> > > MSerialT2;
extern MSerialT2 customizedSerial2;
#endif
@@ -252,17 +252,17 @@
template <uint8_t serial>
struct MMU2SerialCfg {
static constexpr int PORT = serial;
static constexpr unsigned int RX_SIZE = 32;
static constexpr unsigned int TX_SIZE = 32;
static constexpr bool XONOFF = false;
static constexpr bool EMERGENCYPARSER = false;
static constexpr bool DROPPED_RX = false;
static constexpr bool RX_FRAMING_ERRORS = false;
static constexpr bool MAX_RX_QUEUED = false;
static constexpr unsigned int RX_SIZE = 32;
static constexpr unsigned int TX_SIZE = 32;
static constexpr bool RX_OVERRUNS = false;
};
typedef Serial0Type< MarlinSerial< MMU2SerialCfg<MMU2_SERIAL_PORT> > > MSerialT3;
typedef Serial1Class< MarlinSerial< MMU2SerialCfg<MMU2_SERIAL_PORT> > > MSerialT3;
extern MSerialT3 mmuSerial;
#endif
@@ -271,33 +271,22 @@
template <uint8_t serial>
struct LCDSerialCfg {
static constexpr int PORT = serial;
static constexpr unsigned int RX_SIZE = TERN(HAS_DGUS_LCD, DGUS_RX_BUFFER_SIZE, 64);
static constexpr unsigned int TX_SIZE = TERN(HAS_DGUS_LCD, DGUS_TX_BUFFER_SIZE, 128);
static constexpr bool XONOFF = false;
static constexpr bool EMERGENCYPARSER = ENABLED(EMERGENCY_PARSER);
static constexpr bool DROPPED_RX = false;
static constexpr bool RX_FRAMING_ERRORS = false;
static constexpr bool MAX_RX_QUEUED = false;
#if HAS_DGUS_LCD
static constexpr unsigned int RX_SIZE = DGUS_RX_BUFFER_SIZE;
static constexpr unsigned int TX_SIZE = DGUS_TX_BUFFER_SIZE;
static constexpr bool RX_OVERRUNS = ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS);
#elif EITHER(ANYCUBIC_LCD_I3MEGA, ANYCUBIC_LCD_CHIRON)
static constexpr unsigned int RX_SIZE = 64;
static constexpr unsigned int TX_SIZE = 128;
static constexpr bool RX_OVERRUNS = false;
#else
static constexpr unsigned int RX_SIZE = 64;
static constexpr unsigned int TX_SIZE = 128;
static constexpr bool RX_OVERRUNS = false
#endif
static constexpr bool RX_OVERRUNS = BOTH(HAS_DGUS_LCD, SERIAL_STATS_RX_BUFFER_OVERRUNS);
};
typedef Serial0Type< MarlinSerial< LCDSerialCfg<LCD_SERIAL_PORT> > > MSerialT4;
typedef Serial1Class< MarlinSerial< LCDSerialCfg<LCD_SERIAL_PORT> > > MSerialT4;
extern MSerialT4 lcdSerial;
#endif
// Use the UART for Bluetooth in AT90USB configurations
#if defined(USBCON) && ENABLED(BLUETOOTH)
typedef Serial0Type<HardwareSerial> MSerialT5;
typedef Serial1Class<HardwareSerial> MSerialT5;
extern MSerialT5 bluetoothSerial;
#endif

View File

@@ -40,13 +40,13 @@ bool PersistentStore::access_start() { return true; }
bool PersistentStore::access_finish() { return true; }
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
uint16_t written = 0;
while (size--) {
uint8_t * const p = (uint8_t * const)pos;
uint8_t v = *value;
// EEPROM has only ~100,000 write cycles,
// so only write bytes that have changed!
if (v != eeprom_read_byte(p)) {
if (v != eeprom_read_byte(p)) { // EEPROM has only ~100,000 write cycles, so only write bytes that have changed!
eeprom_write_byte(p, v);
if (++written & 0x7F) delay(2); else safe_delay(2); // Avoid triggering watchdog during long EEPROM writes
if (eeprom_read_byte(p) != v) {
SERIAL_ECHO_MSG(STR_ERR_EEPROM_WRITE);
return true;

View File

@@ -241,7 +241,7 @@ uint8_t extDigitalRead(const int8_t pin) {
*
* DC values -1.0 to 1.0. Negative duty cycle inverts the pulse.
*/
uint16_t set_pwm_frequency_hz(const float &hz, const float dca, const float dcb, const float dcc) {
uint16_t set_pwm_frequency_hz(const_float_t hz, const float dca, const float dcb, const float dcc) {
float count = 0;
if (hz > 0 && (dca || dcb || dcc)) {
count = float(F_CPU) / hz; // 1x prescaler, TOP for 16MHz base freq.

View File

@@ -285,7 +285,7 @@ enum ClockSource2 : char {
*/
// Determine which harware PWMs are already in use
#define _PWM_CHK_FAN_B(P) (P == E0_AUTO_FAN_PIN || P == E1_AUTO_FAN_PIN || P == E2_AUTO_FAN_PIN || P == E3_AUTO_FAN_PIN || P == E4_AUTO_FAN_PIN || P == E5_AUTO_FAN_PIN || P == E6_AUTO_FAN_PIN || P == E7_AUTO_FAN_PIN || P == CHAMBER_AUTO_FAN_PIN)
#define _PWM_CHK_FAN_B(P) (P == E0_AUTO_FAN_PIN || P == E1_AUTO_FAN_PIN || P == E2_AUTO_FAN_PIN || P == E3_AUTO_FAN_PIN || P == E4_AUTO_FAN_PIN || P == E5_AUTO_FAN_PIN || P == E6_AUTO_FAN_PIN || P == E7_AUTO_FAN_PIN || P == CHAMBER_AUTO_FAN_PIN || P == COOLER_AUTO_FAN_PIN)
#if PIN_EXISTS(CONTROLLER_FAN)
#define PWM_CHK_FAN_B(P) (_PWM_CHK_FAN_B(P) || P == CONTROLLER_FAN_PIN)
#else

View File

@@ -77,6 +77,8 @@ uint8_t HAL_get_reset_source() {
}
}
void HAL_reboot() { rstc_start_software_reset(RSTC); }
void _delay_ms(const int delay_ms) {
// Todo: port for Due?
delay(delay_ms);
@@ -106,17 +108,17 @@ uint16_t HAL_adc_get_result() {
}
// Forward the default serial ports
#if ANY_SERIAL_IS(0)
DefaultSerial MSerial(false, Serial);
#if USING_HW_SERIAL0
DefaultSerial1 MSerial0(false, Serial);
#endif
#if ANY_SERIAL_IS(1)
DefaultSerial1 MSerial1(false, Serial1);
#if USING_HW_SERIAL1
DefaultSerial2 MSerial1(false, Serial1);
#endif
#if ANY_SERIAL_IS(2)
DefaultSerial2 MSerial2(false, Serial2);
#if USING_HW_SERIAL2
DefaultSerial3 MSerial2(false, Serial2);
#endif
#if ANY_SERIAL_IS(3)
DefaultSerial3 MSerial3(false, Serial3);
#if USING_HW_SERIAL3
DefaultSerial4 MSerial3(false, Serial3);
#endif
#endif // ARDUINO_ARCH_SAM

View File

@@ -38,35 +38,34 @@
#include "../../core/serial_hook.h"
typedef ForwardSerial0Type< decltype(Serial) > DefaultSerial;
typedef ForwardSerial0Type< decltype(Serial1) > DefaultSerial1;
typedef ForwardSerial0Type< decltype(Serial2) > DefaultSerial2;
typedef ForwardSerial0Type< decltype(Serial3) > DefaultSerial3;
extern DefaultSerial MSerial;
extern DefaultSerial1 MSerial1;
extern DefaultSerial2 MSerial2;
extern DefaultSerial3 MSerial3;
typedef ForwardSerial1Class< decltype(Serial) > DefaultSerial1;
typedef ForwardSerial1Class< decltype(Serial1) > DefaultSerial2;
typedef ForwardSerial1Class< decltype(Serial2) > DefaultSerial3;
typedef ForwardSerial1Class< decltype(Serial3) > DefaultSerial4;
extern DefaultSerial1 MSerial0;
extern DefaultSerial2 MSerial1;
extern DefaultSerial3 MSerial2;
extern DefaultSerial4 MSerial3;
#define _MSERIAL(X) MSerial##X
#define MSERIAL(X) _MSERIAL(X)
#define MSerial0 MSerial
// Define MYSERIAL0/1 before MarlinSerial includes!
// Define MYSERIAL1/2 before MarlinSerial includes!
#if SERIAL_PORT == -1 || ENABLED(EMERGENCY_PARSER)
#define MYSERIAL0 customizedSerial1
#define MYSERIAL1 customizedSerial1
#elif WITHIN(SERIAL_PORT, 0, 3)
#define MYSERIAL0 MSERIAL(SERIAL_PORT)
#define MYSERIAL1 MSERIAL(SERIAL_PORT)
#else
#error "The required SERIAL_PORT must be from -1 to 3. Please update your configuration."
#error "The required SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
#endif
#ifdef SERIAL_PORT_2
#if SERIAL_PORT_2 == -1 || ENABLED(EMERGENCY_PARSER)
#define MYSERIAL1 customizedSerial2
#define MYSERIAL2 customizedSerial2
#elif WITHIN(SERIAL_PORT_2, 0, 3)
#define MYSERIAL1 MSERIAL(SERIAL_PORT_2)
#define MYSERIAL2 MSERIAL(SERIAL_PORT_2)
#else
#error "SERIAL_PORT_2 must be from -1 to 3. Please update your configuration."
#error "SERIAL_PORT_2 must be from 0 to 3. You can also use -1 if the board supports Native USB."
#endif
#endif
@@ -74,7 +73,7 @@ extern DefaultSerial3 MSerial3;
#if WITHIN(MMU2_SERIAL_PORT, 0, 3)
#define MMU2_SERIAL MSERIAL(MMU2_SERIAL_PORT)
#else
#error "MMU2_SERIAL_PORT must be from 0 to 3. Please update your configuration."
#error "MMU2_SERIAL_PORT must be from 0 to 3."
#endif
#endif
@@ -84,7 +83,7 @@ extern DefaultSerial3 MSerial3;
#elif WITHIN(LCD_SERIAL_PORT, 0, 3)
#define LCD_SERIAL MSERIAL(LCD_SERIAL_PORT)
#else
#error "LCD_SERIAL_PORT must be from -1 to 3. Please update your configuration."
#error "LCD_SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
#endif
#endif
@@ -114,7 +113,7 @@ void sei(); // Enable interrupts
void HAL_clear_reset_source(); // clear reset reason
uint8_t HAL_get_reset_source(); // get reset reason
inline void HAL_reboot() {} // reboot the board or restart the bootloader
void HAL_reboot();
//
// ADC

View File

@@ -476,7 +476,7 @@ void MarlinSerial<Cfg>::flushTX() {
// If not using the USB port as serial port
#if SERIAL_PORT >= 0
#if defined(SERIAL_PORT) && SERIAL_PORT >= 0
template class MarlinSerial< MarlinSerialCfg<SERIAL_PORT> >;
MSerialT customizedSerial1(MarlinSerialCfg<SERIAL_PORT>::EMERGENCYPARSER);
#endif

View File

@@ -140,12 +140,12 @@ struct MarlinSerialCfg {
static constexpr bool MAX_RX_QUEUED = ENABLED(SERIAL_STATS_MAX_RX_QUEUED);
};
#if SERIAL_PORT >= 0
typedef Serial0Type< MarlinSerial< MarlinSerialCfg<SERIAL_PORT> > > MSerialT;
#if defined(SERIAL_PORT) && SERIAL_PORT >= 0
typedef Serial1Class< MarlinSerial< MarlinSerialCfg<SERIAL_PORT> > > MSerialT;
extern MSerialT customizedSerial1;
#endif
#if defined(SERIAL_PORT_2) && SERIAL_PORT_2 >= 0
typedef Serial0Type< MarlinSerial< MarlinSerialCfg<SERIAL_PORT_2> > > MSerialT2;
typedef Serial1Class< MarlinSerial< MarlinSerialCfg<SERIAL_PORT_2> > > MSerialT2;
extern MSerialT2 customizedSerial2;
#endif

View File

@@ -50,7 +50,7 @@ struct MarlinSerialUSB {
FORCE_INLINE int rxMaxEnqueued() { return 0; }
#endif
};
typedef Serial0Type<MarlinSerialUSB> MSerialT;
typedef Serial1Class<MarlinSerialUSB> MSerialT;
#if SERIAL_PORT == -1
extern MSerialT customizedSerial1;

View File

@@ -976,14 +976,13 @@ bool PersistentStore::access_start() { ee_Init(); return true; }
bool PersistentStore::access_finish() { ee_Flush(); return true; }
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
uint16_t written = 0;
while (size--) {
uint8_t * const p = (uint8_t * const)pos;
uint8_t v = *value;
// EEPROM has only ~100,000 write cycles,
// so only write bytes that have changed!
if (v != ee_Read(uint32_t(p))) {
if (v != ee_Read(uint32_t(p))) { // EEPROM has only ~100,000 write cycles, so only write bytes that have changed!
ee_Write(uint32_t(p), v);
delay(2);
if (++written & 0x7F) delay(2); else safe_delay(2); // Avoid triggering watchdog during long EEPROM writes
if (ee_Read(uint32_t(p)) != v) {
SERIAL_ECHO_MSG(STR_ERR_EEPROM_WRITE);
return true;

View File

@@ -42,14 +42,13 @@ bool PersistentStore::access_start() { eeprom_init(); return true; }
bool PersistentStore::access_finish() { return true; }
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
uint16_t written = 0;
while (size--) {
uint8_t * const p = (uint8_t * const)pos;
uint8_t v = *value;
// EEPROM has only ~100,000 write cycles,
// so only write bytes that have changed!
if (v != eeprom_read_byte(p)) {
if (v != eeprom_read_byte(p)) { // EEPROM has only ~100,000 write cycles, so only write bytes that have changed!
eeprom_write_byte(p, v);
delay(2);
if (++written & 0x7F) delay(2); else safe_delay(2); // Avoid triggering watchdog during long EEPROM writes
if (eeprom_read_byte(p) != v) {
SERIAL_ECHO_MSG(STR_ERR_EEPROM_WRITE);
return true;

View File

@@ -32,7 +32,7 @@ Ctrl_status sd_mmc_spi_test_unit_ready() {
Ctrl_status sd_mmc_spi_read_capacity(uint32_t *nb_sector) {
if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.isMounted())
return CTRL_NO_PRESENT;
*nb_sector = card.getSd2Card().cardSize() - 1;
*nb_sector = card.diskIODriver()->cardSize() - 1;
return CTRL_GOOD;
}
@@ -74,24 +74,24 @@ Ctrl_status sd_mmc_spi_usb_read_10(uint32_t addr, uint16_t nb_sector) {
#endif
// Start reading
if (!card.getSd2Card().readStart(addr))
if (!card.diskIODriver()->readStart(addr))
return CTRL_FAIL;
// For each specified sector
while (nb_sector--) {
// Read a sector
card.getSd2Card().readData(sector_buf);
card.diskIODriver()->readData(sector_buf);
// RAM -> USB
if (!udi_msc_trans_block(true, sector_buf, SD_MMC_BLOCK_SIZE, nullptr)) {
card.getSd2Card().readStop();
card.diskIODriver()->readStop();
return CTRL_FAIL;
}
}
// Stop reading
card.getSd2Card().readStop();
card.diskIODriver()->readStop();
// Done
return CTRL_GOOD;
@@ -113,7 +113,7 @@ Ctrl_status sd_mmc_spi_usb_write_10(uint32_t addr, uint16_t nb_sector) {
}
#endif
if (!card.getSd2Card().writeStart(addr, nb_sector))
if (!card.diskIODriver()->writeStart(addr, nb_sector))
return CTRL_FAIL;
// For each specified sector
@@ -121,16 +121,16 @@ Ctrl_status sd_mmc_spi_usb_write_10(uint32_t addr, uint16_t nb_sector) {
// USB -> RAM
if (!udi_msc_trans_block(false, sector_buf, SD_MMC_BLOCK_SIZE, nullptr)) {
card.getSd2Card().writeStop();
card.diskIODriver()->writeStop();
return CTRL_FAIL;
}
// Write a sector
card.getSd2Card().writeData(sector_buf);
card.diskIODriver()->writeData(sector_buf);
}
// Stop writing
card.getSd2Card().writeStop();
card.diskIODriver()->writeStop();
// Done
return CTRL_GOOD;

View File

@@ -322,7 +322,7 @@ void usb_task_init(void) {
char *sptr;
// Patch in the filament diameter
sprintf_P(diam, PSTR("%d"), (int)((DEFAULT_NOMINAL_FILAMENT_DIA) * 1000.0));
itoa((int)((DEFAULT_NOMINAL_FILAMENT_DIA) * 1000), diam, 10);
// And copy it to the proper place, expanding it to unicode
sptr = &diam[0];

View File

@@ -20,11 +20,10 @@
*
*/
#include "FlushableHardwareSerial.h"
#ifdef ARDUINO_ARCH_ESP32
#include "FlushableHardwareSerial.h"
Serial0Type<FlushableHardwareSerial> flushableSerial(false, 0);
Serial1Class<FlushableHardwareSerial> flushableSerial(false, 0);
#endif // ARDUINO_ARCH_ESP32
#endif

View File

@@ -21,9 +21,9 @@
*/
#pragma once
#ifdef ARDUINO_ARCH_ESP32
#include <HardwareSerial.h>
#include "../shared/Marduino.h"
#include "../../core/serial_hook.h"
class FlushableHardwareSerial : public HardwareSerial {
@@ -31,6 +31,4 @@ public:
FlushableHardwareSerial(int uart_nr) : HardwareSerial(uart_nr) {}
};
extern Serial0Type<FlushableHardwareSerial> flushableSerial;
#endif // ARDUINO_ARCH_ESP32
extern Serial1Class<FlushableHardwareSerial> flushableSerial;

View File

@@ -41,7 +41,7 @@
#endif
#if ENABLED(ESP3D_WIFISUPPORT)
DefaultSerial MSerial(false, Serial2Socket);
DefaultSerial1 MSerial0(false, Serial2Socket);
#endif
// ------------------------
@@ -141,6 +141,8 @@ void HAL_clear_reset_source() { }
uint8_t HAL_get_reset_source() { return rtc_get_reset_reason(1); }
void HAL_reboot() { ESP.restart(); }
void _delay_ms(int delay_ms) { delay(delay_ms); }
// return free memory between end of heap (or end bss) and whatever is current
@@ -185,6 +187,7 @@ void HAL_adc_init() {
TERN_(HAS_TEMP_ADC_7, adc3_set_attenuation(get_channel(TEMP_7_PIN), ADC_ATTEN_11db));
TERN_(HAS_HEATED_BED, adc1_set_attenuation(get_channel(TEMP_BED_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_CHAMBER, adc1_set_attenuation(get_channel(TEMP_CHAMBER_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_COOLER, adc1_set_attenuation(get_channel(TEMP_COOLER_PIN), ADC_ATTEN_11db));
TERN_(FILAMENT_WIDTH_SENSOR, adc1_set_attenuation(get_channel(FILWIDTH_PIN), ADC_ATTEN_11db));
// Note that adc2 is shared with the WiFi module, which has higher priority, so the conversion may fail.

View File

@@ -51,15 +51,15 @@
extern portMUX_TYPE spinlock;
#define MYSERIAL0 flushableSerial
#define MYSERIAL1 flushableSerial
#if EITHER(WIFISUPPORT, ESP3D_WIFISUPPORT)
#if ENABLED(ESP3D_WIFISUPPORT)
typedef ForwardSerial0Type< decltype(Serial2Socket) > DefaultSerial;
extern DefaultSerial MSerial;
#define MYSERIAL1 MSerial
typedef ForwardSerial1Class< decltype(Serial2Socket) > DefaultSerial1;
extern DefaultSerial1 MSerial0;
#define MYSERIAL2 MSerial0
#else
#define MYSERIAL1 webSocketSerial
#define MYSERIAL2 webSocketSerial
#endif
#endif
@@ -101,7 +101,7 @@ void HAL_clear_reset_source();
// reset reason
uint8_t HAL_get_reset_source();
inline void HAL_reboot() {} // reboot the board or restart the bootloader
void HAL_reboot();
void _delay_ms(int delay);

View File

@@ -81,5 +81,5 @@ public:
#endif
};
typedef Serial0Type<WebSocketSerial> MSerialT;
typedef Serial1Class<WebSocketSerial> MSerialT;
extern MSerialT webSocketSerial;

View File

@@ -29,12 +29,6 @@
#include HAL_PATH(.,HAL.h)
#ifdef SERIAL_PORT_2
#define NUM_SERIAL 2
#else
#define NUM_SERIAL 1
#endif
#define HAL_ADC_RANGE _BV(HAL_ADC_RESOLUTION)
#ifndef I2C_ADDRESS

View File

@@ -73,4 +73,6 @@ void HAL_pwm_init() {
}
void HAL_reboot() { /* Reset the application state and GPIO */ }
#endif // __PLAT_LINUX__

View File

@@ -61,7 +61,7 @@ uint8_t _getc();
#define SHARED_SERVOS HAS_SERVOS
extern MSerialT usb_serial;
#define MYSERIAL0 usb_serial
#define MYSERIAL1 usb_serial
#define ST7920_DELAY_1 DELAY_NS(600)
#define ST7920_DELAY_2 DELAY_NS(750)
@@ -107,7 +107,7 @@ uint16_t HAL_adc_get_result();
inline void HAL_clear_reset_source(void) {}
inline uint8_t HAL_get_reset_source(void) { return RST_POWER_ON; }
inline void HAL_reboot() {} // reboot the board or restart the bootloader
void HAL_reboot(); // Reset the application state and GPIO
/* ---------------- Delay in cycles */
FORCE_INLINE static void DELAY_CYCLES(uint64_t x) {

View File

@@ -115,4 +115,4 @@ struct HalSerial {
volatile bool host_connected;
};
typedef Serial0Type<HalSerial> MSerialT;
typedef Serial1Class<HalSerial> MSerialT;

View File

@@ -105,8 +105,8 @@ int main() {
std::thread write_serial (write_serial_thread);
std::thread read_serial (read_serial_thread);
#ifdef MYSERIAL0
MYSERIAL0.begin(BAUDRATE);
#ifdef MYSERIAL1
MYSERIAL1.begin(BAUDRATE);
SERIAL_ECHOLNPGM("x86_64 Initialized");
SERIAL_FLUSHTX();
#endif

View File

@@ -29,7 +29,7 @@
#include "watchdog.h"
#endif
DefaultSerial USBSerial(false, UsbSerial);
DefaultSerial1 USBSerial(false, UsbSerial);
uint32_t HAL_adc_reading = 0;
@@ -67,7 +67,7 @@ void flashFirmware(const int16_t) {
delay(500); // Give OS time to disconnect
USB_Connect(false); // USB clear connection
delay(1000); // Give OS time to notice
NVIC_SystemReset();
HAL_reboot();
}
void HAL_clear_reset_source(void) {
@@ -81,4 +81,6 @@ uint8_t HAL_get_reset_source(void) {
return RST_POWER_ON;
}
void HAL_reboot() { NVIC_SystemReset(); }
#endif // TARGET_LPC1768

View File

@@ -60,28 +60,27 @@ extern "C" volatile uint32_t _millis;
#define ST7920_DELAY_3 DELAY_NS(750)
#endif
typedef ForwardSerial0Type< decltype(UsbSerial) > DefaultSerial;
extern DefaultSerial USBSerial;
typedef ForwardSerial1Class< decltype(UsbSerial) > DefaultSerial1;
extern DefaultSerial1 USBSerial;
#define _MSERIAL(X) MSerial##X
#define MSERIAL(X) _MSERIAL(X)
#define MSerial0 MSerial
#if SERIAL_PORT == -1
#define MYSERIAL0 USBSerial
#define MYSERIAL1 USBSerial
#elif WITHIN(SERIAL_PORT, 0, 3)
#define MYSERIAL0 MSERIAL(SERIAL_PORT)
#define MYSERIAL1 MSERIAL(SERIAL_PORT)
#else
#error "SERIAL_PORT must be from -1 to 3. Please update your configuration."
#error "SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
#endif
#ifdef SERIAL_PORT_2
#if SERIAL_PORT_2 == -1
#define MYSERIAL1 USBSerial
#define MYSERIAL2 USBSerial
#elif WITHIN(SERIAL_PORT_2, 0, 3)
#define MYSERIAL1 MSERIAL(SERIAL_PORT_2)
#define MYSERIAL2 MSERIAL(SERIAL_PORT_2)
#else
#error "SERIAL_PORT_2 must be from -1 to 3. Please update your configuration."
#error "SERIAL_PORT_2 must be from 0 to 3. You can also use -1 if the board supports Native USB."
#endif
#endif
@@ -91,7 +90,7 @@ extern DefaultSerial USBSerial;
#elif WITHIN(MMU2_SERIAL_PORT, 0, 3)
#define MMU2_SERIAL MSERIAL(MMU2_SERIAL_PORT)
#else
#error "MMU2_SERIAL_PORT must be from -1 to 3. Please update your configuration."
#error "MMU2_SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
#endif
#endif
@@ -101,7 +100,10 @@ extern DefaultSerial USBSerial;
#elif WITHIN(LCD_SERIAL_PORT, 0, 3)
#define LCD_SERIAL MSERIAL(LCD_SERIAL_PORT)
#else
#error "LCD_SERIAL_PORT must be from -1 to 3. Please update your configuration."
#error "LCD_SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
#endif
#if HAS_DGUS_LCD
#define SERIAL_GET_TX_BUFFER_FREE() MSerial0.available()
#endif
#endif
@@ -216,4 +218,4 @@ void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255,
void HAL_clear_reset_source(void);
uint8_t HAL_get_reset_source(void);
inline void HAL_reboot() {} // reboot the board or restart the bootloader
void HAL_reboot();

View File

@@ -21,25 +21,26 @@
*/
#ifdef TARGET_LPC1768
#include "../../inc/MarlinConfigPre.h"
#include "MarlinSerial.h"
#if ANY_SERIAL_IS(0)
#include "../../inc/MarlinConfig.h"
#if USING_HW_SERIAL0
MarlinSerial _MSerial(LPC_UART0);
MSerialT MSerial(true, _MSerial);
MSerialT MSerial0(true, _MSerial);
extern "C" void UART0_IRQHandler() { _MSerial.IRQHandler(); }
#endif
#if ANY_SERIAL_IS(1)
#if USING_HW_SERIAL1
MarlinSerial _MSerial1((LPC_UART_TypeDef *) LPC_UART1);
MSerialT MSerial1(true, _MSerial1);
extern "C" void UART1_IRQHandler() { _MSerial1.IRQHandler(); }
#endif
#if ANY_SERIAL_IS(2)
#if USING_HW_SERIAL2
MarlinSerial _MSerial2(LPC_UART2);
MSerialT MSerial2(true, _MSerial2);
extern "C" void UART2_IRQHandler() { _MSerial2.IRQHandler(); }
#endif
#if ANY_SERIAL_IS(3)
#if USING_HW_SERIAL3
MarlinSerial _MSerial3(LPC_UART3);
MSerialT MSerial3(true, _MSerial3);
extern "C" void UART3_IRQHandler() { _MSerial3.IRQHandler(); }
@@ -50,16 +51,16 @@
bool MarlinSerial::recv_callback(const char c) {
// Need to figure out which serial port we are and react in consequence (Marlin does not have CONTAINER_OF macro)
if (false) {}
#if ANY_SERIAL_IS(0)
else if (this == &_MSerial) emergency_parser.update(MSerial.emergency_state, c);
#if USING_HW_SERIAL0
else if (this == &_MSerial) emergency_parser.update(MSerial0.emergency_state, c);
#endif
#if ANY_SERIAL_IS(1)
#if USING_HW_SERIAL1
else if (this == &_MSerial1) emergency_parser.update(MSerial1.emergency_state, c);
#endif
#if ANY_SERIAL_IS(2)
#if USING_HW_SERIAL2
else if (this == &_MSerial2) emergency_parser.update(MSerial2.emergency_state, c);
#endif
#if ANY_SERIAL_IS(3)
#if USING_HW_SERIAL3
else if (this == &_MSerial3) emergency_parser.update(MSerial3.emergency_state, c);
#endif
return true;

View File

@@ -54,8 +54,8 @@ public:
// On LPC176x framework, HardwareSerial does not implement the same interface as Arduino's Serial, so overloads
// of 'available' and 'read' method are not used in this multiple inheritance scenario.
// Instead, use a ForwardSerial here that adapts the interface.
typedef ForwardSerial0Type<MarlinSerial> MSerialT;
extern MSerialT MSerial;
typedef ForwardSerial1Class<MarlinSerial> MSerialT;
extern MSerialT MSerial0;
extern MSerialT MSerial1;
extern MSerialT MSerial2;
extern MSerialT MSerial3;

View File

@@ -42,25 +42,22 @@ bool PersistentStore::access_start() { eeprom_init(); return true; }
bool PersistentStore::access_finish() { return true; }
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
uint16_t written = 0;
while (size--) {
uint8_t v = *value;
// EEPROM has only ~100,000 write cycles,
// so only write bytes that have changed!
uint8_t * const p = (uint8_t * const)pos;
if (v != eeprom_read_byte(p)) {
if (v != eeprom_read_byte(p)) { // EEPROM has only ~100,000 write cycles, so only write bytes that have changed!
eeprom_write_byte(p, v);
if (++written & 0x7F) delay(2); else safe_delay(2); // Avoid triggering watchdog during long EEPROM writes
if (eeprom_read_byte(p) != v) {
SERIAL_ECHO_MSG(STR_ERR_EEPROM_WRITE);
return true;
}
}
crc16(crc, &v, 1);
pos++;
value++;
};
}
return false;
}
@@ -68,7 +65,6 @@ bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t
do {
// Read from external EEPROM
const uint8_t c = eeprom_read_byte((uint8_t*)pos);
if (writing) *value = c;
crc16(crc, &c, 1);
pos++;

View File

@@ -92,7 +92,7 @@ static_assert(DISABLED(BAUD_RATE_GCODE), "BAUD_RATE_GCODE is not yet supported o
#define ANY_TX(N,V...) DO(IS_TX##N,||,V)
#define ANY_RX(N,V...) DO(IS_RX##N,||,V)
#if ANY_SERIAL_IS(0)
#if USING_HW_SERIAL0
#define IS_TX0(P) (P == P0_02)
#define IS_RX0(P) (P == P0_03)
#if IS_TX0(TMC_SW_MISO) || IS_RX0(TMC_SW_MOSI)
@@ -106,7 +106,7 @@ static_assert(DISABLED(BAUD_RATE_GCODE), "BAUD_RATE_GCODE is not yet supported o
#undef IS_RX0
#endif
#if ANY_SERIAL_IS(1)
#if USING_HW_SERIAL1
#define IS_TX1(P) (P == P0_15)
#define IS_RX1(P) (P == P0_16)
#define _IS_TX1_1 IS_TX1
@@ -127,7 +127,7 @@ static_assert(DISABLED(BAUD_RATE_GCODE), "BAUD_RATE_GCODE is not yet supported o
#undef _IS_RX1_1
#endif
#if ANY_SERIAL_IS(2)
#if USING_HW_SERIAL2
#define IS_TX2(P) (P == P0_10)
#define IS_RX2(P) (P == P0_11)
#define _IS_TX2_1 IS_TX2
@@ -161,7 +161,7 @@ static_assert(DISABLED(BAUD_RATE_GCODE), "BAUD_RATE_GCODE is not yet supported o
#undef _IS_RX2_1
#endif
#if ANY_SERIAL_IS(3)
#if USING_HW_SERIAL3
#define PIN_IS_TX3(P) (PIN_EXISTS(P) && P##_PIN == P0_00)
#define PIN_IS_RX3(P) (P##_PIN == P0_01)
#if PIN_IS_TX3(X_MIN) || PIN_IS_RX3(X_MAX)

View File

@@ -25,20 +25,20 @@
#include <wiring_private.h>
#ifdef ADAFRUIT_GRAND_CENTRAL_M4
#if ANY_SERIAL_IS(-1)
DefaultSerial MSerial(false, Serial);
#if USING_HW_SERIALUSB
DefaultSerial1 MSerial0(false, Serial);
#endif
#if ANY_SERIAL_IS(0)
DefaultSerial1 MSerial1(false, Serial1);
#if USING_HW_SERIAL0
DefaultSerial2 MSerial1(false, Serial1);
#endif
#if ANY_SERIAL_IS(1)
DefaultSerial2 MSerial2(false, Serial2);
#if USING_HW_SERIAL1
DefaultSerial3 MSerial2(false, Serial2);
#endif
#if ANY_SERIAL_IS(2)
DefaultSerial3 MSerial3(false, Serial3);
#if USING_HW_SERIAL2
DefaultSerial4 MSerial3(false, Serial3);
#endif
#if ANY_SERIAL_IS(3)
DefaultSerial4 MSerial4(false, Serial4);
#if USING_HW_SERIAL3
DefaultSerial5 MSerial4(false, Serial4);
#endif
#endif
@@ -57,6 +57,7 @@
#define GET_PROBE_ADC() TERN(HAS_TEMP_PROBE, PIN_TO_ADC(TEMP_PROBE_PIN), -1)
#define GET_BED_ADC() TERN(HAS_TEMP_ADC_BED, PIN_TO_ADC(TEMP_BED_PIN), -1)
#define GET_CHAMBER_ADC() TERN(HAS_TEMP_ADC_CHAMBER, PIN_TO_ADC(TEMP_CHAMBER_PIN), -1)
#define GET_COOLER_ADC() TERN(HAS_TEMP_ADC_COOLER, PIN_TO_ADC(TEMP_COOLER_PIN), -1)
#define GET_FILAMENT_WIDTH_ADC() TERN(FILAMENT_WIDTH_SENSOR, PIN_TO_ADC(FILWIDTH_PIN), -1)
#define GET_BUTTONS_ADC() TERN(HAS_ADC_BUTTONS, PIN_TO_ADC(ADC_KEYPAD_PIN), -1)
@@ -66,6 +67,7 @@
|| GET_PROBE_ADC() == n \
|| GET_BED_ADC() == n \
|| GET_CHAMBER_ADC() == n \
|| GET_COOLER_ADC() == n \
|| GET_FILAMENT_WIDTH_ADC() == n \
|| GET_BUTTONS_ADC() == n \
)
@@ -144,6 +146,9 @@ uint16_t HAL_adc_result;
#if GET_CHAMBER_ADC() == 0
TEMP_CHAMBER_PIN,
#endif
#if GET_COOLER_ADC() == 0
TEMP_COOLER_PIN,
#endif
#if GET_FILAMENT_WIDTH_ADC() == 0
FILWIDTH_PIN,
#endif
@@ -184,6 +189,9 @@ uint16_t HAL_adc_result;
#if GET_CHAMBER_ADC() == 1
TEMP_CHAMBER_PIN,
#endif
#if GET_COOLER_ADC() == 1
TEMP_COOLER_PIN,
#endif
#if GET_FILAMENT_WIDTH_ADC() == 1
FILWIDTH_PIN,
#endif
@@ -232,6 +240,9 @@ uint16_t HAL_adc_result;
#if GET_CHAMBER_ADC() == 0
{ PIN_TO_INPUTCTRL(TEMP_CHAMBER_PIN) },
#endif
#if GET_COOLER_ADC() == 0
{ PIN_TO_INPUTCTRL(TEMP_COOLER_PIN) },
#endif
#if GET_FILAMENT_WIDTH_ADC() == 0
{ PIN_TO_INPUTCTRL(FILWIDTH_PIN) },
#endif
@@ -281,6 +292,9 @@ uint16_t HAL_adc_result;
#if GET_CHAMBER_ADC() == 1
{ PIN_TO_INPUTCTRL(TEMP_CHAMBER_PIN) },
#endif
#if GET_COOLER_ADC() == 1
{ PIN_TO_INPUTCTRL(TEMP_COOLER_PIN) },
#endif
#if GET_FILAMENT_WIDTH_ADC() == 1
{ PIN_TO_INPUTCTRL(FILWIDTH_PIN) },
#endif
@@ -422,6 +436,8 @@ uint8_t HAL_get_reset_source() {
}
#pragma pop_macro("WDT")
void HAL_reboot() { NVIC_SystemReset(); }
extern "C" {
void * _sbrk(int incr);

View File

@@ -32,58 +32,58 @@
#include "MarlinSerial_AGCM4.h"
// Serial ports
typedef ForwardSerial0Type< decltype(Serial) > DefaultSerial;
typedef ForwardSerial0Type< decltype(Serial1) > DefaultSerial1;
typedef ForwardSerial0Type< decltype(Serial2) > DefaultSerial2;
typedef ForwardSerial0Type< decltype(Serial3) > DefaultSerial3;
typedef ForwardSerial0Type< decltype(Serial4) > DefaultSerial4;
extern DefaultSerial MSerial;
extern DefaultSerial1 MSerial1;
extern DefaultSerial2 MSerial2;
extern DefaultSerial3 MSerial3;
extern DefaultSerial4 MSerial4;
typedef ForwardSerial1Class< decltype(Serial) > DefaultSerial1;
typedef ForwardSerial1Class< decltype(Serial1) > DefaultSerial2;
typedef ForwardSerial1Class< decltype(Serial2) > DefaultSerial3;
typedef ForwardSerial1Class< decltype(Serial3) > DefaultSerial4;
typedef ForwardSerial1Class< decltype(Serial4) > DefaultSerial5;
extern DefaultSerial1 MSerial0;
extern DefaultSerial2 MSerial1;
extern DefaultSerial3 MSerial2;
extern DefaultSerial4 MSerial3;
extern DefaultSerial5 MSerial4;
// MYSERIAL0 required before MarlinSerial includes!
// MYSERIAL1 required before MarlinSerial includes!
#define __MSERIAL(X) MSerial##X
#define _MSERIAL(X) __MSERIAL(X)
#define MSERIAL(X) _MSERIAL(INCREMENT(X))
#if SERIAL_PORT == -1
#define MYSERIAL0 MSerial
#define MYSERIAL1 MSerial0
#elif WITHIN(SERIAL_PORT, 0, 3)
#define MYSERIAL0 MSERIAL(SERIAL_PORT)
#define MYSERIAL1 MSERIAL(SERIAL_PORT)
#else
#error "SERIAL_PORT must be from -1 to 3. Please update your configuration."
#error "SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
#endif
#ifdef SERIAL_PORT_2
#if SERIAL_PORT_2 == -1
#define MYSERIAL1 MSerial
#define MYSERIAL2 MSerial0
#elif WITHIN(SERIAL_PORT_2, 0, 3)
#define MYSERIAL1 MSERIAL(SERIAL_PORT_2)
#define MYSERIAL2 MSERIAL(SERIAL_PORT_2)
#else
#error "SERIAL_PORT_2 must be from -1 to 3. Please update your configuration."
#error "SERIAL_PORT_2 must be from 0 to 3. You can also use -1 if the board supports Native USB."
#endif
#endif
#ifdef MMU2_SERIAL_PORT
#if MMU2_SERIAL_PORT == -1
#define MMU2_SERIAL MSerial
#define MMU2_SERIAL MSerial0
#elif WITHIN(MMU2_SERIAL_PORT, 0, 3)
#define MMU2_SERIAL MSERIAL(MMU2_SERIAL_PORT)
#else
#error "MMU2_SERIAL_PORT must be from -1 to 3. Please update your configuration."
#error "MMU2_SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
#endif
#endif
#ifdef LCD_SERIAL_PORT
#if LCD_SERIAL_PORT == -1
#define LCD_SERIAL MSerial
#define LCD_SERIAL MSerial0
#elif WITHIN(LCD_SERIAL_PORT, 0, 3)
#define LCD_SERIAL MSERIAL(LCD_SERIAL_PORT)
#else
#error "LCD_SERIAL_PORT must be from -1 to 3. Please update your configuration."
#error "LCD_SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
#endif
#endif
@@ -109,7 +109,7 @@ typedef int8_t pin_t;
void HAL_clear_reset_source(); // clear reset reason
uint8_t HAL_get_reset_source(); // get reset reason
inline void HAL_reboot() {} // reboot the board or restart the bootloader
void HAL_reboot();
//
// ADC

View File

@@ -27,7 +27,7 @@
#include "../../inc/MarlinConfig.h"
#if ANY_SERIAL_IS(1)
#if USING_HW_SERIAL1
UartT Serial2(false, &sercom4, PIN_SERIAL2_RX, PIN_SERIAL2_TX, PAD_SERIAL2_RX, PAD_SERIAL2_TX);
void SERCOM4_0_Handler() { Serial2.IrqHandler(); }
void SERCOM4_1_Handler() { Serial2.IrqHandler(); }
@@ -35,7 +35,7 @@
void SERCOM4_3_Handler() { Serial2.IrqHandler(); }
#endif
#if ANY_SERIAL_IS(2)
#if USING_HW_SERIAL2
UartT Serial3(false, &sercom1, PIN_SERIAL3_RX, PIN_SERIAL3_TX, PAD_SERIAL3_RX, PAD_SERIAL3_TX);
void SERCOM1_0_Handler() { Serial3.IrqHandler(); }
void SERCOM1_1_Handler() { Serial3.IrqHandler(); }
@@ -43,7 +43,7 @@
void SERCOM1_3_Handler() { Serial3.IrqHandler(); }
#endif
#if ANY_SERIAL_IS(3)
#if USING_HW_SERIAL3
UartT Serial4(false, &sercom5, PIN_SERIAL4_RX, PIN_SERIAL4_TX, PAD_SERIAL4_RX, PAD_SERIAL4_TX);
void SERCOM5_0_Handler() { Serial4.IrqHandler(); }
void SERCOM5_1_Handler() { Serial4.IrqHandler(); }

View File

@@ -22,7 +22,7 @@
#include "../../core/serial_hook.h"
typedef Serial0Type<Uart> UartT;
typedef Serial1Class<Uart> UartT;
extern UartT Serial2;
extern UartT Serial3;

View File

@@ -41,12 +41,13 @@ bool PersistentStore::access_start() { eeprom_init(); return true; }
bool PersistentStore::access_finish() { return true; }
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
uint16_t written = 0;
while (size--) {
const uint8_t v = *value;
uint8_t * const p = (uint8_t * const)pos;
if (v != eeprom_read_byte(p)) {
if (v != eeprom_read_byte(p)) { // EEPROM has only ~100,000 write cycles, so only write bytes that have changed!
eeprom_write_byte(p, v);
delay(2);
if (++written & 0x7F) delay(2); else safe_delay(2); // Avoid triggering watchdog during long EEPROM writes
if (eeprom_read_byte(p) != v) {
SERIAL_ECHO_MSG(STR_ERR_EEPROM_WRITE);
return true;

View File

@@ -29,7 +29,7 @@
#include "../shared/Delay.h"
#ifdef USBCON
DefaultSerial MSerial(false, SerialUSB);
DefaultSerial1 MSerial0(false, SerialUSB);
#endif
#if ENABLED(SRAM_EEPROM_EMULATION)
@@ -133,6 +133,8 @@ uint8_t HAL_get_reset_source() {
;
}
void HAL_reboot() { NVIC_SystemReset(); }
void _delay_ms(const int delay_ms) { delay(delay_ms); }
extern "C" {
@@ -147,8 +149,8 @@ extern "C" {
void HAL_adc_start_conversion(const uint8_t adc_pin) { HAL_adc_result = analogRead(adc_pin); }
uint16_t HAL_adc_get_result() { return HAL_adc_result; }
// Reset the system (to initiate a firmware flash)
void flashFirmware(const int16_t) { NVIC_SystemReset(); }
// Reset the system to initiate a firmware flash
void flashFirmware(const int16_t) { HAL_reboot(); }
// Maple Compatibility
volatile uint32_t systick_uptime_millis = 0;

View File

@@ -40,8 +40,8 @@
#ifdef USBCON
#include <USBSerial.h>
#include "../../core/serial_hook.h"
typedef ForwardSerial0Type< decltype(SerialUSB) > DefaultSerial;
extern DefaultSerial MSerial;
typedef ForwardSerial1Class< decltype(SerialUSB) > DefaultSerial1;
extern DefaultSerial1 MSerial0;
#endif
// ------------------------
@@ -51,40 +51,40 @@
#define MSERIAL(X) _MSERIAL(X)
#if SERIAL_PORT == -1
#define MYSERIAL0 MSerial
#define MYSERIAL1 MSerial0
#elif WITHIN(SERIAL_PORT, 1, 6)
#define MYSERIAL0 MSERIAL(SERIAL_PORT)
#define MYSERIAL1 MSERIAL(SERIAL_PORT)
#else
#error "SERIAL_PORT must be -1 or from 1 to 6. Please update your configuration."
#error "SERIAL_PORT must be from 1 to 6. You can also use -1 if the board supports Native USB."
#endif
#ifdef SERIAL_PORT_2
#if SERIAL_PORT_2 == -1
#define MYSERIAL1 MSerial
#define MYSERIAL2 MSerial0
#elif WITHIN(SERIAL_PORT_2, 1, 6)
#define MYSERIAL1 MSERIAL(SERIAL_PORT_2)
#define MYSERIAL2 MSERIAL(SERIAL_PORT_2)
#else
#error "SERIAL_PORT_2 must be -1 or from 1 to 6. Please update your configuration."
#error "SERIAL_PORT_2 must be from 1 to 6. You can also use -1 if the board supports Native USB."
#endif
#endif
#ifdef MMU2_SERIAL_PORT
#if MMU2_SERIAL_PORT == -1
#define MMU2_SERIAL MSerial
#define MMU2_SERIAL MSerial0
#elif WITHIN(MMU2_SERIAL_PORT, 1, 6)
#define MMU2_SERIAL MSERIAL(MMU2_SERIAL_PORT)
#else
#error "MMU2_SERIAL_PORT must be -1 or from 1 to 6. Please update your configuration."
#error "MMU2_SERIAL_PORT must be from 1 to 6. You can also use -1 if the board supports Native USB."
#endif
#endif
#ifdef LCD_SERIAL_PORT
#if LCD_SERIAL_PORT == -1
#define LCD_SERIAL MSerial
#define LCD_SERIAL MSerial0
#elif WITHIN(LCD_SERIAL_PORT, 1, 6)
#define LCD_SERIAL MSERIAL(LCD_SERIAL_PORT)
#else
#error "LCD_SERIAL_PORT must be -1 or from 1 to 6. Please update your configuration."
#error "LCD_SERIAL_PORT must be from 1 to 6. You can also use -1 if the board supports Native USB."
#endif
#if HAS_DGUS_LCD
#define SERIAL_GET_TX_BUFFER_FREE() LCD_SERIAL.availableForWrite()
@@ -144,7 +144,7 @@ void HAL_clear_reset_source();
// Reset reason
uint8_t HAL_get_reset_source();
inline void HAL_reboot() {} // reboot the board or restart the bootloader
void HAL_reboot();
void _delay_ms(const int delay);

View File

@@ -19,7 +19,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC)
#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC) && !defined(STM32H7xx)
#include "MarlinSPI.h"

View File

@@ -28,7 +28,6 @@
#ifndef USART4
#define USART4 UART4
#endif
#ifndef USART5
#define USART5 UART5
#endif
@@ -38,22 +37,38 @@
MSerialT MSerial ## ser_num (true, USART ## ser_num, &_rx_complete_irq_ ## ser_num); \
void _rx_complete_irq_ ## ser_num (serial_t * obj) { MSerial ## ser_num ._rx_complete_irq(obj); }
#define DECLARE_SERIAL_PORT_EXP(ser_num) DECLARE_SERIAL_PORT(ser_num)
#if defined(SERIAL_PORT) && SERIAL_PORT >= 0
DECLARE_SERIAL_PORT_EXP(SERIAL_PORT)
#if USING_HW_SERIAL1
DECLARE_SERIAL_PORT(1)
#endif
#if defined(SERIAL_PORT_2) && SERIAL_PORT_2 >= 0
DECLARE_SERIAL_PORT_EXP(SERIAL_PORT_2)
#if USING_HW_SERIAL2
DECLARE_SERIAL_PORT(2)
#endif
#if defined(MMU2_SERIAL_PORT) && MMU2_SERIAL_PORT >= 0
DECLARE_SERIAL_PORT_EXP(MMU2_SERIAL_PORT)
#if USING_HW_SERIAL3
DECLARE_SERIAL_PORT(3)
#endif
#if defined(LCD_SERIAL_PORT) && LCD_SERIAL_PORT >= 0
DECLARE_SERIAL_PORT_EXP(LCD_SERIAL_PORT)
#if USING_HW_SERIAL4
DECLARE_SERIAL_PORT(4)
#endif
#if USING_HW_SERIAL5
DECLARE_SERIAL_PORT(5)
#endif
#if USING_HW_SERIAL6
DECLARE_SERIAL_PORT(6)
#endif
#if USING_HW_SERIAL7
DECLARE_SERIAL_PORT(7)
#endif
#if USING_HW_SERIAL8
DECLARE_SERIAL_PORT(8)
#endif
#if USING_HW_SERIAL9
DECLARE_SERIAL_PORT(9)
#endif
#if USING_HW_SERIAL10
DECLARE_SERIAL_PORT(10)
#endif
#if USING_HW_SERIALLP1
DECLARE_SERIAL_PORT(LP1)
#endif
void MarlinSerial::begin(unsigned long baud, uint8_t config) {

View File

@@ -42,7 +42,7 @@ protected:
usart_rx_callback_t _rx_callback;
};
typedef Serial0Type<MarlinSerial> MSerialT;
typedef Serial1Class<MarlinSerial> MSerialT;
extern MSerialT MSerial1;
extern MSerialT MSerial2;
extern MSerialT MSerial3;

View File

@@ -36,7 +36,8 @@
// use USB drivers
extern "C" { int8_t SD_MSC_Read(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
extern "C" {
int8_t SD_MSC_Read(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
int8_t SD_MSC_Write(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
extern SD_HandleTypeDef hsd;
}
@@ -75,7 +76,18 @@
#error "ERROR - Only STM32F103xE, STM32F103xG, STM32F4xx or STM32F7xx CPUs supported"
#endif
// Fixed
#define SDIO_D0_PIN PC8
#define SDIO_D1_PIN PC9
#define SDIO_D2_PIN PC10
#define SDIO_D3_PIN PC11
#define SDIO_CK_PIN PC12
#define SDIO_CMD_PIN PD2
SD_HandleTypeDef hsd; // create SDIO structure
// F4 supports one DMA for RX and another for TX, but Marlin will never
// do read and write at same time, so we use the same DMA for both.
DMA_HandleTypeDef hdma_sdio;
/*
SDIO_INIT_CLK_DIV is 118
@@ -96,7 +108,7 @@
// Target Clock, configurable. Default is 18MHz, from STM32F1
#ifndef SDIO_CLOCK
#define SDIO_CLOCK 18000000 /* 18 MHz */
#define SDIO_CLOCK 18000000 // 18 MHz
#endif
// SDIO retries, configurable. Default is 3, from STM32F1
@@ -120,24 +132,21 @@
}
void go_to_transfer_speed() {
SD_InitTypeDef Init;
/* Default SDIO peripheral configuration for SD card initialization */
Init.ClockEdge = hsd.Init.ClockEdge;
Init.ClockBypass = hsd.Init.ClockBypass;
Init.ClockPowerSave = hsd.Init.ClockPowerSave;
Init.BusWide = hsd.Init.BusWide;
Init.HardwareFlowControl = hsd.Init.HardwareFlowControl;
Init.ClockDiv = clock_to_divider(SDIO_CLOCK);
hsd.Init.ClockEdge = hsd.Init.ClockEdge;
hsd.Init.ClockBypass = hsd.Init.ClockBypass;
hsd.Init.ClockPowerSave = hsd.Init.ClockPowerSave;
hsd.Init.BusWide = hsd.Init.BusWide;
hsd.Init.HardwareFlowControl = hsd.Init.HardwareFlowControl;
hsd.Init.ClockDiv = clock_to_divider(SDIO_CLOCK);
/* Initialize SDIO peripheral interface with default configuration */
SDIO_Init(hsd.Instance, Init);
SDIO_Init(hsd.Instance, hsd.Init);
}
void SD_LowLevel_Init(void) {
uint32_t tempreg;
__HAL_RCC_SDIO_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE(); //enable GPIO clocks
__HAL_RCC_GPIOD_CLK_ENABLE(); //enable GPIO clocks
@@ -163,11 +172,45 @@
GPIO_InitStruct.Pin = GPIO_PIN_2;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
#if DISABLED(STM32F1xx)
// TODO: use __HAL_RCC_SDIO_RELEASE_RESET() and __HAL_RCC_SDIO_CLK_ENABLE();
RCC->APB2RSTR &= ~RCC_APB2RSTR_SDIORST_Msk; // take SDIO out of reset
RCC->APB2ENR |= RCC_APB2RSTR_SDIORST_Msk; // enable SDIO clock
// Enable the DMA2 Clock
// Setup DMA
#if defined(STM32F1xx)
hdma_sdio.Init.Mode = DMA_NORMAL;
hdma_sdio.Instance = DMA2_Channel4;
HAL_NVIC_EnableIRQ(DMA2_Channel4_5_IRQn);
#elif defined(STM32F4xx)
hdma_sdio.Init.Mode = DMA_PFCTRL;
hdma_sdio.Instance = DMA2_Stream3;
hdma_sdio.Init.Channel = DMA_CHANNEL_4;
hdma_sdio.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
hdma_sdio.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_sdio.Init.MemBurst = DMA_MBURST_INC4;
hdma_sdio.Init.PeriphBurst = DMA_PBURST_INC4;
HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
#endif
HAL_NVIC_EnableIRQ(SDIO_IRQn);
hdma_sdio.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_sdio.Init.MemInc = DMA_MINC_ENABLE;
hdma_sdio.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_sdio.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_sdio.Init.Priority = DMA_PRIORITY_LOW;
__HAL_LINKDMA(&hsd, hdmarx, hdma_sdio);
__HAL_LINKDMA(&hsd, hdmatx, hdma_sdio);
#if defined(STM32F1xx)
__HAL_RCC_SDIO_CLK_ENABLE();
__HAL_RCC_DMA2_CLK_ENABLE();
#else
__HAL_RCC_SDIO_FORCE_RESET();
delay(2);
__HAL_RCC_SDIO_RELEASE_RESET();
delay(2);
__HAL_RCC_SDIO_CLK_ENABLE();
__HAL_RCC_DMA2_FORCE_RESET();
delay(2);
__HAL_RCC_DMA2_RELEASE_RESET();
delay(2);
__HAL_RCC_DMA2_CLK_ENABLE();
#endif
//Initialize the SDIO (with initial <400Khz Clock)
@@ -179,6 +222,7 @@
// Power up the SDIO
SDIO_PowerState_ON(SDIO);
hsd.Instance = SDIO;
}
void HAL_SD_MspInit(SD_HandleTypeDef *hsd) { // application specific init
@@ -222,107 +266,81 @@
if (!status) break;
if (!--retry_Cnt) return false; // return failing status if retries are exhausted
}
go_to_transfer_speed();
}
#endif
return true;
}
/*
void init_SDIO_pins(void) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
// SDIO GPIO Configuration
// PC8 ------> SDIO_D0
// PC12 ------> SDIO_CK
// PD2 ------> SDIO_CMD
static bool SDIO_ReadWriteBlock_DMA(uint32_t block, const uint8_t *src, uint8_t *dst) {
if (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER) return false;
GPIO_InitStruct.Pin = GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
}
*/
//bool SDIO_init() { return (bool) (SD_SDIO_Init() ? 1 : 0);}
//bool SDIO_Init_C() { return (bool) (SD_SDIO_Init() ? 1 : 0);}
bool SDIO_ReadBlock(uint32_t block, uint8_t *dst) {
hsd.Instance = SDIO;
uint8_t retryCnt = SDIO_READ_RETRIES;
bool status;
for (;;) {
TERN_(USE_WATCHDOG, HAL_watchdog_refresh());
status = (bool) HAL_SD_ReadBlocks(&hsd, (uint8_t*)dst, block, 1, 1000); // read one 512 byte block with 500mS timeout
status |= (bool) HAL_SD_GetCardState(&hsd); // make sure all is OK
if (!status) break; // return passing status
if (!--retryCnt) break; // return failing status if retries are exhausted
HAL_StatusTypeDef ret;
if (src) {
hdma_sdio.Init.Direction = DMA_MEMORY_TO_PERIPH;
HAL_DMA_Init(&hdma_sdio);
ret = HAL_SD_WriteBlocks_DMA(&hsd, (uint8_t *)src, block, 1);
}
else {
hdma_sdio.Init.Direction = DMA_PERIPH_TO_MEMORY;
HAL_DMA_Init(&hdma_sdio);
ret = HAL_SD_ReadBlocks_DMA(&hsd, (uint8_t *)dst, block, 1);
}
return status;
/*
return (bool) ((status_read | status_card) ? 1 : 0);
if (SDIO_GetCardState() != SDIO_CARD_TRANSFER) return false;
if (blockAddress >= SdCard.LogBlockNbr) return false;
if ((0x03 & (uint32_t)data)) return false; // misaligned data
if (SdCard.CardType != CARD_SDHC_SDXC) { blockAddress *= 512U; }
if (!SDIO_CmdReadSingleBlock(blockAddress)) {
SDIO_CLEAR_FLAG(SDIO_ICR_CMD_FLAGS);
dma_disable(SDIO_DMA_DEV, SDIO_DMA_CHANNEL);
if (ret != HAL_OK) {
HAL_DMA_Abort_IT(&hdma_sdio);
HAL_DMA_DeInit(&hdma_sdio);
return false;
}
while (!SDIO_GET_FLAG(SDIO_STA_DATAEND | SDIO_STA_TRX_ERROR_FLAGS)) {}
dma_disable(SDIO_DMA_DEV, SDIO_DMA_CHANNEL);
if (SDIO->STA & SDIO_STA_RXDAVL) {
while (SDIO->STA & SDIO_STA_RXDAVL) (void)SDIO->FIFO;
SDIO_CLEAR_FLAG(SDIO_ICR_CMD_FLAGS | SDIO_ICR_DATA_FLAGS);
millis_t timeout = millis() + 500;
// Wait the transfer
while (hsd.State != HAL_SD_STATE_READY) {
if (ELAPSED(millis(), timeout)) {
HAL_DMA_Abort_IT(&hdma_sdio);
HAL_DMA_DeInit(&hdma_sdio);
return false;
}
if (SDIO_GET_FLAG(SDIO_STA_TRX_ERROR_FLAGS)) {
SDIO_CLEAR_FLAG(SDIO_ICR_CMD_FLAGS | SDIO_ICR_DATA_FLAGS);
return false;
}
SDIO_CLEAR_FLAG(SDIO_ICR_CMD_FLAGS | SDIO_ICR_DATA_FLAGS);
*/
while (__HAL_DMA_GET_FLAG(&hdma_sdio, __HAL_DMA_GET_TC_FLAG_INDEX(&hdma_sdio)) != 0
|| __HAL_DMA_GET_FLAG(&hdma_sdio, __HAL_DMA_GET_TE_FLAG_INDEX(&hdma_sdio)) != 0) { /* nada */ }
HAL_DMA_Abort_IT(&hdma_sdio);
HAL_DMA_DeInit(&hdma_sdio);
timeout = millis() + 500;
while (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER) if (ELAPSED(millis(), timeout)) return false;
return true;
}
bool SDIO_ReadBlock(uint32_t block, uint8_t *dst) {
uint8_t retries = SDIO_READ_RETRIES;
while (retries--) if (SDIO_ReadWriteBlock_DMA(block, NULL, dst)) return true;
return false;
}
bool SDIO_WriteBlock(uint32_t block, const uint8_t *src) {
hsd.Instance = SDIO;
uint8_t retryCnt = SDIO_READ_RETRIES;
bool status;
for (;;) {
status = (bool) HAL_SD_WriteBlocks(&hsd, (uint8_t*)src, block, 1, 500); // write one 512 byte block with 500mS timeout
status |= (bool) HAL_SD_GetCardState(&hsd); // make sure all is OK
if (!status) break; // return passing status
if (!--retryCnt) break; // return failing status if retries are exhausted
}
return status;
uint8_t retries = SDIO_READ_RETRIES;
while (retries--) if (SDIO_ReadWriteBlock_DMA(block, src, NULL)) return true;
return false;
}
#if defined(STM32F1xx)
#define DMA_IRQ_HANDLER DMA2_Channel4_5_IRQHandler
#elif defined(STM32F4xx)
#define DMA_IRQ_HANDLER DMA2_Stream3_IRQHandler
#else
#error "Unknown STM32 architecture."
#endif
extern "C" void SDIO_IRQHandler(void) { HAL_SD_IRQHandler(&hsd); }
extern "C" void DMA_IRQ_HANDLER(void) { HAL_DMA_IRQHandler(&hdma_sdio); }
#endif // !USBD_USE_CDC_COMPOSITE
#endif // SDIO_SUPPORT
#endif // ARDUINO_ARCH_STM32 && !STM32GENERIC

View File

@@ -43,25 +43,22 @@ bool PersistentStore::access_start() { eeprom_init(); return true; }
bool PersistentStore::access_finish() { return true; }
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
uint16_t written = 0;
while (size--) {
uint8_t v = *value;
// EEPROM has only ~100,000 write cycles,
// so only write bytes that have changed!
uint8_t * const p = (uint8_t * const)pos;
if (v != eeprom_read_byte(p)) {
if (v != eeprom_read_byte(p)) { // EEPROM has only ~100,000 write cycles, so only write bytes that have changed!
eeprom_write_byte(p, v);
if (++written & 0x7F) delay(2); else safe_delay(2); // Avoid triggering watchdog during long EEPROM writes
if (eeprom_read_byte(p) != v) {
SERIAL_ECHO_MSG(STR_ERR_EEPROM_WRITE);
return true;
}
}
crc16(crc, &v, 1);
pos++;
value++;
};
}
return false;
}

View File

@@ -52,6 +52,6 @@
#error "SERIAL_STATS_DROPPED_RX is not supported on STM32."
#endif
#if ANY(TFT_COLOR_UI, TFT_LVGL_UI, TFT_CLASSIC_UI) && NOT_TARGET(STM32F4xx, STM32F1xx)
#error "TFT_COLOR_UI, TFT_LVGL_UI and TFT_CLASSIC_UI are currently only supported on STM32F4 and STM32F1 hardware."
#if ANY(TFT_COLOR_UI, TFT_LVGL_UI, TFT_CLASSIC_UI) && NOT_TARGET(STM32H7xx, STM32F4xx, STM32F1xx)
#error "TFT_COLOR_UI, TFT_LVGL_UI and TFT_CLASSIC_UI are currently only supported on STM32H7, STM32F4 and STM32F1 hardware."
#endif

View File

@@ -30,54 +30,66 @@
class Sd2CardUSBMscHandler : public USBMscHandler {
public:
DiskIODriver* diskIODriver() {
#if ENABLED(MULTI_VOLUME)
#if SHARED_VOLUME_IS(SD_ONBOARD)
return &card.media_sd_spi;
#elif SHARED_VOLUME_IS(USB_FLASH_DRIVE)
return &card.media_usbFlashDrive;
#endif
#else
return diskIODriver();
#endif
}
bool GetCapacity(uint32_t *pBlockNum, uint16_t *pBlockSize) {
*pBlockNum = card.getSd2Card().cardSize();
*pBlockNum = diskIODriver()->cardSize();
*pBlockSize = BLOCK_SIZE;
return true;
}
bool Write(uint8_t *pBuf, uint32_t blkAddr, uint16_t blkLen) {
auto sd2card = card.getSd2Card();
auto sd2card = diskIODriver();
// single block
if (blkLen == 1) {
watchdog_refresh();
sd2card.writeBlock(blkAddr, pBuf);
sd2card->writeBlock(blkAddr, pBuf);
return true;
}
// multi block optmization
sd2card.writeStart(blkAddr, blkLen);
sd2card->writeStart(blkAddr, blkLen);
while (blkLen--) {
watchdog_refresh();
sd2card.writeData(pBuf);
sd2card->writeData(pBuf);
pBuf += BLOCK_SIZE;
}
sd2card.writeStop();
sd2card->writeStop();
return true;
}
bool Read(uint8_t *pBuf, uint32_t blkAddr, uint16_t blkLen) {
auto sd2card = card.getSd2Card();
auto sd2card = diskIODriver();
// single block
if (blkLen == 1) {
watchdog_refresh();
sd2card.readBlock(blkAddr, pBuf);
sd2card->readBlock(blkAddr, pBuf);
return true;
}
// multi block optmization
sd2card.readStart(blkAddr);
sd2card->readStart(blkAddr);
while (blkLen--) {
watchdog_refresh();
sd2card.readData(pBuf);
sd2card->readData(pBuf);
pBuf += BLOCK_SIZE;
}
sd2card.readStop();
sd2card->readStop();
return true;
}
bool IsReady() {
return card.isMounted();
return diskIODriver()->isReady();
}
};
@@ -105,8 +117,8 @@ USBMscHandler *pSingleMscHandler = &usbMscHandler;
void MSC_SD_init() {
USBDevice.end();
delay(200);
USBDevice.begin();
USBDevice.registerMscHandlers(1, &pSingleMscHandler, Marlin_STORAGE_Inquirydata);
USBDevice.begin();
}
#endif // __STM32F1__ && HAS_SD_HOST_DRIVE

View File

@@ -0,0 +1,390 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2021 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 <https://www.gnu.org/licenses/>.
*
*/
#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC)
#include "../../../inc/MarlinConfig.h"
#if HAS_LTDC_TFT
#include "tft_ltdc.h"
#include "pinconfig.h"
#define FRAME_BUFFER_ADDRESS 0XC0000000 // SDRAM address
#define SDRAM_TIMEOUT ((uint32_t)0xFFFF)
#define REFRESH_COUNT ((uint32_t)0x02A5) // SDRAM refresh counter
#define SDRAM_MODEREG_BURST_LENGTH_1 ((uint16_t)0x0000)
#define SDRAM_MODEREG_BURST_LENGTH_2 ((uint16_t)0x0001)
#define SDRAM_MODEREG_BURST_LENGTH_4 ((uint16_t)0x0002)
#define SDRAM_MODEREG_BURST_LENGTH_8 ((uint16_t)0x0004)
#define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000)
#define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008)
#define SDRAM_MODEREG_CAS_LATENCY_2 ((uint16_t)0x0020)
#define SDRAM_MODEREG_CAS_LATENCY_3 ((uint16_t)0x0030)
#define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((uint16_t)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200)
void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram, FMC_SDRAM_CommandTypeDef *Command) {
__IO uint32_t tmpmrd =0;
/* Step 1: Configure a clock configuration enable command */
Command->CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
Command->AutoRefreshNumber = 1;
Command->ModeRegisterDefinition = 0;
/* Send the command */
HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);
/* Step 2: Insert 100 us minimum delay */
/* Inserted delay is equal to 1 ms due to systick time base unit (ms) */
HAL_Delay(1);
/* Step 3: Configure a PALL (precharge all) command */
Command->CommandMode = FMC_SDRAM_CMD_PALL;
Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
Command->AutoRefreshNumber = 1;
Command->ModeRegisterDefinition = 0;
/* Send the command */
HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);
/* Step 4 : Configure a Auto-Refresh command */
Command->CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
Command->AutoRefreshNumber = 8;
Command->ModeRegisterDefinition = 0;
/* Send the command */
HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);
/* Step 5: Program the external memory mode register */
tmpmrd = (uint32_t)(SDRAM_MODEREG_BURST_LENGTH_1 |
SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |
SDRAM_MODEREG_CAS_LATENCY_2 |
SDRAM_MODEREG_OPERATING_MODE_STANDARD |
SDRAM_MODEREG_WRITEBURST_MODE_SINGLE);
Command->CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
Command->AutoRefreshNumber = 1;
Command->ModeRegisterDefinition = tmpmrd;
/* Send the command */
HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);
/* Step 6: Set the refresh rate counter */
/* Set the device refresh rate */
HAL_SDRAM_ProgramRefreshRate(hsdram, REFRESH_COUNT);
}
void SDRAM_Config() {
__HAL_RCC_SYSCFG_CLK_ENABLE();
__HAL_RCC_FMC_CLK_ENABLE();
SDRAM_HandleTypeDef hsdram;
FMC_SDRAM_TimingTypeDef SDRAM_Timing;
FMC_SDRAM_CommandTypeDef command;
/* Configure the SDRAM device */
hsdram.Instance = FMC_SDRAM_DEVICE;
hsdram.Init.SDBank = FMC_SDRAM_BANK1;
hsdram.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_9;
hsdram.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_13;
hsdram.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_16;
hsdram.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
hsdram.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_2;
hsdram.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
hsdram.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2;
hsdram.Init.ReadBurst = FMC_SDRAM_RBURST_ENABLE;
hsdram.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_0;
/* Timing configuration for 100Mhz as SDRAM clock frequency (System clock is up to 200Mhz) */
SDRAM_Timing.LoadToActiveDelay = 2;
SDRAM_Timing.ExitSelfRefreshDelay = 8;
SDRAM_Timing.SelfRefreshTime = 6;
SDRAM_Timing.RowCycleDelay = 6;
SDRAM_Timing.WriteRecoveryTime = 2;
SDRAM_Timing.RPDelay = 2;
SDRAM_Timing.RCDDelay = 2;
/* Initialize the SDRAM controller */
if (HAL_SDRAM_Init(&hsdram, &SDRAM_Timing) != HAL_OK)
{
/* Initialization Error */
}
/* Program the SDRAM external device */
SDRAM_Initialization_Sequence(&hsdram, &command);
}
void LTDC_Config() {
__HAL_RCC_LTDC_CLK_ENABLE();
__HAL_RCC_DMA2D_CLK_ENABLE();
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
/* The PLL3R is configured to provide the LTDC PCLK clock */
/* PLL3_VCO Input = HSE_VALUE / PLL3M = 25Mhz / 5 = 5 Mhz */
/* PLL3_VCO Output = PLL3_VCO Input * PLL3N = 5Mhz * 160 = 800 Mhz */
/* PLLLCDCLK = PLL3_VCO Output/PLL3R = 800Mhz / 16 = 50Mhz */
/* LTDC clock frequency = PLLLCDCLK = 50 Mhz */
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC;
PeriphClkInitStruct.PLL3.PLL3M = 5;
PeriphClkInitStruct.PLL3.PLL3N = 160;
PeriphClkInitStruct.PLL3.PLL3FRACN = 0;
PeriphClkInitStruct.PLL3.PLL3P = 2;
PeriphClkInitStruct.PLL3.PLL3Q = 2;
PeriphClkInitStruct.PLL3.PLL3R = (800 / LTDC_LCD_CLK);
PeriphClkInitStruct.PLL3.PLL3VCOSEL = RCC_PLL3VCOWIDE;
PeriphClkInitStruct.PLL3.PLL3RGE = RCC_PLL3VCIRANGE_2;
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
LTDC_HandleTypeDef hltdc_F;
LTDC_LayerCfgTypeDef pLayerCfg;
/* LTDC Initialization -------------------------------------------------------*/
/* Polarity configuration */
/* Initialize the horizontal synchronization polarity as active low */
hltdc_F.Init.HSPolarity = LTDC_HSPOLARITY_AL;
/* Initialize the vertical synchronization polarity as active low */
hltdc_F.Init.VSPolarity = LTDC_VSPOLARITY_AL;
/* Initialize the data enable polarity as active low */
hltdc_F.Init.DEPolarity = LTDC_DEPOLARITY_AL;
/* Initialize the pixel clock polarity as input pixel clock */
hltdc_F.Init.PCPolarity = LTDC_PCPOLARITY_IPC;
/* Timing configuration */
hltdc_F.Init.HorizontalSync = (LTDC_LCD_HSYNC - 1);
hltdc_F.Init.VerticalSync = (LTDC_LCD_VSYNC - 1);
hltdc_F.Init.AccumulatedHBP = (LTDC_LCD_HSYNC + LTDC_LCD_HBP - 1);
hltdc_F.Init.AccumulatedVBP = (LTDC_LCD_VSYNC + LTDC_LCD_VBP - 1);
hltdc_F.Init.AccumulatedActiveH = (TFT_HEIGHT + LTDC_LCD_VSYNC + LTDC_LCD_VBP - 1);
hltdc_F.Init.AccumulatedActiveW = (TFT_WIDTH + LTDC_LCD_HSYNC + LTDC_LCD_HBP - 1);
hltdc_F.Init.TotalHeigh = (TFT_HEIGHT + LTDC_LCD_VSYNC + LTDC_LCD_VBP + LTDC_LCD_VFP - 1);
hltdc_F.Init.TotalWidth = (TFT_WIDTH + LTDC_LCD_HSYNC + LTDC_LCD_HBP + LTDC_LCD_HFP - 1);
/* Configure R,G,B component values for LCD background color : all black background */
hltdc_F.Init.Backcolor.Blue = 0;
hltdc_F.Init.Backcolor.Green = 0;
hltdc_F.Init.Backcolor.Red = 0;
hltdc_F.Instance = LTDC;
/* Layer0 Configuration ------------------------------------------------------*/
/* Windowing configuration */
pLayerCfg.WindowX0 = 0;
pLayerCfg.WindowX1 = TFT_WIDTH;
pLayerCfg.WindowY0 = 0;
pLayerCfg.WindowY1 = TFT_HEIGHT;
/* Pixel Format configuration*/
pLayerCfg.PixelFormat = LTDC_PIXEL_FORMAT_RGB565;
/* Start Address configuration : frame buffer is located at SDRAM memory */
pLayerCfg.FBStartAdress = (uint32_t)(FRAME_BUFFER_ADDRESS);
/* Alpha constant (255 == totally opaque) */
pLayerCfg.Alpha = 255;
/* Default Color configuration (configure A,R,G,B component values) : no background color */
pLayerCfg.Alpha0 = 0; /* fully transparent */
pLayerCfg.Backcolor.Blue = 0;
pLayerCfg.Backcolor.Green = 0;
pLayerCfg.Backcolor.Red = 0;
/* Configure blending factors */
pLayerCfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_CA;
pLayerCfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_CA;
/* Configure the number of lines and number of pixels per line */
pLayerCfg.ImageWidth = TFT_WIDTH;
pLayerCfg.ImageHeight = TFT_HEIGHT;
/* Configure the LTDC */
if (HAL_LTDC_Init(&hltdc_F) != HAL_OK)
{
/* Initialization Error */
}
/* Configure the Layer*/
if (HAL_LTDC_ConfigLayer(&hltdc_F, &pLayerCfg, 0) != HAL_OK)
{
/* Initialization Error */
}
}
uint16_t TFT_LTDC::x_min = 0;
uint16_t TFT_LTDC::x_max = 0;
uint16_t TFT_LTDC::y_min = 0;
uint16_t TFT_LTDC::y_max = 0;
uint16_t TFT_LTDC::x_cur = 0;
uint16_t TFT_LTDC::y_cur = 0;
uint8_t TFT_LTDC::reg = 0;
volatile uint16_t* TFT_LTDC::framebuffer = (volatile uint16_t* )FRAME_BUFFER_ADDRESS;
void TFT_LTDC::Init() {
// SDRAM pins init
for (uint16_t i = 0; PinMap_SDRAM[i].pin != NC; i++)
pinmap_pinout(PinMap_SDRAM[i].pin, PinMap_SDRAM);
// SDRAM peripheral config
SDRAM_Config();
// LTDC pins init
for (uint16_t i = 0; PinMap_LTDC[i].pin != NC; i++)
pinmap_pinout(PinMap_LTDC[i].pin, PinMap_LTDC);
// LTDC peripheral config
LTDC_Config();
}
uint32_t TFT_LTDC::GetID() {
return 0xABAB;
}
uint32_t TFT_LTDC::ReadID(tft_data_t Reg) {
return 0xABAB;
}
bool TFT_LTDC::isBusy() {
return false;
}
uint16_t TFT_LTDC::ReadPoint(uint16_t x, uint16_t y) {
return framebuffer[(TFT_WIDTH * y) + x];
}
void TFT_LTDC::DrawPoint(uint16_t x, uint16_t y, uint16_t color) {
framebuffer[(TFT_WIDTH * y) + x] = color;
}
void TFT_LTDC::DrawRect(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t color) {
if (sx == ex || sy == ey) return;
uint16_t offline = TFT_WIDTH - (ex - sx);
uint32_t addr = (uint32_t)&framebuffer[(TFT_WIDTH * sy) + sx];
DMA2D->CR &= ~(1 << 0);
DMA2D->CR = 3 << 16;
DMA2D->OPFCCR = 0X02;
DMA2D->OOR = offline;
DMA2D->OMAR = addr;
DMA2D->NLR = (ey - sy) | ((ex - sx) << 16);
DMA2D->OCOLR = color;
DMA2D->CR |= 1<<0;
uint32_t timeout = 0;
while((DMA2D->ISR & (1<<1)) == 0)
{
timeout++;
if(timeout>0X1FFFFF)break;
}
DMA2D->IFCR |= 1<<1;
}
void TFT_LTDC::DrawImage(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t *colors) {
if (sx == ex || sy == ey) return;
uint16_t offline = TFT_WIDTH - (ex - sx);
uint32_t addr = (uint32_t)&framebuffer[(TFT_WIDTH * sy) + sx];
DMA2D->CR &= ~(1 << 0);
DMA2D->CR = 0 << 16;
DMA2D->FGPFCCR = 0X02;
DMA2D->FGOR = 0;
DMA2D->OOR = offline;
DMA2D->FGMAR = (uint32_t)colors;
DMA2D->OMAR = addr;
DMA2D->NLR = (ey - sy) | ((ex - sx) << 16);
DMA2D->CR |= 1<<0;
uint32_t timeout = 0;
while((DMA2D->ISR & (1<<1)) == 0)
{
timeout++;
if(timeout>0X1FFFFF)break;
}
DMA2D->IFCR |= 1<<1;
}
void TFT_LTDC::WriteData(uint16_t data) {
switch (reg) {
case 0x01: x_cur = x_min = data; return;
case 0x02: x_max = data; return;
case 0x03: y_cur = y_min = data; return;
case 0x04: y_max = data; return;
}
Transmit(data);
}
void TFT_LTDC::Transmit(tft_data_t Data) {
DrawPoint(x_cur, y_cur, Data);
x_cur++;
if (x_cur > x_max) {
x_cur = x_min;
y_cur++;
if (y_cur > y_max) y_cur = y_min;
}
}
void TFT_LTDC::WriteReg(uint16_t Reg) {
reg = Reg;
}
void TFT_LTDC::TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) {
while (x_cur != x_min && Count) {
Transmit(*Data);
if (MemoryIncrease == DMA_PINC_ENABLE) Data++;
Count--;
}
uint16_t width = x_max - x_min + 1;
uint16_t height = Count / width;
uint16_t x_end_cnt = Count - (width * height);
if (height) {
if (MemoryIncrease == DMA_PINC_ENABLE) {
DrawImage(x_min, y_cur, x_min + width, y_cur + height, Data);
Data += width * height;
} else {
DrawRect(x_min, y_cur, x_min + width, y_cur + height, *Data);
}
y_cur += height;
}
while (x_end_cnt) {
Transmit(*Data);
if (MemoryIncrease == DMA_PINC_ENABLE) Data++;
x_end_cnt--;
}
}
#endif // HAS_LTDC_TFT
#endif // ARDUINO_ARCH_STM32 && !STM32GENERIC

View File

@@ -0,0 +1,155 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2021 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 <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#include "../../../inc/MarlinConfig.h"
#ifdef STM32H7xx
#include "stm32h7xx_hal.h"
#else
#error "LTDC TFT is currently only supported on STM32H7 hardware."
#endif
#define DATASIZE_8BIT SPI_DATASIZE_8BIT
#define DATASIZE_16BIT SPI_DATASIZE_16BIT
#define TFT_IO_DRIVER TFT_LTDC
#define TFT_DATASIZE DATASIZE_16BIT
typedef uint16_t tft_data_t;
class TFT_LTDC {
private:
static volatile uint16_t *framebuffer;
static uint16_t x_min, x_max, y_min, y_max, x_cur, y_cur;
static uint8_t reg;
static uint32_t ReadID(tft_data_t Reg);
static uint16_t ReadPoint(uint16_t x, uint16_t y);
static void DrawPoint(uint16_t x, uint16_t y, uint16_t color);
static void DrawRect(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t color);
static void DrawImage(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t *colors);
static void Transmit(tft_data_t Data);
static void TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count);
public:
static void Init();
static uint32_t GetID();
static bool isBusy();
static void Abort() { /*__HAL_DMA_DISABLE(&DMAtx);*/ }
static void DataTransferBegin(uint16_t DataWidth = TFT_DATASIZE) {}
static void DataTransferEnd() {};
static void WriteData(uint16_t Data);
static void WriteReg(uint16_t Reg);
static void WriteSequence(uint16_t *Data, uint16_t Count) { TransmitDMA(DMA_PINC_ENABLE, Data, Count); }
static void WriteMultiple(uint16_t Color, uint16_t Count) { static uint16_t Data; Data = Color; TransmitDMA(DMA_PINC_DISABLE, &Data, Count); }
static void WriteMultiple(uint16_t Color, uint32_t Count) {
static uint16_t Data; Data = Color;
while (Count > 0) {
TransmitDMA(DMA_MINC_DISABLE, &Data, Count > 0xFFFF ? 0xFFFF : Count);
Count = Count > 0xFFFF ? Count - 0xFFFF : 0;
}
}
};
const PinMap PinMap_LTDC[] = {
{PF_10, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_DE
{PG_7, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_CLK
{PI_9, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_VSYNC
{PI_10, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_HSYNC
{PG_6, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_R7
{PH_12, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_R6
{PH_11, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_R5
{PH_10, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_R4
{PH_9, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_R3
{PI_2, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_G7
{PI_1, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_G6
{PI_0, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_G5
{PH_15, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_G4
{PH_14, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_G3
{PH_13, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_G2
{PI_7, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_B7
{PI_6, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_B6
{PI_5, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_B5
{PI_4, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_B4
{PG_11, LTDC, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_LTDC)}, // LCD_B3
{NC, NP, 0}
};
const PinMap PinMap_SDRAM[] = {
{PC_0, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_SDNWE
{PC_2, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_SDNE0
{PC_3, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_SDCKE0
{PE_0, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_NBL0
{PE_1, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_NBL1
{PF_11, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_SDNRAS
{PG_8, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_SDCLK
{PG_15, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_SDNCAS
{PG_4, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_BA0
{PG_5, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_BA1
{PD_14, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_D0
{PD_15, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_D1
{PD_0, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_D2
{PD_1, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_D3
{PE_7, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_D4
{PE_8, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_D5
{PE_9, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_D6
{PE_10, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_D7
{PE_11, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_D8
{PE_12, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_D9
{PE_13, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_D10
{PE_14, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_D11
{PE_15, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_D12
{PD_8, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_D13
{PD_9, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_D14
{PD_10, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_D15
{PF_0, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_A0
{PF_1, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_A1
{PF_2, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_A2
{PF_3, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_A3
{PF_4, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_A4
{PF_5, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_A5
{PF_12, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_A6
{PF_13, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_A7
{PF_14, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_A8
{PF_15, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_A9
{PG_0, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_A10
{PG_1, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_A11
{PG_2, FMC_Bank1_R, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF12_FMC)}, // FMC_A12
{NC, NP, 0}
};
const PinMap PinMap_QUADSPI[] = {
{PB_2, QUADSPI, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_CLK
{PB_10, QUADSPI, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_NCS
{PF_6, QUADSPI, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO3
{PF_7, QUADSPI, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)}, // QUADSPI_BK1_IO2
{PF_8, QUADSPI, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO0
{PF_9, QUADSPI, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO1
{NC, NP, 0}
};

View File

@@ -74,7 +74,7 @@
#elif defined(STM32F401xC) || defined(STM32F401xE)
#define MCU_STEP_TIMER 9
#define MCU_TEMP_TIMER 10
#elif defined(STM32F4xx) || defined(STM32F7xx)
#elif defined(STM32F4xx) || defined(STM32F7xx) || defined(STM32H7xx)
#define MCU_STEP_TIMER 6 // STM32F401 has no TIM6, TIM7, or TIM8
#define MCU_TEMP_TIMER 14 // TIM7 is consumed by Software Serial if used.
#endif

View File

@@ -84,7 +84,7 @@
#if defined(SERIAL_USB) && !HAS_SD_HOST_DRIVE
USBSerial SerialUSB;
DefaultSerial MSerial(true, SerialUSB);
DefaultSerial1 MSerial0(true, SerialUSB);
#if ENABLED(EMERGENCY_PARSER)
#include "../libmaple/usb/stm32f1/usb_reg_map.h"
@@ -107,7 +107,7 @@
len = usb_cdcacm_peek(buf, total);
for (uint32 i = 0; i < len; i++)
emergency_parser.update(MSerial.emergency_state, buf[i + total - len]);
emergency_parser.update(MSerial0.emergency_state, buf[i + total - len]);
}
#endif
#endif
@@ -132,6 +132,9 @@ const uint8_t adc_pins[] = {
#if HAS_TEMP_CHAMBER
TEMP_CHAMBER_PIN,
#endif
#if HAS_TEMP_COOLER
TEMP_COOLER_PIN,
#endif
#if HAS_TEMP_ADC_1
TEMP_1_PIN,
#endif
@@ -189,6 +192,9 @@ enum TempPinIndex : char {
#if HAS_TEMP_CHAMBER
TEMP_CHAMBER,
#endif
#if HAS_TEMP_COOLER
TEMP_COOLER_PIN,
#endif
#if HAS_TEMP_ADC_1
TEMP_1,
#endif
@@ -385,6 +391,9 @@ void HAL_adc_start_conversion(const uint8_t adc_pin) {
#if HAS_TEMP_CHAMBER
case TEMP_CHAMBER_PIN: pin_index = TEMP_CHAMBER; break;
#endif
#if HAS_TEMP_COOLER
case TEMP_COOLER_PIN: pin_index = TEMP_COOLER; break;
#endif
#if HAS_TEMP_ADC_1
case TEMP_1_PIN: pin_index = TEMP_1; break;
#endif
@@ -444,6 +453,8 @@ void analogWrite(pin_t pin, int pwm_val8) {
analogWrite(uint8_t(pin), pwm_val8);
}
void flashFirmware(const int16_t) { nvic_sys_reset(); }
void HAL_reboot() { nvic_sys_reset(); }
void flashFirmware(const int16_t) { HAL_reboot(); }
#endif // __STM32F1__

View File

@@ -53,7 +53,7 @@
// ------------------------
#ifndef STM32_FLASH_SIZE
#if EITHER(MCU_STM32F103RE, MCU_STM32F103VE)
#if ANY(MCU_STM32F103RE, MCU_STM32F103VE, MCU_STM32F103ZE)
#define STM32_FLASH_SIZE 512
#else
#define STM32_FLASH_SIZE 256
@@ -61,11 +61,11 @@
#endif
#ifdef SERIAL_USB
typedef ForwardSerial0Type< USBSerial > DefaultSerial;
extern DefaultSerial MSerial;
typedef ForwardSerial1Class< USBSerial > DefaultSerial1;
extern DefaultSerial1 MSerial0;
#if !HAS_SD_HOST_DRIVE
#define UsbSerial MSerial
#define UsbSerial MSerial0
#else
#define UsbSerial MarlinCompositeSerial
#endif
@@ -81,24 +81,30 @@
#endif
#if SERIAL_PORT == -1
#define MYSERIAL0 UsbSerial
#define MYSERIAL1 UsbSerial
#elif WITHIN(SERIAL_PORT, 1, NUM_UARTS)
#define MYSERIAL0 MSERIAL(SERIAL_PORT)
#elif NUM_UARTS == 5
#error "SERIAL_PORT must be -1 or from 1 to 5. Please update your configuration."
#define MYSERIAL1 MSERIAL(SERIAL_PORT)
#else
#error "SERIAL_PORT must be -1 or from 1 to 3. Please update your configuration."
#define MYSERIAL1 MSERIAL(1) // dummy port
#if NUM_UARTS == 5
#error "SERIAL_PORT must be from 1 to 5. You can also use -1 if the board supports Native USB."
#else
#error "SERIAL_PORT must be from 1 to 3. You can also use -1 if the board supports Native USB."
#endif
#endif
#ifdef SERIAL_PORT_2
#if SERIAL_PORT_2 == -1
#define MYSERIAL1 UsbSerial
#define MYSERIAL2 UsbSerial
#elif WITHIN(SERIAL_PORT_2, 1, NUM_UARTS)
#define MYSERIAL1 MSERIAL(SERIAL_PORT_2)
#elif NUM_UARTS == 5
#error "SERIAL_PORT_2 must be -1 or from 1 to 5. Please update your configuration."
#define MYSERIAL2 MSERIAL(SERIAL_PORT_2)
#else
#error "SERIAL_PORT_2 must be -1 or from 1 to 3. Please update your configuration."
#define MYSERIAL2 MSERIAL(1) // dummy port
#if NUM_UARTS == 5
#error "SERIAL_PORT_2 must be from 1 to 5. You can also use -1 if the board supports Native USB."
#else
#error "SERIAL_PORT_2 must be from 1 to 3. You can also use -1 if the board supports Native USB."
#endif
#endif
#endif
@@ -107,10 +113,13 @@
#define MMU2_SERIAL UsbSerial
#elif WITHIN(MMU2_SERIAL_PORT, 1, NUM_UARTS)
#define MMU2_SERIAL MSERIAL(MMU2_SERIAL_PORT)
#elif NUM_UARTS == 5
#error "MMU2_SERIAL_PORT must be -1 or from 1 to 5. Please update your configuration."
#else
#error "MMU2_SERIAL_PORT must be -1 or from 1 to 3. Please update your configuration."
#define MMU2_SERIAL MSERIAL(1) // dummy port
#if NUM_UARTS == 5
#error "MMU2_SERIAL_PORT must be from 1 to 5. You can also use -1 if the board supports Native USB."
#else
#error "MMU2_SERIAL_PORT must be from 1 to 3. You can also use -1 if the board supports Native USB."
#endif
#endif
#endif
@@ -119,10 +128,13 @@
#define LCD_SERIAL UsbSerial
#elif WITHIN(LCD_SERIAL_PORT, 1, NUM_UARTS)
#define LCD_SERIAL MSERIAL(LCD_SERIAL_PORT)
#elif NUM_UARTS == 5
#error "LCD_SERIAL_PORT must be -1 or from 1 to 5. Please update your configuration."
#else
#error "LCD_SERIAL_PORT must be -1 or from 1 to 3. Please update your configuration."
#define LCD_SERIAL MSERIAL(1) // dummy port
#if NUM_UARTS == 5
#error "LCD_SERIAL_PORT must be from 1 to 5. You can also use -1 if the board supports Native USB."
#else
#error "LCD_SERIAL_PORT must be from 1 to 3. You can also use -1 if the board supports Native USB."
#endif
#endif
#if HAS_DGUS_LCD
#define SERIAL_GET_TX_BUFFER_FREE() LCD_SERIAL.availableForWrite()
@@ -195,7 +207,7 @@ void HAL_clear_reset_source();
// Reset reason
uint8_t HAL_get_reset_source();
inline void HAL_reboot() {} // reboot the board or restart the bootloader
void HAL_reboot();
void _delay_ms(const int delay);

View File

@@ -44,8 +44,8 @@ static void TXBegin() {
#warning "Using POSTMORTEM_DEBUGGING requires a physical U(S)ART hardware in case of severe error."
#warning "Disabling the severe error reporting feature currently because the used serial port is not a HW port."
#else
// We use MYSERIAL0 here, so we need to figure out how to get the linked register
struct usart_dev* dev = MYSERIAL0.c_dev();
// We use MYSERIAL1 here, so we need to figure out how to get the linked register
struct usart_dev* dev = MYSERIAL1.c_dev();
// Or use this if removing libmaple
// int irq = dev->irq_num;
@@ -80,7 +80,7 @@ static void TXBegin() {
#define sw_barrier() __asm__ volatile("": : :"memory");
static void TX(char c) {
#if WITHIN(SERIAL_PORT, 1, 6)
struct usart_dev* dev = MYSERIAL0.c_dev();
struct usart_dev* dev = MYSERIAL1.c_dev();
while (!(dev->regs->SR & USART_SR_TXE)) {
TERN_(USE_WATCHDOG, HAL_watchdog_refresh());
sw_barrier();

View File

@@ -60,7 +60,7 @@ static inline __always_inline void my_usart_irq(ring_buffer *rb, ring_buffer *wb
}
else if (srflags & USART_SR_ORE) {
// overrun and empty data, just do a dummy read to clear ORE
// and prevent a raise condition where a continous interrupt stream (due to ORE set) occurs
// and prevent a raise condition where a continuous interrupt stream (due to ORE set) occurs
// (see chapter "Overrun error" ) in STM32 reference manual
regs->DR;
}
@@ -134,12 +134,12 @@ constexpr bool IsSerialClassAllowed(const HardwareSerial&) { return false; }
// If you encounter this error, replace SerialX with MSerialX, for example MSerial3.
// Non-TMC ports were already validated in HAL.h, so do not require verbose error messages.
#ifdef MYSERIAL0
CHECK_CFG_SERIAL(MYSERIAL0);
#endif
#ifdef MYSERIAL1
CHECK_CFG_SERIAL(MYSERIAL1);
#endif
#ifdef MYSERIAL2
CHECK_CFG_SERIAL(MYSERIAL2);
#endif
#ifdef LCD_SERIAL
CHECK_CFG_SERIAL(LCD_SERIAL);
#endif

View File

@@ -47,7 +47,7 @@ struct MarlinSerial : public HardwareSerial {
#endif
};
typedef Serial0Type<MarlinSerial> MSerialT;
typedef Serial1Class<MarlinSerial> MSerialT;
extern MSerialT MSerial1;
extern MSerialT MSerial2;

View File

@@ -19,14 +19,13 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifdef __STM32F1__
/**
* PersistentStore for Arduino-style EEPROM interface
* with simple implementations supplied by Marlin.
*/
#ifdef __STM32F1__
#include "../../inc/MarlinConfig.h"
#if ENABLED(IIC_BL24CXX_EEPROM)
@@ -48,13 +47,11 @@ bool PersistentStore::access_start() { eeprom_init(); return true; }
bool PersistentStore::access_finish() { return true; }
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
size_t written = 0;
uint16_t written = 0;
while (size--) {
uint8_t v = *value;
uint8_t * const p = (uint8_t * const)pos;
// EEPROM has only ~100,000 write cycles,
// so only write bytes that have changed!
if (v != eeprom_read_byte(p)) {
if (v != eeprom_read_byte(p)) { // EEPROM has only ~100,000 write cycles, so only write bytes that have changed!
eeprom_write_byte(p, v);
if (++written & 0x7F) delay(2); else safe_delay(2); // Avoid triggering watchdog during long EEPROM writes
if (eeprom_read_byte(p) != v) {

View File

@@ -40,7 +40,7 @@ void eeprom_init() { BL24CXX::init(); }
// Public functions
// ------------------------
void eeprom_write_byte(uint8_t *pos, unsigned char value) {
void eeprom_write_byte(uint8_t *pos, uint8_t value) {
const unsigned eeprom_address = (unsigned)pos;
return BL24CXX::writeOneByte(eeprom_address, value);
}

View File

@@ -52,13 +52,13 @@ bool PersistentStore::access_start() {
}
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
uint16_t written = 0;
while (size--) {
uint8_t * const p = (uint8_t * const)pos;
uint8_t v = *value;
// EEPROM has only ~100,000 write cycles,
// so only write bytes that have changed!
if (v != eeprom_read_byte(p)) {
if (v != eeprom_read_byte(p)) { // EEPROM has only ~100,000 write cycles, so only write bytes that have changed!
eeprom_write_byte(p, v);
if (++written & 0x7F) delay(2); else safe_delay(2); // Avoid triggering watchdog during long EEPROM writes
if (eeprom_read_byte(p) != v) {
SERIAL_ECHO_MSG(STR_ERR_EEPROM_WRITE);
return true;

View File

@@ -24,7 +24,7 @@
#define PRODUCT_ID 0x29
USBMassStorage MarlinMSC;
Serial0Type<USBCompositeSerial> MarlinCompositeSerial(true);
Serial1Class<USBCompositeSerial> MarlinCompositeSerial(true);
#include "../../inc/MarlinConfig.h"
@@ -63,6 +63,7 @@ void my_rx_callback(unsigned int, void*) {
for (uint32 i = 0; i < len; i++)
emergency_parser.update(MarlinCompositeSerial.emergency_state, buf[i+total-len]);
}
#endif
void MSC_SD_init() {

View File

@@ -21,6 +21,6 @@
#include "../../core/serial_hook.h"
extern USBMassStorage MarlinMSC;
extern Serial0Type<USBCompositeSerial> MarlinCompositeSerial;
extern Serial1Class<USBCompositeSerial> MarlinCompositeSerial;
void MSC_SD_init();

View File

@@ -31,7 +31,13 @@
#include <Wire.h>
DefaultSerial MSerial(false);
#define _IMPLEMENT_SERIAL(X) DefaultSerial##X MSerial##X(false, Serial##X)
#define IMPLEMENT_SERIAL(X) _IMPLEMENT_SERIAL(X)
#if WITHIN(SERIAL_PORT, 0, 3)
IMPLEMENT_SERIAL(SERIAL_PORT);
#else
#error "SERIAL_PORT must be from 0 to 3."
#endif
USBSerialType USBSerial(false, SerialUSB);
uint16_t HAL_adc_result;
@@ -72,6 +78,8 @@ uint8_t HAL_get_reset_source() {
return 0;
}
void HAL_reboot() { _reboot_Teensyduino_(); }
extern "C" {
extern char __bss_end;
extern char __heap_start;

View File

@@ -34,7 +34,6 @@
#include "fastio.h"
#include "watchdog.h"
#include <stdint.h>
#define ST7920_DELAY_1 DELAY_NS(600)
@@ -51,19 +50,24 @@
#endif
#include "../../core/serial_hook.h"
typedef Serial0Type<decltype(Serial)> DefaultSerial;
extern DefaultSerial MSerial;
typedef ForwardSerial0Type<decltype(SerialUSB)> USBSerialType;
#define Serial0 Serial
#define _DECLARE_SERIAL(X) \
typedef ForwardSerial1Class<decltype(Serial##X)> DefaultSerial##X; \
extern DefaultSerial##X MSerial##X
#define DECLARE_SERIAL(X) _DECLARE_SERIAL(X)
typedef ForwardSerial1Class<decltype(SerialUSB)> USBSerialType;
extern USBSerialType USBSerial;
#define _MSERIAL(X) MSerial##X
#define MSERIAL(X) _MSERIAL(X)
#define MSerial0 MSerial
#if SERIAL_PORT == -1
#define MYSERIAL0 USBSerial
#define MYSERIAL1 USBSerial
#elif WITHIN(SERIAL_PORT, 0, 3)
#define MYSERIAL0 MSERIAL(SERIAL_PORT)
DECLARE_SERIAL(SERIAL_PORT);
#define MYSERIAL1 MSERIAL(SERIAL_PORT)
#endif
#define HAL_SERVO_LIB libServo
@@ -88,7 +92,7 @@ void HAL_clear_reset_source();
// Get the reason for the reset
uint8_t HAL_get_reset_source();
inline void HAL_reboot() {} // reboot the board or restart the bootloader
void HAL_reboot();
FORCE_INLINE void _delay_ms(const int delay_ms) { delay(delay_ms); }

View File

@@ -18,14 +18,14 @@
*/
#ifdef __MK20DX256__
#include "../../inc/MarlinConfig.h"
#if USE_WIRED_EEPROM
/**
* HAL PersistentStore for Teensy 3.2 (MK20DX256)
*/
#include "../../inc/MarlinConfig.h"
#if USE_WIRED_EEPROM
#include "../shared/eeprom_api.h"
#include <avr/eeprom.h>
@@ -38,13 +38,13 @@ bool PersistentStore::access_start() { return true; }
bool PersistentStore::access_finish() { return true; }
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
uint16_t written = 0;
while (size--) {
uint8_t * const p = (uint8_t * const)pos;
uint8_t v = *value;
// EEPROM has only ~100,000 write cycles,
// so only write bytes that have changed!
if (v != eeprom_read_byte(p)) {
if (v != eeprom_read_byte(p)) { // EEPROM has only ~100,000 write cycles, so only write bytes that have changed!
eeprom_write_byte(p, v);
if (++written & 0x7F) delay(2); else safe_delay(2); // Avoid triggering watchdog during long EEPROM writes
if (eeprom_read_byte(p) != v) {
SERIAL_ECHO_MSG(STR_ERR_EEPROM_WRITE);
return true;

View File

@@ -31,7 +31,12 @@
#include <Wire.h>
DefaultSerial MSerial(false);
#define _IMPLEMENT_SERIAL(X) DefaultSerial##X MSerial##X(false, Serial##X)
#define IMPLEMENT_SERIAL(X) _IMPLEMENT_SERIAL(X)
#if WITHIN(SERIAL_PORT, 0, 3)
IMPLEMENT_SERIAL(SERIAL_PORT);
#endif
USBSerialType USBSerial(false, SerialUSB);
uint16_t HAL_adc_result, HAL_adc_select;
@@ -81,6 +86,8 @@ uint8_t HAL_get_reset_source() {
return 0;
}
void HAL_reboot() { _reboot_Teensyduino_(); }
extern "C" {
extern char __bss_end;
extern char __heap_start;

View File

@@ -54,19 +54,26 @@
#endif
#include "../../core/serial_hook.h"
typedef Serial0Type<decltype(Serial)> DefaultSerial;
extern DefaultSerial MSerial;
typedef ForwardSerial0Type<decltype(SerialUSB)> USBSerialType;
#define Serial0 Serial
#define _DECLARE_SERIAL(X) \
typedef ForwardSerial1Class<decltype(Serial##X)> DefaultSerial##X; \
extern DefaultSerial##X MSerial##X
#define DECLARE_SERIAL(X) _DECLARE_SERIAL(X)
typedef ForwardSerial1Class<decltype(SerialUSB)> USBSerialType;
extern USBSerialType USBSerial;
#define _MSERIAL(X) MSerial##X
#define MSERIAL(X) _MSERIAL(X)
#define MSerial0 MSerial
#if SERIAL_PORT == -1
#define MYSERIAL0 USBSerial
#define MYSERIAL1 USBSerial
#elif WITHIN(SERIAL_PORT, 0, 3)
#define MYSERIAL0 MSERIAL(SERIAL_PORT)
#define MYSERIAL1 MSERIAL(SERIAL_PORT)
DECLARE_SERIAL(SERIAL_PORT);
#else
#error "SERIAL_PORT must be from 0 to 3, or -1 for Native USB."
#endif
#define HAL_SERVO_LIB libServo
@@ -94,7 +101,7 @@ void HAL_clear_reset_source();
// Reset reason
uint8_t HAL_get_reset_source();
inline void HAL_reboot() {} // reboot the board or restart the bootloader
void HAL_reboot();
FORCE_INLINE void _delay_ms(const int delay_ms) { delay(delay_ms); }

View File

@@ -42,13 +42,13 @@ bool PersistentStore::access_start() { return true; }
bool PersistentStore::access_finish() { return true; }
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
uint16_t written = 0;
while (size--) {
uint8_t * const p = (uint8_t * const)pos;
uint8_t v = *value;
// EEPROM has only ~100,000 write cycles,
// so only write bytes that have changed!
if (v != eeprom_read_byte(p)) {
if (v != eeprom_read_byte(p)) { // EEPROM has only ~100,000 write cycles, so only write bytes that have changed!
eeprom_write_byte(p, v);
if (++written & 0x7F) delay(2); else safe_delay(2); // Avoid triggering watchdog during long EEPROM writes
if (eeprom_read_byte(p) != v) {
SERIAL_ECHO_MSG(STR_ERR_EEPROM_WRITE);
return true;

View File

@@ -32,7 +32,11 @@
#include <Wire.h>
DefaultSerial MSerial(false);
#define _IMPLEMENT_SERIAL(X) DefaultSerial##X MSerial##X(false, Serial##X)
#define IMPLEMENT_SERIAL(X) _IMPLEMENT_SERIAL(X)
#if WITHIN(SERIAL_PORT, 0, 3)
IMPLEMENT_SERIAL(SERIAL_PORT);
#endif
USBSerialType USBSerial(false, SerialUSB);
uint16_t HAL_adc_result, HAL_adc_select;
@@ -116,6 +120,8 @@ uint8_t HAL_get_reset_source() {
return 0;
}
void HAL_reboot() { _reboot_Teensyduino_(); }
#define __bss_end _ebss
extern "C" {

View File

@@ -56,32 +56,36 @@
#endif
#include "../../core/serial_hook.h"
typedef Serial0Type<decltype(Serial)> DefaultSerial;
extern DefaultSerial MSerial;
typedef ForwardSerial0Type<decltype(SerialUSB)> USBSerialType;
#define Serial0 Serial
#define _DECLARE_SERIAL(X) \
typedef ForwardSerial1Class<decltype(Serial##X)> DefaultSerial##X; \
extern DefaultSerial##X MSerial##X
#define DECLARE_SERIAL(X) _DECLARE_SERIAL(X)
typedef ForwardSerial1Class<decltype(SerialUSB)> USBSerialType;
extern USBSerialType USBSerial;
#define _MSERIAL(X) MSerial##X
#define MSERIAL(X) _MSERIAL(X)
#define MSerial0 MSerial
#if SERIAL_PORT == -1
#define MYSERIAL0 SerialUSB
#define MYSERIAL1 SerialUSB
#elif WITHIN(SERIAL_PORT, 0, 8)
#define MYSERIAL0 MSERIAL(SERIAL_PORT)
DECLARE_SERIAL(SERIAL_PORT);
#define MYSERIAL1 MSERIAL(SERIAL_PORT)
#else
#error "The required SERIAL_PORT must be from -1 to 8. Please update your configuration."
#error "The required SERIAL_PORT must be from 0 to 8, or -1 for Native USB."
#endif
#ifdef SERIAL_PORT_2
#if SERIAL_PORT_2 == -1
#define MYSERIAL1 usbSerial
#define MYSERIAL2 usbSerial
#elif SERIAL_PORT_2 == -2
#define MYSERIAL1 ethernet.telnetClient
#define MYSERIAL2 ethernet.telnetClient
#elif WITHIN(SERIAL_PORT_2, 0, 8)
#define MYSERIAL1 MSERIAL(SERIAL_PORT_2)
#define MYSERIAL2 MSERIAL(SERIAL_PORT_2)
#else
#error "SERIAL_PORT_2 must be from -2 to 8. Please update your configuration."
#error "SERIAL_PORT_2 must be from 0 to 8, or -1 for Native USB, or -2 for Ethernet."
#endif
#endif
@@ -117,6 +121,8 @@ void HAL_clear_reset_source();
// Reset reason
uint8_t HAL_get_reset_source();
void HAL_reboot();
FORCE_INLINE void _delay_ms(const int delay_ms) { delay(delay_ms); }
#if GCC_VERSION <= 50000

View File

@@ -22,14 +22,14 @@
*/
#ifdef __IMXRT1062__
#include "../../inc/MarlinConfig.h"
#if USE_WIRED_EEPROM
/**
* HAL PersistentStore for Teensy 4.0 (IMXRT1062DVL6A) / 4.1 (IMXRT1062DVJ6A)
*/
#include "../../inc/MarlinConfig.h"
#if USE_WIRED_EEPROM
#include "../shared/eeprom_api.h"
#include <avr/eeprom.h>
@@ -42,13 +42,13 @@ bool PersistentStore::access_start() { return true; }
bool PersistentStore::access_finish() { return true; }
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
uint16_t written = 0;
while (size--) {
uint8_t * const p = (uint8_t * const)pos;
uint8_t v = *value;
// EEPROM has only ~100,000 write cycles,
// so only write bytes that have changed!
if (v != eeprom_read_byte(p)) {
if (v != eeprom_read_byte(p)) { // EEPROM has only ~100,000 write cycles, so only write bytes that have changed!
eeprom_write_byte(p, v);
if (++written & 0x7F) delay(2); else safe_delay(2); // Avoid triggering watchdog during long EEPROM writes
if (eeprom_read_byte(p) != v) {
SERIAL_ECHO_MSG(STR_ERR_EEPROM_WRITE);
return true;

View File

@@ -150,8 +150,37 @@ void calibrate_delay_loop();
#endif
// Delay in nanoseconds
#define DELAY_NS(x) DELAY_CYCLES((x) * ((F_CPU) / 1000000UL) / 1000UL)
/**************************************************************
* Delay in nanoseconds. Requires the F_CPU macro.
* These macros follow avr-libc delay conventions.
*
* For AVR there are three possible operation modes, due to its
* slower clock speeds and thus coarser delay resolution. For
* example, when F_CPU = 16000000 the resolution is 62.5ns.
*
* Round up (default)
* Round up the delay according to the CPU clock resolution.
* e.g., 100 will give a delay of 2 cycles (125ns).
*
* Round down (DELAY_NS_ROUND_DOWN)
* Round down the delay according to the CPU clock resolution.
* e.g., 100 will be rounded down to 1 cycle (62.5ns).
*
* Nearest (DELAY_NS_ROUND_CLOSEST)
* Round the delay to the nearest number of clock cycles.
* e.g., 165 will be rounded up to 3 cycles (187.5ns) because
* it's closer to the requested delay than 2 cycle (125ns).
*/
#ifndef __AVR__
#undef DELAY_NS_ROUND_DOWN
#undef DELAY_NS_ROUND_CLOSEST
#endif
#if ENABLED(DELAY_NS_ROUND_DOWN)
#define DELAY_NS(x) DELAY_CYCLES((x) * ((F_CPU) / 1000000UL) / 1000UL) // floor
#elif ENABLED(DELAY_NS_ROUND_CLOSEST)
#define DELAY_NS(x) DELAY_CYCLES(((x) * ((F_CPU) / 1000000UL) + 500) / 1000UL) // round
#else
#define DELAY_NS(x) DELAY_CYCLES(((x) * ((F_CPU) / 1000000UL) + 999) / 1000UL) // "ceil"
#endif

View File

@@ -321,7 +321,7 @@ void hook_cpu_exceptions() {
// probably break if the flash happens to be more than 128MB, but in this case, we are not magician, we need help from outside.
unsigned long *vecAddr = (unsigned long*)get_vtor();
SERIAL_ECHO("Vector table addr: ");
SERIAL_ECHOPGM("Vector table addr: ");
SERIAL_PRINTLN(get_vtor(), HEX);
#ifdef VECTOR_TABLE_SIZE
@@ -348,7 +348,7 @@ void hook_cpu_exceptions() {
// 128 bytes alignement is required for writing the VTOR register
alignas(128) static unsigned long vectable[VECTOR_TABLE_SENTINEL];
SERIAL_ECHO("Detected vector table size: ");
SERIAL_ECHOPGM("Detected vector table size: ");
SERIAL_PRINTLN(vec_size, HEX);
#endif
@@ -372,7 +372,7 @@ void hook_cpu_exceptions() {
HW_REG(0xE000ED08) = (unsigned long)vectable | _BV32(29); // 29th bit is for telling the CPU the table is now in SRAM (should be present already)
SERIAL_ECHOLN("Installed fault handlers");
SERIAL_ECHOLNPGM("Installed fault handlers");
#endif
}

View File

@@ -25,5 +25,5 @@
// EEPROM
//
void eeprom_init();
void eeprom_write_byte(uint8_t *pos, unsigned char value);
void eeprom_write_byte(uint8_t *pos, uint8_t value);
uint8_t eeprom_read_byte(uint8_t *pos);

View File

@@ -55,12 +55,15 @@ static constexpr uint8_t eeprom_device_address = I2C_ADDRESS(EEPROM_DEVICE_ADDRE
// Public functions
// ------------------------
void eeprom_write_byte(uint8_t *pos, unsigned char value) {
static void _eeprom_begin(uint8_t * const pos) {
const unsigned eeprom_address = (unsigned)pos;
Wire.beginTransmission(eeprom_device_address);
Wire.write(int(eeprom_address >> 8)); // MSB
Wire.write(int(eeprom_address & 0xFF)); // LSB
Wire.write(int(eeprom_address >> 8)); // Address High
Wire.write(int(eeprom_address & 0xFF)); // Address Low
}
void eeprom_write_byte(uint8_t *pos, uint8_t value) {
_eeprom_begin(pos);
Wire.write(value);
Wire.endTransmission();
@@ -70,11 +73,7 @@ void eeprom_write_byte(uint8_t *pos, unsigned char value) {
}
uint8_t eeprom_read_byte(uint8_t *pos) {
const unsigned eeprom_address = (unsigned)pos;
Wire.beginTransmission(eeprom_device_address);
Wire.write(int(eeprom_address >> 8)); // MSB
Wire.write(int(eeprom_address & 0xFF)); // LSB
_eeprom_begin(pos);
Wire.endTransmission();
Wire.requestFrom(eeprom_device_address, (byte)1);
return Wire.available() ? Wire.read() : 0xFF;

View File

@@ -43,44 +43,41 @@ void eeprom_init() {}
#define EEPROM_WRITE_DELAY 7
#endif
uint8_t eeprom_read_byte(uint8_t* pos) {
uint8_t v;
uint8_t eeprom_temp[3];
// set read location
// begin transmission from device
eeprom_temp[0] = CMD_READ;
eeprom_temp[1] = ((unsigned)pos>>8) & 0xFF; // addr High
eeprom_temp[2] = (unsigned)pos& 0xFF; // addr Low
WRITE(SPI_EEPROM1_CS, HIGH);
WRITE(SPI_EEPROM1_CS, LOW);
static void _eeprom_begin(uint8_t * const pos, const uint8_t cmd) {
const uint8_t eeprom_temp[3] = {
cmd,
(unsigned(pos) >> 8) & 0xFF, // Address High
unsigned(pos) & 0xFF // Address Low
};
WRITE(SPI_EEPROM1_CS, HIGH); // Usually free already
WRITE(SPI_EEPROM1_CS, LOW); // Activate the Bus
spiSend(SPI_CHAN_EEPROM1, eeprom_temp, 3);
// Leave the Bus in-use
}
uint8_t eeprom_read_byte(uint8_t *pos) {
_eeprom_begin(pos, CMD_READ); // Set read location and begin transmission
const uint8_t v = spiRec(SPI_CHAN_EEPROM1); // After READ a value sits on the Bus
WRITE(SPI_EEPROM1_CS, HIGH); // Done with device
v = spiRec(SPI_CHAN_EEPROM1);
WRITE(SPI_EEPROM1_CS, HIGH);
return v;
}
void eeprom_write_byte(uint8_t *pos, uint8_t value) {
uint8_t eeprom_temp[3];
/*write enable*/
eeprom_temp[0] = CMD_WREN;
const uint8_t eeprom_temp = CMD_WREN;
WRITE(SPI_EEPROM1_CS, LOW);
spiSend(SPI_CHAN_EEPROM1, eeprom_temp, 1);
WRITE(SPI_EEPROM1_CS, HIGH);
delay(1);
spiSend(SPI_CHAN_EEPROM1, &eeprom_temp, 1); // Write Enable
/*write addr*/
eeprom_temp[0] = CMD_WRITE;
eeprom_temp[1] = ((unsigned)pos>>8) & 0xFF; //addr High
eeprom_temp[2] = (unsigned)pos & 0xFF; //addr Low
WRITE(SPI_EEPROM1_CS, LOW);
spiSend(SPI_CHAN_EEPROM1, eeprom_temp, 3);
WRITE(SPI_EEPROM1_CS, HIGH); // Done with the Bus
delay(1); // For a small amount of time
spiSend(SPI_CHAN_EEPROM1, value);
WRITE(SPI_EEPROM1_CS, HIGH);
delay(EEPROM_WRITE_DELAY); // wait for page write to complete
_eeprom_begin(pos, CMD_WRITE); // Set write address and begin transmission
spiSend(SPI_CHAN_EEPROM1, value); // Send the value to be written
WRITE(SPI_EEPROM1_CS, HIGH); // Done with the Bus
delay(EEPROM_WRITE_DELAY); // Give page write time to complete
}
#endif // USE_SHARED_EEPROM

View File

@@ -76,7 +76,6 @@
#if ENABLED(DWIN_CREALITY_LCD)
#include "lcd/dwin/e3v2/dwin.h"
#include "lcd/dwin/dwin_lcd.h"
#include "lcd/dwin/e3v2/rotary_encoder.h"
#endif
@@ -211,9 +210,7 @@
#include "feature/fanmux.h"
#endif
#if DO_SWITCH_EXTRUDER || ANY(SWITCHING_NOZZLE, PARKING_EXTRUDER, MAGNETIC_PARKING_EXTRUDER, ELECTROMAGNETIC_SWITCHING_TOOLHEAD, SWITCHING_TOOLHEAD)
#include "module/tool_change.h"
#endif
#if ENABLED(USE_CONTROLLER_FAN)
#include "feature/controllerfan.h"
@@ -235,6 +232,10 @@
#include "lcd/extui/lib/dgus/DGUSScreenHandler.h"
#endif
#if HAS_DRIVER_SAFE_POWER_PROTECT
#include "feature/stepper_driver_safety.h"
#endif
PGMSTR(M112_KILL_STR, "M112 Shutdown");
MarlinState marlin_state = MF_INITIALIZING;
@@ -456,7 +457,8 @@ inline void manage_inactivity(const bool ignore_stepper_queue=false) {
already_shutdown_steppers = false;
}
#if PIN_EXISTS(CHDK) // Check if pin should be set to LOW (after M240 set it HIGH)
#if ENABLED(PHOTO_GCODE) && PIN_EXISTS(CHDK)
// Check if CHDK should be set to LOW (after M240 set it HIGH)
extern millis_t chdk_timeout;
if (chdk_timeout && ELAPSED(ms, chdk_timeout)) {
chdk_timeout = 0;
@@ -602,7 +604,7 @@ inline void manage_inactivity(const bool ignore_stepper_queue=false) {
TERN_(HOTEND_IDLE_TIMEOUT, hotend_idle.check());
#if ENABLED(EXTRUDER_RUNOUT_PREVENT)
if (thermalManager.degHotend(active_extruder) > EXTRUDER_RUNOUT_MINTEMP
if (thermalManager.degHotend(active_extruder) > (EXTRUDER_RUNOUT_MINTEMP)
&& ELAPSED(ms, gcode.previous_move_ms + SEC_TO_MS(EXTRUDER_RUNOUT_SECONDS))
&& !planner.has_blocks_queued()
) {
@@ -732,6 +734,9 @@ void idle(TERN_(ADVANCED_PAUSE_FEATURE, bool no_stepper_sleep/*=false*/)) {
// Return if setup() isn't completed
if (marlin_state == MF_INITIALIZING) goto IDLE_DONE;
// TODO: Still causing errors
(void)check_tool_sensor_stats(active_extruder, true);
// Handle filament runout sensors
TERN_(HAS_FILAMENT_SENSOR, runout.run());
@@ -758,7 +763,7 @@ void idle(TERN_(ADVANCED_PAUSE_FEATURE, bool no_stepper_sleep/*=false*/)) {
TERN_(SDSUPPORT, card.manage_media());
// Handle USB Flash Drive insert / remove
TERN_(USB_FLASH_DRIVE_SUPPORT, Sd2Card::idle());
TERN_(USB_FLASH_DRIVE_SUPPORT, card.diskIODriver()->idle());
// Announce Host Keepalive state (if any)
TERN_(HOST_KEEPALIVE_FEATURE, gcode.host_keepalive());
@@ -862,20 +867,22 @@ void minkill(const bool steppers_off/*=false*/) {
TERN_(HAS_SUICIDE, suicide());
#if HAS_KILL
#if EITHER(HAS_KILL, SOFT_RESET_ON_KILL)
// Wait for kill to be released
while (kill_state()) watchdog_refresh();
// Wait for both KILL and ENC to be released
while (TERN0(HAS_KILL, !kill_state()) || TERN0(SOFT_RESET_ON_KILL, !ui.button_pressed()))
watchdog_refresh();
// Wait for kill to be pressed
while (!kill_state()) watchdog_refresh();
// Wait for either KILL or ENC press
while (TERN1(HAS_KILL, kill_state()) && TERN1(SOFT_RESET_ON_KILL, ui.button_pressed()))
watchdog_refresh();
void (*resetFunc)() = 0; // Declare resetFunc() at address 0
resetFunc(); // Jump to address 0
// Reboot the board
HAL_reboot();
#else
for (;;) watchdog_refresh(); // Wait for reset
for (;;) watchdog_refresh(); // Wait for RESET button or power-cycle
#endif
}
@@ -889,8 +896,8 @@ void stop() {
print_job_timer.stop();
#if ENABLED(PROBING_FANS_OFF)
if (thermalManager.fans_paused) thermalManager.set_fans_paused(false); // put things back the way they were
#if EITHER(PROBING_FANS_OFF, ADVANCED_PAUSE_FANS_PAUSE)
thermalManager.set_fans_paused(false); // Un-pause fans for safety
#endif
if (IsRunning()) {
@@ -953,23 +960,92 @@ inline void tmc_standby_setup() {
}
/**
* Marlin entry-point: Set up before the program loop
* - Set up the kill pin, filament runout, power hold, custom user buttons
* - Start the serial port
* Marlin Firmware entry-point. Abandon Hope All Ye Who Enter Here.
* Setup before the program loop:
*
* - Call any special pre-init set for the board
* - Put TMC drivers into Low Power Standby mode
* - Init the serial ports (so setup can be debugged)
* - Set up the kill and suicide pins
* - Prepare (disable) board JTAG and Debug ports
* - Init serial for a connected MKS TFT with WiFi
* - Install Marlin custom Exception Handlers, if set.
* - Init Marlin's HAL interfaces (for SPI, i2c, etc.)
* - Init some optional hardware and features:
* • MAX Thermocouple pins
* • Duet Smart Effector
* • Filament Runout Sensor
* • TMC220x Stepper Drivers (Serial)
* • PSU control
* • Power-loss Recovery
* • L64XX Stepper Drivers (SPI)
* • Stepper Driver Reset: DISABLE
* • TMC Stepper Drivers (SPI)
* • Run BOARD_INIT if defined
* • ESP WiFi
* - Get the Reset Reason and report it
* - Print startup messages and diagnostics
* - Get EEPROM or default settings
* - Initialize managers for:
* • temperature
* • planner
* • watchdog
* • stepper
* • photo pin
* • servos
* • LCD controller
* • Digipot I2C
* • Z probe sled
* • status LEDs
* • Max7219
* - Calibrate the HAL DELAY for precise timing
* - Init the buzzer, possibly a custom timer
* - Init more optional hardware:
* • Color LED illumination
* • Neopixel illumination
* • Controller Fan
* • Creality DWIN LCD (show boot image)
* • Tare the Probe if possible
* - Mount the (most likely external) SD Card
* - Load settings from EEPROM (or use defaults)
* - Init the Ethernet Port
* - Init Touch Buttons (for emulated DOGLCD)
* - Adjust the (certainly wrong) current position by the home offset
* - Init the Planner::position (steps) based on current (native) position
* - Initialize more managers and peripherals:
* • Temperatures
* • Print Job Timer
* • Endstops and Endstop Interrupts
* • Stepper ISR - Kind of Important!
* • Servos
* • Servo-based Probe
* • Photograph Pin
* • Laser/Spindle tool Power / PWM
* • Coolant Control
* • Bed Probe
* • Stepper Driver Reset: ENABLE
* • Digipot I2C - Stepper driver current control
* • Stepper DAC - Stepper driver current control
* • Solenoid (probe, or for other use)
* • Home Pin
* • Custom User Buttons
* • Red/Blue Status LEDs
* • Case Light
* • Prusa MMU filament changer
* • Fan Multiplexer
* • Mixing Extruder
* • BLTouch Probe
* • I2C Position Encoders
* • Custom I2C Bus handlers
* • Enhanced tools or extruders:
* • Switching Extruder
* • Switching Nozzle
* • Parking Extruder
* • Magnetic Parking Extruder
* • Switching Toolhead
* • Electromagnetic Switching Toolhead
* • Watchdog Timer - Also Kind of Important!
* • Closed Loop Controller
* - Run Startup Commands, if defined
* - Tell host to close Host Prompts
* - Test Trinamic driver connections
* - Init Prusa MMU2 filament changer
* - Init and test BL24Cxx EEPROM
* - Init Creality DWIN encoder, show faux progress bar
* - Reset Status Message / Show Service Messages
* - Init MAX7219 LED Matrix
* - Init Direct Stepping (Klipper-style motion control)
* - Init TFT LVGL UI (with 3D Graphics)
* - Apply Password Lock - Hold for Authentication
* - Open Touch Screen Calibration screen, if not calibrated
* - Set Marlin to RUNNING State
*/
void setup() {
#ifdef BOARD_PREINIT
@@ -990,14 +1066,14 @@ void setup() {
#endif
#define SETUP_RUN(C) do{ SETUP_LOG(STRINGIFY(C)); C; }while(0)
MYSERIAL0.begin(BAUDRATE);
MYSERIAL1.begin(BAUDRATE);
millis_t serial_connect_timeout = millis() + 1000UL;
while (!MYSERIAL0.connected() && PENDING(millis(), serial_connect_timeout)) { /*nada*/ }
while (!MYSERIAL1.connected() && PENDING(millis(), serial_connect_timeout)) { /*nada*/ }
#if HAS_MULTI_SERIAL && !HAS_ETHERNET
MYSERIAL1.begin(BAUDRATE);
MYSERIAL2.begin(BAUDRATE);
serial_connect_timeout = millis() + 1000UL;
while (!MYSERIAL1.connected() && PENDING(millis(), serial_connect_timeout)) { /*nada*/ }
while (!MYSERIAL2.connected() && PENDING(millis(), serial_connect_timeout)) { /*nada*/ }
#endif
SERIAL_ECHOLNPGM("start");
@@ -1054,6 +1130,10 @@ void setup() {
SETUP_RUN(runout.setup());
#endif
#if HAS_TMC220x
SETUP_RUN(tmc_serial_begin());
#endif
#if ENABLED(PSU_CONTROL)
SETUP_LOG("PSU_CONTROL");
powersupply_on = ENABLED(PSU_DEFAULT_OFF);
@@ -1068,10 +1148,6 @@ void setup() {
SETUP_RUN(L64xxManager.init()); // Set up SPI, init drivers
#endif
#if HAS_TMC220x
SETUP_RUN(tmc_serial_begin());
#endif
#if HAS_STEPPER_RESET
SETUP_RUN(disableStepperDrivers());
#endif
@@ -1144,12 +1220,22 @@ void setup() {
DWIN_UpdateLCD(); // Show bootscreen (first image)
#else
SETUP_RUN(ui.init());
#if HAS_WIRED_LCD && ENABLED(SHOW_BOOTSCREEN)
#if BOTH(HAS_WIRED_LCD, SHOW_BOOTSCREEN)
SETUP_RUN(ui.show_bootscreen());
const millis_t bootscreen_ms = millis();
#endif
SETUP_RUN(ui.reset_status()); // Load welcome message early. (Retained if no errors exist.)
#endif
#if PIN_EXISTS(SAFE_POWER)
#if HAS_DRIVER_SAFE_POWER_PROTECT
SETUP_RUN(stepper_driver_backward_check());
#else
SETUP_LOG("SAFE_POWER");
OUT_WRITE(SAFE_POWER_PIN, HIGH);
#endif
#endif
#if ENABLED(PROBE_TARE)
SETUP_RUN(probe.tare_init());
#endif
@@ -1311,7 +1397,6 @@ void setup() {
#if PIN_EXISTS(STAT_LED_RED)
OUT_WRITE(STAT_LED_RED_PIN, LOW); // OFF
#endif
#if PIN_EXISTS(STAT_LED_BLUE)
OUT_WRITE(STAT_LED_BLUE_PIN, LOW); // OFF
#endif
@@ -1364,19 +1449,13 @@ void setup() {
#endif
#endif
#if ENABLED(MAGNETIC_PARKING_EXTRUDER)
SETUP_RUN(mpe_settings_init());
#endif
#if ENABLED(PARKING_EXTRUDER)
SETUP_RUN(pe_solenoid_init());
#endif
#if ENABLED(SWITCHING_TOOLHEAD)
#elif ENABLED(MAGNETIC_PARKING_EXTRUDER)
SETUP_RUN(mpe_settings_init());
#elif ENABLED(SWITCHING_TOOLHEAD)
SETUP_RUN(swt_init());
#endif
#if ENABLED(ELECTROMAGNETIC_SWITCHING_TOOLHEAD)
#elif ENABLED(ELECTROMAGNETIC_SWITCHING_TOOLHEAD)
SETUP_RUN(est_init());
#endif
@@ -1401,6 +1480,10 @@ void setup() {
SETUP_RUN(test_tmc_connection(true, true, true, true));
#endif
#if HAS_DRIVER_SAFE_POWER_PROTECT
SETUP_RUN(stepper_driver_backward_report());
#endif
#if HAS_PRUSA_MMU2
SETUP_RUN(mmu2.init());
#endif
@@ -1414,7 +1497,9 @@ void setup() {
#if ENABLED(DWIN_CREALITY_LCD)
Encoder_Configuration();
HMI_Init();
DWIN_JPG_CacheTo1(Language_English);
HMI_StartFrame(true);
DWIN_StatusChanged(GET_TEXT(WELCOME_MSG));
#endif
#if HAS_SERVICE_INTERVALS && DISABLED(DWIN_CREALITY_LCD)
@@ -1436,6 +1521,14 @@ void setup() {
SETUP_RUN(tft_lvgl_init());
#endif
#if BOTH(HAS_WIRED_LCD, SHOW_BOOTSCREEN)
const millis_t elapsed = millis() - bootscreen_ms;
#if ENABLED(MARLIN_DEV_MODE)
SERIAL_ECHOLNPAIR("elapsed=", elapsed);
#endif
SETUP_RUN(ui.bootscreen_completion(elapsed));
#endif
#if ENABLED(PASSWORD_ON_STARTUP)
SETUP_RUN(password.lock_machine()); // Will not proceed until correct password provided
#endif

View File

@@ -68,8 +68,8 @@
#define BOARD_MKS_GEN_13 1112 // MKS GEN v1.3 or 1.4
#define BOARD_MKS_GEN_L 1113 // MKS GEN L
#define BOARD_KFB_2 1114 // BigTreeTech or BIQU KFB2.0
#define BOARD_ZRIB_V20 1115 // zrib V2.0 control board (Chinese knock off RAMPS replica)
#define BOARD_ZRIB_V52 1116 // zrib V5.2 control board (Chinese knock off RAMPS replica)
#define BOARD_ZRIB_V20 1115 // zrib V2.0 (Chinese RAMPS replica)
#define BOARD_ZRIB_V52 1116 // zrib V5.2 (Chinese RAMPS replica)
#define BOARD_FELIX2 1117 // Felix 2.0+ Electronics Board (RAMPS like)
#define BOARD_RIGIDBOARD 1118 // Invent-A-Part RigidBoard
#define BOARD_RIGIDBOARD_V2 1119 // Invent-A-Part RigidBoard V2
@@ -87,7 +87,7 @@
#define BOARD_FORMBOT_RAPTOR 1131 // Formbot Raptor
#define BOARD_FORMBOT_RAPTOR2 1132 // Formbot Raptor 2
#define BOARD_BQ_ZUM_MEGA_3D 1133 // bq ZUM Mega 3D
#define BOARD_MAKEBOARD_MINI 1134 // MakeBoard Mini v2.1.2 is a control board sold by MicroMake
#define BOARD_MAKEBOARD_MINI 1134 // MakeBoard Mini v2.1.2 by MicroMake
#define BOARD_TRIGORILLA_13 1135 // TriGorilla Anycubic version 1.3-based on RAMPS EFB
#define BOARD_TRIGORILLA_14 1136 // ... Ver 1.4
#define BOARD_TRIGORILLA_14_11 1137 // ... Rev 1.1 (new servo pin order)
@@ -146,17 +146,19 @@
#define BOARD_ELEFU_3 1311 // Elefu Ra Board (v3)
#define BOARD_LEAPFROG 1312 // Leapfrog
#define BOARD_MEGACONTROLLER 1313 // Mega controller
#define BOARD_GT2560_REV_A 1314 // Geeetech GT2560 Rev. A
#define BOARD_GT2560_REV_A_PLUS 1315 // Geeetech GT2560 Rev. A+ (with auto level probe)
#define BOARD_GT2560_V3 1316 // Geeetech GT2560 Rev B for A10(M/D)
#define BOARD_GT2560_V3_MC2 1317 // Geeetech GT2560 Rev B for Mecreator2
#define BOARD_GT2560_V3_A20 1318 // Geeetech GT2560 Rev B for A20(M/D)
#define BOARD_EINSTART_S 1319 // Einstart retrofit
#define BOARD_WANHAO_ONEPLUS 1320 // Wanhao 0ne+ i3 Mini
#define BOARD_LEAPFROG_XEED2015 1321 // Leapfrog Xeed 2015
#define BOARD_PICA_REVB 1322 // PICA Shield (original version)
#define BOARD_PICA 1323 // PICA Shield (rev C or later)
#define BOARD_INTAMSYS40 1324 // Intamsys 4.0 (Funmat HT)
#define BOARD_GT2560_REV_A 1314 // Geeetech GT2560 Rev A
#define BOARD_GT2560_REV_A_PLUS 1315 // Geeetech GT2560 Rev A+ (with auto level probe)
#define BOARD_GT2560_REV_B 1316 // Geeetech GT2560 Rev B
#define BOARD_GT2560_V3 1317 // Geeetech GT2560 Rev B for A10(M/D)
#define BOARD_GT2560_V4 1318 // Geeetech GT2560 Rev B for A10(M/D)
#define BOARD_GT2560_V3_MC2 1319 // Geeetech GT2560 Rev B for Mecreator2
#define BOARD_GT2560_V3_A20 1320 // Geeetech GT2560 Rev B for A20(M/D)
#define BOARD_EINSTART_S 1321 // Einstart retrofit
#define BOARD_WANHAO_ONEPLUS 1322 // Wanhao 0ne+ i3 Mini
#define BOARD_LEAPFROG_XEED2015 1323 // Leapfrog Xeed 2015
#define BOARD_PICA_REVB 1324 // PICA Shield (original version)
#define BOARD_PICA 1325 // PICA Shield (rev C or later)
#define BOARD_INTAMSYS40 1326 // Intamsys 4.0 (Funmat HT)
//
// ATmega1281, ATmega2561
@@ -174,8 +176,8 @@
#define BOARD_MELZI 1502 // Melzi
#define BOARD_MELZI_V2 1503 // Melzi V2
#define BOARD_MELZI_MAKR3D 1504 // Melzi with ATmega1284 (MaKr3d version)
#define BOARD_MELZI_CREALITY 1505 // Melzi Creality3D board (for CR-10 etc)
#define BOARD_MELZI_MALYAN 1506 // Melzi Malyan M150 board
#define BOARD_MELZI_CREALITY 1505 // Melzi Creality3D (for CR-10 etc)
#define BOARD_MELZI_MALYAN 1506 // Melzi Malyan M150
#define BOARD_MELZI_TRONXY 1507 // Tronxy X5S
#define BOARD_STB_11 1508 // STB V1.1
#define BOARD_AZTEEG_X1 1509 // Azteeg X1
@@ -194,8 +196,8 @@
#define BOARD_GEN7_12 1605 // Gen7 v1.1, v1.2
#define BOARD_GEN7_13 1606 // Gen7 v1.3
#define BOARD_GEN7_14 1607 // Gen7 v1.4
#define BOARD_OMCA_A 1608 // Alpha OMCA board
#define BOARD_OMCA 1609 // Final OMCA board
#define BOARD_OMCA_A 1608 // Alpha OMCA
#define BOARD_OMCA 1609 // Final OMCA
#define BOARD_SETHI 1610 // Sethi 3D_1
//
@@ -226,7 +228,7 @@
#define BOARD_SELENA_COMPACT 2008 // Selena Compact (Power outputs: Hotend0, Hotend1, Bed0, Bed1, Fan0, Fan1)
#define BOARD_BIQU_B300_V1_0 2009 // BIQU B300_V1.0 (Power outputs: Hotend0, Fan, Bed, SPI Driver)
#define BOARD_MKS_SGEN_L 2010 // MKS-SGen-L (Power outputs: Hotend0, Hotend1, Bed, Fan)
#define BOARD_GMARSH_X6_REV1 2011 // GMARSH X6 board, revision 1 prototype
#define BOARD_GMARSH_X6_REV1 2011 // GMARSH X6, revision 1 prototype
#define BOARD_BTT_SKR_V1_1 2012 // BigTreeTech SKR v1.1 (Power outputs: Hotend0, Hotend1, Fan, Bed)
#define BOARD_BTT_SKR_V1_3 2013 // BigTreeTech SKR v1.3 (Power outputs: Hotend0, Hotend1, Fan, Bed)
#define BOARD_BTT_SKR_V1_4 2014 // BigTreeTech SKR v1.4 (Power outputs: Hotend0, Hotend1, Fan, Bed)
@@ -279,6 +281,7 @@
#define BOARD_ARCHIM2 3024 // UltiMachine Archim2 (with TMC2130 drivers)
#define BOARD_ALLIGATOR 3025 // Alligator Board R2
#define BOARD_CNCONTROLS_15D 3026 // Cartesio CN Controls V15 on DUE
#define BOARD_KRATOS32 3027 // K.3D Kratos32 (Arduino Due Shield)
//
// SAM3X8C ARM Cortex M3
@@ -340,6 +343,7 @@
#define BOARD_FLSUN_HISPEED 4046 // FLSUN HiSpeedV1 (STM32F103VET6)
#define BOARD_BEAST 4047 // STM32F103RET6 Libmaple-based controller
#define BOARD_MINGDA_MPX_ARM_MINI 4048 // STM32F103ZET6 Mingda MD-16
#define BOARD_GTM32_PRO_VD 4049 // STM32F103VET6 controller
//
// ARM Cortex-M4F
@@ -359,23 +363,26 @@
#define BOARD_BLACK_STM32F407VE 4204 // BLACK_STM32F407VE
#define BOARD_BLACK_STM32F407ZE 4205 // BLACK_STM32F407ZE
#define BOARD_STEVAL_3DP001V1 4206 // STEVAL-3DP001V1 3D PRINTER BOARD
#define BOARD_BTT_SKR_PRO_V1_1 4207 // BigTreeTech SKR Pro v1.1 (STM32F407ZG)
#define BOARD_BTT_SKR_PRO_V1_2 4208 // BigTreeTech SKR Pro v1.2 (STM32F407ZG)
#define BOARD_BTT_BTT002_V1_0 4209 // BigTreeTech BTT002 v1.0 (STM32F407VG)
#define BOARD_BTT_GTR_V1_0 4210 // BigTreeTech GTR v1.0 (STM32F407IGT)
#define BOARD_LERDGE_K 4211 // Lerdge K (STM32F407ZG)
#define BOARD_LERDGE_S 4212 // Lerdge S (STM32F407VE)
#define BOARD_LERDGE_X 4213 // Lerdge X (STM32F407VE)
#define BOARD_VAKE403D 4214 // VAkE 403D (STM32F446VET6)
#define BOARD_FYSETC_S6 4215 // FYSETC S6 board
#define BOARD_FYSETC_S6_V2_0 4216 // FYSETC S6 v2.0 board
#define BOARD_FLYF407ZG 4217 // FLYF407ZG board (STM32F407ZG)
#define BOARD_MKS_ROBIN2 4218 // MKS_ROBIN2 (STM32F407ZE)
#define BOARD_MKS_ROBIN_PRO_V2 4219 // MKS Robin Pro V2 (STM32F407VE)
#define BOARD_MKS_ROBIN_NANO_V3 4220 // MKS Robin Nano V3 (STM32F407VG)
#define BOARD_ANET_ET4 4221 // ANET ET4 V1.x (STM32F407VGT6)
#define BOARD_ANET_ET4P 4222 // ANET ET4P V1.x (STM32F407VGT6)
#define BOARD_FYSETC_CHEETAH_V20 4223 // FYSETC Cheetah V2.0
#define BOARD_BTT_SKR_PRO_V1_1 4207 // BigTreeTech SKR Pro v1.1 (STM32F407ZGT6)
#define BOARD_BTT_SKR_PRO_V1_2 4208 // BigTreeTech SKR Pro v1.2 (STM32F407ZGT6)
#define BOARD_BTT_BTT002_V1_0 4209 // BigTreeTech BTT002 v1.0 (STM32F407VGT6)
#define BOARD_BTT_E3_RRF 4210 // BigTreeTech E3 RRF (STM32F407VGT6)
#define BOARD_BTT_SKR_V2_0 4211 // BigTreeTech SKR v2.0 (STM32F407VGT6)
#define BOARD_BTT_GTR_V1_0 4212 // BigTreeTech GTR v1.0 (STM32F407IGT)
#define BOARD_LERDGE_K 4213 // Lerdge K (STM32F407ZG)
#define BOARD_LERDGE_S 4214 // Lerdge S (STM32F407VE)
#define BOARD_LERDGE_X 4215 // Lerdge X (STM32F407VE)
#define BOARD_VAKE403D 4216 // VAkE 403D (STM32F446VET6)
#define BOARD_FYSETC_S6 4217 // FYSETC S6 (STM32F446VET6)
#define BOARD_FYSETC_S6_V2_0 4218 // FYSETC S6 v2.0 (STM32F446VET6)
#define BOARD_FYSETC_SPIDER 4219 // FYSETC Spider (STM32F446VET6)
#define BOARD_FLYF407ZG 4220 // FLYF407ZG (STM32F407ZG)
#define BOARD_MKS_ROBIN2 4221 // MKS_ROBIN2 (STM32F407ZE)
#define BOARD_MKS_ROBIN_PRO_V2 4222 // MKS Robin Pro V2 (STM32F407VE)
#define BOARD_MKS_ROBIN_NANO_V3 4223 // MKS Robin Nano V3 (STM32F407VG)
#define BOARD_ANET_ET4 4224 // ANET ET4 V1.x (STM32F407VGT6)
#define BOARD_ANET_ET4P 4225 // ANET ET4P V1.x (STM32F407VGT6)
#define BOARD_FYSETC_CHEETAH_V20 4226 // FYSETC Cheetah V2.0
//
// ARM Cortex M7
@@ -385,14 +392,15 @@
#define BOARD_TEENSY41 5001 // Teensy 4.1
#define BOARD_T41U5XBB 5002 // T41U5XBB Teensy 4.1 breakout board
#define BOARD_NUCLEO_F767ZI 5003 // ST NUCLEO-F767ZI Dev Board
#define BOARD_BTT_SKR_SE_BX 5004 // BigTreeTech SKR SE BX (STM32H743II)
//
// Espressif ESP32 WiFi
//
#define BOARD_ESPRESSIF_ESP32 6000 // Generic ESP32
#define BOARD_MRR_ESPA 6001 // MRR ESPA board based on ESP32 (native pins only)
#define BOARD_MRR_ESPE 6002 // MRR ESPE board based on ESP32 (with I2S stepper stream)
#define BOARD_MRR_ESPA 6001 // MRR ESPA based on ESP32 (native pins only)
#define BOARD_MRR_ESPE 6002 // MRR ESPE based on ESP32 (with I2S stepper stream)
#define BOARD_E4D_BOX 6003 // E4d@BOX
#define BOARD_FYSETC_E4 6004 // FYSETC E4

View File

@@ -27,10 +27,12 @@
// Useful macro for stopping the CPU on an unexpected condition
// This is used like SERIAL_ECHOPAIR, that is: a key-value call of the local variables you want
// to dump to the serial port before stopping the CPU.
#define BUG_ON(V...) do { SERIAL_ECHOPAIR(ONLY_FILENAME, __LINE__, ": "); SERIAL_ECHOLNPAIR(V); SERIAL_FLUSHTX(); *(char*)0 = 42; } while(0)
// \/ Don't replace by SERIAL_ECHOPAIR since ONLY_FILENAME cannot be transformed to a PGM string on Arduino and it breaks building
#define BUG_ON(V...) do { SERIAL_ECHO(ONLY_FILENAME); SERIAL_ECHO(__LINE__); SERIAL_ECHOLNPGM(": "); SERIAL_ECHOLNPAIR(V); SERIAL_FLUSHTX(); *(char*)0 = 42; } while(0)
#elif ENABLED(MARLIN_DEV_MODE)
// Don't stop the CPU here, but at least dump the bug on the serial port
#define BUG_ON(V...) do { SERIAL_ECHOPAIR(ONLY_FILENAME, __LINE__, ": BUG!\n"); SERIAL_ECHOLNPAIR(V); SERIAL_FLUSHTX(); } while(0)
// \/ Don't replace by SERIAL_ECHOPAIR since ONLY_FILENAME cannot be transformed to a PGM string on Arduino and it breaks building
#define BUG_ON(V...) do { SERIAL_ECHO(ONLY_FILENAME); SERIAL_ECHO(__LINE__); SERIAL_ECHOLNPGM(": BUG!"); SERIAL_ECHOLNPAIR(V); SERIAL_FLUSHTX(); } while(0)
#else
// Release mode, let's ignore the bug
#define BUG_ON(V...) NOOP

View File

@@ -27,7 +27,7 @@
//
#undef DEBUG_SECTION
#undef DEBUG_PRINT_P
#undef DEBUG_ECHOPGM_P
#undef DEBUG_ECHO_START
#undef DEBUG_ERROR_START
#undef DEBUG_CHAR

View File

@@ -130,6 +130,7 @@
#define STR_COUNT_A " Count A:"
#define STR_WATCHDOG_FIRED "Watchdog timeout. Reset required."
#define STR_ERR_KILLED "Printer halted. kill() called!"
#define STR_FLOWMETER_FAULT "Coolant flow fault. Flowmeter safety is active. Attention required."
#define STR_ERR_STOPPED "Printer stopped due to errors. Fix the error and use M999 to restart. (Temperature is reset. Set it after restarting)"
#define STR_ERR_SERIAL_MISMATCH "Serial status mismatch"
#define STR_BUSY_PROCESSING "busy: processing"
@@ -247,6 +248,8 @@
#define STR_HEATER_BED "bed"
#define STR_HEATER_CHAMBER "chamber"
#define STR_COOLER "cooler"
#define STR_LASER_TEMP "laser temperature"
#define STR_STOPPED_HEATER ", system stopped! Heater_ID: "
#define STR_REDUNDANCY "Heater switched off. Temperature difference between temp sensors is too high !"

View File

@@ -187,14 +187,21 @@
#define DISABLED(V...) DO(DIS,&&,V)
#define COUNT_ENABLED(V...) DO(ENA,+,V)
#define TERN(O,A,B) _TERN(_ENA_1(O),B,A) // OPTION converted to '0' or '1'
#define TERN0(O,A) _TERN(_ENA_1(O),0,A) // OPTION converted to A or '0'
#define TERN1(O,A) _TERN(_ENA_1(O),1,A) // OPTION converted to A or '1'
#define TERN_(O,A) _TERN(_ENA_1(O),,A) // OPTION converted to A or '<nul>'
#define TERN(O,A,B) _TERN(_ENA_1(O),B,A) // OPTION ? 'A' : 'B'
#define TERN0(O,A) _TERN(_ENA_1(O),0,A) // OPTION ? 'A' : '0'
#define TERN1(O,A) _TERN(_ENA_1(O),1,A) // OPTION ? 'A' : '1'
#define TERN_(O,A) _TERN(_ENA_1(O),,A) // OPTION ? 'A' : '<nul>'
#define _TERN(E,V...) __TERN(_CAT(T_,E),V) // Prepend 'T_' to get 'T_0' or 'T_1'
#define __TERN(T,V...) ___TERN(_CAT(_NO,T),V) // Prepend '_NO' to get '_NOT_0' or '_NOT_1'
#define ___TERN(P,V...) THIRD(P,V) // If first argument has a comma, A. Else B.
// Macros to avoid 'f + 0.0' which is not always optimized away. Minus included for symmetry.
// Compiler flags -fno-signed-zeros -ffinite-math-only also cover 'f * 1.0', 'f - f', etc.
#define PLUS_TERN0(O,A) _TERN(_ENA_1(O),,+ (A)) // OPTION ? '+ (A)' : '<nul>'
#define MINUS_TERN0(O,A) _TERN(_ENA_1(O),,- (A)) // OPTION ? '- (A)' : '<nul>'
#define SUM_TERN(O,B,A) ((B) PLUS_TERN0(O,A)) // ((B) (OPTION ? '+ (A)' : '<nul>'))
#define DIFF_TERN(O,B,A) ((B) MINUS_TERN0(O,A)) // ((B) (OPTION ? '- (A)' : '<nul>'))
#define IF_ENABLED TERN_
#define IF_DISABLED(O,A) TERN(O,,A)
@@ -318,6 +325,16 @@
#endif
// Allow manipulating enumeration value like flags without ugly cast everywhere
#define ENUM_FLAGS(T) \
FORCE_INLINE constexpr T operator&(T x, T y) { return static_cast<T>(static_cast<int>(x) & static_cast<int>(y)); } \
FORCE_INLINE constexpr T operator|(T x, T y) { return static_cast<T>(static_cast<int>(x) | static_cast<int>(y)); } \
FORCE_INLINE constexpr T operator^(T x, T y) { return static_cast<T>(static_cast<int>(x) ^ static_cast<int>(y)); } \
FORCE_INLINE constexpr T operator~(T x) { return static_cast<T>(~static_cast<int>(x)); } \
FORCE_INLINE T & operator&=(T &x, T y) { return x &= y; } \
FORCE_INLINE T & operator|=(T &x, T y) { return x |= y; } \
FORCE_INLINE T & operator^=(T &x, T y) { return x ^= y; }
// C++11 solution that is standard compliant. <type_traits> is not available on all platform
namespace Private {
template<bool, typename _Tp = void> struct enable_if { };
@@ -357,23 +374,43 @@
return *str ? findStringEnd(str + 1) : str;
}
// Check whether a string contains a slash
constexpr bool containsSlash(const char *str) {
return *str == '/' ? true : (*str ? containsSlash(str + 1) : false);
// Check whether a string contains a specific character
constexpr bool contains(const char *str, const char ch) {
return *str == ch ? true : (*str ? contains(str + 1, ch) : false);
}
// Find the last position of the slash
constexpr const char* findLastSlashPos(const char* str) {
return *str == '/' ? (str + 1) : findLastSlashPos(str - 1);
// Find the last position of the specific character (should be called with findStringEnd)
constexpr const char* findLastPos(const char *str, const char ch) {
return *str == ch ? (str + 1) : findLastPos(str - 1, ch);
}
// Compile-time evaluation of the last part of a file path
// Typically used to shorten the path to file in compiled strings
// CompileTimeString::baseName(__FILE__) returns "macros.h" and not /path/to/Marlin/src/core/macros.h
constexpr const char* baseName(const char *str) {
return containsSlash(str) ? findLastSlashPos(findStringEnd(str)) : str;
return contains(str, '/') ? findLastPos(findStringEnd(str), '/') : str;
}
// Find the first occurence of a character in a string (or return the last position in the string)
constexpr const char* findFirst(const char *str, const char ch) {
return *str == ch || *str == 0 ? (str + 1) : findFirst(str + 1, ch);
}
// Compute the string length at compile time
constexpr unsigned stringLen(const char *str) {
return *str == 0 ? 0 : 1 + stringLen(str + 1);
}
}
#define ONLY_FILENAME CompileTimeString::baseName(__FILE__)
/** Get the templated type name. This does not depends on RTTI, but on the preprocessor, so it should be quite safe to use even on old compilers.
WARNING: DO NOT RENAME THIS FUNCTION (or change the text inside the function to match what the preprocessor will generate)
The name is chosen very short since the binary will store "const char* gtn(T*) [with T = YourTypeHere]" so avoid long function name here */
template <typename T>
inline const char* gtn(T*) {
// It works on GCC by instantiating __PRETTY_FUNCTION__ and parsing the result. So the syntax here is very limited to GCC output
constexpr unsigned verboseChatLen = sizeof("const char* gtn(T*) [with T = ") - 1;
static char templateType[sizeof(__PRETTY_FUNCTION__) - verboseChatLen] = {};
__builtin_memcpy(templateType, __PRETTY_FUNCTION__ + verboseChatLen, sizeof(__PRETTY_FUNCTION__) - verboseChatLen - 2);
return templateType;
}
#else

View File

@@ -37,23 +37,22 @@ PGMSTR(SP_A_STR, " A"); PGMSTR(SP_B_STR, " B"); PGMSTR(SP_C_STR, " C");
PGMSTR(SP_X_STR, " X"); PGMSTR(SP_Y_STR, " Y"); PGMSTR(SP_Z_STR, " Z"); PGMSTR(SP_E_STR, " E");
PGMSTR(SP_X_LBL, " X:"); PGMSTR(SP_Y_LBL, " Y:"); PGMSTR(SP_Z_LBL, " Z:"); PGMSTR(SP_E_LBL, " E:");
#if HAS_MULTI_SERIAL
#ifdef SERIAL_CATCHALL
SerialOutputT multiSerial(MYSERIAL, SERIAL_CATCHALL);
#else
#if HAS_ETHERNET
// Runtime checking of the condition variable
ConditionalSerial<decltype(MYSERIAL1)> serialOut1(ethernet.have_telnet_client, MYSERIAL1, false); // Takes reference here
#else
// Don't pay for runtime checking a true variable, instead use the output directly
#define serialOut1 MYSERIAL1
#endif
SerialOutputT multiSerial(MYSERIAL0, serialOut1);
// Hook Meatpack if it's enabled on the first leaf
#if ENABLED(MEATPACK_ON_SERIAL_PORT_1)
SerialLeafT1 mpSerial1(false, _SERIAL_LEAF_1);
#endif
#if ENABLED(MEATPACK_ON_SERIAL_PORT_2)
SerialLeafT2 mpSerial2(false, _SERIAL_LEAF_2);
#endif
#if ENABLED(MEATPACK)
MeatpackSerial<decltype(_SERIAL_IMPL)> mpSerial(false, _SERIAL_IMPL);
// Step 2: For multiserial, handle the second serial port as well
#if HAS_MULTI_SERIAL
#if HAS_ETHERNET
// We need a definition here
SerialLeafT2 msSerial2(ethernet.have_telnet_client, MYSERIAL2, false);
#endif
SerialOutputT multiSerial(SERIAL_LEAF_1, SERIAL_LEAF_2);
#endif
void serialprintPGM(PGM_P str) {
@@ -92,7 +91,7 @@ void print_bin(uint16_t val) {
}
}
void print_xyz(const float &x, const float &y, const float &z, PGM_P const prefix/*=nullptr*/, PGM_P const suffix/*=nullptr*/) {
void print_xyz(const_float_t x, const_float_t y, const_float_t z, PGM_P const prefix/*=nullptr*/, PGM_P const suffix/*=nullptr*/) {
if (prefix) serialprintPGM(prefix);
SERIAL_ECHOPAIR_P(SP_X_STR, x, SP_Y_STR, y, SP_Z_STR, z);
if (suffix) serialprintPGM(suffix); else SERIAL_EOL();

View File

@@ -24,7 +24,7 @@
#include "../inc/MarlinConfig.h"
#include "serial_hook.h"
#if ENABLED(MEATPACK)
#if HAS_MEATPACK
#include "../feature/meatpack.h"
#endif
@@ -62,37 +62,66 @@ extern uint8_t marlin_debug_flags;
//
// Serial redirection
//
#define SERIAL_ALL 0x7F
// Step 1: Find what's the first serial leaf
#if BOTH(HAS_MULTI_SERIAL, SERIAL_CATCHALL)
#define _SERIAL_LEAF_1 MYSERIAL
#else
#define _SERIAL_LEAF_1 MYSERIAL1
#endif
// Hook Meatpack if it's enabled on the first leaf
#if ENABLED(MEATPACK_ON_SERIAL_PORT_1)
typedef MeatpackSerial<decltype(_SERIAL_LEAF_1)> SerialLeafT1;
extern SerialLeafT1 mpSerial1;
#define SERIAL_LEAF_1 mpSerial1
#else
#define SERIAL_LEAF_1 _SERIAL_LEAF_1
#endif
// Step 2: For multiserial, handle the second serial port as well
#if HAS_MULTI_SERIAL
#define _PORT_REDIRECT(n,p) REMEMBER(n,multiSerial.portMask,p)
#define _PORT_RESTORE(n,p) RESTORE(n)
#define SERIAL_ASSERT(P) if(multiSerial.portMask!=(P)){ debugger(); }
// If we have a catchall, use that directly
#ifdef SERIAL_CATCHALL
typedef MultiSerial<decltype(MYSERIAL), decltype(SERIAL_CATCHALL), 0> SerialOutputT;
#define _SERIAL_LEAF_2 SERIAL_CATCHALL
#else
typedef MultiSerial<decltype(MYSERIAL0), TERN(HAS_ETHERNET, ConditionalSerial<decltype(MYSERIAL1)>, decltype(MYSERIAL1)), 0> SerialOutputT;
#if HAS_ETHERNET
// We need to create an instance here
typedef ConditionalSerial<decltype(MYSERIAL2)> SerialLeafT2;
extern SerialLeafT2 msSerial2;
#define _SERIAL_LEAF_2 msSerial2
#else
// Don't create a useless instance here, directly use the existing instance
#define _SERIAL_LEAF_2 MYSERIAL2
#endif
#endif
// Hook Meatpack if it's enabled on the second leaf
#if ENABLED(MEATPACK_ON_SERIAL_PORT_2)
typedef MeatpackSerial<decltype(_SERIAL_LEAF_2)> SerialLeafT2;
extern SerialLeafT2 mpSerial2;
#define SERIAL_LEAF_2 mpSerial2
#else
#define SERIAL_LEAF_2 _SERIAL_LEAF_2
#endif
typedef MultiSerial<decltype(SERIAL_LEAF_1), decltype(SERIAL_LEAF_2), 0> SerialOutputT;
extern SerialOutputT multiSerial;
#define _SERIAL_IMPL multiSerial
#define SERIAL_IMPL multiSerial
#else
#define _PORT_REDIRECT(n,p) NOOP
#define _PORT_RESTORE(n) NOOP
#define SERIAL_ASSERT(P) NOOP
#define _SERIAL_IMPL MYSERIAL0
#endif
#if ENABLED(MEATPACK)
extern MeatpackSerial<decltype(_SERIAL_IMPL)> mpSerial;
#define SERIAL_IMPL mpSerial
#else
#define SERIAL_IMPL _SERIAL_IMPL
#define SERIAL_IMPL SERIAL_LEAF_1
#endif
#define SERIAL_OUT(WHAT, V...) (void)SERIAL_IMPL.WHAT(V)
#define PORT_REDIRECT(p) _PORT_REDIRECT(1,p)
#define PORT_RESTORE() _PORT_RESTORE(1)
#define SERIAL_PORTMASK(P) _BV(P)
#define SERIAL_PORTMASK(P) SerialMask::from(P)
//
// SERIAL_CHAR - Print one or more individual chars
@@ -115,6 +144,7 @@ void SERIAL_ECHO(T x) { SERIAL_IMPL.print(x); }
typedef struct SerialChar { char c; SerialChar(char n) : c(n) { } } serial_char_t;
inline void SERIAL_ECHO(serial_char_t x) { SERIAL_IMPL.write(x.c); }
#define AS_CHAR(C) serial_char_t(C)
#define AS_DIGIT(C) AS_CHAR('0' + (C))
// SERIAL_ECHO_F prints a floating point value with optional precision
inline void SERIAL_ECHO_F(EnsureDouble x, int digit=2) { SERIAL_IMPL.print(x, digit); }
@@ -358,7 +388,7 @@ void serialprint_truefalse(const bool tf);
void serial_spaces(uint8_t count);
void print_bin(const uint16_t val);
void print_xyz(const float &x, const float &y, const float &z, PGM_P const prefix=nullptr, PGM_P const suffix=nullptr);
void print_xyz(const_float_t x, const_float_t y, const_float_t z, PGM_P const prefix=nullptr, PGM_P const suffix=nullptr);
inline void print_xyz(const xyz_pos_t &xyz, PGM_P const prefix=nullptr, PGM_P const suffix=nullptr) {
print_xyz(xyz.x, xyz.y, xyz.z, prefix, suffix);

View File

@@ -22,15 +22,28 @@
#pragma once
#include "../inc/MarlinConfigPre.h"
#include "macros.h"
#if ENABLED(EMERGENCY_PARSER)
#include "../feature/e_parser.h"
#endif
// flushTX is not implemented in all HAL, so use SFINAE to call the method where it is.
CALL_IF_EXISTS_IMPL(void, flushTX);
CALL_IF_EXISTS_IMPL(bool, connected, true);
// Used in multiple places
// You can build it but not manipulate it.
// There are only few places where it's required to access the underlying member: GCodeQueue, SerialMask and MultiSerial
struct serial_index_t {
// A signed index, where -1 is a special case meaning no action (neither output or input)
int8_t index;
// Check if the index is within the range [a ... b]
constexpr inline bool within(const int8_t a, const int8_t b) const { return WITHIN(index, a, b); }
constexpr inline bool valid() const { return WITHIN(index, 0, 7); } // At most, 8 bits
// Construction is either from an index
constexpr serial_index_t(const int8_t index) : index(index) {}
// Default to "no index"
constexpr serial_index_t() : index(-1) {}
};
// In order to catch usage errors in code, we make the base to encode number explicit
// If given a number (and not this enum), the compiler will reject the overload, falling back to the (double, digit) version
@@ -42,19 +55,34 @@ enum class PrintBase {
Bin = 2
};
// A simple forward struct that prevent the compiler to select print(double, int) as a default overload for any type different than
// double or float. For double or float, a conversion exists so the call will be transparent
// A simple feature list enumeration
enum class SerialFeature {
None = 0x00,
MeatPack = 0x01, //!< Enabled when Meatpack is present
BinaryFileTransfer = 0x02, //!< Enabled for BinaryFile transfer support (in the future)
Virtual = 0x04, //!< Enabled for virtual serial port (like Telnet / Websocket / ...)
Hookable = 0x08, //!< Enabled if the serial class supports a setHook method
};
ENUM_FLAGS(SerialFeature);
// flushTX is not implemented in all HAL, so use SFINAE to call the method where it is.
CALL_IF_EXISTS_IMPL(void, flushTX);
CALL_IF_EXISTS_IMPL(bool, connected, true);
CALL_IF_EXISTS_IMPL(SerialFeature, features, SerialFeature::None);
// A simple forward struct to prevent the compiler from selecting print(double, int) as a default overload
// for any type other than double/float. For double/float, a conversion exists so the call will be invisible.
struct EnsureDouble {
double a;
FORCE_INLINE operator double() { return a; }
// If the compiler breaks on ambiguity here, it's likely because you're calling print(X, base) with X not a double or a float, and a
// base that's not one of PrintBase's value. This exact code is made to detect such error, you NEED to set a base explicitely like this:
// If the compiler breaks on ambiguity here, it's likely because print(X, base) is called with X not a double/float, and
// a base that's not a PrintBase value. This code is made to detect the error. You MUST set a base explicitly like this:
// SERIAL_PRINT(v, PrintBase::Hex)
FORCE_INLINE EnsureDouble(double a) : a(a) {}
FORCE_INLINE EnsureDouble(float a) : a(a) {}
};
// Using Curiously Recurring Template Pattern here to avoid virtual table cost when compiling.
// Using Curiously-Recurring Template Pattern here to avoid virtual table cost when compiling.
// Since the real serial class is known at compile time, this results in the compiler writing
// a completely efficient code.
template <class Child>
@@ -68,27 +96,44 @@ struct SerialBase {
SerialBase(const bool) {}
#endif
#define SerialChild static_cast<Child*>(this)
// Static dispatch methods below:
// The most important method here is where it all ends to:
size_t write(uint8_t c) { return static_cast<Child*>(this)->write(c); }
void write(uint8_t c) { SerialChild->write(c); }
// Called when the parser finished processing an instruction, usually build to nothing
void msgDone() { static_cast<Child*>(this)->msgDone(); }
// Called upon initialization
void begin(const long baudRate) { static_cast<Child*>(this)->begin(baudRate); }
// Called upon destruction
void end() { static_cast<Child*>(this)->end(); }
void msgDone() const { SerialChild->msgDone(); }
// Called on initialization
void begin(const long baudRate) { SerialChild->begin(baudRate); }
// Called on destruction
void end() { SerialChild->end(); }
/** Check for available data from the port
@param index The port index, usually 0 */
int available(uint8_t index = 0) { return static_cast<Child*>(this)->available(index); }
int available(serial_index_t index=0) const { return SerialChild->available(index); }
/** Read a value from the port
@param index The port index, usually 0 */
int read(uint8_t index = 0) { return static_cast<Child*>(this)->read(index); }
int read(serial_index_t index=0) { return SerialChild->read(index); }
/** Combine the features of this serial instance and return it
@param index The port index, usually 0 */
SerialFeature features(serial_index_t index=0) const { return static_cast<const Child*>(this)->features(index); }
// Check if the serial port has a feature
bool has_feature(serial_index_t index, SerialFeature flag) const { return (features(index) & flag) != SerialFeature::None; }
// Check if the serial port is connected (usually bypassed)
bool connected() { return static_cast<Child*>(this)->connected(); }
bool connected() const { return SerialChild->connected(); }
// Redirect flush
void flush() { static_cast<Child*>(this)->flush(); }
void flush() { SerialChild->flush(); }
// Not all implementation have a flushTX, so let's call them only if the child has the implementation
void flushTX() { CALL_IF_EXISTS(void, static_cast<Child*>(this), flushTX); }
void flushTX() { CALL_IF_EXISTS(void, SerialChild, flushTX); }
// Glue code here
FORCE_INLINE void write(const char *str) { while (*str) write(*str++); }

View File

@@ -21,11 +21,32 @@
*/
#pragma once
#include "macros.h"
#include "serial_base.h"
// Used in multiple places
typedef int8_t serial_index_t;
// A mask containing a bitmap of the serial port to act upon
// This is written to ensure a serial index is never used as a serial mask
class SerialMask {
uint8_t mask;
// This constructor is private to ensure you can't convert an index to a mask
// The compiler will stop here if you are mixing index and mask in your code.
// If you need to, you'll have to use the explicit static "from" method here
SerialMask(const serial_index_t);
public:
inline constexpr bool enabled(const SerialMask PortMask) const { return mask & PortMask.mask; }
inline constexpr SerialMask combine(const SerialMask other) const { return SerialMask(mask | other.mask); }
inline constexpr SerialMask operator<< (const int offset) const { return SerialMask(mask << offset); }
static inline SerialMask from(const serial_index_t index) {
if (index.valid()) return SerialMask(_BV(index.index));
return SerialMask(0); // A invalid index mean no output
}
constexpr SerialMask(const uint8_t mask) : mask(mask) {}
constexpr SerialMask(const SerialMask & other) : mask(other.mask) {} // Can't use = default here since not all framework support this
static constexpr uint8_t All = 0xFF;
};
// The most basic serial class: it dispatch to the base serial class with no hook whatsoever. This will compile to nothing but the base serial class
template <class SerialT>
@@ -39,11 +60,13 @@ struct BaseSerial : public SerialBase< BaseSerial<SerialT> >, public SerialT {
void msgDone() {}
// We don't care about indices here, since if one can call us, it's the right index anyway
int available(uint8_t) { return (int)SerialT::available(); }
int read(uint8_t) { return (int)SerialT::read(); }
int available(serial_index_t) { return (int)SerialT::available(); }
int read(serial_index_t) { return (int)SerialT::read(); }
bool connected() { return CALL_IF_EXISTS(bool, static_cast<SerialT*>(this), connected);; }
void flushTX() { CALL_IF_EXISTS(void, static_cast<SerialT*>(this), flushTX); }
SerialFeature features(serial_index_t index) const { return CALL_IF_EXISTS(SerialFeature, static_cast<const SerialT*>(this), features, index); }
// We have 2 implementation of the same method in both base class, let's say which one we want
using SerialT::available;
using SerialT::read;
@@ -77,11 +100,11 @@ struct ConditionalSerial : public SerialBase< ConditionalSerial<SerialT> > {
bool connected() { return CALL_IF_EXISTS(bool, &out, connected); }
void flushTX() { CALL_IF_EXISTS(void, &out, flushTX); }
int available(uint8_t ) { return (int)out.available(); }
int read(uint8_t ) { return (int)out.read(); }
int available(serial_index_t) { return (int)out.available(); }
int read(serial_index_t) { return (int)out.read(); }
int available() { return (int)out.available(); }
int read() { return (int)out.read(); }
SerialFeature features(serial_index_t index) const { return CALL_IF_EXISTS(SerialFeature, &out, features, index); }
ConditionalSerial(bool & conditionVariable, SerialT & out, const bool e) : BaseClassT(e), condition(conditionVariable), out(out) {}
};
@@ -102,10 +125,11 @@ struct ForwardSerial : public SerialBase< ForwardSerial<SerialT> > {
bool connected() { return Private::HasMember_connected<SerialT>::value ? CALL_IF_EXISTS(bool, &out, connected) : (bool)out; }
void flushTX() { CALL_IF_EXISTS(void, &out, flushTX); }
int available(uint8_t) { return (int)out.available(); }
int read(uint8_t) { return (int)out.read(); }
int available(serial_index_t) { return (int)out.available(); }
int read(serial_index_t) { return (int)out.read(); }
int available() { return (int)out.available(); }
int read() { return (int)out.read(); }
SerialFeature features(serial_index_t index) const { return CALL_IF_EXISTS(SerialFeature, &out, features, index); }
ForwardSerial(const bool e, SerialT & out) : BaseClassT(e), out(out) {}
};
@@ -130,8 +154,8 @@ struct RuntimeSerial : public SerialBase< RuntimeSerial<SerialT> >, public Seria
if (eofHook) eofHook(userPointer);
}
int available(uint8_t) { return (int)SerialT::available(); }
int read(uint8_t) { return (int)SerialT::read(); }
int available(serial_index_t) { return (int)SerialT::available(); }
int read(serial_index_t) { return (int)SerialT::read(); }
using SerialT::available;
using SerialT::read;
using SerialT::flush;
@@ -143,10 +167,16 @@ struct RuntimeSerial : public SerialBase< RuntimeSerial<SerialT> >, public Seria
// Underlying implementation might use Arduino's bool operator
bool connected() {
return Private::HasMember_connected<SerialT>::value ? CALL_IF_EXISTS(bool, static_cast<SerialT*>(this), connected) : static_cast<SerialT*>(this)->operator bool();
return Private::HasMember_connected<SerialT>::value
? CALL_IF_EXISTS(bool, static_cast<SerialT*>(this), connected)
: static_cast<SerialT*>(this)->operator bool();
}
void flushTX() { CALL_IF_EXISTS(void, static_cast<SerialT*>(this), flushTX); }
// Append Hookable for this class
SerialFeature features(serial_index_t index) const { return SerialFeature::Hookable | CALL_IF_EXISTS(SerialFeature, static_cast<const SerialT*>(this), features, index); }
void setHook(WriteHook writeHook = 0, EndOfMessageHook eofHook = 0, void * userPointer = 0) {
// Order is important here as serial code can be called inside interrupts
// When setting a hook, the user pointer must be set first so if writeHook is called as soon as it's set, it'll be valid
@@ -165,58 +195,54 @@ struct RuntimeSerial : public SerialBase< RuntimeSerial<SerialT> >, public Seria
RuntimeSerial(const bool e, Args... args) : BaseClassT(e), SerialT(args...), writeHook(0), eofHook(0), userPointer(0) {}
};
// A class that's duplicating its output conditionally to 2 serial interface
// A class that duplicates its output conditionally to 2 serial interfaces
template <class Serial0T, class Serial1T, const uint8_t offset = 0, const uint8_t step = 1>
struct MultiSerial : public SerialBase< MultiSerial<Serial0T, Serial1T, offset, step> > {
typedef SerialBase< MultiSerial<Serial0T, Serial1T, offset, step> > BaseClassT;
uint8_t portMask;
SerialMask portMask;
Serial0T & serial0;
Serial1T & serial1;
enum Masks {
UsageMask = ((1 << step) - 1), // A bit mask containing as many bits as step
FirstOutputMask = (UsageMask << offset),
SecondOutputMask = (UsageMask << (offset + step)),
AllMask = FirstOutputMask | SecondOutputMask,
};
static constexpr uint8_t Usage = ((1 << step) - 1); // A bit mask containing as many bits as step
static constexpr uint8_t FirstOutput = (Usage << offset);
static constexpr uint8_t SecondOutput = (Usage << (offset + step));
static constexpr uint8_t Both = FirstOutput | SecondOutput;
NO_INLINE size_t write(uint8_t c) {
size_t ret = 0;
if (portMask & FirstOutputMask) ret = serial0.write(c);
if (portMask & SecondOutputMask) ret = serial1.write(c) | ret;
return ret;
NO_INLINE void write(uint8_t c) {
if (portMask.enabled(FirstOutput)) serial0.write(c);
if (portMask.enabled(SecondOutput)) serial1.write(c);
}
NO_INLINE void msgDone() {
if (portMask & FirstOutputMask) serial0.msgDone();
if (portMask & SecondOutputMask) serial1.msgDone();
if (portMask.enabled(FirstOutput)) serial0.msgDone();
if (portMask.enabled(SecondOutput)) serial1.msgDone();
}
int available(uint8_t index) {
if (index >= 0 + offset && index < step + offset)
int available(serial_index_t index) {
if (index.within(0 + offset, step + offset - 1))
return serial0.available(index);
else if (index >= step + offset && index < 2 * step + offset)
else if (index.within(step + offset, 2 * step + offset - 1))
return serial1.available(index);
return false;
}
int read(uint8_t index) {
if (index >= 0 + offset && index < step + offset)
int read(serial_index_t index) {
if (index.within(0 + offset, step + offset - 1))
return serial0.read(index);
else if (index >= step + offset && index < 2 * step + offset)
else if (index.within(step + offset, 2 * step + offset - 1))
return serial1.read(index);
return -1;
}
void begin(const long br) {
if (portMask & FirstOutputMask) serial0.begin(br);
if (portMask & SecondOutputMask) serial1.begin(br);
if (portMask.enabled(FirstOutput)) serial0.begin(br);
if (portMask.enabled(SecondOutput)) serial1.begin(br);
}
void end() {
if (portMask & FirstOutputMask) serial0.end();
if (portMask & SecondOutputMask) serial1.end();
if (portMask.enabled(FirstOutput)) serial0.end();
if (portMask.enabled(SecondOutput)) serial1.end();
}
bool connected() {
bool ret = true;
if (portMask & FirstOutputMask) ret = CALL_IF_EXISTS(bool, &serial0, connected);
if (portMask & SecondOutputMask) ret = ret && CALL_IF_EXISTS(bool, &serial1, connected);
if (portMask.enabled(FirstOutput)) ret = CALL_IF_EXISTS(bool, &serial0, connected);
if (portMask.enabled(SecondOutput)) ret = ret && CALL_IF_EXISTS(bool, &serial1, connected);
return ret;
}
@@ -225,22 +251,31 @@ struct MultiSerial : public SerialBase< MultiSerial<Serial0T, Serial1T, offset,
// Redirect flush
NO_INLINE void flush() {
if (portMask & FirstOutputMask) serial0.flush();
if (portMask & SecondOutputMask) serial1.flush();
if (portMask.enabled(FirstOutput)) serial0.flush();
if (portMask.enabled(SecondOutput)) serial1.flush();
}
NO_INLINE void flushTX() {
if (portMask & FirstOutputMask) CALL_IF_EXISTS(void, &serial0, flushTX);
if (portMask & SecondOutputMask) CALL_IF_EXISTS(void, &serial1, flushTX);
if (portMask.enabled(FirstOutput)) CALL_IF_EXISTS(void, &serial0, flushTX);
if (portMask.enabled(SecondOutput)) CALL_IF_EXISTS(void, &serial1, flushTX);
}
MultiSerial(Serial0T & serial0, Serial1T & serial1, int8_t mask = AllMask, const bool e = false) :
// Forward feature queries
SerialFeature features(serial_index_t index) const {
if (index.within(0 + offset, step + offset - 1))
return serial0.features(index);
else if (index.within(step + offset, 2 * step + offset - 1))
return serial1.features(index);
return SerialFeature::None;
}
MultiSerial(Serial0T & serial0, Serial1T & serial1, const SerialMask mask = Both, const bool e = false) :
BaseClassT(e),
portMask(mask), serial0(serial0), serial1(serial1) {}
};
// Build the actual serial object depending on current configuration
#define Serial0Type TERN(SERIAL_RUNTIME_HOOK, RuntimeSerial, BaseSerial)
#define ForwardSerial0Type TERN(SERIAL_RUNTIME_HOOK, RuntimeSerial, ForwardSerial)
#define Serial1Class TERN(SERIAL_RUNTIME_HOOK, RuntimeSerial, BaseSerial)
#define ForwardSerial1Class TERN(SERIAL_RUNTIME_HOOK, RuntimeSerial, ForwardSerial)
#ifdef HAS_MULTI_SERIAL
#define Serial1Type ConditionalSerial
#define Serial2Class ConditionalSerial
#endif

View File

@@ -72,16 +72,34 @@ struct IF<true, L, R> { typedef L type; };
//
typedef float feedRate_t;
//
// celsius_t is the native unit of temperature. Signed to handle a disconnected thermistor value (-14).
// For more resolition (e.g., for a chocolate printer) this may later be changed to Celsius x 100
//
typedef int16_t celsius_t;
typedef float celsius_float_t;
//
// On AVR pointers are only 2 bytes so use 'const float &' for 'const float'
//
#ifdef __AVR__
typedef const float & const_float_t;
#else
typedef const float const_float_t;
#endif
typedef const_float_t const_feedRate_t;
typedef const_float_t const_celsius_float_t;
// Conversion macros
#define MMM_TO_MMS(MM_M) feedRate_t(float(MM_M) / 60.0f)
#define MMS_TO_MMM(MM_S) (float(MM_S) * 60.0f)
#define MMM_TO_MMS(MM_M) feedRate_t(static_cast<float>(MM_M) / 60.0f)
#define MMS_TO_MMM(MM_S) (static_cast<float>(MM_S) * 60.0f)
//
// Coordinates structures for XY, XYZ, XYZE...
//
// Helpers
#define _RECIP(N) ((N) ? 1.0f / float(N) : 0.0f)
#define _RECIP(N) ((N) ? 1.0f / static_cast<float>(N) : 0.0f)
#define _ABS(N) ((N) < 0 ? -(N) : (N))
#define _LS(N) (N = (T)(uint32_t(N) << v))
#define _RS(N) (N = (T)(uint32_t(N) >> v))
@@ -198,8 +216,8 @@ struct XYval {
FI XYval<int32_t> asLong() const { return { int32_t(x), int32_t(y) }; }
FI XYval<int32_t> ROUNDL() { return { int32_t(LROUND(x)), int32_t(LROUND(y)) }; }
FI XYval<int32_t> ROUNDL() const { return { int32_t(LROUND(x)), int32_t(LROUND(y)) }; }
FI XYval<float> asFloat() { return { float(x), float(y) }; }
FI XYval<float> asFloat() const { return { float(x), float(y) }; }
FI XYval<float> asFloat() { return { static_cast<float>(x), static_cast<float>(y) }; }
FI XYval<float> asFloat() const { return { static_cast<float>(x), static_cast<float>(y) }; }
FI XYval<float> reciprocal() const { return { _RECIP(x), _RECIP(y) }; }
FI XYval<float> asLogical() const { XYval<float> o = asFloat(); toLogical(o); return o; }
FI XYval<float> asNative() const { XYval<float> o = asFloat(); toNative(o); return o; }
@@ -309,8 +327,8 @@ struct XYZval {
FI XYZval<int32_t> asLong() const { return { int32_t(x), int32_t(y), int32_t(z) }; }
FI XYZval<int32_t> ROUNDL() { return { int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)) }; }
FI XYZval<int32_t> ROUNDL() const { return { int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)) }; }
FI XYZval<float> asFloat() { return { float(x), float(y), float(z) }; }
FI XYZval<float> asFloat() const { return { float(x), float(y), float(z) }; }
FI XYZval<float> asFloat() { return { static_cast<float>(x), static_cast<float>(y), static_cast<float>(z) }; }
FI XYZval<float> asFloat() const { return { static_cast<float>(x), static_cast<float>(y), static_cast<float>(z) }; }
FI XYZval<float> reciprocal() const { return { _RECIP(x), _RECIP(y), _RECIP(z) }; }
FI XYZval<float> asLogical() const { XYZval<float> o = asFloat(); toLogical(o); return o; }
FI XYZval<float> asNative() const { XYZval<float> o = asFloat(); toNative(o); return o; }
@@ -420,8 +438,8 @@ struct XYZEval {
FI XYZEval<int32_t> asLong() const { return { int32_t(x), int32_t(y), int32_t(z), int32_t(e) }; }
FI XYZEval<int32_t> ROUNDL() { return { int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(e)) }; }
FI XYZEval<int32_t> ROUNDL() const { return { int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(e)) }; }
FI XYZEval<float> asFloat() { return { float(x), float(y), float(z), float(e) }; }
FI XYZEval<float> asFloat() const { return { float(x), float(y), float(z), float(e) }; }
FI XYZEval<float> asFloat() { return { static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(e) }; }
FI XYZEval<float> asFloat() const { return { static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(e) }; }
FI XYZEval<float> reciprocal() const { return { _RECIP(x), _RECIP(y), _RECIP(z), _RECIP(e) }; }
FI XYZEval<float> asLogical() const { XYZEval<float> o = asFloat(); toLogical(o); return o; }
FI XYZEval<float> asNative() const { XYZEval<float> o = asFloat(); toNative(o); return o; }

View File

@@ -35,6 +35,18 @@ void safe_delay(millis_t ms) {
thermalManager.manage_heater(); // This keeps us safe if too many small safe_delay() calls are made
}
#if ENABLED(MARLIN_DEV_MODE)
void early_safe_delay(millis_t ms) {
while (ms > 50) {
ms -= 50;
delay(50);
watchdog_refresh();
}
delay(ms);
watchdog_refresh();
}
#endif
// A delay to provide brittle hosts time to receive bytes
#if ENABLED(SERIAL_OVERRUN_PROTECTION)

View File

@@ -25,8 +25,12 @@
#include "../core/types.h"
#include "../core/millis_t.h"
// Delay that ensures heaters and watchdog are kept alive
void safe_delay(millis_t ms);
void safe_delay(millis_t ms); // Delay ensuring that temperatures are updated and the watchdog is kept alive.
#if ENABLED(MARLIN_DEV_MODE)
void early_safe_delay(millis_t ms); // Delay ensuring that the watchdog is kept alive. Can be used before the Temperature ISR starts.
#else
inline void early_safe_delay(millis_t ms) { safe_delay(ms); }
#endif
#if ENABLED(SERIAL_OVERRUN_PROTECTION)
void serial_delay(const millis_t ms);
@@ -34,7 +38,7 @@ void safe_delay(millis_t ms);
inline void serial_delay(const millis_t) {}
#endif
#if GRID_MAX_POINTS_X && GRID_MAX_POINTS_Y
#if (GRID_MAX_POINTS_X) && (GRID_MAX_POINTS_Y)
// 16x16 bit arrays
template <int W, int H>

View File

@@ -50,7 +50,7 @@ void Babystep::step_axis(const AxisEnum axis) {
}
}
void Babystep::add_mm(const AxisEnum axis, const float &mm) {
void Babystep::add_mm(const AxisEnum axis, const_float_t mm) {
add_steps(axis, mm * planner.settings.axis_steps_per_mm[axis]);
}

View File

@@ -61,7 +61,7 @@ public:
#endif
static void add_steps(const AxisEnum axis, const int16_t distance);
static void add_mm(const AxisEnum axis, const float &mm);
static void add_mm(const AxisEnum axis, const_float_t mm);
static inline bool has_steps() {
return steps[BS_AXIS_IND(X_AXIS)] || steps[BS_AXIS_IND(Y_AXIS)] || steps[BS_AXIS_IND(Z_AXIS)];

View File

@@ -63,10 +63,24 @@ Backlash backlash;
void Backlash::add_correction_steps(const int32_t &da, const int32_t &db, const int32_t &dc, const uint8_t dm, block_t * const block) {
static uint8_t last_direction_bits;
uint8_t changed_dir = last_direction_bits ^ dm;
// Ignore direction change if no steps are taken in that direction
if (da == 0) CBI(changed_dir, X_AXIS);
if (db == 0) CBI(changed_dir, Y_AXIS);
if (dc == 0) CBI(changed_dir, Z_AXIS);
// Ignore direction change unless steps are taken in that direction
#if DISABLED(CORE_BACKLASH) || ENABLED(MARKFORGED_XY)
if (!da) CBI(changed_dir, X_AXIS);
if (!db) CBI(changed_dir, Y_AXIS);
if (!dc) CBI(changed_dir, Z_AXIS);
#elif CORE_IS_XY
if (!(da + db)) CBI(changed_dir, X_AXIS);
if (!(da - db)) CBI(changed_dir, Y_AXIS);
if (!dc) CBI(changed_dir, Z_AXIS);
#elif CORE_IS_XZ
if (!(da + dc)) CBI(changed_dir, X_AXIS);
if (!(da - dc)) CBI(changed_dir, Z_AXIS);
if (!db) CBI(changed_dir, Y_AXIS);
#elif CORE_IS_YZ
if (!(db + dc)) CBI(changed_dir, Y_AXIS);
if (!(db - dc)) CBI(changed_dir, Z_AXIS);
if (!da) CBI(changed_dir, X_AXIS);
#endif
last_direction_bits ^= changed_dir;
if (correction == 0) return;
@@ -105,18 +119,35 @@ void Backlash::add_correction_steps(const int32_t &da, const int32_t &db, const
// Take up a portion of the residual_error in this segment, but only when
// the current segment travels in the same direction as the correction
if (reversing == (error_correction < 0)) {
if (segment_proportion == 0)
segment_proportion = _MIN(1.0f, block->millimeters / smoothing_mm);
if (segment_proportion == 0) segment_proportion = _MIN(1.0f, block->millimeters / smoothing_mm);
error_correction = CEIL(segment_proportion * error_correction);
}
else
error_correction = 0; // Don't take up any backlash in this segment, as it would subtract steps
}
#endif
// Making a correction reduces the residual error and adds block steps
// This correction reduces the residual error and adds block steps
if (error_correction) {
block->steps[axis] += ABS(error_correction);
#if ENABLED(CORE_BACKLASH)
switch (axis) {
case CORE_AXIS_1:
//block->steps[CORE_AXIS_2] += influence_distance_mm[axis] * planner.settings.axis_steps_per_mm[CORE_AXIS_2];
//SERIAL_ECHOLNPAIR("CORE_AXIS_1 dir change. distance=", distance_mm[axis], " r.err=", residual_error[axis],
// " da=", da, " db=", db, " block->steps[axis]=", block->steps[axis], " err_corr=", error_correction);
break;
case CORE_AXIS_2:
//block->steps[CORE_AXIS_1] += influence_distance_mm[axis] * planner.settings.axis_steps_per_mm[CORE_AXIS_1];;
//SERIAL_ECHOLNPAIR("CORE_AXIS_2 dir change. distance=", distance_mm[axis], " r.err=", residual_error[axis],
// " da=", da, " db=", db, " block->steps[axis]=", block->steps[axis], " err_corr=", error_correction);
break;
case NORMAL_AXIS: break;
}
residual_error[axis] = 0; // No residual_error needed for next CORE block, I think...
#else
residual_error[axis] -= error_correction;
#endif
}
}
}

View File

@@ -35,7 +35,7 @@ public:
static float smoothing_mm;
#endif
static inline void set_correction(const float &v) { correction = _MAX(0, _MIN(1.0, v)) * all_on; }
static inline void set_correction(const_float_t v) { correction = _MAX(0, _MIN(1.0, v)) * all_on; }
static inline float get_correction() { return float(ui8_to_percent(correction)) / 100.0f; }
#else
static constexpr uint8_t correction = (BACKLASH_CORRECTION) * 0xFF;

View File

@@ -85,9 +85,9 @@ static void extrapolate_one_point(const uint8_t x, const uint8_t y, const int8_t
//#define EXTRAPOLATE_FROM_EDGE
#if ENABLED(EXTRAPOLATE_FROM_EDGE)
#if GRID_MAX_POINTS_X < GRID_MAX_POINTS_Y
#if (GRID_MAX_POINTS_X) < (GRID_MAX_POINTS_Y)
#define HALF_IN_X
#elif GRID_MAX_POINTS_Y < GRID_MAX_POINTS_X
#elif (GRID_MAX_POINTS_Y) < (GRID_MAX_POINTS_X)
#define HALF_IN_Y
#endif
#endif
@@ -98,23 +98,23 @@ static void extrapolate_one_point(const uint8_t x, const uint8_t y, const int8_t
*/
void extrapolate_unprobed_bed_level() {
#ifdef HALF_IN_X
constexpr uint8_t ctrx2 = 0, xlen = GRID_MAX_POINTS_X - 1;
constexpr uint8_t ctrx2 = 0, xend = GRID_MAX_POINTS_X - 1;
#else
constexpr uint8_t ctrx1 = (GRID_MAX_POINTS_X - 1) / 2, // left-of-center
constexpr uint8_t ctrx1 = (GRID_MAX_CELLS_X) / 2, // left-of-center
ctrx2 = (GRID_MAX_POINTS_X) / 2, // right-of-center
xlen = ctrx1;
xend = ctrx1;
#endif
#ifdef HALF_IN_Y
constexpr uint8_t ctry2 = 0, ylen = GRID_MAX_POINTS_Y - 1;
constexpr uint8_t ctry2 = 0, yend = GRID_MAX_POINTS_Y - 1;
#else
constexpr uint8_t ctry1 = (GRID_MAX_POINTS_Y - 1) / 2, // top-of-center
constexpr uint8_t ctry1 = (GRID_MAX_CELLS_Y) / 2, // top-of-center
ctry2 = (GRID_MAX_POINTS_Y) / 2, // bottom-of-center
ylen = ctry1;
yend = ctry1;
#endif
LOOP_LE_N(xo, xlen)
LOOP_LE_N(yo, ylen) {
LOOP_LE_N(xo, xend)
LOOP_LE_N(yo, yend) {
uint8_t x2 = ctrx2 + xo, y2 = ctry2 + yo;
#ifndef HALF_IN_X
const uint8_t x1 = ctrx1 - xo;
@@ -143,8 +143,8 @@ void print_bilinear_leveling_grid() {
#if ENABLED(ABL_BILINEAR_SUBDIVISION)
#define ABL_GRID_POINTS_VIRT_X (GRID_MAX_POINTS_X - 1) * (BILINEAR_SUBDIVISIONS) + 1
#define ABL_GRID_POINTS_VIRT_Y (GRID_MAX_POINTS_Y - 1) * (BILINEAR_SUBDIVISIONS) + 1
#define ABL_GRID_POINTS_VIRT_X GRID_MAX_CELLS_X * (BILINEAR_SUBDIVISIONS) + 1
#define ABL_GRID_POINTS_VIRT_Y GRID_MAX_CELLS_Y * (BILINEAR_SUBDIVISIONS) + 1
#define ABL_TEMP_POINTS_X (GRID_MAX_POINTS_X + 2)
#define ABL_TEMP_POINTS_Y (GRID_MAX_POINTS_Y + 2)
float z_values_virt[ABL_GRID_POINTS_VIRT_X][ABL_GRID_POINTS_VIRT_Y];
@@ -161,7 +161,7 @@ void print_bilinear_leveling_grid() {
#define LINEAR_EXTRAPOLATION(E, I) ((E) * 2 - (I))
float bed_level_virt_coord(const uint8_t x, const uint8_t y) {
uint8_t ep = 0, ip = 1;
if (x > GRID_MAX_POINTS_X + 1 || y > GRID_MAX_POINTS_Y + 1) {
if (x > (GRID_MAX_POINTS_X) + 1 || y > (GRID_MAX_POINTS_Y) + 1) {
// The requested point requires extrapolating two points beyond the mesh.
// These values are only requested for the edges of the mesh, which are always an actual mesh point,
// and do not require interpolation. When interpolation is not needed, this "Mesh + 2" point is
@@ -171,8 +171,8 @@ void print_bilinear_leveling_grid() {
}
if (!x || x == ABL_TEMP_POINTS_X - 1) {
if (x) {
ep = GRID_MAX_POINTS_X - 1;
ip = GRID_MAX_POINTS_X - 2;
ep = (GRID_MAX_POINTS_X) - 1;
ip = GRID_MAX_CELLS_X - 1;
}
if (WITHIN(y, 1, ABL_TEMP_POINTS_Y - 2))
return LINEAR_EXTRAPOLATION(
@@ -187,8 +187,8 @@ void print_bilinear_leveling_grid() {
}
if (!y || y == ABL_TEMP_POINTS_Y - 1) {
if (y) {
ep = GRID_MAX_POINTS_Y - 1;
ip = GRID_MAX_POINTS_Y - 2;
ep = (GRID_MAX_POINTS_Y) - 1;
ip = GRID_MAX_CELLS_Y - 1;
}
if (WITHIN(x, 1, ABL_TEMP_POINTS_X - 2))
return LINEAR_EXTRAPOLATION(
@@ -213,7 +213,7 @@ void print_bilinear_leveling_grid() {
) * 0.5f;
}
static float bed_level_virt_2cmr(const uint8_t x, const uint8_t y, const float &tx, const float &ty) {
static float bed_level_virt_2cmr(const uint8_t x, const uint8_t y, const_float_t tx, const_float_t ty) {
float row[4], column[4];
LOOP_L_N(i, 4) {
LOOP_L_N(j, 4) {
@@ -356,7 +356,7 @@ float bilinear_z_offset(const xy_pos_t &raw) {
* Prepare a bilinear-leveled linear move on Cartesian,
* splitting the move where it crosses grid borders.
*/
void bilinear_line_to_destination(const feedRate_t &scaled_fr_mm_s, uint16_t x_splits, uint16_t y_splits) {
void bilinear_line_to_destination(const_feedRate_t scaled_fr_mm_s, uint16_t x_splits, uint16_t y_splits) {
// Get current and destination cells for this line
xy_int_t c1 { CELL_INDEX(x, current_position.x), CELL_INDEX(y, current_position.y) },
c2 { CELL_INDEX(x, destination.x), CELL_INDEX(y, destination.y) };

View File

@@ -37,7 +37,7 @@ void refresh_bed_level();
#endif
#if IS_CARTESIAN && DISABLED(SEGMENT_LEVELED_MOVES)
void bilinear_line_to_destination(const feedRate_t &scaled_fr_mm_s, uint16_t x_splits=0xFFFF, uint16_t y_splits=0xFFFF);
void bilinear_line_to_destination(const_feedRate_t scaled_fr_mm_s, uint16_t x_splits=0xFFFF, uint16_t y_splits=0xFFFF);
#endif
#define _GET_MESH_X(I) float(bilinear_start.x + (I) * bilinear_grid_spacing.x)

View File

@@ -98,7 +98,7 @@ TemporaryBedLevelingState::TemporaryBedLevelingState(const bool enable) : saved(
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
void set_z_fade_height(const float zfh, const bool do_report/*=true*/) {
void set_z_fade_height(const_float_t zfh, const bool do_report/*=true*/) {
if (planner.z_fade_height == zfh) return;
@@ -213,27 +213,27 @@ void reset_bed_level() {
void _manual_goto_xy(const xy_pos_t &pos) {
// Get the resting Z position for after the XY move
#ifdef MANUAL_PROBE_START_Z
constexpr float startz = _MAX(0, MANUAL_PROBE_START_Z);
#if MANUAL_PROBE_HEIGHT > 0
do_blocking_move_to_xy_z(pos, MANUAL_PROBE_HEIGHT);
do_blocking_move_to_z(startz);
constexpr float finalz = _MAX(0, MANUAL_PROBE_START_Z); // If a MANUAL_PROBE_START_Z value is set, always respect it
#else
do_blocking_move_to_xy_z(pos, startz);
#warning "It's recommended to set some MANUAL_PROBE_START_Z value for manual leveling."
#endif
#elif MANUAL_PROBE_HEIGHT > 0
const float prev_z = current_position.z;
do_blocking_move_to_xy_z(pos, MANUAL_PROBE_HEIGHT);
do_blocking_move_to_z(prev_z);
#else
do_blocking_move_to_xy(pos);
#if Z_CLEARANCE_BETWEEN_MANUAL_PROBES > 0 // A probe/obstacle clearance exists so there is a raise:
#ifndef MANUAL_PROBE_START_Z
const float finalz = current_position.z; // - Use the current Z for starting-Z if no MANUAL_PROBE_START_Z was provided
#endif
do_blocking_move_to_xy_z(pos, Z_CLEARANCE_BETWEEN_MANUAL_PROBES); // - Raise Z, then move to the new XY
do_blocking_move_to_z(finalz); // - Lower down to the starting Z height, ready for adjustment!
#elif defined(MANUAL_PROBE_START_Z) // A starting-Z was provided, but there's no raise:
do_blocking_move_to_xy_z(pos, finalz); // - Move in XY then down to the starting Z height, ready for adjustment!
#else // Zero raise and no starting Z height either:
do_blocking_move_to_xy(pos); // - Move over with no raise, ready for adjustment!
#endif
current_position = pos;
TERN_(LCD_BED_LEVELING, ui.wait_for_move = false);
}
#endif
#endif // MESH_BED_LEVELING || PROBE_MANUALLY
#endif // HAS_LEVELING

View File

@@ -38,7 +38,7 @@ void set_bed_leveling_enabled(const bool enable=true);
void reset_bed_level();
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
void set_z_fade_height(const float zfh, const bool do_report=true);
void set_z_fade_height(const_float_t zfh, const bool do_report=true);
#endif
#if EITHER(MESH_BED_LEVELING, PROBE_MANUALLY)

Some files were not shown because too many files have changed in this diff Show More