Merge branch 'bugfix-2.1.x' into pr/27714

This commit is contained in:
Scott Lahteine 2025-09-28 17:21:20 -05:00
commit a769ffeaec
805 changed files with 21115 additions and 13965 deletions

View file

@ -38,7 +38,7 @@
"platformio.platformio-ide",
"marlinfirmware.auto-build",
"editorconfig.editorconfig"
],
]
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],

View file

@ -21,6 +21,7 @@ on:
branches:
- bugfix-2.1.x
- 2.1.x
- release-*
paths-ignore:
- config/**
- data/**
@ -36,6 +37,9 @@ jobs:
runs-on: ubuntu-22.04
env:
CONFIG_BRANCH: ${{ github.base_ref || github.ref_name }}
strategy:
fail-fast: true
matrix:
@ -113,7 +117,7 @@ jobs:
- BTT_GTR_V1_0
- BTT_SKR_PRO
- FLYF407ZG
- FYSETC_S6
- STM32F446VE_fysetc
- LERDGEK
- LERDGEX
- mks_robin_pro2
@ -151,6 +155,12 @@ jobs:
# HC32
- HC32F460C_aquila_101
# GD32F3
- GD32F303RE_creality_mfl
# GD32F1
- GD32F103RC_aquila_mfl
# LPC176x - Lengthy tests
- LPC1768
- LPC1769
@ -164,15 +174,20 @@ jobs:
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
key: ${{ runner.os }}-pip-build-v1
restore-keys: |
${{ runner.os }}-pip-
${{ runner.os }}-pip-build-
- name: Cache PlatformIO
uses: actions/cache@v4
with:
path: ~/.platformio
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
path: |
~/.platformio
.pio/build
.pio/libdeps
key: ${{ runner.os }}-pio-build-v1
restore-keys: |
${{ runner.os }}-pio-build-
- name: Select Python 3.9
uses: actions/setup-python@v5

View file

@ -46,15 +46,20 @@ jobs:
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
key: ${{ runner.os }}-pip-unit-v1
restore-keys: |
${{ runner.os }}-pip-
${{ runner.os }}-pip-unit-
- name: Cache PlatformIO
uses: actions/cache@v4
with:
path: ~/.platformio
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
path: |
~/.platformio
.pio/build
.pio/libdeps
key: ${{ runner.os }}-pio-tests-v1
restore-keys: |
${{ runner.os }}-pio-tests-
- name: Select Python 3.9
uses: actions/setup-python@v5

View file

@ -9,14 +9,14 @@ name: CI - Validate boards.h
on:
pull_request:
branches:
- bugfix-2.1.x
- bugfix-2.1.x
paths:
- 'Marlin/src/core/boards.h'
- "Marlin/src/core/boards.h"
push:
branches:
- bugfix-2.1.x
- bugfix-2.1.x
paths:
- 'Marlin/src/core/boards.h'
- "Marlin/src/core/boards.h"
jobs:
validate_pins_files:
@ -26,23 +26,23 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Check out the PR
uses: actions/checkout@v4
- name: Check out the PR
uses: actions/checkout@v4
- name: Cache pip
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Cache pip
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-validation-v1
restore-keys: |
${{ runner.os }}-pip-validation-
- name: Select Python 3.9
uses: actions/setup-python@v5
with:
python-version: '3.9'
architecture: 'x64'
- name: Select Python 3.9
uses: actions/setup-python@v5
with:
python-version: "3.9"
architecture: "x64"
- name: Validate core/boards.h
run: |
make validate-boards -j
- name: Validate core/boards.h
run: |
make validate-boards -j

40
.github/workflows/ci-validate-lines.yml vendored Normal file
View file

@ -0,0 +1,40 @@
#
# ci-validate-lines.yml
# Validate that all text files are unchanged by linesformat.py
#
name: CI - Validate Source Files
on:
pull_request:
branches:
- bugfix-2.1.x
- 2.1.x
push:
branches:
- bugfix-2.1.x
- 2.1.x
jobs:
validate_source_files:
name: Validate Source Files
if: github.repository == 'MarlinFirmware/Marlin'
runs-on: ubuntu-22.04
steps:
- name: Check out the PR
uses: actions/checkout@v4
- name: Cache node_modules
uses: actions/cache@v4
with:
path: node_modules
key: ${{ runner.os }}-npm-lines-v1
restore-keys: |
${{ runner.os }}-npm-lines-
- name: Validate text file formatting
run: |
npm install --save-dev prettier
make validate-lines -j

View file

@ -8,18 +8,18 @@ name: CI - Validate Pins Files
on:
pull_request:
branches:
- bugfix-2.1.x
- bugfix-2.1.x
# Cannot be enabled on 2.1.x until it contains the unit test framework
#- 2.1.x
paths:
- 'Marlin/src/pins/*/**'
- "Marlin/src/pins/*/**"
push:
branches:
- bugfix-2.1.x
- bugfix-2.1.x
# Cannot be enabled on 2.1.x until it contains the unit test framework
#- 2.1.x
paths:
- 'Marlin/src/pins/*/**'
- "Marlin/src/pins/*/**"
jobs:
validate_pins_files:
@ -29,23 +29,23 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Check out the PR
uses: actions/checkout@v4
- name: Check out the PR
uses: actions/checkout@v4
- name: Cache pip
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Cache pip
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-validation-v1
restore-keys: |
${{ runner.os }}-pip-validation-
- name: Select Python 3.9
uses: actions/setup-python@v5
with:
python-version: '3.9'
architecture: 'x64'
- name: Select Python 3.9
uses: actions/setup-python@v5
with:
python-version: "3.9"
architecture: "x64"
- name: Validate all pins files
run: |
make validate-pins -j
- name: Validate all pins files
run: |
make validate-pins -j

5
.gitignore vendored
View file

@ -31,6 +31,11 @@ out-language/
*.gen
*.sublime-workspace
# npm
node_modules/
package.json
package-lock.json
# OS
applet/
.DS_Store

10
.prettierignore Normal file
View file

@ -0,0 +1,10 @@
# Prettier Ignore file
*.min.js
web-ui/
buildroot/share/PlatformIO/boards
buildroot/share/PlatformIO/variants
*.sublime-project
*.sublime-syntax
.github
.vscode
launch.json

View file

@ -8,6 +8,7 @@ help:
@echo "Tasks for local development:"
@echo "make marlin : Build Marlin for the configured board"
@echo "make format-pins -j : Reformat all pins files (-j for parallel execution)"
@echo "make validate-lines -j : Validate line endings, fails on trailing whitespace, etc."
@echo "make validate-pins -j : Validate all pins files, fails if any require reformatting"
@echo "make validate-boards -j : Validate boards.h and pins.h for standards compliance"
@echo "make tests-single-ci : Run a single test from inside the CI"
@ -17,7 +18,7 @@ help:
@echo "make tests-all-local-docker : Run all tests locally, using docker"
@echo "make unit-test-single-local : Run unit tests for a single config locally"
@echo "make unit-test-single-local-docker : Run unit tests for a single config locally, using docker"
@echo "make unit-test-all-local : Run all code tests locally"
@echo "make unit-test-all-local : Run all code tests locally"
@echo "make unit-test-all-local-docker : Run all code tests locally, using docker"
@echo "make setup-local-docker : Setup local docker using buildx"
@echo ""
@ -95,7 +96,7 @@ PINS := $(shell find Marlin/src/pins -mindepth 2 -name '*.h')
.PHONY: $(PINS) format-pins validate-pins
$(PINS): %:
@echo "Formatting $@"
@echo "Formatting pins $@"
@python $(SCRIPTS_DIR)/pinsformat.py $< $@
format-pins: $(PINS)
@ -104,6 +105,17 @@ validate-pins: format-pins
@echo "Validating pins files"
@git diff --exit-code || (git status && echo "\nError: Pins files are not formatted correctly. Run \"make format-pins\" to fix.\n" && exit 1)
.PHONY: format-lines validate-lines
format-lines:
@echo "Formatting all sources"
@python $(SCRIPTS_DIR)/linesformat.py buildroot
@python $(SCRIPTS_DIR)/linesformat.py Marlin
validate-lines:
@echo "Validating text formatting"
@npx prettier --check . --editorconfig --object-wrap preserve
BOARDS_FILE := Marlin/src/core/boards.h
.PHONY: validate-boards

View file

@ -129,6 +129,7 @@
// Name displayed in the LCD "Ready" message and Info menu
//#define CUSTOM_MACHINE_NAME "3D Printer"
//#define CONFIGURABLE_MACHINE_NAME // Add G-code M550 to set/report the machine name
// Printer's unique ID, used by some programs to differentiate between machines.
// Choose your own or use a service like https://www.uuidgenerator.net/version4
@ -147,9 +148,9 @@
* Options: A4988, A5984, DRV8825, LV8729, TB6560, TB6600, TMC2100,
* TMC2130, TMC2130_STANDALONE, TMC2160, TMC2160_STANDALONE,
* TMC2208, TMC2208_STANDALONE, TMC2209, TMC2209_STANDALONE,
* TMC2660, TMC2660_STANDALONE, TMC5130, TMC5130_STANDALONE,
* TMC5160, TMC5160_STANDALONE
* :['A4988', 'A5984', 'DRV8825', 'LV8729', 'TB6560', 'TB6600', 'TMC2100', 'TMC2130', 'TMC2130_STANDALONE', 'TMC2160', 'TMC2160_STANDALONE', 'TMC2208', 'TMC2208_STANDALONE', 'TMC2209', 'TMC2209_STANDALONE', 'TMC2660', 'TMC2660_STANDALONE', 'TMC5130', 'TMC5130_STANDALONE', 'TMC5160', 'TMC5160_STANDALONE']
* TMC2240, TMC2660, TMC2660_STANDALONE,
* TMC5130, TMC5130_STANDALONE, TMC5160, TMC5160_STANDALONE
* :['A4988', 'A5984', 'DRV8825', 'LV8729', 'TB6560', 'TB6600', 'TMC2100', 'TMC2130', 'TMC2130_STANDALONE', 'TMC2160', 'TMC2160_STANDALONE', 'TMC2208', 'TMC2208_STANDALONE', 'TMC2209', 'TMC2209_STANDALONE', 'TMC2240', 'TMC2660', 'TMC2660_STANDALONE', 'TMC5130', 'TMC5130_STANDALONE', 'TMC5160', 'TMC5160_STANDALONE']
*/
#define X_DRIVER_TYPE A4988
#define Y_DRIVER_TYPE A4988
@ -259,6 +260,7 @@
#define SWITCHING_NOZZLE_SERVO_ANGLES { 0, 90 } // A pair of angles for { E0, E1 }.
// For Dual Servo use two pairs: { { lower, raise }, { lower, raise } }
#define SWITCHING_NOZZLE_SERVO_DWELL 2500 // Dwell time to wait for servo to make physical move
#define SWITCHING_NOZZLE_LIFT_TO_PROBE // Lift toolheads out of the way while probing
#endif
// Switch nozzles by bumping the toolhead. Requires EVENT_GCODE_TOOLCHANGE_#.
@ -695,8 +697,9 @@
#define PID_K1 0.95 // Smoothing factor within any PID loop
#if ENABLED(PIDTEMP)
//#define MIN_POWER 0
//#define PID_DEBUG // Print PID debug data to the serial port. Use 'M303 D' to toggle activation.
//#define MIN_POWER 0 // Min power to improve PID stability (0..PID_MAX).
// Get the power from the temperature report ('M105' => @:nnn) and try P*2-20 to P*2-10.
//#define PID_DEBUG // Print PID debug data to the serial port. Use 'M303 D' to enable/disable.
//#define PID_PARAMS_PER_HOTEND // Use separate PID parameters for each extruder (useful for mismatched extruders)
// Set/get with G-code: M301 E[extruder number, 0-2]
@ -732,7 +735,12 @@
//#define MPC_AUTOTUNE_MENU // Add MPC auto-tuning to the "Advanced Settings" menu. (~350 bytes of flash)
#define MPC_MAX 255 // (0..255) Current to nozzle while MPC is active.
#define MPC_HEATER_POWER { 40.0f } // (W) Heat cartridge powers.
#define MPC_HEATER_POWER { 40.0f } // (W) Nominal heat cartridge powers.
//#define MPC_PTC // Hotend power changes with temperature (e.g., PTC heat cartridges).
#if ENABLED(MPC_PTC)
#define MPC_HEATER_ALPHA { 0.0028f } // Temperature coefficient of resistance of the heat cartridges.
#define MPC_HEATER_REFTEMP { 20 } // (°C) Reference temperature for MPC_HEATER_POWER and MPC_HEATER_ALPHA.
#endif
#define MPC_INCLUDE_FAN // Model the fan speed?
@ -764,6 +772,7 @@
#define MPC_TUNING_POS { X_CENTER, Y_CENTER, 1.0f } // (mm) M306 Autotuning position, ideally bed center at first layer height.
#define MPC_TUNING_END_Z 10.0f // (mm) M306 Autotuning final Z position.
//#define EVENT_GCODE_AFTER_MPC_TUNE "M84" // G-code to execute after MPC tune finished and Z raised.
#endif
//===========================================================================
@ -795,13 +804,14 @@
//#define PIDTEMPBED
#if ENABLED(PIDTEMPBED)
//#define MIN_BED_POWER 0
//#define PID_BED_DEBUG // Print Bed PID debug data to the serial port.
//#define MIN_BED_POWER 0 // Min power to improve PID stability (0..MAX_BED_POWER).
// Get the power from the temperature report ('M105' => B@:nnn) and try P*2-20 to P*2-10.
//#define PID_BED_DEBUG // Print Bed PID debug data to the serial port. Use 'M303 D' to enable/disable.
// 120V 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)
// from FOPDT model - kp=.39 Tp=405 Tdead=66, Tc set to 79.2, aggressive factor of .15 (vs .1, 1, 10)
#define DEFAULT_bedKp 10.00
#define DEFAULT_bedKi .023
#define DEFAULT_bedKp 10.00
#define DEFAULT_bedKi 0.023
#define DEFAULT_bedKd 305.4
// FIND YOUR OWN: "M303 E-1 C8 S90" to run autotune on the bed at 90 degreesC for 8 cycles.
@ -877,12 +887,12 @@
#define MAX_CHAMBER_POWER 255 // limits duty cycle to chamber heater; 255=full current
#if ENABLED(PIDTEMPCHAMBER)
#define MIN_CHAMBER_POWER 0
//#define PID_CHAMBER_DEBUG // Print Chamber PID debug data to the serial port.
//#define MIN_CHAMBER_POWER 0 // Min power to improve PID stability. (0..MAX_CHAMBER_POWER)
// Get the power from the temperature report ('M105' => C@:nnn) and try P*2-20 to P*2-10.
//#define PID_CHAMBER_DEBUG // Print Chamber PID debug data to the serial port. Use 'M303 D' to enable/disable.
// Lasko "MyHeat Personal Heater" (200w) modified with a Fotek SSR-10DA to control only the heating element
// and placed inside the small Creality printer enclosure tent.
//
#define DEFAULT_chamberKp 37.04
#define DEFAULT_chamberKi 1.40
#define DEFAULT_chamberKd 655.17
@ -896,7 +906,7 @@
#if ANY(PIDTEMP, PIDTEMPBED, PIDTEMPCHAMBER)
//#define PID_OPENLOOP // Puts PID in open loop. M104/M140 sets the output power from 0 to PID_MAX
//#define SLOW_PWM_HEATERS // PWM with very low frequency (roughly 0.125Hz=8s) and minimum state time of approximately 1s useful for heaters driven by a relay
#define PID_FUNCTIONAL_RANGE 10 // If the temperature difference between the target temperature and the actual temperature
#define PID_FUNCTIONAL_RANGE 20 // If the temperature difference between the target temperature and the actual temperature
// is more than PID_FUNCTIONAL_RANGE then the PID will be shut off and the heater will be set to min/max.
//#define PID_EDIT_MENU // Add PID editing to the "Advanced Settings" menu. (~700 bytes of flash)
@ -1024,9 +1034,6 @@
// Print surface diameter/2 minus unreachable space (avoid collisions with vertical towers).
#define PRINTABLE_RADIUS 140.0 // (mm)
// Maximum reachable area
#define DELTA_MAX_RADIUS 140.0 // (mm)
// Center-to-center distance of the holes in the diagonal push rods.
#define DELTA_DIAGONAL_ROD 250.0 // (mm)
@ -1539,6 +1546,20 @@
#define PROBE_DEPLOY_FEEDRATE (133*60) // (mm/min) Probe deploy speed
#define PROBE_STOW_FEEDRATE (133*60) // (mm/min) Probe stow speed
/**
* Magnetically Mounted Probe with a Servo mechanism
* Probe Deploy and Stow both follow the same basic sequence:
* - Rotate the SERVO to its Deployed angle
* - Perform XYZ moves to deploy or stow the PROBE
* - Rotate the SERVO to its Stowed angle
*/
//#define MAG_MOUNTED_PROBE_SERVO_NR 0 // Servo Number for this probe
#ifdef MAG_MOUNTED_PROBE_SERVO_NR
#define MAG_MOUNTED_PROBE_SERVO_ANGLES { 90, 0 } // Servo Angles for Deployed, Stowed
#define MAG_MOUNTED_PRE_DEPLOY { PROBE_DEPLOY_FEEDRATE, { 15, 160, 30 } } // Safe position for servo activation
#define MAG_MOUNTED_PRE_STOW { PROBE_DEPLOY_FEEDRATE, { 15, 160, 30 } } // Safe position for servo deactivation
#endif
#define MAG_MOUNTED_DEPLOY_1 { PROBE_DEPLOY_FEEDRATE, { 245, 114, 30 } } // Move to side Dock & Attach probe
#define MAG_MOUNTED_DEPLOY_2 { PROBE_DEPLOY_FEEDRATE, { 210, 114, 30 } } // Move probe off dock
#define MAG_MOUNTED_DEPLOY_3 { PROBE_DEPLOY_FEEDRATE, { 0, 0, 0 } } // Extra move if needed
@ -2022,8 +2043,11 @@
//#define FILAMENT_MOTION_SENSOR
#if ENABLED(FILAMENT_MOTION_SENSOR)
//#define FILAMENT_SWITCH_AND_MOTION
//#define FILAMENT_SWITCH_AND_MOTION // Define separate pins below to sense motion
#if ENABLED(FILAMENT_SWITCH_AND_MOTION)
#define FILAMENT_MOTION_DISTANCE_MM 3.0 // (mm) Missing distance required to trigger runout
#define NUM_MOTION_SENSORS 1 // Number of sensors, up to one per extruder. Define a FIL_MOTION#_PIN for each.
//#define FIL_MOTION1_PIN -1
@ -2059,7 +2083,7 @@
//#define FIL_MOTION8_STATE LOW
//#define FIL_MOTION8_PULLUP
//#define FIL_MOTION8_PULLDOWN
#endif
#endif // FILAMENT_SWITCH_AND_MOTION
#endif // FILAMENT_MOTION_SENSOR
#endif // FILAMENT_RUNOUT_DISTANCE_MM
#endif // FILAMENT_RUNOUT_SENSOR
@ -2269,7 +2293,7 @@
//===========================================================================
#define MESH_INSET 10 // Set Mesh bounds as an inset region of the bed
#define GRID_MAX_POINTS_X 3 // Don't use more than 7 points per axis, implementation limited.
#define GRID_MAX_POINTS_X 3
#define GRID_MAX_POINTS_Y GRID_MAX_POINTS_X
//#define MESH_G28_REST_ORIGIN // After homing all axes ('G28' or 'G28 XYZ') rest Z at Z_MIN_POS
@ -2905,13 +2929,15 @@
//
//#define MAKEBOARD_MINI_2_LINE_DISPLAY_1602
//
// ANET and Tronxy 20x4 Controller
//
//#define ZONESTAR_LCD // Requires ADC_KEYPAD_PIN to be assigned to an analog pin.
// This LCD is known to be susceptible to electrical interference
// which scrambles the display. Pressing any button clears it up.
// This is a LCD2004 display with 5 analog buttons.
/**
* ANET and Tronxy 20x4 Controller
* LCD2004 display with 5 analog buttons.
*
* NOTE: Requires ADC_KEYPAD_PIN to be assigned to an analog pin.
* This LCD is known to be susceptible to electrical interference which
* scrambles the display. Press any button to clear it up.
*/
//#define ZONESTAR_LCD
//
// Generic 16x2, 16x4, 20x2, or 20x4 character-based LCD.
@ -3099,7 +3125,7 @@
//
// FYSETC variant of the MINI12864 graphic controller with SD support
// https://wiki.fysetc.com/Mini12864_Panel/
// https://wiki.fysetc.com/docs/Mini12864Panel
//
//#define FYSETC_MINI_12864_X_X // Type C/D/E/F. No tunable RGB Backlight by default
//#define FYSETC_MINI_12864_1_2 // Type C/D/E/F. Simple RGB Backlight (always on)
@ -3273,7 +3299,7 @@
#endif
//
// Touch-screen LCD for Malyan M200/M300 printers
// LCD for Malyan M200/M300 printers
//
//#define MALYAN_LCD
@ -3495,6 +3521,11 @@
//#define DWIN_MARLINUI_PORTRAIT // MarlinUI (portrait orientation)
//#define DWIN_MARLINUI_LANDSCAPE // MarlinUI (landscape orientation)
#if ENABLED(DWIN_CREALITY_LCD)
//#define USE_STRING_HEADINGS // Use string headings for Creality UI instead of images
//#define USE_STRING_TITLES // Use string titles for Creality UI instead of images
#endif
//
// Touch Screen Settings
//
@ -3548,22 +3579,26 @@
// :[1,2,3,4,5,6,7,8]
//#define NUM_M106_FANS 1
// Use software PWM to drive the fan, as for the heaters. This uses a very low frequency
// which is not as annoying as with the hardware PWM. On the other hand, if this frequency
// is too low, you should also increment SOFT_PWM_SCALE.
/**
* Use software PWM to drive the fan, as for the heaters. This uses a very low frequency
* which is not as annoying as with the hardware PWM. On the other hand, if this frequency
* is too low, you should also increment SOFT_PWM_SCALE.
*/
//#define FAN_SOFT_PWM
// Incrementing this by 1 will double the software PWM frequency,
// affecting heaters, and the fan if FAN_SOFT_PWM is enabled.
// However, control resolution will be halved for each increment;
// at zero value, there are 128 effective control positions.
// :[0,1,2,3,4,5,6,7]
/**
* Incrementing this by 1 will double the software PWM frequency, affecting heaters, and
* the fan if FAN_SOFT_PWM is enabled. However, control resolution will be halved for each
* increment; at zero value, there are 128 effective control positions.
* :[0,1,2,3,4,5,6,7]
*/
#define SOFT_PWM_SCALE 0
// If SOFT_PWM_SCALE is set to a value higher than 0, dithering can
// be used to mitigate the associated resolution loss. If enabled,
// some of the PWM cycles are stretched so on average the desired
// duty cycle is attained.
/**
* If SOFT_PWM_SCALE is set to a value higher than 0, dithering can be used to mitigate the
* associated resolution loss. If enabled, some of the PWM cycles are stretched so on average
* the desired duty cycle is attained.
*/
//#define SOFT_PWM_DITHER
// @section extras
@ -3573,9 +3608,11 @@
// @section lights
// Temperature status LEDs that display the hotend and bed temperature.
// If all hotends, bed temperature, and target temperature are under 54C
// then the BLUE led is on. Otherwise the RED led is on. (1C hysteresis)
/**
* Temperature status LEDs that display the hotend and bed temperature.
* If all hotends, bed temperature, and target temperature are under 54C
* the BLUE led is on. Otherwise the RED led is on. (1C hysteresis)
*/
//#define TEMP_STAT_LEDS
// Support for BlinkM/CyzRgb

View file

@ -1081,11 +1081,26 @@
#define G34_MAX_GRADE 5 // (%) Maximum incline that G34 will handle
#define Z_STEPPER_ALIGN_ITERATIONS 5 // Number of iterations to apply during alignment
#define Z_STEPPER_ALIGN_ACC 0.02 // Stop iterating early if the accuracy is better than this
#define RESTORE_LEVELING_AFTER_G34 // Restore leveling after G34 is done?
// After G34, re-home Z (G28 Z) or just calculate it from the last probe heights?
// Re-homing might be more precise in reproducing the actual 'G28 Z' homing height, especially on an uneven bed.
#define HOME_AFTER_G34
#endif
/**
* Commands to execute at the start of G34 probing,
* after switching to the PROBING_TOOL.
*/
//#define EVENT_GCODE_BEFORE_G34 "M300 P440 S200"
/**
* Commands to execute at the end of G34 probing.
* Useful to retract or move the Z probe out of the way.
*/
//#define EVENT_GCODE_AFTER_G34 "G1 Z10 F12000\nG1 X15 Y330\nG1 Z0.5\nG1 Z10"
#endif // Z_STEPPER_AUTO_ALIGN
/**
* Assisted Tramming
@ -1128,47 +1143,73 @@
/**
* Fixed-time-based Motion Control -- BETA FEATURE
* Enable/disable and set parameters with G-code M493.
* Enable/disable and set parameters with G-code M493 and M494.
* See ft_types.h for named values used by FTM options.
*/
//#define FT_MOTION
#if ENABLED(FT_MOTION)
//#define FTM_IS_DEFAULT_MOTION // Use FT Motion as the factory default?
//#define FTM_IS_DEFAULT_MOTION // Use FT Motion as the factory default?
//#define FT_MOTION_MENU // Provide a MarlinUI menu to set M493 and M494 parameters
#define FTM_DEFAULT_DYNFREQ_MODE dynFreqMode_DISABLED // Default mode of dynamic frequency calculation. (DISABLED, Z_BASED, MASS_BASED)
#define FTM_LINEAR_ADV_DEFAULT_ENA false // Default linear advance enable (true) or disable (false)
#define FTM_LINEAR_ADV_DEFAULT_K 0.0f // Default linear advance gain. (Acceleration-based scaling factor.)
#define FTM_DEFAULT_SHAPER_X ftMotionShaper_NONE // Default shaper mode on X axis (NONE, ZV, ZVD, ZVDD, ZVDDD, EI, 2HEI, 3HEI, MZV)
#define FTM_SHAPING_DEFAULT_FREQ_X 37.0f // (Hz) Default peak frequency used by input shapers
#define FTM_SHAPING_ZETA_X 0.1f // Zeta used by input shapers for X axis
#define FTM_SHAPING_V_TOL_X 0.05f // Vibration tolerance used by EI input shapers for X axis
#define FTM_DEFAULT_SHAPER_Y ftMotionShaper_NONE // Default shaper mode on Y axis
#define FTM_SHAPING_DEFAULT_FREQ_X 37.0f // (Hz) Default peak frequency used by input shapers
#define FTM_SHAPING_DEFAULT_FREQ_Y 37.0f // (Hz) Default peak frequency used by input shapers
#define FTM_LINEAR_ADV_DEFAULT_ENA false // Default linear advance enable (true) or disable (false)
#define FTM_LINEAR_ADV_DEFAULT_K 0.0f // Default linear advance gain. (Acceleration-based scaling factor.)
#define FTM_SHAPING_ZETA_X 0.1f // Zeta used by input shapers for X axis
#define FTM_SHAPING_ZETA_Y 0.1f // Zeta used by input shapers for Y axis
#define FTM_SHAPING_DEFAULT_FREQ_Y 37.0f // (Hz) Default peak frequency used by input shapers
#define FTM_SHAPING_ZETA_Y 0.1f // Zeta used by input shapers for Y axis
#define FTM_SHAPING_V_TOL_Y 0.05f // Vibration tolerance used by EI input shapers for Y axis
#define FTM_SHAPING_V_TOL_X 0.05f // Vibration tolerance used by EI input shapers for X axis
#define FTM_SHAPING_V_TOL_Y 0.05f // Vibration tolerance used by EI input shapers for Y axis
//#define FTM_SHAPER_Z // Include Z shaping support
#define FTM_DEFAULT_SHAPER_Z ftMotionShaper_NONE // Default shaper mode on Z axis
#define FTM_SHAPING_DEFAULT_FREQ_Z 21.0f // (Hz) Default peak frequency used by input shapers
#define FTM_SHAPING_ZETA_Z 0.03f // Zeta used by input shapers for Z axis
#define FTM_SHAPING_V_TOL_Z 0.05f // Vibration tolerance used by EI input shapers for Z axis
//#define FT_MOTION_MENU // Provide a MarlinUI menu to set M493 parameters
//#define FTM_SHAPER_E // Include E shaping support
// Required to synchronise extruder with XYZ (better quality)
#define FTM_DEFAULT_SHAPER_E ftMotionShaper_NONE // Default shaper mode on Extruder axis
#define FTM_SHAPING_DEFAULT_FREQ_E 21.0f // (Hz) Default peak frequency used by input shapers
#define FTM_SHAPING_ZETA_E 0.03f // Zeta used by input shapers for E axis
#define FTM_SHAPING_V_TOL_E 0.05f // Vibration tolerance used by EI input shapers for E axis
//#define FTM_SMOOTHING // Smoothing can reduce artifacts and make steppers quieter
// on sharp corners, but too much will round corners.
#if ENABLED(FTM_SMOOTHING)
#define FTM_MAX_SMOOTHING_TIME 0.10f // Maximum smoothing time (seconds), higher consumes more RAM.
// Increase smoothing time to reduce jerky motion, ghosting and noises.
#define FTM_SMOOTHING_TIME_X 0.00f // (s) Smoothing time for X axis. Zero means disabled.
#define FTM_SMOOTHING_TIME_Y 0.00f // (s) Smoothing time for Y axis
#define FTM_SMOOTHING_TIME_Z 0.00f // (s) Smoothing time for Z axis
#define FTM_SMOOTHING_TIME_E 0.02f // (s) Smoothing time for E axis. Prevents noise/skipping from LA by
// smoothing acceleration peaks, which may also smooth curved surfaces.
#endif
/**
* Advanced configuration
*/
#define FTM_UNIFIED_BWS // DON'T DISABLE unless you use Ulendo FBS (not implemented)
#define FTM_UNIFIED_BWS // DON'T DISABLE unless you use Ulendo FBS (not implemented)
#if ENABLED(FTM_UNIFIED_BWS)
#define FTM_BW_SIZE 100 // Unified Window and Batch size with a ratio of 2
#define FTM_BW_SIZE 100 // Unified Window and Batch size with a ratio of 2
#else
#define FTM_WINDOW_SIZE 200 // Custom Window size for trajectory generation needed by Ulendo FBS
#define FTM_BATCH_SIZE 100 // Custom Batch size for trajectory generation needed by Ulendo FBS
#define FTM_WINDOW_SIZE 200 // Custom Window size for trajectory generation needed by Ulendo FBS
#define FTM_BATCH_SIZE 100 // Custom Batch size for trajectory generation needed by Ulendo FBS
#endif
#define FTM_FS 1000 // (Hz) Frequency for trajectory generation. (Reciprocal of FTM_TS)
#define FTM_TS 0.001f // (s) Time step for trajectory generation. (Reciprocal of FTM_FS)
#define FTM_FS 1000 // (Hz) Frequency for trajectory generation. (Reciprocal of FTM_TS)
#if DISABLED(COREXY)
#define FTM_STEPPER_FS 20000 // (Hz) Frequency for stepper I/O update
#define FTM_STEPPER_FS 20000 // (Hz) Frequency for stepper I/O update
// Use this to adjust the time required to consume the command buffer.
// Try increasing this value if stepper motion is choppy.
#define FTM_STEPPERCMD_BUFF_SIZE 3000 // Size of the stepper command buffers
#define FTM_STEPPERCMD_BUFF_SIZE 3000 // Size of the stepper command buffers
#else
// CoreXY motion needs a larger buffer size. These values are based on our testing.
@ -1176,19 +1217,8 @@
#define FTM_STEPPERCMD_BUFF_SIZE 6000
#endif
#define FTM_STEPS_PER_UNIT_TIME (FTM_STEPPER_FS / FTM_FS) // Interpolated stepper commands per unit time
#define FTM_CTS_COMPARE_VAL (FTM_STEPS_PER_UNIT_TIME / 2) // Comparison value used in interpolation algorithm
#define FTM_MIN_TICKS ((STEPPER_TIMER_RATE) / (FTM_STEPPER_FS)) // Minimum stepper ticks between steps
#define FTM_MIN_SHAPE_FREQ 10 // Minimum shaping frequency
#define FTM_RATIO (FTM_FS / FTM_MIN_SHAPE_FREQ) // Factor for use in FTM_ZMAX. DON'T CHANGE.
#define FTM_ZMAX (FTM_RATIO * 2) // Maximum delays for shaping functions (even numbers only!)
// Calculate as:
// ZV : FTM_RATIO / 2
// ZVD, MZV : FTM_RATIO
// 2HEI : FTM_RATIO * 3 / 2
// 3HEI : FTM_RATIO * 2
#endif
#define FTM_MIN_SHAPE_FREQ 10 // (Hz) Minimum shaping frequency, lower consumes more RAM
#endif // FT_MOTION
/**
* Input Shaping
@ -1342,20 +1372,20 @@
//#define CALIBRATION_SCRIPT_PRE "M117 Starting Auto-Calibration\nT0\nG28\nG12\nM117 Calibrating..."
//#define CALIBRATION_SCRIPT_POST "M500\nM117 Calibration data saved"
#define CALIBRATION_FEEDRATE_SLOW 60 // mm/min
#define CALIBRATION_FEEDRATE_FAST 1200 // mm/min
#define CALIBRATION_FEEDRATE_TRAVEL 3000 // mm/min
#define CALIBRATION_FEEDRATE_SLOW 60 // (mm/min)
#define CALIBRATION_FEEDRATE_FAST 1200 // (mm/min)
#define CALIBRATION_FEEDRATE_TRAVEL 3000 // (mm/min)
// The following parameters refer to the conical section of the nozzle tip.
#define CALIBRATION_NOZZLE_TIP_HEIGHT 1.0 // mm
#define CALIBRATION_NOZZLE_OUTER_DIAMETER 2.0 // mm
#define CALIBRATION_NOZZLE_TIP_HEIGHT 1.0 // (mm)
#define CALIBRATION_NOZZLE_OUTER_DIAMETER 2.0 // (mm)
// Uncomment to enable reporting (required for "G425 V", but consumes flash).
//#define CALIBRATION_REPORTING
// The true location and dimension the cube/bolt/washer on the bed.
#define CALIBRATION_OBJECT_CENTER { 264.0, -22.0, -2.0 } // mm
#define CALIBRATION_OBJECT_DIMENSIONS { 10.0, 10.0, 10.0 } // mm
#define CALIBRATION_OBJECT_CENTER { 264.0, -22.0, -2.0 } // (mm)
#define CALIBRATION_OBJECT_DIMENSIONS { 10.0, 10.0, 10.0 } // (mm)
// Comment out any sides which are unreachable by the probe. For best
// auto-calibration results, all sides must be reachable.
@ -1394,7 +1424,7 @@
* Multi-stepping sends steps in bursts to reduce MCU usage for high step-rates.
* This allows higher feedrates than the MCU could otherwise support.
*/
#define MULTISTEPPING_LIMIT 16 //: [1, 2, 4, 8, 16, 32, 64, 128]
#define MULTISTEPPING_LIMIT 16 // :[1, 2, 4, 8, 16, 32, 64, 128]
/**
* Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies
@ -1419,24 +1449,24 @@
#define MICROSTEP_MODES { 16, 16, 16, 16, 16, 16 } // [1,2,4,8,16]
/**
* @section stepper motor current
* @section stepper motor current
*
* Some boards have a means of setting the stepper motor current via firmware.
* Some boards have a means of setting the stepper motor current via firmware.
*
* The power on motor currents are set by:
* PWM_MOTOR_CURRENT - used by MINIRAMBO & ULTIMAIN_2
* known compatible chips: A4982
* DIGIPOT_MOTOR_CURRENT - used by BQ_ZUM_MEGA_3D, RAMBO & SCOOVO_X9H
* known compatible chips: AD5206
* DAC_MOTOR_CURRENT_DEFAULT - used by PRINTRBOARD_REVF & RIGIDBOARD_V2
* known compatible chips: MCP4728
* DIGIPOT_I2C_MOTOR_CURRENTS - used by 5DPRINT, AZTEEG_X3_PRO, AZTEEG_X5_MINI_WIFI, MIGHTYBOARD_REVE
* known compatible chips: MCP4451, MCP4018
* The power on motor currents are set by:
* PWM_MOTOR_CURRENT - used by MINIRAMBO & ULTIMAIN_2
* known compatible chips: A4982
* DIGIPOT_MOTOR_CURRENT - used by BQ_ZUM_MEGA_3D, RAMBO & SCOOVO_X9H
* known compatible chips: AD5206
* DAC_MOTOR_CURRENT_DEFAULT - used by PRINTRBOARD_REVF & RIGIDBOARD_V2
* known compatible chips: MCP4728
* DIGIPOT_I2C_MOTOR_CURRENTS - used by 5DPRINT, AZTEEG_X3_PRO, AZTEEG_X5_MINI_WIFI, MIGHTYBOARD_REVE
* known compatible chips: MCP4451, MCP4018
*
* Motor currents can also be set by M907 - M910 and by the LCD.
* M907 - applies to all.
* M908 - BQ_ZUM_MEGA_3D, RAMBO, PRINTRBOARD_REVF, RIGIDBOARD_V2 & SCOOVO_X9H
* M909, M910 & LCD - only PRINTRBOARD_REVF & RIGIDBOARD_V2
* Motor currents can also be set by M907 - M910 and by the LCD.
* M907 - applies to all.
* M908 - BQ_ZUM_MEGA_3D, RAMBO, PRINTRBOARD_REVF, RIGIDBOARD_V2 & SCOOVO_X9H
* M909, M910 & LCD - only PRINTRBOARD_REVF & RIGIDBOARD_V2
*/
//#define PWM_MOTOR_CURRENT { 1300, 1300, 1250 } // Values in milliamps
//#define DIGIPOT_MOTOR_CURRENT { 135,135,135,135,135 } // Values 0-255 (RAMBO 135 = ~0.75A, 185 = ~1A)
@ -1619,6 +1649,10 @@
//#define SOUND_MENU_ITEM // Add a mute option to the LCD menu
#define SOUND_ON_DEFAULT // Buzzer/speaker default enabled state
#if ENABLED(U8GLIB_SSD1309)
//#define LCD_DOUBLE_BUFFER // Optimize display updates. Costs ~1K of SRAM.
#endif
#if HAS_WIRED_LCD
//#define DOUBLE_LCD_FRAMERATE // Not recommended for slow boards.
#endif
@ -1669,11 +1703,12 @@
#endif // HAS_DISPLAY
#if HAS_FEEDRATE_EDIT
// Some displays offer Feedrate / Flow editing.
#if ANY(HAS_MARLINUI_MENU, DWIN_CREALITY_LCD, DWIN_LCD_PROUI, MALYAN_LCD, TOUCH_SCREEN, ULTIPANEL_FEEDMULTIPLY)
#define SPEED_EDIT_MIN 10 // (%) Feedrate percentage edit range minimum
#define SPEED_EDIT_MAX 999 // (%) Feedrate percentage edit range maximum
#endif
#if HAS_FLOW_EDIT
#if ANY(HAS_MARLINUI_MENU, DWIN_CREALITY_LCD, DWIN_LCD_PROUI, MALYAN_LCD, TOUCH_SCREEN)
#define FLOW_EDIT_MIN 10 // (%) Flow percentage edit range minimum
#define FLOW_EDIT_MAX 999 // (%) Flow percentage edit range maximum
#endif
@ -1934,6 +1969,9 @@
//#define CUSTOM_FIRMWARE_UPLOAD
#endif
// "Over-the-air" Firmware Update with M936 - Required to set EEPROM flag
//#define OTA_FIRMWARE_UPDATE
/**
* Set this option to one of the following (or the board's defaults apply):
*
@ -1956,8 +1994,8 @@
#if ENABLED(MULTI_VOLUME)
#define VOLUME_SD_ONBOARD
#define VOLUME_USB_FLASH_DRIVE
#define DEFAULT_VOLUME SV_SD_ONBOARD
#define DEFAULT_SHARED_VOLUME SV_USB_FLASH_DRIVE
#define DEFAULT_VOLUME SD_ONBOARD // :[ 'SD_ONBOARD', 'USB_FLASH_DRIVE' ]
#define DEFAULT_SHARED_VOLUME USB_FLASH_DRIVE // :[ 'SD_ONBOARD', 'USB_FLASH_DRIVE' ]
#endif
#endif // HAS_MEDIA
@ -2227,7 +2265,7 @@
// Developer menu (accessed by touching "About Printer" copyright text)
//#define TOUCH_UI_DEVELOPER_MENU
#endif
#endif // TOUCH_UI_FTDI_EVE
//
// Classic UI Options
@ -2264,6 +2302,8 @@
#define ADC_BUTTON_DEBOUNCE_DELAY 16 // (count) Increase if buttons bounce or repeat too fast
#endif
//#define FAST_BUTTON_POLLING // Poll buttons at ~1kHz on 8-bit AVR. Set to 'false' for slow polling on 32-bit.
// @section safety
/**
@ -2346,6 +2386,24 @@
//#define ADVANCE_K_EXTRA // Add a second linear advance constant, configurable with M900 L.
//#define LA_DEBUG // Print debug information to serial during operation. Disable for production use.
//#define EXPERIMENTAL_I2S_LA // Allow I2S_STEPPER_STREAM to be used with LA. Performance degrades as the LA step rate reaches ~20kHz.
//#define SMOOTH_LIN_ADVANCE // Remove limits on acceleration by gradual increase of nozzle pressure
#if ENABLED(SMOOTH_LIN_ADVANCE)
/**
* ADVANCE_TAU is also the time ahead that the smoother needs to look
* into the planner, so the planner needs to have enough blocks loaded.
* For k=0.04 at 10k acceleration and an "Orbiter 2" extruder it can be as low as 0.0075.
* Adjust by lowering the value until you observe the extruder skipping, then raise slightly.
* Higher k and higher XY acceleration may require larger ADVANCE_TAU to avoid skipping steps.
*/
#if ENABLED(DISTINCT_E_FACTORS)
#define ADVANCE_TAU { 0.02 } // (s) Smoothing time to reduce extruder acceleration, per extruder
#else
#define ADVANCE_TAU 0.02 // (s) Smoothing time to reduce extruder acceleration
#endif
#define SMOOTH_LIN_ADV_HZ 1000 // (Hz) How often to update extruder speed
#define INPUT_SHAPING_E_SYNC // Synchronize the extruder-shaped XY axes (to increase precision)
#endif
#endif
/**
@ -2356,6 +2414,9 @@
* For better results also enable ADAPTIVE_STEP_SMOOTHING.
*/
//#define NONLINEAR_EXTRUSION
#if ENABLED(NONLINEAR_EXTRUSION)
//#define NONLINEAR_EXTRUSION_DEFAULT_ON // Enable if NLE should be ON by default
#endif
// @section leveling
@ -2634,19 +2695,23 @@
#define MAX_CMD_SIZE 96
#define BUFSIZE 4
// Transmission to Host Buffer Size
// To save 386 bytes of flash (and TX_BUFFER_SIZE+3 bytes of RAM) set to 0.
// To buffer a simple "ok" you need 4 bytes.
// For ADVANCED_OK (M105) you need 32 bytes.
// For debug-echo: 128 bytes for the optimal speed.
// Other output doesn't need to be that speedy.
// :[0, 2, 4, 8, 16, 32, 64, 128, 256]
/**
* Host Transmit Buffer Size
* - Costs 386 bytes of flash and TX_BUFFER_SIZE+3 bytes of SRAM (if not 0).
* - 4 bytes required to buffer a simple "ok".
* - 32 bytes for ADVANCED_OK (M105).
* - 128 bytes for the optimal speed of 'debug-echo:'
* - Other output doesn't need to be that speedy.
* :[0, 2, 4, 8, 16, 32, 64, 128, 256]
*/
#define TX_BUFFER_SIZE 0
// Host Receive Buffer Size
// Without XON/XOFF flow control (see SERIAL_XON_XOFF below) 32 bytes should be enough.
// To use flow control, set this buffer size to at least 1024 bytes.
// :[0, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048]
/**
* Host Receive Buffer Size
* Without XON/XOFF flow control (see SERIAL_XON_XOFF below) 32 bytes should be enough.
* To use flow control, set this buffer size to at least 1024 bytes.
* :[0, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048]
*/
//#define RX_BUFFER_SIZE 1024
#if RX_BUFFER_SIZE >= 1024
@ -2965,7 +3030,7 @@
/**
* Trinamic Smart Drivers
*
* To use TMC2130, TMC2160, TMC2660, TMC5130, TMC5160 stepper drivers in SPI mode:
* To use TMC2130, TMC2160, TMC2240, TMC2660, TMC5130, TMC5160 stepper drivers in SPI mode:
* - Connect your SPI pins to the Hardware SPI interface on the board.
* Some boards have simple jumper connections! See your board's documentation.
* - Define the required Stepper CS pins in your `pins_MYBOARD.h` file.
@ -2987,12 +3052,22 @@
#define HOLD_MULTIPLIER 0.5 // Scales down the holding current from run current
//#define EDITABLE_HOMING_CURRENT // Add a G-code and menu to modify the Homing Current
/**
* Interpolate microsteps to 256
* Override for each driver with <driver>_INTERPOLATE settings below
*/
#define INTERPOLATE true
#if HAS_DRIVER(TMC2240)
#define TMC2240_RREF 12000 // (Ω) 12000 .. 60000. (FLY TMC2240 = 12300)
// Max Current. Lower for more internal resolution. Raise to run cooler.
#define TMC2240_CURRENT_RANGE 1 // :{ 0:'RMS=690mA PEAK=1A', 1:'RMS=1410mA PEAK=2A', 2:'RMS=2120mA PEAK=3A', 3:'RMS=2110mA PEAK=3A' }
// Slope Control: Lower is more silent. Higher runs cooler.
#define TMC2240_SLOPE_CONTROL 0 // :{ 0:'100V/µs', 1:'200V/µs', 2:'400V/µs', 3:'800V/µs' }
#endif
#if AXIS_IS_TMC_CONFIG(X)
#define X_CURRENT 800 // (mA) RMS current. Multiply by 1.414 for peak current.
#define X_CURRENT_HOME X_CURRENT // (mA) RMS current for homing. (Typically lower than *_CURRENT.)
@ -3215,7 +3290,7 @@
// @section tmc/spi
/**
* Override default SPI pins for TMC2130, TMC2160, TMC2660, TMC5130 and TMC5160 drivers here.
* Override default SPI pins for TMC2130, TMC2160, TMC2240, TMC2660, TMC5130 and TMC5160 drivers here.
* The default pins can be found in your board's pins file.
*/
//#define X_CS_PIN -1
@ -3242,7 +3317,7 @@
//#define E7_CS_PIN -1
/**
* Software option for SPI driven drivers (TMC2130, TMC2160, TMC2660, TMC5130 and TMC5160).
* Software option for SPI driven drivers (TMC2130, TMC2160, TMC2240, TMC2660, TMC5130 and TMC5160).
* The default SW SPI pins are defined the respective pins files,
* but you can override or define them here.
*/
@ -3301,7 +3376,7 @@
// @section tmc/stealthchop
/**
* TMC2130, TMC2160, TMC2208, TMC2209, TMC5130 and TMC5160 only
* TMC2130, TMC2160, TMC2208, TMC2209, TMC2240, TMC5130 and TMC5160 only
* Use Trinamic's ultra quiet stepping mode.
* When disabled, Marlin will use spreadCycle stepping mode.
*/
@ -3380,7 +3455,7 @@
// @section tmc/hybrid
/**
* TMC2130, TMC2160, TMC2208, TMC2209, TMC5130 and TMC5160 only
* TMC2130, TMC2160, TMC2208, TMC2209, TMC2240, TMC5130 and TMC5160 only
* The driver will switch to spreadCycle when stepper speed is over HYBRID_THRESHOLD.
* This mode allows for faster movements at the expense of higher noise levels.
* STEALTHCHOP_(XY|Z|E) must be enabled to use HYBRID_THRESHOLD.
@ -3414,20 +3489,20 @@
/**
* Use StallGuard to home / probe X, Y, Z.
*
* TMC2130, TMC2160, TMC2209, TMC2660, TMC5130, and TMC5160 only
* TMC2130, TMC2160, TMC2209, TMC2240, TMC2660, TMC5130, and TMC5160 only
* Connect the stepper driver's DIAG1 pin to the X/Y endstop pin.
* X, Y, and Z homing will always be done in spreadCycle mode.
*
* X/Y/Z_STALL_SENSITIVITY is the default stall threshold.
* Use M914 X Y Z to set the stall threshold at runtime:
*
* Sensitivity TMC2209 Others
* HIGHEST 255 -64 (Too sensitive => False positive)
* LOWEST 0 63 (Too insensitive => No trigger)
* Sensitivity TMC2209 Others
* HIGHEST 255 -64 (Too sensitive => False positive)
* LOWEST 0 63 (Too insensitive => No trigger)
*
* It is recommended to set HOMING_BUMP_MM to { 0, 0, 0 }.
*
* SPI_ENDSTOPS *** TMC2130/TMC5160 Only ***
* SPI_ENDSTOPS *** TMC2130, TMC2240, and TMC5160 Only ***
* Poll the driver through SPI to determine load when homing.
* Removes the need for a wire from DIAG1 to an endstop pin.
*
@ -3455,8 +3530,9 @@
//#define U_STALL_SENSITIVITY 8
//#define V_STALL_SENSITIVITY 8
//#define W_STALL_SENSITIVITY 8
//#define SPI_ENDSTOPS // TMC2130/TMC5160 only
//#define SPI_ENDSTOPS // TMC2130, TMC2240, and TMC5160
//#define IMPROVE_HOMING_RELIABILITY
//#define SENSORLESS_STALLGUARD_DELAY 0 // (ms) Delay to allow drivers to settle
#endif
// @section tmc/config
@ -3672,6 +3748,8 @@
#define SPEED_POWER_MIN 5000 // (RPM)
#define SPEED_POWER_MAX 30000 // (RPM) SuperPID router controller 0 - 30,000 RPM
#define SPEED_POWER_STARTUP 25000 // (RPM) M3/M4 speed/power default (with no arguments)
//#define DEFAULT_ACCELERATION_SPINDLE 1000 // (°/s/s) Default spindle acceleration (speed change with time)
#endif
#else
@ -3913,7 +3991,7 @@
/**
* Extra options for the M114 "Current Position" report
*/
//#define M114_DETAIL // Use 'M114` for details to check planner calculations
//#define M114_DETAIL // Use 'M114 D' 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.
@ -3942,7 +4020,7 @@
#endif
/**
* M115 - Report capabilites. Disable to save ~1150 bytes of flash.
* M115 - Report capabilities. Disable to save ~1150 bytes of flash.
* Some hosts (and serial TFT displays) rely on this feature.
*/
#define CAPABILITIES_REPORT
@ -3960,7 +4038,6 @@
* Spend 28 bytes of SRAM to optimize the G-code parser
*/
#define FASTER_GCODE_PARSER
#if ENABLED(FASTER_GCODE_PARSER)
//#define GCODE_QUOTED_STRINGS // Support for quoted string parameters
#endif

View file

@ -127,9 +127,9 @@ NEOPIXEL ?= 0
# on GCC versions:
# https://www.avrfreaks.net/comment/1789106#comment-1789106
CC_MAJ:=$(shell $(CC) -dM -E - < /dev/null | grep __GNUC__ | cut -f3 -d\ )
CC_MIN:=$(shell $(CC) -dM -E - < /dev/null | grep __GNUC_MINOR__ | cut -f3 -d\ )
CC_PATCHLEVEL:=$(shell $(CC) -dM -E - < /dev/null | grep __GNUC_PATCHLEVEL__ | cut -f3 -d\ )
CC_MAJ:=$(shell $(CC) -dM -E - < /dev/null | grep __GNUC__ | cut -f3 -d' ' )
CC_MIN:=$(shell $(CC) -dM -E - < /dev/null | grep __GNUC_MINOR__ | cut -f3 -d' ' )
CC_PATCHLEVEL:=$(shell $(CC) -dM -E - < /dev/null | grep __GNUC_PATCHLEVEL__ | cut -f3 -d' ' )
CC_VER:=$(shell echo $$(( $(CC_MAJ) * 10000 + $(CC_MIN) * 100 + $(CC_PATCHLEVEL) )))
ifeq ($(shell test $(CC_VER) -lt 40901 && echo 1),1)
$(warning This GCC version $(CC_VER) is likely broken. Enabling relocation workaround.)
@ -338,7 +338,8 @@ else ifeq ($(HARDWARE_MOTHERBOARD),1164)
else ifeq ($(HARDWARE_MOTHERBOARD),1165)
# XTLW MFF V2.0
else ifeq ($(HARDWARE_MOTHERBOARD),1166)
# E3D Rumba BigBox
else ifeq ($(HARDWARE_MOTHERBOARD),1167)
#
# RAMBo and derivatives
@ -798,10 +799,10 @@ endif
ifeq ($(TMC), 1)
LIB_CXXSRC += TMCStepper.cpp COOLCONF.cpp DRV_STATUS.cpp IHOLD_IRUN.cpp \
CHOPCONF.cpp GCONF.cpp PWMCONF.cpp DRV_CONF.cpp DRVCONF.cpp DRVCTRL.cpp \
DRVSTATUS.cpp ENCMODE.cpp RAMP_STAT.cpp SGCSCONF.cpp SHORT_CONF.cpp \
SMARTEN.cpp SW_MODE.cpp SW_SPI.cpp TMC2130Stepper.cpp TMC2208Stepper.cpp \
TMC2209Stepper.cpp TMC2660Stepper.cpp TMC5130Stepper.cpp TMC5160Stepper.cpp
CHOPCONF.cpp GCONF.cpp PWMCONF.cpp DRV_CONF.cpp DRVCONF.cpp DRVCTRL.cpp DRVSTATUS.cpp \
GLOBAL_SCALER.cpp SLAVECONF.cpp IOIN.cpp ENCMODE.cpp RAMP_STAT.cpp SGCSCONF.cpp \
SHORT_CONF.cpp SMARTEN.cpp SW_MODE.cpp SW_SPI.cpp TMC2130Stepper.cpp TMC2208Stepper.cpp \
TMC2209Stepper.cpp TMC2240Stepper.cpp TMC2660Stepper.cpp TMC5130Stepper.cpp TMC5160Stepper.cpp
endif
ifeq ($(RELOC_WORKAROUND), 1)
@ -868,8 +869,8 @@ else ifeq ($(HARDWARE_VARIANT), archim)
endif
# Add all the source directories as include directories too
CINCS = ${addprefix -I ,${VPATH}}
CXXINCS = ${addprefix -I ,${VPATH}}
CINCS = ${addprefix -I, ${VPATH}}
CXXINCS = ${addprefix -I, ${VPATH}}
# Silence warnings for library code (won't work for .h files, unfortunately)
LIBWARN = -w -Wno-packed-bitfield-compat

View file

@ -41,7 +41,7 @@
* here we define this default string as the date where the latest release
* version was tagged.
*/
//#define STRING_DISTRIBUTION_DATE "2025-03-14"
//#define STRING_DISTRIBUTION_DATE "2025-09-28"
/**
* The protocol for communication to the host. Protocol indicates communication

View file

@ -204,7 +204,7 @@ public:
static void isr_on() { sei(); }
static void isr_off() { cli(); }
static void delay_ms(const int ms) { _delay_ms(ms); }
static void delay_ms(const int ms) { delay(ms); }
// Tasks, called from idle()
static void idletask() {}

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_t hz, const float dca, const float dcb, const float dcc) {
uint16_t set_pwm_frequency_hz(const float 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

@ -363,8 +363,11 @@
#define AIO7_PWM 0
#define AIO7_DDR DDRF
//-- Begin not supported by Teensyduino
//-- don't use Arduino functions on these pins pinMode/digitalWrite/etc
//-- 46-47 are not supported by Teensyduino
//-- Don't use Arduino functions (pinMode, digitalWrite, etc.) on these pins
#define PIN_E2 46
#define PIN_E3 47
#define DIO46_PIN PINE2
#define DIO46_RPORT PINE
#define DIO46_WPORT PORTE
@ -377,10 +380,7 @@
#define DIO47_PWM 0
#define DIO47_DDR DDRE
#define TEENSY_E2 46
#define TEENSY_E3 47
//-- end not supported by Teensyduino
//--
#undef PA0
#define PA0_PIN PINA0

View file

@ -377,16 +377,16 @@ void printPinPort(const pin_t pin) { // print port number
uint8_t x;
SERIAL_ECHOPGM(" Port: ");
#if AVR_AT90USB1286_FAMILY
x = (pin == 46 || pin == 47) ? 'E' : digitalPinToPort_DEBUG(pin) + 64;
x = (pin == PIN_E2 || pin == PIN_E3) ? 'E' : 'A' + digitalPinToPort_DEBUG(pin) - 1;
#else
x = digitalPinToPort_DEBUG(pin) + 64;
x = 'A' + digitalPinToPort_DEBUG(pin) - 1;
#endif
SERIAL_CHAR(x);
#if AVR_AT90USB1286_FAMILY
if (pin == 46)
if (pin == PIN_E2)
x = '2';
else if (pin == 47)
else if (pin == PIN_E3)
x = '3';
else {
uint8_t temp = digitalPinToBitMask_DEBUG(pin);

View file

@ -48,92 +48,92 @@
const uint8_t PROGMEM digital_pin_to_port_PGM_plus_70[] = {
// PORTLIST
// ------------------------
PE , // PE 0 ** 0 ** USART0_RX
PE , // PE 1 ** 1 ** USART0_TX
PE , // PE 4 ** 2 ** PWM2
PE , // PE 5 ** 3 ** PWM3
PG , // PG 5 ** 4 ** PWM4
PE , // PE 3 ** 5 ** PWM5
PH , // PH 3 ** 6 ** PWM6
PH , // PH 4 ** 7 ** PWM7
PH , // PH 5 ** 8 ** PWM8
PH , // PH 6 ** 9 ** PWM9
PB , // PB 4 ** 10 ** PWM10
PB , // PB 5 ** 11 ** PWM11
PB , // PB 6 ** 12 ** PWM12
PB , // PB 7 ** 13 ** PWM13
PJ , // PJ 1 ** 14 ** USART3_TX
PJ , // PJ 0 ** 15 ** USART3_RX
PH , // PH 1 ** 16 ** USART2_TX
PH , // PH 0 ** 17 ** USART2_RX
PD , // PD 3 ** 18 ** USART1_TX
PD , // PD 2 ** 19 ** USART1_RX
PD , // PD 1 ** 20 ** I2C_SDA
PD , // PD 0 ** 21 ** I2C_SCL
PA , // PA 0 ** 22 ** D22
PA , // PA 1 ** 23 ** D23
PA , // PA 2 ** 24 ** D24
PA , // PA 3 ** 25 ** D25
PA , // PA 4 ** 26 ** D26
PA , // PA 5 ** 27 ** D27
PA , // PA 6 ** 28 ** D28
PA , // PA 7 ** 29 ** D29
PC , // PC 7 ** 30 ** D30
PC , // PC 6 ** 31 ** D31
PC , // PC 5 ** 32 ** D32
PC , // PC 4 ** 33 ** D33
PC , // PC 3 ** 34 ** D34
PC , // PC 2 ** 35 ** D35
PC , // PC 1 ** 36 ** D36
PC , // PC 0 ** 37 ** D37
PD , // PD 7 ** 38 ** D38
PG , // PG 2 ** 39 ** D39
PG , // PG 1 ** 40 ** D40
PG , // PG 0 ** 41 ** D41
PL , // PL 7 ** 42 ** D42
PL , // PL 6 ** 43 ** D43
PL , // PL 5 ** 44 ** D44
PL , // PL 4 ** 45 ** D45
PL , // PL 3 ** 46 ** D46
PL , // PL 2 ** 47 ** D47
PL , // PL 1 ** 48 ** D48
PL , // PL 0 ** 49 ** D49
PB , // PB 3 ** 50 ** SPI_MISO
PB , // PB 2 ** 51 ** SPI_MOSI
PB , // PB 1 ** 52 ** SPI_SCK
PB , // PB 0 ** 53 ** SPI_SS
PF , // PF 0 ** 54 ** A0
PF , // PF 1 ** 55 ** A1
PF , // PF 2 ** 56 ** A2
PF , // PF 3 ** 57 ** A3
PF , // PF 4 ** 58 ** A4
PF , // PF 5 ** 59 ** A5
PF , // PF 6 ** 60 ** A6
PF , // PF 7 ** 61 ** A7
PK , // PK 0 ** 62 ** A8
PK , // PK 1 ** 63 ** A9
PK , // PK 2 ** 64 ** A10
PK , // PK 3 ** 65 ** A11
PK , // PK 4 ** 66 ** A12
PK , // PK 5 ** 67 ** A13
PK , // PK 6 ** 68 ** A14
PK , // PK 7 ** 69 ** A15
PG , // PG 4 ** 70 **
PG , // PG 3 ** 71 **
PJ , // PJ 2 ** 72 **
PJ , // PJ 3 ** 73 **
PJ , // PJ 7 ** 74 **
PJ , // PJ 4 ** 75 **
PJ , // PJ 5 ** 76 **
PJ , // PJ 6 ** 77 **
PE , // PE 2 ** 78 **
PE , // PE 6 ** 79 **
PE , // PE 7 ** 80 **
PD , // PD 4 ** 81 **
PD , // PD 5 ** 82 **
PD , // PD 6 ** 83 **
PH , // PH 2 ** 84 **
PH , // PH 7 ** 85 **
PE, // PE 0 ** 0 ** USART0_RX
PE, // PE 1 ** 1 ** USART0_TX
PE, // PE 4 ** 2 ** PWM2
PE, // PE 5 ** 3 ** PWM3
PG, // PG 5 ** 4 ** PWM4
PE, // PE 3 ** 5 ** PWM5
PH, // PH 3 ** 6 ** PWM6
PH, // PH 4 ** 7 ** PWM7
PH, // PH 5 ** 8 ** PWM8
PH, // PH 6 ** 9 ** PWM9
PB, // PB 4 ** 10 ** PWM10
PB, // PB 5 ** 11 ** PWM11
PB, // PB 6 ** 12 ** PWM12
PB, // PB 7 ** 13 ** PWM13
PJ, // PJ 1 ** 14 ** USART3_TX
PJ, // PJ 0 ** 15 ** USART3_RX
PH, // PH 1 ** 16 ** USART2_TX
PH, // PH 0 ** 17 ** USART2_RX
PD, // PD 3 ** 18 ** USART1_TX
PD, // PD 2 ** 19 ** USART1_RX
PD, // PD 1 ** 20 ** I2C_SDA
PD, // PD 0 ** 21 ** I2C_SCL
PA, // PA 0 ** 22 ** D22
PA, // PA 1 ** 23 ** D23
PA, // PA 2 ** 24 ** D24
PA, // PA 3 ** 25 ** D25
PA, // PA 4 ** 26 ** D26
PA, // PA 5 ** 27 ** D27
PA, // PA 6 ** 28 ** D28
PA, // PA 7 ** 29 ** D29
PC, // PC 7 ** 30 ** D30
PC, // PC 6 ** 31 ** D31
PC, // PC 5 ** 32 ** D32
PC, // PC 4 ** 33 ** D33
PC, // PC 3 ** 34 ** D34
PC, // PC 2 ** 35 ** D35
PC, // PC 1 ** 36 ** D36
PC, // PC 0 ** 37 ** D37
PD, // PD 7 ** 38 ** D38
PG, // PG 2 ** 39 ** D39
PG, // PG 1 ** 40 ** D40
PG, // PG 0 ** 41 ** D41
PL, // PL 7 ** 42 ** D42
PL, // PL 6 ** 43 ** D43
PL, // PL 5 ** 44 ** D44
PL, // PL 4 ** 45 ** D45
PL, // PL 3 ** 46 ** D46
PL, // PL 2 ** 47 ** D47
PL, // PL 1 ** 48 ** D48
PL, // PL 0 ** 49 ** D49
PB, // PB 3 ** 50 ** SPI_MISO
PB, // PB 2 ** 51 ** SPI_MOSI
PB, // PB 1 ** 52 ** SPI_SCK
PB, // PB 0 ** 53 ** SPI_SS
PF, // PF 0 ** 54 ** A0
PF, // PF 1 ** 55 ** A1
PF, // PF 2 ** 56 ** A2
PF, // PF 3 ** 57 ** A3
PF, // PF 4 ** 58 ** A4
PF, // PF 5 ** 59 ** A5
PF, // PF 6 ** 60 ** A6
PF, // PF 7 ** 61 ** A7
PK, // PK 0 ** 62 ** A8
PK, // PK 1 ** 63 ** A9
PK, // PK 2 ** 64 ** A10
PK, // PK 3 ** 65 ** A11
PK, // PK 4 ** 66 ** A12
PK, // PK 5 ** 67 ** A13
PK, // PK 6 ** 68 ** A14
PK, // PK 7 ** 69 ** A15
PG, // PG 4 ** 70 **
PG, // PG 3 ** 71 **
PJ, // PJ 2 ** 72 **
PJ, // PJ 3 ** 73 **
PJ, // PJ 7 ** 74 **
PJ, // PJ 4 ** 75 **
PJ, // PJ 5 ** 76 **
PJ, // PJ 6 ** 77 **
PE, // PE 2 ** 78 **
PE, // PE 6 ** 79 **
PE, // PE 7 ** 80 **
PD, // PD 4 ** 81 **
PD, // PD 5 ** 82 **
PD, // PD 6 ** 83 **
PH, // PH 2 ** 84 **
PH, // PH 7 ** 85 **
};
#define digitalPinToPort_plus_70(P) ( pgm_read_byte( digital_pin_to_port_PGM_plus_70 + (P) ) )
@ -141,92 +141,92 @@ const uint8_t PROGMEM digital_pin_to_port_PGM_plus_70[] = {
const uint8_t PROGMEM digital_pin_to_bit_mask_PGM_plus_70[] = {
// PIN IN PORT
// ------------------------
_BV( 0 ) , // PE 0 ** 0 ** USART0_RX
_BV( 1 ) , // PE 1 ** 1 ** USART0_TX
_BV( 4 ) , // PE 4 ** 2 ** PWM2
_BV( 5 ) , // PE 5 ** 3 ** PWM3
_BV( 5 ) , // PG 5 ** 4 ** PWM4
_BV( 3 ) , // PE 3 ** 5 ** PWM5
_BV( 3 ) , // PH 3 ** 6 ** PWM6
_BV( 4 ) , // PH 4 ** 7 ** PWM7
_BV( 5 ) , // PH 5 ** 8 ** PWM8
_BV( 6 ) , // PH 6 ** 9 ** PWM9
_BV( 4 ) , // PB 4 ** 10 ** PWM10
_BV( 5 ) , // PB 5 ** 11 ** PWM11
_BV( 6 ) , // PB 6 ** 12 ** PWM12
_BV( 7 ) , // PB 7 ** 13 ** PWM13
_BV( 1 ) , // PJ 1 ** 14 ** USART3_TX
_BV( 0 ) , // PJ 0 ** 15 ** USART3_RX
_BV( 1 ) , // PH 1 ** 16 ** USART2_TX
_BV( 0 ) , // PH 0 ** 17 ** USART2_RX
_BV( 3 ) , // PD 3 ** 18 ** USART1_TX
_BV( 2 ) , // PD 2 ** 19 ** USART1_RX
_BV( 1 ) , // PD 1 ** 20 ** I2C_SDA
_BV( 0 ) , // PD 0 ** 21 ** I2C_SCL
_BV( 0 ) , // PA 0 ** 22 ** D22
_BV( 1 ) , // PA 1 ** 23 ** D23
_BV( 2 ) , // PA 2 ** 24 ** D24
_BV( 3 ) , // PA 3 ** 25 ** D25
_BV( 4 ) , // PA 4 ** 26 ** D26
_BV( 5 ) , // PA 5 ** 27 ** D27
_BV( 6 ) , // PA 6 ** 28 ** D28
_BV( 7 ) , // PA 7 ** 29 ** D29
_BV( 7 ) , // PC 7 ** 30 ** D30
_BV( 6 ) , // PC 6 ** 31 ** D31
_BV( 5 ) , // PC 5 ** 32 ** D32
_BV( 4 ) , // PC 4 ** 33 ** D33
_BV( 3 ) , // PC 3 ** 34 ** D34
_BV( 2 ) , // PC 2 ** 35 ** D35
_BV( 1 ) , // PC 1 ** 36 ** D36
_BV( 0 ) , // PC 0 ** 37 ** D37
_BV( 7 ) , // PD 7 ** 38 ** D38
_BV( 2 ) , // PG 2 ** 39 ** D39
_BV( 1 ) , // PG 1 ** 40 ** D40
_BV( 0 ) , // PG 0 ** 41 ** D41
_BV( 7 ) , // PL 7 ** 42 ** D42
_BV( 6 ) , // PL 6 ** 43 ** D43
_BV( 5 ) , // PL 5 ** 44 ** D44
_BV( 4 ) , // PL 4 ** 45 ** D45
_BV( 3 ) , // PL 3 ** 46 ** D46
_BV( 2 ) , // PL 2 ** 47 ** D47
_BV( 1 ) , // PL 1 ** 48 ** D48
_BV( 0 ) , // PL 0 ** 49 ** D49
_BV( 3 ) , // PB 3 ** 50 ** SPI_MISO
_BV( 2 ) , // PB 2 ** 51 ** SPI_MOSI
_BV( 1 ) , // PB 1 ** 52 ** SPI_SCK
_BV( 0 ) , // PB 0 ** 53 ** SPI_SS
_BV( 0 ) , // PF 0 ** 54 ** A0
_BV( 1 ) , // PF 1 ** 55 ** A1
_BV( 2 ) , // PF 2 ** 56 ** A2
_BV( 3 ) , // PF 3 ** 57 ** A3
_BV( 4 ) , // PF 4 ** 58 ** A4
_BV( 5 ) , // PF 5 ** 59 ** A5
_BV( 6 ) , // PF 6 ** 60 ** A6
_BV( 7 ) , // PF 7 ** 61 ** A7
_BV( 0 ) , // PK 0 ** 62 ** A8
_BV( 1 ) , // PK 1 ** 63 ** A9
_BV( 2 ) , // PK 2 ** 64 ** A10
_BV( 3 ) , // PK 3 ** 65 ** A11
_BV( 4 ) , // PK 4 ** 66 ** A12
_BV( 5 ) , // PK 5 ** 67 ** A13
_BV( 6 ) , // PK 6 ** 68 ** A14
_BV( 7 ) , // PK 7 ** 69 ** A15
_BV( 4 ) , // PG 4 ** 70 **
_BV( 3 ) , // PG 3 ** 71 **
_BV( 2 ) , // PJ 2 ** 72 **
_BV( 3 ) , // PJ 3 ** 73 **
_BV( 7 ) , // PJ 7 ** 74 **
_BV( 4 ) , // PJ 4 ** 75 **
_BV( 5 ) , // PJ 5 ** 76 **
_BV( 6 ) , // PJ 6 ** 77 **
_BV( 2 ) , // PE 2 ** 78 **
_BV( 6 ) , // PE 6 ** 79 **
_BV( 7 ) , // PE 7 ** 80 **
_BV( 4 ) , // PD 4 ** 81 **
_BV( 5 ) , // PD 5 ** 82 **
_BV( 6 ) , // PD 6 ** 83 **
_BV( 2 ) , // PH 2 ** 84 **
_BV( 7 ) , // PH 7 ** 85 **
_BV( 0 ), // PE 0 ** 0 ** USART0_RX
_BV( 1 ), // PE 1 ** 1 ** USART0_TX
_BV( 4 ), // PE 4 ** 2 ** PWM2
_BV( 5 ), // PE 5 ** 3 ** PWM3
_BV( 5 ), // PG 5 ** 4 ** PWM4
_BV( 3 ), // PE 3 ** 5 ** PWM5
_BV( 3 ), // PH 3 ** 6 ** PWM6
_BV( 4 ), // PH 4 ** 7 ** PWM7
_BV( 5 ), // PH 5 ** 8 ** PWM8
_BV( 6 ), // PH 6 ** 9 ** PWM9
_BV( 4 ), // PB 4 ** 10 ** PWM10
_BV( 5 ), // PB 5 ** 11 ** PWM11
_BV( 6 ), // PB 6 ** 12 ** PWM12
_BV( 7 ), // PB 7 ** 13 ** PWM13
_BV( 1 ), // PJ 1 ** 14 ** USART3_TX
_BV( 0 ), // PJ 0 ** 15 ** USART3_RX
_BV( 1 ), // PH 1 ** 16 ** USART2_TX
_BV( 0 ), // PH 0 ** 17 ** USART2_RX
_BV( 3 ), // PD 3 ** 18 ** USART1_TX
_BV( 2 ), // PD 2 ** 19 ** USART1_RX
_BV( 1 ), // PD 1 ** 20 ** I2C_SDA
_BV( 0 ), // PD 0 ** 21 ** I2C_SCL
_BV( 0 ), // PA 0 ** 22 ** D22
_BV( 1 ), // PA 1 ** 23 ** D23
_BV( 2 ), // PA 2 ** 24 ** D24
_BV( 3 ), // PA 3 ** 25 ** D25
_BV( 4 ), // PA 4 ** 26 ** D26
_BV( 5 ), // PA 5 ** 27 ** D27
_BV( 6 ), // PA 6 ** 28 ** D28
_BV( 7 ), // PA 7 ** 29 ** D29
_BV( 7 ), // PC 7 ** 30 ** D30
_BV( 6 ), // PC 6 ** 31 ** D31
_BV( 5 ), // PC 5 ** 32 ** D32
_BV( 4 ), // PC 4 ** 33 ** D33
_BV( 3 ), // PC 3 ** 34 ** D34
_BV( 2 ), // PC 2 ** 35 ** D35
_BV( 1 ), // PC 1 ** 36 ** D36
_BV( 0 ), // PC 0 ** 37 ** D37
_BV( 7 ), // PD 7 ** 38 ** D38
_BV( 2 ), // PG 2 ** 39 ** D39
_BV( 1 ), // PG 1 ** 40 ** D40
_BV( 0 ), // PG 0 ** 41 ** D41
_BV( 7 ), // PL 7 ** 42 ** D42
_BV( 6 ), // PL 6 ** 43 ** D43
_BV( 5 ), // PL 5 ** 44 ** D44
_BV( 4 ), // PL 4 ** 45 ** D45
_BV( 3 ), // PL 3 ** 46 ** D46
_BV( 2 ), // PL 2 ** 47 ** D47
_BV( 1 ), // PL 1 ** 48 ** D48
_BV( 0 ), // PL 0 ** 49 ** D49
_BV( 3 ), // PB 3 ** 50 ** SPI_MISO
_BV( 2 ), // PB 2 ** 51 ** SPI_MOSI
_BV( 1 ), // PB 1 ** 52 ** SPI_SCK
_BV( 0 ), // PB 0 ** 53 ** SPI_SS
_BV( 0 ), // PF 0 ** 54 ** A0
_BV( 1 ), // PF 1 ** 55 ** A1
_BV( 2 ), // PF 2 ** 56 ** A2
_BV( 3 ), // PF 3 ** 57 ** A3
_BV( 4 ), // PF 4 ** 58 ** A4
_BV( 5 ), // PF 5 ** 59 ** A5
_BV( 6 ), // PF 6 ** 60 ** A6
_BV( 7 ), // PF 7 ** 61 ** A7
_BV( 0 ), // PK 0 ** 62 ** A8
_BV( 1 ), // PK 1 ** 63 ** A9
_BV( 2 ), // PK 2 ** 64 ** A10
_BV( 3 ), // PK 3 ** 65 ** A11
_BV( 4 ), // PK 4 ** 66 ** A12
_BV( 5 ), // PK 5 ** 67 ** A13
_BV( 6 ), // PK 6 ** 68 ** A14
_BV( 7 ), // PK 7 ** 69 ** A15
_BV( 4 ), // PG 4 ** 70 **
_BV( 3 ), // PG 3 ** 71 **
_BV( 2 ), // PJ 2 ** 72 **
_BV( 3 ), // PJ 3 ** 73 **
_BV( 7 ), // PJ 7 ** 74 **
_BV( 4 ), // PJ 4 ** 75 **
_BV( 5 ), // PJ 5 ** 76 **
_BV( 6 ), // PJ 6 ** 77 **
_BV( 2 ), // PE 2 ** 78 **
_BV( 6 ), // PE 6 ** 79 **
_BV( 7 ), // PE 7 ** 80 **
_BV( 4 ), // PD 4 ** 81 **
_BV( 5 ), // PD 5 ** 82 **
_BV( 6 ), // PD 6 ** 83 **
_BV( 2 ), // PH 2 ** 84 **
_BV( 7 ), // PH 7 ** 85 **
};
#define digitalPinToBitMask_plus_70(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM_plus_70 + (P) ) )
@ -234,86 +234,86 @@ const uint8_t PROGMEM digital_pin_to_bit_mask_PGM_plus_70[] = {
const uint8_t PROGMEM digital_pin_to_timer_PGM_plus_70[] = {
// TIMERS
// ------------------------
NOT_ON_TIMER , // PE 0 ** 0 ** USART0_RX
NOT_ON_TIMER , // PE 1 ** 1 ** USART0_TX
TIMER3B , // PE 4 ** 2 ** PWM2
TIMER3C , // PE 5 ** 3 ** PWM3
TIMER0B , // PG 5 ** 4 ** PWM4
TIMER3A , // PE 3 ** 5 ** PWM5
TIMER4A , // PH 3 ** 6 ** PWM6
TIMER4B , // PH 4 ** 7 ** PWM7
TIMER4C , // PH 5 ** 8 ** PWM8
TIMER2B , // PH 6 ** 9 ** PWM9
TIMER2A , // PB 4 ** 10 ** PWM10
TIMER1A , // PB 5 ** 11 ** PWM11
TIMER1B , // PB 6 ** 12 ** PWM12
TIMER0A , // PB 7 ** 13 ** PWM13
NOT_ON_TIMER , // PJ 1 ** 14 ** USART3_TX
NOT_ON_TIMER , // PJ 0 ** 15 ** USART3_RX
NOT_ON_TIMER , // PH 1 ** 16 ** USART2_TX
NOT_ON_TIMER , // PH 0 ** 17 ** USART2_RX
NOT_ON_TIMER , // PD 3 ** 18 ** USART1_TX
NOT_ON_TIMER , // PD 2 ** 19 ** USART1_RX
NOT_ON_TIMER , // PD 1 ** 20 ** I2C_SDA
NOT_ON_TIMER , // PD 0 ** 21 ** I2C_SCL
NOT_ON_TIMER , // PA 0 ** 22 ** D22
NOT_ON_TIMER , // PA 1 ** 23 ** D23
NOT_ON_TIMER , // PA 2 ** 24 ** D24
NOT_ON_TIMER , // PA 3 ** 25 ** D25
NOT_ON_TIMER , // PA 4 ** 26 ** D26
NOT_ON_TIMER , // PA 5 ** 27 ** D27
NOT_ON_TIMER , // PA 6 ** 28 ** D28
NOT_ON_TIMER , // PA 7 ** 29 ** D29
NOT_ON_TIMER , // PC 7 ** 30 ** D30
NOT_ON_TIMER , // PC 6 ** 31 ** D31
NOT_ON_TIMER , // PC 5 ** 32 ** D32
NOT_ON_TIMER , // PC 4 ** 33 ** D33
NOT_ON_TIMER , // PC 3 ** 34 ** D34
NOT_ON_TIMER , // PC 2 ** 35 ** D35
NOT_ON_TIMER , // PC 1 ** 36 ** D36
NOT_ON_TIMER , // PC 0 ** 37 ** D37
NOT_ON_TIMER , // PD 7 ** 38 ** D38
NOT_ON_TIMER , // PG 2 ** 39 ** D39
NOT_ON_TIMER , // PG 1 ** 40 ** D40
NOT_ON_TIMER , // PG 0 ** 41 ** D41
NOT_ON_TIMER , // PL 7 ** 42 ** D42
NOT_ON_TIMER , // PL 6 ** 43 ** D43
TIMER5C , // PL 5 ** 44 ** D44
TIMER5B , // PL 4 ** 45 ** D45
TIMER5A , // PL 3 ** 46 ** D46
NOT_ON_TIMER , // PL 2 ** 47 ** D47
NOT_ON_TIMER , // PL 1 ** 48 ** D48
NOT_ON_TIMER , // PL 0 ** 49 ** D49
NOT_ON_TIMER , // PB 3 ** 50 ** SPI_MISO
NOT_ON_TIMER , // PB 2 ** 51 ** SPI_MOSI
NOT_ON_TIMER , // PB 1 ** 52 ** SPI_SCK
NOT_ON_TIMER , // PB 0 ** 53 ** SPI_SS
NOT_ON_TIMER , // PF 0 ** 54 ** A0
NOT_ON_TIMER , // PF 1 ** 55 ** A1
NOT_ON_TIMER , // PF 2 ** 56 ** A2
NOT_ON_TIMER , // PF 3 ** 57 ** A3
NOT_ON_TIMER , // PF 4 ** 58 ** A4
NOT_ON_TIMER , // PF 5 ** 59 ** A5
NOT_ON_TIMER , // PF 6 ** 60 ** A6
NOT_ON_TIMER , // PF 7 ** 61 ** A7
NOT_ON_TIMER , // PK 0 ** 62 ** A8
NOT_ON_TIMER , // PK 1 ** 63 ** A9
NOT_ON_TIMER , // PK 2 ** 64 ** A10
NOT_ON_TIMER , // PK 3 ** 65 ** A11
NOT_ON_TIMER , // PK 4 ** 66 ** A12
NOT_ON_TIMER , // PK 5 ** 67 ** A13
NOT_ON_TIMER , // PK 6 ** 68 ** A14
NOT_ON_TIMER , // PK 7 ** 69 ** A15
NOT_ON_TIMER , // PG 4 ** 70 **
NOT_ON_TIMER , // PG 3 ** 71 **
NOT_ON_TIMER , // PJ 2 ** 72 **
NOT_ON_TIMER , // PJ 3 ** 73 **
NOT_ON_TIMER , // PJ 7 ** 74 **
NOT_ON_TIMER , // PJ 4 ** 75 **
NOT_ON_TIMER , // PJ 5 ** 76 **
NOT_ON_TIMER , // PJ 6 ** 77 **
NOT_ON_TIMER , // PE 2 ** 78 **
NOT_ON_TIMER , // PE 6 ** 79 **
NOT_ON_TIMER, // PE 0 ** 0 ** USART0_RX
NOT_ON_TIMER, // PE 1 ** 1 ** USART0_TX
TIMER3B, // PE 4 ** 2 ** PWM2
TIMER3C, // PE 5 ** 3 ** PWM3
TIMER0B, // PG 5 ** 4 ** PWM4
TIMER3A, // PE 3 ** 5 ** PWM5
TIMER4A, // PH 3 ** 6 ** PWM6
TIMER4B, // PH 4 ** 7 ** PWM7
TIMER4C, // PH 5 ** 8 ** PWM8
TIMER2B, // PH 6 ** 9 ** PWM9
TIMER2A, // PB 4 ** 10 ** PWM10
TIMER1A, // PB 5 ** 11 ** PWM11
TIMER1B, // PB 6 ** 12 ** PWM12
TIMER0A, // PB 7 ** 13 ** PWM13
NOT_ON_TIMER, // PJ 1 ** 14 ** USART3_TX
NOT_ON_TIMER, // PJ 0 ** 15 ** USART3_RX
NOT_ON_TIMER, // PH 1 ** 16 ** USART2_TX
NOT_ON_TIMER, // PH 0 ** 17 ** USART2_RX
NOT_ON_TIMER, // PD 3 ** 18 ** USART1_TX
NOT_ON_TIMER, // PD 2 ** 19 ** USART1_RX
NOT_ON_TIMER, // PD 1 ** 20 ** I2C_SDA
NOT_ON_TIMER, // PD 0 ** 21 ** I2C_SCL
NOT_ON_TIMER, // PA 0 ** 22 ** D22
NOT_ON_TIMER, // PA 1 ** 23 ** D23
NOT_ON_TIMER, // PA 2 ** 24 ** D24
NOT_ON_TIMER, // PA 3 ** 25 ** D25
NOT_ON_TIMER, // PA 4 ** 26 ** D26
NOT_ON_TIMER, // PA 5 ** 27 ** D27
NOT_ON_TIMER, // PA 6 ** 28 ** D28
NOT_ON_TIMER, // PA 7 ** 29 ** D29
NOT_ON_TIMER, // PC 7 ** 30 ** D30
NOT_ON_TIMER, // PC 6 ** 31 ** D31
NOT_ON_TIMER, // PC 5 ** 32 ** D32
NOT_ON_TIMER, // PC 4 ** 33 ** D33
NOT_ON_TIMER, // PC 3 ** 34 ** D34
NOT_ON_TIMER, // PC 2 ** 35 ** D35
NOT_ON_TIMER, // PC 1 ** 36 ** D36
NOT_ON_TIMER, // PC 0 ** 37 ** D37
NOT_ON_TIMER, // PD 7 ** 38 ** D38
NOT_ON_TIMER, // PG 2 ** 39 ** D39
NOT_ON_TIMER, // PG 1 ** 40 ** D40
NOT_ON_TIMER, // PG 0 ** 41 ** D41
NOT_ON_TIMER, // PL 7 ** 42 ** D42
NOT_ON_TIMER, // PL 6 ** 43 ** D43
TIMER5C, // PL 5 ** 44 ** D44
TIMER5B, // PL 4 ** 45 ** D45
TIMER5A, // PL 3 ** 46 ** D46
NOT_ON_TIMER, // PL 2 ** 47 ** D47
NOT_ON_TIMER, // PL 1 ** 48 ** D48
NOT_ON_TIMER, // PL 0 ** 49 ** D49
NOT_ON_TIMER, // PB 3 ** 50 ** SPI_MISO
NOT_ON_TIMER, // PB 2 ** 51 ** SPI_MOSI
NOT_ON_TIMER, // PB 1 ** 52 ** SPI_SCK
NOT_ON_TIMER, // PB 0 ** 53 ** SPI_SS
NOT_ON_TIMER, // PF 0 ** 54 ** A0
NOT_ON_TIMER, // PF 1 ** 55 ** A1
NOT_ON_TIMER, // PF 2 ** 56 ** A2
NOT_ON_TIMER, // PF 3 ** 57 ** A3
NOT_ON_TIMER, // PF 4 ** 58 ** A4
NOT_ON_TIMER, // PF 5 ** 59 ** A5
NOT_ON_TIMER, // PF 6 ** 60 ** A6
NOT_ON_TIMER, // PF 7 ** 61 ** A7
NOT_ON_TIMER, // PK 0 ** 62 ** A8
NOT_ON_TIMER, // PK 1 ** 63 ** A9
NOT_ON_TIMER, // PK 2 ** 64 ** A10
NOT_ON_TIMER, // PK 3 ** 65 ** A11
NOT_ON_TIMER, // PK 4 ** 66 ** A12
NOT_ON_TIMER, // PK 5 ** 67 ** A13
NOT_ON_TIMER, // PK 6 ** 68 ** A14
NOT_ON_TIMER, // PK 7 ** 69 ** A15
NOT_ON_TIMER, // PG 4 ** 70 **
NOT_ON_TIMER, // PG 3 ** 71 **
NOT_ON_TIMER, // PJ 2 ** 72 **
NOT_ON_TIMER, // PJ 3 ** 73 **
NOT_ON_TIMER, // PJ 7 ** 74 **
NOT_ON_TIMER, // PJ 4 ** 75 **
NOT_ON_TIMER, // PJ 5 ** 76 **
NOT_ON_TIMER, // PJ 6 ** 77 **
NOT_ON_TIMER, // PE 2 ** 78 **
NOT_ON_TIMER, // PE 6 ** 79 **
};
#define digitalPinToTimer_plus_70(P) ( pgm_read_byte( digital_pin_to_timer_PGM_plus_70 + (P) ) )

View file

@ -55,12 +55,12 @@
#if defined(ARDUINO) && !defined(ARDUINO_ARCH_STM32) && !defined(ARDUINO_ARCH_SAM)
#include "../../inc/MarlinConfigPre.h"
#include "../../../inc/MarlinConfigPre.h"
#if HAS_MARLINUI_U8GLIB
#include "../shared/Marduino.h"
#include "../shared/Delay.h"
#include "../../shared/Marduino.h"
#include "../../shared/Delay.h"
#include <U8glib-HAL.h>

View file

@ -102,6 +102,10 @@ void watchdogSetup() {
#if ENABLED(USE_WATCHDOG)
#ifndef WATCHDOG_PIO_RESET
#define WATCHDOG_PIO_RESET
#endif
// 4 seconds timeout
uint32_t timeout = TERN(WATCHDOG_DURATION_8S, 8000, 4000);
@ -115,15 +119,16 @@ void watchdogSetup() {
timeout = 0xFFF;
// We want to enable the watchdog with the specified timeout
uint32_t value =
WDT_MR_WDV(timeout) | // With the specified timeout
WDT_MR_WDD(timeout) | // and no invalid write window
#if !(SAMV70 || SAMV71 || SAME70 || SAMS70)
WDT_MR_WDRPROC | // WDT fault resets processor only - We want
// to keep PIO controller state
#endif
WDT_MR_WDDBGHLT | // WDT stops in debug state.
WDT_MR_WDIDLEHLT; // WDT stops in idle state.
uint32_t value = (0
| WDT_MR_WDV(timeout) // With the specified timeout
| WDT_MR_WDD(timeout) // and no invalid write window
#if NONE(WATCHDOG_PIO_RESET, SAMV70, SAMV71, SAME70, SAMS70)
| WDT_MR_WDRPROC // WDT fault resets processor only with this flag.
// Omit to also reset the PIO controller.
#endif
| WDT_MR_WDDBGHLT // WDT stops in debug state.
| WDT_MR_WDIDLEHLT // WDT stops in idle state.
);
#if ENABLED(WATCHDOG_RESET_MANUAL)
// We enable the watchdog timer, but only for the interrupt.

View file

@ -208,8 +208,8 @@
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
A("bfi %[bin],%[work],#0,#1") /* Store read bit as the bit 0 */
: [bin]"+r"(bin),
[work]"+r"(work)
: [bin]"+r"( bin ),
[work]"+r"( work )
: [bitband_miso_port]"r"( BITBAND_MISO_PORT ),
[sck_mask]"r"( SCK_MASK ),
[sck_port]"r"( SCK_PORT_PLUS30 )
@ -350,7 +350,7 @@
static void spiRxBlock0(uint8_t *ptr, uint32_t todo) {
uint32_t bin = 0;
uint32_t work = 0;
uint32_t BITBAND_MISO_PORT = BITBAND_ADDRESS( ((uint32_t)PORT(SD_MISO_PIN))+0x3C, PIN_SHIFT(SD_MISO_PIN)); /* PDSR of port in bitband area */
uint32_t BITBAND_MISO_PORT = BITBAND_ADDRESS(((uint32_t)PORT(SD_MISO_PIN))+0x3C, PIN_SHIFT(SD_MISO_PIN)); /* PDSR of port in bitband area */
uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SD_SCK_PIN)) + 0x30; /* SODR of port */
uint32_t SCK_MASK = PIN_MASK(SD_SCK_PIN);
@ -412,10 +412,10 @@
A("strb.w %[bin], [%[ptr]], #1") /* Store read value into buffer, increment buffer pointer */
A("bne.n loop%=") /* Repeat until done */
: [ptr]"+r"(ptr),
[todo]"+r"(todo),
[bin]"+r"(bin),
[work]"+r"(work)
: [ptr]"+r"( ptr ),
[todo]"+r"( todo ),
[bin]"+r"( bin ),
[work]"+r"( work )
: [bitband_miso_port]"r"( BITBAND_MISO_PORT ),
[sck_mask]"r"( SCK_MASK ),
[sck_port]"r"( SCK_PORT_PLUS30 )

View file

@ -21,7 +21,7 @@
*/
#ifdef ARDUINO_ARCH_SAM
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if ENABLED(FLASH_EEPROM_EMULATION)
@ -132,7 +132,7 @@ static uint8_t buffer[256] = {0}, // The RAM buffer to accumulate writes
curGroup = 0xFF; // Current FLASH group
#define DEBUG_OUT ENABLED(EE_EMU_DEBUG)
#include "../../core/debug_out.h"
#include "../../../core/debug_out.h"
static void ee_Dump(const int page, const void *data) {
@ -953,7 +953,7 @@ static void ee_Init() {
/* PersistentStore -----------------------------------------------------------*/
#include "../shared/eeprom_api.h"
#include "../../shared/eeprom_api.h"
#ifndef MARLIN_EEPROM_SIZE
#define MARLIN_EEPROM_SIZE 0x1000 // 4KB

View file

@ -21,7 +21,7 @@
*/
#ifdef ARDUINO_ARCH_SAM
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if USE_WIRED_EEPROM
@ -30,8 +30,8 @@
* with simple implementations supplied by Marlin.
*/
#include "../shared/eeprom_if.h"
#include "../shared/eeprom_api.h"
#include "../../shared/eeprom_if.h"
#include "../../shared/eeprom_api.h"
#ifndef MARLIN_EEPROM_SIZE
#error "MARLIN_EEPROM_SIZE is required for I2C / SPI EEPROM."

View file

@ -40,11 +40,12 @@
* Some jitter in the Vref signal is OK so the interrupt priority is left at its default value.
*/
#include "../../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfigPre.h"
#if MB(PRINTRBOARD_G2)
#include "G2_PWM.h"
#include "../../../module/stepper.h"
#if PIN_EXISTS(MOTOR_CURRENT_PWM_X)
#define G2_PWM_X 1
@ -56,16 +57,12 @@
#else
#define G2_PWM_Y 0
#endif
#if PIN_EXISTS(MOTOR_CURRENT_PWM_Z)
#if HAS_MOTOR_CURRENT_PWM_Z
#define G2_PWM_Z 1
#else
#define G2_PWM_Z 0
#endif
#if HAS_MOTOR_CURRENT_PWM_E
#define G2_PWM_E 1
#else
#define G2_PWM_E 0
#endif
#define G2_PWM_E HAS_MOTOR_CURRENT_PWM_E
#define G2_MASK_X(V) (G2_PWM_X * (V))
#define G2_MASK_Y(V) (G2_PWM_Y * (V))
#define G2_MASK_Z(V) (G2_PWM_Z * (V))
@ -80,17 +77,22 @@ PWM_map ISR_table[NUM_PWMS] = PWM_MAP_INIT;
void Stepper::digipot_init() {
#if PIN_EXISTS(MOTOR_CURRENT_PWM_X)
OUT_WRITE(MOTOR_CURRENT_PWM_X_PIN, 0); // init pins
#if G2_PWM_X
OUT_WRITE(MOTOR_CURRENT_PWM_X_PIN, LOW); // init pins
#endif
#if PIN_EXISTS(MOTOR_CURRENT_PWM_Y)
OUT_WRITE(MOTOR_CURRENT_PWM_Y_PIN, 0);
#if G2_PWM_Y
OUT_WRITE(MOTOR_CURRENT_PWM_Y_PIN, LOW);
#endif
#if G2_PWM_Z
OUT_WRITE(MOTOR_CURRENT_PWM_Z_PIN, 0);
OUT_WRITE(MOTOR_CURRENT_PWM_Z_PIN, LOW);
#endif
#if G2_PWM_E
OUT_WRITE(MOTOR_CURRENT_PWM_E_PIN, 0);
#if PIN_EXISTS(MOTOR_CURRENT_PWM_E)
OUT_WRITE(MOTOR_CURRENT_PWM_E_PIN, LOW);
#endif
#if PIN_EXISTS(MOTOR_CURRENT_PWM_E0)
OUT_WRITE(MOTOR_CURRENT_PWM_E0_PIN, LOW);
#endif
#endif
#define WPKEY (0x50574D << 8) // “PWM” in ASCII

View file

@ -26,10 +26,7 @@
* PR #7500. It is hardwired for the PRINTRBOARD_G2 Motor Current needs.
*/
#include "../../../inc/MarlinConfigPre.h"
#include "../../../module/stepper.h"
//C:\Users\bobku\Documents\GitHub\Marlin-Bob-2\Marlin\src\module\stepper.h
//C:\Users\bobku\Documents\GitHub\Marlin-Bob-2\Marlin\src\HAL\HAL_DUE\G2_PWM.h
#include <stdint.h>
#define PWM_PERIOD_US 100 // base repetition rate in micro seconds

View file

@ -63,8 +63,8 @@
#include "compiler.h"
#include "preprocessor.h"
#ifdef FREERTOS_USED
#include "FreeRTOS.h"
#include "semphr.h"
#include <FreeRTOS.h>
#include <semphr.h>
#endif
#include "ctrl_access.h"

View file

@ -19,7 +19,7 @@ void sd_mmc_spi_mem_init() {
}
inline bool media_ready() {
return IS_SD_MOUNTED() && IS_SD_INSERTED() && !IS_SD_FILE_OPEN() && !IS_SD_PRINTING();
return card.isMounted() && card.isInserted() && !card.isFileOpen() && !card.isStillPrinting();
}
bool sd_mmc_spi_unload(bool) { return true; }
@ -29,11 +29,10 @@ bool sd_mmc_spi_wr_protect() { return false; }
bool sd_mmc_spi_removal() { return !media_ready(); }
Ctrl_status sd_mmc_spi_test_unit_ready() {
#ifdef DISABLE_DUE_SD_MMC
#if ENABLED(DISABLE_DUE_SD_MMC)
return CTRL_NO_PRESENT;
#endif
if (sd_mmc_spi_removal()) return CTRL_NO_PRESENT;
return CTRL_GOOD;
return sd_mmc_spi_removal() ? CTRL_NO_PRESENT : CTRL_GOOD;
}
// NOTE: This function is defined as returning the address of the last block
@ -58,9 +57,10 @@ uint8_t sector_buf[SD_MMC_BLOCK_SIZE];
// #define DEBUG_MMC
Ctrl_status sd_mmc_spi_usb_read_10(uint32_t addr, uint16_t nb_sector) {
#ifdef DISABLE_DUE_SD_MMC
#if ENABLED(DISABLE_DUE_SD_MMC)
return CTRL_NO_PRESENT;
#endif
if (sd_mmc_spi_removal()) return CTRL_NO_PRESENT;
#ifdef DEBUG_MMC
@ -97,9 +97,10 @@ Ctrl_status sd_mmc_spi_usb_read_10(uint32_t addr, uint16_t nb_sector) {
}
Ctrl_status sd_mmc_spi_usb_write_10(uint32_t addr, uint16_t nb_sector) {
#ifdef DISABLE_DUE_SD_MMC
#if ENABLED(DISABLE_DUE_SD_MMC)
return CTRL_NO_PRESENT;
#endif
if (sd_mmc_spi_removal()) return CTRL_NO_PRESENT;
#ifdef DEBUG_MMC

View file

@ -229,7 +229,7 @@ usb_iface_desc_t UDC_DESC_STORAGE *udc_get_interface_desc(void);
* - USB Device Controller (UDC) provides USB chapter 9 compliance
* - USB Device Interface (UDI) provides USB Class compliance
* - USB Device Driver (UDD) provides USB Driver for each Atmel MCU
*
* Many USB Device applications can be implemented on Atmel MCU.
* Atmel provides many application notes for different applications:
* - AVR4900, provides general information about Device Stack

View file

@ -523,7 +523,7 @@ static bool udd_ep_interrupt(void);
* \internal
* \brief Function called by UOTGHS interrupt to manage USB Device interrupts
*
* USB Device interrupt events are splited in three parts:
* USB Device interrupt events are split in three parts:
* - USB line events (SOF, reset, suspend, resume, wakeup)
* - control endpoint events (setup reception, end of data transfer, underflow, overflow, stall)
* - bulk/interrupt/isochronous endpoints events (end of data transfer)
@ -1567,7 +1567,7 @@ static void udd_ctrl_out_received(void)
udd_ctrl_payload_buf_cnt))) {
// End of reception because it is a short packet
// Before send ZLP, call intermediate callback
// in case of data receiv generate a stall
// in case of data receive generate a stall
udd_g_ctrlreq.payload_size = udd_ctrl_payload_buf_cnt;
if (NULL != udd_g_ctrlreq.over_under_run) {
if (!udd_g_ctrlreq.over_under_run()) {
@ -1808,7 +1808,7 @@ static void udd_ep_trans_done(udd_ep_id_t ep)
}
if (ptr_job->buf_cnt != ptr_job->buf_size) {
// Need to send or receiv other data
// Need to send or receive other data
next_trans = ptr_job->buf_size - ptr_job->buf_cnt;
if (UDD_ENDPOINT_MAX_TRANS < next_trans) {

View file

@ -34,13 +34,13 @@
#if ENABLED(WIFISUPPORT)
#include <ESPAsyncWebServer.h>
#include "wifi.h"
#include "wifi/wifi.h"
#if ENABLED(OTASUPPORT)
#include "ota.h"
#include "wifi/ota.h"
#endif
#if ENABLED(WEBSUPPORT)
#include "spiffs.h"
#include "web.h"
#include "wifi/spiffs.h"
#include "wifi/web.h"
#endif
#endif
@ -175,8 +175,6 @@ uint8_t MarlinHAL::get_reset_source() { return rtc_get_reset_reason(1); }
void MarlinHAL::reboot() { ESP.restart(); }
void _delay_ms(const int ms) { delay(ms); }
// return free memory between end of heap (or end bss) and whatever is current
int MarlinHAL::freeMemory() { return ESP.getFreeHeap(); }
@ -244,12 +242,13 @@ void MarlinHAL::adc_init() {
TERN_(HAS_TEMP_ADC_5, adc1_set_attenuation(get_channel(TEMP_5_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_6, adc2_set_attenuation(get_channel(TEMP_6_PIN), ADC_ATTEN_11db));
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_PROBE, adc1_set_attenuation(get_channel(TEMP_PROBE_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_COOLER, adc1_set_attenuation(get_channel(TEMP_COOLER_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_BOARD, adc1_set_attenuation(get_channel(TEMP_BOARD_PIN), ADC_ATTEN_11db));
TERN_(FILAMENT_WIDTH_SENSOR, adc1_set_attenuation(get_channel(FILWIDTH_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_BED, adc1_set_attenuation(get_channel(TEMP_BED_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_CHAMBER, adc1_set_attenuation(get_channel(TEMP_CHAMBER_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_PROBE, adc1_set_attenuation(get_channel(TEMP_PROBE_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_COOLER, adc1_set_attenuation(get_channel(TEMP_COOLER_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_BOARD, adc1_set_attenuation(get_channel(TEMP_BOARD_PIN), ADC_ATTEN_11db));
TERN_(HAS_FILWIDTH_ADC, adc1_set_attenuation(get_channel(FILWIDTH_PIN), ADC_ATTEN_11db));
TERN_(HAS_FILWIDTH2_ADC, adc1_set_attenuation(get_channel(FILWIDTH2_PIN), ADC_ATTEN_11db));
// Note that adc2 is shared with the WiFi module, which has higher priority, so the conversion may fail.
// That's why we're not setting it up here.

View file

@ -37,11 +37,11 @@
#include "i2s.h"
#if ENABLED(WIFISUPPORT)
#include "WebSocketSerial.h"
#include "wifi/WebSocketSerial.h"
#endif
#if ENABLED(ESP3D_WIFISUPPORT)
#include "esp3dlib.h"
#include <esp3dlib.h>
#endif
#include "FlushableHardwareSerial.h"
@ -165,8 +165,6 @@ int freeMemory();
#pragma GCC diagnostic pop
void _delay_ms(const int ms);
// ------------------------
// MarlinHAL Class
// ------------------------
@ -194,7 +192,7 @@ public:
static void isr_on() { if (spinlock.owner != portMUX_FREE_VAL) portEXIT_CRITICAL(&spinlock); }
static void isr_off() { portENTER_CRITICAL(&spinlock); }
static void delay_ms(const int ms) { _delay_ms(ms); }
static void delay_ms(const int ms) { delay(ms); }
// Tasks, called from idle()
static void idletask();

View file

@ -145,7 +145,7 @@ static void IRAM_ATTR i2s_intr_handler_default(void *arg) {
void stepperTask(void *parameter) {
uint32_t nextMainISR = 0;
#if ENABLED(LIN_ADVANCE)
uint32_t nextAdvanceISR = Stepper::LA_ADV_NEVER;
uint32_t nextAdvanceISR = stepper.LA_ADV_NEVER;
#endif
for (;;) {
@ -167,13 +167,13 @@ void stepperTask(void *parameter) {
if (!using_ftMotion) {
if (!nextMainISR) {
Stepper::pulse_phase_isr();
nextMainISR = Stepper::block_phase_isr();
stepper.pulse_phase_isr();
nextMainISR = stepper.block_phase_isr();
}
#if ENABLED(LIN_ADVANCE)
else if (!nextAdvanceISR) {
Stepper::advance_isr();
nextAdvanceISR = Stepper::la_interval;
stepper.advance_isr();
nextAdvanceISR = stepper.la_interval;
}
#endif
else
@ -182,10 +182,10 @@ void stepperTask(void *parameter) {
nextMainISR--;
#if ENABLED(LIN_ADVANCE)
if (nextAdvanceISR == Stepper::LA_ADV_NEVER)
nextAdvanceISR = Stepper::la_interval;
if (nextAdvanceISR == stepper.LA_ADV_NEVER)
nextAdvanceISR = stepper.la_interval;
if (nextAdvanceISR && nextAdvanceISR != Stepper::LA_ADV_NEVER)
if (nextAdvanceISR && nextAdvanceISR != stepper.LA_ADV_NEVER)
nextAdvanceISR--;
#endif
}

View file

@ -35,7 +35,7 @@
#if HAS_MEDIA
#include "../../sd/cardreader.h"
#if ENABLED(ESP3D_WIFISUPPORT)
#include "sd_ESP32.h"
#include <sd_ESP32.h>
#endif
#endif

View file

@ -21,7 +21,7 @@
*/
#ifdef ARDUINO_ARCH_ESP32
#include "../../inc/MarlinConfigPre.h"
#include "../../../inc/MarlinConfigPre.h"
#if ENABLED(WIFISUPPORT)

View file

@ -21,8 +21,8 @@
*/
#pragma once
#include "../../inc/MarlinConfig.h"
#include "../../core/serial_hook.h"
#include "../../../inc/MarlinConfig.h"
#include "../../../core/serial_hook.h"
#include <Stream.h>

View file

@ -27,7 +27,7 @@
#undef ENABLED
#undef DISABLED
#include "../../inc/MarlinConfigPre.h"
#include "../../../inc/MarlinConfigPre.h"
#if ALL(WIFISUPPORT, OTASUPPORT)

View file

@ -21,11 +21,11 @@
*/
#ifdef ARDUINO_ARCH_ESP32
#include "../../inc/MarlinConfigPre.h"
#include "../../../inc/MarlinConfigPre.h"
#if ALL(WIFISUPPORT, WEBSUPPORT)
#include "../../core/serial.h"
#include "../../../core/serial.h"
#include <FS.h>
#include <SPIFFS.h>

View file

@ -21,11 +21,11 @@
*/
#ifdef ARDUINO_ARCH_ESP32
#include "../../inc/MarlinConfigPre.h"
#include "../../../inc/MarlinConfigPre.h"
#if ALL(WIFISUPPORT, WEBSUPPORT)
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#undef DISABLED // esp32-hal-gpio.h
#include <SPIFFS.h>

View file

@ -21,11 +21,11 @@
*/
#ifdef ARDUINO_ARCH_ESP32
#include "../../inc/MarlinConfigPre.h"
#include "../../../inc/MarlinConfigPre.h"
#if ENABLED(WIFISUPPORT)
#include "../../core/serial.h"
#include "../../../core/serial.h"
#include <WiFi.h>
#include <ESPmDNS.h>

View file

@ -0,0 +1,120 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 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/>.
*
*/
#include "../platforms.h"
#ifdef ARDUINO_ARCH_MFL
#include "../../inc/MarlinConfig.h"
#include "../shared/Delay.h"
uint16_t MarlinHAL::adc_result;
#if ENABLED(POSTMORTEM_DEBUGGING)
extern void install_min_serial();
#endif
#if ENABLED(MARLIN_DEV_MODE)
// Dump the clock frequencies of the system, AHB, APB1, APB2, and F_CPU.
static inline void HAL_clock_frequencies_dump() {
auto& rcuInstance = rcu::RCU::get_instance();
uint32_t freq = rcuInstance.get_clock_frequency(rcu::Clock_Frequency::CK_SYS);
SERIAL_ECHOPGM("\nSYSTEM_CLOCK=", freq);
freq = rcuInstance.get_clock_frequency(rcu::Clock_Frequency::CK_AHB);
SERIAL_ECHOPGM("\nABH_CLOCK=", freq);
freq = rcuInstance.get_clock_frequency(rcu::Clock_Frequency::CK_APB1);
SERIAL_ECHOPGM("\nAPB1_CLOCK=", freq);
freq = rcuInstance.get_clock_frequency(rcu::Clock_Frequency::CK_APB2);
SERIAL_ECHOPGM("\nAPB2_CLOCK=", freq,
"\nF_CPU=", F_CPU);
// Done
SERIAL_ECHOPGM("\n--\n");
}
#endif // MARLIN_DEV_MODE
// Initializes the Marlin HAL
void MarlinHAL::init() {
constexpr unsigned int cpuFreq = F_CPU;
UNUSED(cpuFreq);
#if PIN_EXISTS(LED)
OUT_WRITE(LED_PIN, LOW);
#endif
SetTimerInterruptPriorities();
// Print clock frequencies to host serial
TERN_(MARLIN_DEV_MODE, HAL_clock_frequencies_dump());
// Register min serial
TERN_(POSTMORTEM_DEBUGGING, install_min_serial());
}
// Returns the reset source based on the flags set in the RCU module
uint8_t MarlinHAL::get_reset_source() {
return
(RCU_I.get_flag(rcu::Status_Flags::FLAG_FWDGTRST)) ? RST_WATCHDOG :
(RCU_I.get_flag(rcu::Status_Flags::FLAG_SWRST)) ? RST_SOFTWARE :
(RCU_I.get_flag(rcu::Status_Flags::FLAG_EPRST)) ? RST_EXTERNAL :
(RCU_I.get_flag(rcu::Status_Flags::FLAG_PORRST)) ? RST_POWER_ON :
(RCU_I.get_flag(rcu::Status_Flags::FLAG_LPRST)) ? RST_BROWN_OUT :
0;
}
// Returns the amount of free memory available in bytes
int MarlinHAL::freeMemory() {
volatile char top;
return &top - reinterpret_cast<char*>(_sbrk(0));
}
// Watchdog Timer
#if ENABLED(USE_WATCHDOG)
#define WDT_TIMEOUT_US TERN(WATCHDOG_DURATION_8S, 8000000, 4000000) // 4 or 8 second timeout
#include <FWatchdogTimer.h>
FWatchdogTimer& watchdogTimer = FWatchdogTimer::get_instance();
// Initializes the watchdog timer
void MarlinHAL::watchdog_init() {
IF_DISABLED(DISABLE_WATCHDOG_INIT, watchdogTimer.begin(WDT_TIMEOUT_US));
}
// Refreshes the watchdog timer to prevent system reset
void MarlinHAL::watchdog_refresh() {
watchdogTimer.reload();
#if DISABLED(PINS_DEBUGGING) && PIN_EXISTS(LED)
TOGGLE(LED_PIN); // Heartbeat indicator
#endif
}
#endif
extern "C" {
extern unsigned int _ebss; // End of bss section
}
// Resets the system to initiate a firmware flash.
WEAK void flashFirmware(const int16_t) {
hal.reboot();
}
#endif // ARDUINO_ARCH_MFL

View file

@ -0,0 +1,160 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 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
#define CPU_32_BIT
#include "../../core/macros.h"
#include "../shared/Marduino.h"
#include "../shared/math_32bit.h"
#include "../shared/HAL_SPI.h"
#include "temp_soc.h"
#include "fastio.h"
#include "Servo.h"
#include "../../inc/MarlinConfigPre.h"
#include <stdint.h>
#include <GPIO.hpp>
#include <AFIO.hpp>
// Default graphical display delays
#define CPU_ST7920_DELAY_1 300
#define CPU_ST7920_DELAY_2 40
#define CPU_ST7920_DELAY_3 340
// Serial Ports
#include "MarlinSerial.h"
// Interrupts
#define CRITICAL_SECTION_START() const bool irqon = !__get_PRIMASK(); __disable_irq()
#define CRITICAL_SECTION_END() if (irqon) __enable_irq()
#define cli() __disable_irq()
#define sei() __enable_irq()
// Alias of __bss_end__
#define __bss_end __bss_end__
// Types
typedef double isr_float_t; // FPU ops are used for single-precision, so use double for ISRs.
typedef uint8_t pin_t; // Parity with mfl platform
// Servo
class libServo;
typedef libServo hal_servo_t;
#define PAUSE_SERVO_OUTPUT() libServo::pause_all_servos()
#define RESUME_SERVO_OUTPUT() libServo::resume_all_servos()
// Debugging
#define JTAG_DISABLE() AFIO_I.set_remap(gpio::Pin_Remap_Select::SWJ_DP_ONLY_REMAP)
#define JTAGSWD_DISABLE() AFIO_I.set_remap(gpio::Pin_Remap_Select::SWJ_ALL_DISABLED_REMAP)
#define JTAGSWD_RESET() AFIO_I.set_remap(gpio::Pin_Remap_Select::FULL_SWJ_REMAP)
// ADC
#ifdef ADC_RESOLUTION
#define HAL_ADC_RESOLUTION ADC_RESOLUTION
#else
#define HAL_ADC_RESOLUTION 12
#endif
#define HAL_ADC_VREF_MV 3300
// Disable Marlin's software oversampling.
// The MFL framework uses 16x hardware oversampling by default
#ifdef GD32F303RE
#define HAL_ADC_FILTERED
#endif
#define GET_PIN_MAP_PIN(index) index
#define GET_PIN_MAP_INDEX(pin) pin
#define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval)
#ifndef PLATFORM_M997_SUPPORT
#define PLATFORM_M997_SUPPORT
#endif
void flashFirmware(const int16_t);
#define HAL_CAN_SET_PWM_FREQ // This HAL supports PWM Frequency adjustment
extern "C" char* _sbrk(int incr);
extern "C" char* dtostrf(double val, signed char width, unsigned char prec, char* sout);
// MarlinHAL Class
class MarlinHAL {
public:
// Before setup()
MarlinHAL() = default;
// Watchdog
static void watchdog_init() IF_DISABLED(USE_WATCHDOG, {});
static void watchdog_refresh() IF_DISABLED(USE_WATCHDOG, {});
static void init(); // called early in setup()
static void init_board() {} // called less early in setup()
static void reboot() { NVIC_SystemReset(); } // restart the firmware from 0x0
// Interrupts
static bool isr_state() { return !__get_PRIMASK(); }
static void isr_on() { sei(); }
static void isr_off() { cli(); }
static void delay_ms(const int ms) { delay(ms); }
// Tasks called from idle()
static void idletask() {}
// Reset
static uint8_t get_reset_source();
static void clear_reset_source() { RCU_I.clear_all_reset_flags(); }
// Free SRAM
static int freeMemory();
// ADC methods
static uint16_t adc_result;
// Called by Temperature::init once at startup
static void adc_init() { analogReadResolution(HAL_ADC_RESOLUTION); }
// Called by Temperature::init for each sensor at startup
static void adc_enable(const pin_t pin) { pinMode(pin, INPUT); }
// Called from Temperature::isr to start ADC sampling on the given pin
static void adc_start(const pin_t pin) { adc_result = static_cast<uint16_t>(analogRead(pin)); }
// Check if ADC is ready for reading
static bool adc_ready() { return true; }
// Current value of the ADC register
static uint16_t adc_value() { return adc_result; }
// Set the PWM duty cycle for the pin to the given value.
// Optionally invert the duty cycle [default = false]
// Optionally change the maximum size of the provided value to enable finer PWM duty control [default = 255]
static void set_pwm_duty(const pin_t pin, const uint16_t value, const uint16_t scale = 255U, const bool invert = false);
// Set the frequency of the timer for the given pin.
// All Timer PWM pins run at the same frequency.
static void set_pwm_frequency(const pin_t pin, const uint16_t f_desired);
};

View file

@ -0,0 +1,26 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 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 <SPI.h>
using MarlinSPI = SPIClass;

View file

@ -0,0 +1,97 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 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/>.
*
*/
#include "../platforms.h"
#ifdef ARDUINO_ARCH_MFL
#include "../../inc/MarlinConfig.h"
#include "MarlinSerial.h"
#if ENABLED(EMERGENCY_PARSER)
#include "../../feature/e_parser.h"
#endif
using namespace arduino;
auto MarlinSerial::get_instance(usart::USART_Base Base, pin_size_t rxPin, pin_size_t txPin) -> MarlinSerial& {
auto& serial = UsartSerial::get_instance(Base, rxPin, txPin);
return *reinterpret_cast<MarlinSerial*>(&serial);
}
#if USING_HW_SERIAL0
MSerialT MSerial0(true, MarlinSerial::get_instance(usart::USART_Base::USART0_BASE, NO_PIN, NO_PIN));
#endif
#if USING_HW_SERIAL1
MSerialT MSerial1(true, MarlinSerial::get_instance(usart::USART_Base::USART1_BASE, NO_PIN, NO_PIN));
#endif
#if USING_HW_SERIAL2
MSerialT MSerial2(true, MarlinSerial::get_instance(usart::USART_Base::USART2_BASE, NO_PIN, NO_PIN));
#endif
#if USING_HW_SERIAL3
MSerialT MSerial3(true, MarlinSerial::get_instance(usart::USART_Base::UART3_BASE, NO_PIN, NO_PIN));
#endif
#if USING_HW_SERIAL4
MSerialT MSerial4(true, MarlinSerial::get_instance(usart::USART_Base::UART4_BASE, NO_PIN, NO_PIN));
#endif
#if ENABLED(EMERGENCY_PARSER)
// This callback needs to access the specific MarlinSerial instance
// We'll use a static pointer to track the current instance
static MarlinSerial* current_serial_instance = nullptr;
static void emergency_callback() {
if (!current_serial_instance) return;
const auto last_data = current_serial_instance->get_last_data();
emergency_parser.update(current_serial_instance->emergency_state, last_data);
}
void MarlinSerial::register_emergency_callback(void (*callback)()) {
usart_.register_interrupt_callback(usart::Interrupt_Type::INTR_RBNEIE, callback);
}
#endif
void MarlinSerial::begin(unsigned long baudrate, uint16_t config) {
UsartSerial::begin(baudrate, config, ENABLED(SERIAL_DMA));
#if ENABLED(EMERGENCY_PARSER) && DISABLED(SERIAL_DMA)
current_serial_instance = this;
register_emergency_callback(emergency_callback);
#endif
}
void MarlinSerial::updateRxDmaBuffer() {
#if ENABLED(EMERGENCY_PARSER)
// Get the number of bytes available in the receive buffer
const size_t available_bytes = usart_.available_for_read(true);
// Process only the available data
for (size_t i = 0; i < available_bytes; ++i) {
uint8_t data;
if (usart_.read_rx_buffer(data))
emergency_parser.update(emergency_state, data);
}
#endif
// Call the base class implementation to handle any additional updates
UsartSerial::updateRxDmaBuffer();
}
#endif // ARDUINO_ARCH_MFL

View file

@ -0,0 +1,75 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 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/MarlinConfigPre.h"
#if ENABLED(EMERGENCY_PARSER)
#include "../../feature/e_parser.h"
#endif
#include <UsartSerial.hpp>
#include "../../core/serial_hook.h"
#define SERIAL_INDEX_MIN 0
#define SERIAL_INDEX_MAX 4
#include "../shared/serial_ports.h"
#if defined(LCD_SERIAL_PORT) && ANY(HAS_DGUS_LCD, EXTENSIBLE_UI)
#define LCD_SERIAL_TX_BUFFER_FREE() LCD_SERIAL.availableForWrite()
#endif
using namespace arduino;
struct MarlinSerial : public UsartSerial {
static auto get_instance(usart::USART_Base Base, pin_size_t rxPin = NO_PIN, pin_size_t txPin = NO_PIN) -> MarlinSerial&;
void begin(unsigned long baudrate, uint16_t config);
inline void begin(unsigned long baudrate) { begin(baudrate, SERIAL_8N1); }
void updateRxDmaBuffer();
#if DISABLED(SERIAL_DMA)
FORCE_INLINE static uint8_t buffer_overruns() { return 0; }
#endif
#if ENABLED(EMERGENCY_PARSER)
EmergencyParser::State emergency_state;
// Accessor method to get the last received byte
auto get_last_data() -> uint8_t { return usart_.get_last_data(); }
// Register the emergency callback
void register_emergency_callback(void (*callback)());
#endif
protected:
using UsartSerial::UsartSerial;
};
typedef Serial1Class<MarlinSerial> MSerialT;
extern MSerialT MSerial0;
extern MSerialT MSerial1;
extern MSerialT MSerial2;
extern MSerialT MSerial3;
extern MSerialT MSerial4;

View file

@ -0,0 +1,163 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 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/>.
*
*/
#include "../platforms.h"
#ifdef ARDUINO_ARCH_MFL
#include "../../inc/MarlinConfigPre.h"
#if ENABLED(POSTMORTEM_DEBUGGING)
#include "../shared/MinSerial.h"
// Base addresses for USART peripherals
static constexpr uintptr_t USART_base[] = {
0x40013800, // USART0
0x40004400, // USART1
0x40004800, // USART2
0x40004C00, // UART3
0x40005000 // UART4
};
// Register offsets
static constexpr uint32_t STAT0_OFFSET = 0x00U;
static constexpr uint32_t DATA_OFFSET = 0x04U;
static constexpr uint32_t BAUD_OFFSET = 0x08U;
static constexpr uint32_t CTL0_OFFSET = 0x0CU;
static constexpr uint32_t CTL1_OFFSET = 0x14U;
// Bit positions
static constexpr uint32_t TBE_BIT = 7;
static constexpr uint32_t TEN_BIT = 3;
static constexpr uint32_t UEN_BIT = 13;
// NVIC interrupt numbers for USART
static constexpr int nvicUART[] = { 37, 38, 39, 52, 53 };
// RCU PCLK values for USART
static constexpr rcu::RCU_PCLK clockRegs[] = {
rcu::RCU_PCLK::PCLK_USART0,
rcu::RCU_PCLK::PCLK_USART1,
rcu::RCU_PCLK::PCLK_USART2,
rcu::RCU_PCLK::PCLK_UART3,
rcu::RCU_PCLK::PCLK_UART4
};
// Memory barrier instructions
#define isb() __asm__ __volatile__ ("isb" : : : "memory")
#define dsb() __asm__ __volatile__ ("dsb" : : : "memory")
#define sw_barrier() __asm__ volatile("" : : : "memory")
// Direct register access macros
#define USART_REG(offset) (*(volatile uint32_t*)(USART_base[SERIAL_PORT] + (offset)))
#define USART_STAT0 USART_REG(STAT0_OFFSET)
#define USART_DATA USART_REG(DATA_OFFSET)
#define USART_BAUD USART_REG(BAUD_OFFSET)
#define USART_CTL0 USART_REG(CTL0_OFFSET)
#define USART_CTL1 USART_REG(CTL1_OFFSET)
// Bit manipulation macros
#define READ_BIT(reg, bit) (((reg) >> (bit)) & 1U)
#define SET_BIT(reg, bit) ((reg) |= (1U << (bit)))
#define CLEAR_BIT(reg, bit) ((reg) &= ~(1U << (bit)))
// Initializes the MinSerial interface.
// This function sets up the USART interface for serial communication.
// If the selected serial port is not a hardware port, it disables the severe error reporting feature.
static void MinSerialBegin() {
#if !WITHIN(SERIAL_PORT, 0, 4)
#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
int nvicIndex = nvicUART[SERIAL_PORT];
// NVIC base address for interrupt disable
struct NVICMin {
volatile uint32_t ISER[32];
volatile uint32_t ICER[32];
};
NVICMin *nvicBase = (NVICMin*)0xE000E100;
SBI32(nvicBase->ICER[nvicIndex >> 5], nvicIndex & 0x1F);
// We require memory barriers to properly disable interrupts
// (https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the)
dsb();
isb();
// Get the RCU PCLK for this USART
rcu::RCU_PCLK pclk = clockRegs[SERIAL_PORT];
// Disable then enable usart peripheral clocks
rcu::RCU_DEVICE.set_pclk_enable(pclk, false);
rcu::RCU_DEVICE.set_pclk_enable(pclk, true);
// Save current baudrate
uint32_t baudrate = USART_BAUD;
// Reset USART control registers
USART_CTL0 = 0;
USART_CTL1 = 0; // 1 stop bit
// Restore baudrate
USART_BAUD = baudrate;
// Enable transmitter and USART (8 bits, no parity, 1 stop bit)
SET_BIT(USART_CTL0, TEN_BIT);
SET_BIT(USART_CTL0, UEN_BIT);
#endif
}
// Writes a single character to the serial port.
static void MinSerialWrite(char c) {
#if WITHIN(SERIAL_PORT, 0, 4)
// Wait until transmit buffer is empty
while (!READ_BIT(USART_STAT0, TBE_BIT)) {
hal.watchdog_refresh();
sw_barrier();
}
// Write character to data register
USART_DATA = c;
#endif
}
// Installs the minimum serial interface.
// Sets the HAL_min_serial_init and HAL_min_serial_out function pointers to MinSerialBegin and MinSerialWrite respectively.
void install_min_serial() {
HAL_min_serial_init = &MinSerialBegin;
HAL_min_serial_out = &MinSerialWrite;
}
extern "C" {
// A low-level assembly-based jump handler.
// Unconditionally branches to the CommonHandler_ASM function.
__attribute__((naked, aligned(4))) void JumpHandler_ASM() {
__asm__ __volatile__ ("b CommonHandler_ASM\n");
}
void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) HardFault_Handler();
void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) BusFault_Handler();
void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) UsageFault_Handler();
void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) MemManage_Handler();
void __attribute__((naked, alias("JumpHandler_ASM"), nothrow)) NMI_Handler();
}
#endif // POSTMORTEM_DEBUGGING
#endif // ARDUINO_ARCH_MFL

View file

@ -0,0 +1,9 @@
# Generic GD32 HAL based on the MFL Arduino Core
This HAL is eventually intended to act as the generic HAL for all GD32 chips using the MFL library.
Currently it supports:
- GD32F303RET6
Targeting the official [MFL Arduino Core](https://github.com/bnmguy/ArduinoCore_MFL).

View file

@ -0,0 +1,125 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 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/>.
*
*/
#include "../platforms.h"
#ifdef ARDUINO_ARCH_MFL
#include "../../inc/MarlinConfig.h"
#if HAS_SERVOS
#include "Servo.h"
static uint_fast8_t servoCount = 0;
static libServo* servos[NUM_SERVOS] = {0};
constexpr millis_t servoDelay[] = SERVO_DELAY;
static_assert(COUNT(servoDelay) == NUM_SERVOS, "SERVO_DELAY must be an array NUM_SERVOS long.");
// Initialize to the default timer priority. This will be overridden by a call from timers.cpp.
// This allows all timer interrupt priorities to be managed from a single location in the HAL.
static uint32_t servo_interrupt_priority = NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 12, 0);
// This must be called after the MFL Servo class has initialized the timer.
// To be safe this is currently called after every call to attach().
static void fixServoTimerInterruptPriority() {
auto& servoTimerIdx = GeneralTimer::get_instance(static_cast<timer::TIMER_Base>(TIMER_SERVO));
NVIC_SetPriority(servoTimerIdx.getTimerUpIRQ(), servo_interrupt_priority);
}
// Default constructor for libServo class.
// Initializes the servo delay, pause state, and pause value.
// Registers the servo instance in the servos array.
libServo::libServo() :
delay(servoDelay[servoCount]),
was_attached_before_pause(false),
value_before_pause(0)
{
servos[servoCount++] = this;
}
// Attaches a servo to a specified pin.
int8_t libServo::attach(const int pin) {
if (servoCount >= MAX_SERVOS) return -1;
if (pin > 0) servoPin = pin;
auto result = mflServo.attach(servoPin);
fixServoTimerInterruptPriority();
return result;
}
// Attaches a servo to a specified pin with minimum and maximum pulse widths.
int8_t libServo::attach(const int pin, const int min, const int max) {
if (servoCount >= MAX_SERVOS) return -1;
if (pin > 0) servoPin = pin;
auto result = mflServo.attach(servoPin, min, max);
fixServoTimerInterruptPriority();
return result;
}
// Moves the servo to a specified position.
void libServo::move(const int value) {
if (attach(0) >= 0) {
mflServo.write(value);
safe_delay(delay);
TERN_(DEACTIVATE_SERVOS_AFTER_MOVE, detach());
}
}
// Pause the servo by detaching it and storing its current state.
void libServo::pause() {
was_attached_before_pause = mflServo.attached();
if (was_attached_before_pause) {
value_before_pause = mflServo.read();
mflServo.detach();
}
}
// Resume a previously paused servo.
// If the servo was attached before the pause, this function re-attaches
// the servo and moves it to the position it was in before the pause.
void libServo::resume() {
if (was_attached_before_pause) {
attach();
move(value_before_pause);
}
}
// Pause all servos by stopping their timers.
void libServo::pause_all_servos() {
for (auto& servo : servos)
if (servo) servo->pause();
}
// Resume all paused servos by starting their timers.
void libServo::resume_all_servos() {
for (auto& servo : servos)
if (servo) servo->resume();
}
// Set the interrupt priority for the servo.
// @param preemptPriority The preempt priority level.
// @param subPriority The sub priority level.
void libServo::setInterruptPriority(uint32_t preemptPriority, uint32_t subPriority) {
servo_interrupt_priority = NVIC_EncodePriority(NVIC_GetPriorityGrouping(), preemptPriority, subPriority);
}
#endif // HAS_SERVOS
#endif // ARDUINO_ARCH_MFL

View file

@ -0,0 +1,56 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 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 <Servo.h>
#include "../../core/millis_t.h"
// Inherit and expand on the official library
class libServo {
public:
libServo();
int8_t attach(const int pin = 0); // pin == 0 uses value from previous call
int8_t attach(const int pin, const int min, const int max);
void detach() { mflServo.detach(); }
int read() { return mflServo.read(); }
void move(const int value);
void pause();
void resume();
static void pause_all_servos();
static void resume_all_servos();
static void setInterruptPriority(uint32_t preemptPriority, uint32_t subPriority);
private:
Servo mflServo;
int servoPin = 0;
millis_t delay = 0;
bool was_attached_before_pause;
int value_before_pause;
};

View file

@ -0,0 +1,129 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm / Ryan Power
*
* 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/>.
*
*/
#ifdef ARDUINO_ARCH_MFL
#include "../../../inc/MarlinConfig.h"
#if ALL(HAS_MARLINUI_U8GLIB, FORCE_SOFT_SPI)
#include <U8glib-HAL.h>
#include "../../shared/HAL_SPI.h"
#define nop asm volatile ("\tnop\n")
static inline uint8_t swSpiTransfer_mode_0(uint8_t b) {
for (uint8_t i = 0; i < 8; ++i) {
const uint8_t state = (b & 0x80) ? HIGH : LOW;
WRITE(DOGLCD_SCK, HIGH);
WRITE(DOGLCD_MOSI, state);
b <<= 1;
WRITE(DOGLCD_SCK, LOW);
}
return b;
}
static inline uint8_t swSpiTransfer_mode_3(uint8_t b) {
for (uint8_t i = 0; i < 8; ++i) {
const uint8_t state = (b & 0x80) ? HIGH : LOW;
WRITE(DOGLCD_SCK, LOW);
WRITE(DOGLCD_MOSI, state);
b <<= 1;
WRITE(DOGLCD_SCK, HIGH);
}
return b;
}
static void u8g_sw_spi_shift_out(uint8_t val) {
#if U8G_SPI_USE_MODE_3
swSpiTransfer_mode_3(val);
#else
swSpiTransfer_mode_0(val);
#endif
}
static void swSpiInit() {
#if PIN_EXISTS(LCD_RESET)
SET_OUTPUT(LCD_RESET_PIN);
#endif
SET_OUTPUT(DOGLCD_A0);
OUT_WRITE(DOGLCD_SCK, LOW);
OUT_WRITE(DOGLCD_MOSI, LOW);
OUT_WRITE(DOGLCD_CS, HIGH);
}
uint8_t u8g_com_HAL_MFL_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
switch (msg) {
case U8G_COM_MSG_INIT:
swSpiInit();
break;
case U8G_COM_MSG_STOP:
break;
case U8G_COM_MSG_RESET:
#if PIN_EXISTS(LCD_RESET)
WRITE(LCD_RESET_PIN, arg_val);
#endif
break;
case U8G_COM_MSG_CHIP_SELECT:
#if U8G_SPI_USE_MODE_3 // This LCD SPI is running mode 3 while SD card is running mode 0
if (arg_val) { // SCK idle state needs to be set to the proper idle state before
// the next chip select goes active
WRITE(DOGLCD_SCK, HIGH); // Set SCK to mode 3 idle state before CS goes active
WRITE(DOGLCD_CS, LOW);
nop; // Hold SCK high for a few ns
nop;
}
else {
WRITE(DOGLCD_CS, HIGH);
WRITE(DOGLCD_SCK, LOW); // Set SCK to mode 0 idle state after CS goes inactive
}
#else
WRITE(DOGLCD_CS, !arg_val);
#endif
break;
case U8G_COM_MSG_WRITE_BYTE:
u8g_sw_spi_shift_out(arg_val);
break;
case U8G_COM_MSG_WRITE_SEQ: {
uint8_t* ptr = (uint8_t*)arg_ptr;
while (arg_val > 0) {
u8g_sw_spi_shift_out(*ptr++);
arg_val--;
}
} break;
case U8G_COM_MSG_WRITE_SEQ_P: {
uint8_t* ptr = (uint8_t*)arg_ptr;
while (arg_val > 0) {
u8g_sw_spi_shift_out(u8g_pgm_read(ptr));
ptr++;
arg_val--;
}
} break;
case U8G_COM_MSG_ADDRESS: // Define cmd (arg_val = 0) or data mode (arg_val = 1)
WRITE(DOGLCD_A0, arg_val);
break;
}
return 1;
}
#endif // HAS_MARLINUI_U8GLIB && FORCE_SOFT_SPI
#endif // ARDUINO_ARCH_MFL

View file

@ -0,0 +1,93 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 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/>.
*
*/
/**
* PersistentStore for Arduino-style EEPROM interface
* with simple implementations supplied by Marlin.
*/
#include "../../platforms.h"
#ifdef ARDUINO_ARCH_MFL
#include "../../../inc/MarlinConfig.h"
#if ENABLED(IIC_BL24CXX_EEPROM)
#include "../../shared/eeprom_if.h"
#include "../../shared/eeprom_api.h"
#ifndef MARLIN_EEPROM_SIZE
#error "MARLIN_EEPROM_SIZE is required for IIC_BL24CXX_EEPROM."
#endif
size_t PersistentStore::capacity() {
return MARLIN_EEPROM_SIZE - eeprom_exclude_size;
}
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;
uint8_t * const p = (uint8_t * const)REAL_EEPROM_ADDR(pos);
// EPROM has only ~100,000 write cycles,
// so only write bytes that have changed!
if (v != eeprom_read_byte(p)) {
eeprom_write_byte(p, v);
if (++written & 0x7F) delay(2); else safe_delay(2);
if (eeprom_read_byte(p) != v) {
SERIAL_ECHO_MSG(STR_ERR_EEPROM_WRITE);
return true;
}
}
crc16(crc, &v, 1);
pos++;
value++;
}
return false;
}
bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
do {
const uint8_t c = eeprom_read_byte((uint8_t*)REAL_EEPROM_ADDR(pos));
if (writing) *value = c;
crc16(crc, &c, 1);
pos++;
value++;
} while (--size);
return false;
}
#endif // IIC_BL24CXX_EEPROM
#endif // ARDUINO_ARCH_MFL

View file

@ -0,0 +1,54 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 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/>.
*
*/
/**
* Platform-independent Arduino functions for I2C EEPROM.
* Enable USE_SHARED_EEPROM if not supplied by the framework.
*/
#include "../../platforms.h"
#ifdef ARDUINO_ARCH_MFL
#include "../../../inc/MarlinConfig.h"
#if ENABLED(IIC_BL24CXX_EEPROM)
#include "../../../libs/BL24CXX.h"
#include "../../shared/eeprom_if.h"
void eeprom_init() {
BL24CXX::init();
}
void eeprom_write_byte(uint8_t *pos, uint8_t value) {
const unsigned eeprom_address = (unsigned)pos;
BL24CXX::writeOneByte(eeprom_address, value);
}
uint8_t eeprom_read_byte(uint8_t *pos) {
const unsigned eeprom_address = (unsigned)pos;
return BL24CXX::readOneByte(eeprom_address);
}
#endif // IIC_BL24CXX_EEPROM
#endif // ARDUINO_ARCH_MFL

View file

@ -0,0 +1,96 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 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/>.
*
*/
#include "../../platforms.h"
#ifdef ARDUINO_ARCH_MFL
#include "../../../inc/MarlinConfig.h"
#if USE_WIRED_EEPROM
/**
* PersistentStore for Arduino-style EEPROM interface
* with simple implementations supplied by Marlin.
*/
#include "../../shared/eeprom_if.h"
#include "../../shared/eeprom_api.h"
#ifndef MARLIN_EEPROM_SIZE
#define MARLIN_EEPROM_SIZE size_t(E2END + 1)
#endif
size_t PersistentStore::capacity() {
return MARLIN_EEPROM_SIZE - eeprom_exclude_size;
}
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;
uint8_t * const p = (uint8_t * const)REAL_EEPROM_ADDR(pos);
// EEPROM has only ~100,000 write cycles,
// so only write bytes that have changed!
if (v != eeprom_read_byte(p)) {
eeprom_write_byte(p, v);
// Avoid triggering watchdog during long EEPROM writes
if (++written & 0x7F)
delay(2);
else
safe_delay(2);
if (eeprom_read_byte(p) != v) {
SERIAL_ECHO_MSG(STR_ERR_EEPROM_WRITE);
return true;
}
}
crc16(crc, &v, 1);
pos++;
value++;
}
return false;
}
bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
do {
const uint8_t c = eeprom_read_byte((uint8_t*)REAL_EEPROM_ADDR(pos));
if (writing)
*value = c;
crc16(crc, &c, 1);
pos++;
value++;
} while (--size);
return false;
}
#endif // USE_WIRED_EEPROM
#endif // ARDUINO_ARCH_MFL

View file

@ -0,0 +1,61 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 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 "../../module/endstops.h"
// One ISR for all EXT-Interrupts
void endstop_ISR() { endstops.update(); }
void setup_endstop_interrupts() {
#define _ATTACH(P) attachInterrupt(P, endstop_ISR, CHANGE)
TERN_(USE_X_MAX, _ATTACH(X_MAX_PIN));
TERN_(USE_X_MIN, _ATTACH(X_MIN_PIN));
TERN_(USE_Y_MAX, _ATTACH(Y_MAX_PIN));
TERN_(USE_Y_MIN, _ATTACH(Y_MIN_PIN));
TERN_(USE_Z_MAX, _ATTACH(Z_MAX_PIN));
TERN_(USE_Z_MIN, _ATTACH(Z_MIN_PIN));
TERN_(USE_X2_MAX, _ATTACH(X2_MAX_PIN));
TERN_(USE_X2_MIN, _ATTACH(X2_MIN_PIN));
TERN_(USE_Y2_MAX, _ATTACH(Y2_MAX_PIN));
TERN_(USE_Y2_MIN, _ATTACH(Y2_MIN_PIN));
TERN_(USE_Z2_MAX, _ATTACH(Z2_MAX_PIN));
TERN_(USE_Z2_MIN, _ATTACH(Z2_MIN_PIN));
TERN_(USE_Z3_MAX, _ATTACH(Z3_MAX_PIN));
TERN_(USE_Z3_MIN, _ATTACH(Z3_MIN_PIN));
TERN_(USE_Z4_MAX, _ATTACH(Z4_MAX_PIN));
TERN_(USE_Z4_MIN, _ATTACH(Z4_MIN_PIN));
TERN_(USE_Z_MIN_PROBE, _ATTACH(Z_MIN_PROBE_PIN));
TERN_(USE_CALIBRATION, _ATTACH(CALIBRATION_PIN));
TERN_(USE_I_MAX, _ATTACH(I_MAX_PIN));
TERN_(USE_I_MIN, _ATTACH(I_MIN_PIN));
TERN_(USE_J_MAX, _ATTACH(J_MAX_PIN));
TERN_(USE_J_MIN, _ATTACH(J_MIN_PIN));
TERN_(USE_K_MAX, _ATTACH(K_MAX_PIN));
TERN_(USE_K_MIN, _ATTACH(K_MIN_PIN));
TERN_(USE_U_MAX, _ATTACH(U_MAX_PIN));
TERN_(USE_U_MIN, _ATTACH(U_MIN_PIN));
TERN_(USE_V_MAX, _ATTACH(V_MAX_PIN));
TERN_(USE_V_MIN, _ATTACH(V_MIN_PIN));
TERN_(USE_W_MAX, _ATTACH(W_MAX_PIN));
TERN_(USE_W_MIN, _ATTACH(W_MIN_PIN));
}

View file

@ -0,0 +1,97 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 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/>.
*
*/
#include "../platforms.h"
#ifdef ARDUINO_ARCH_MFL
#include "../../inc/MarlinConfig.h"
#include <PinOpsMap.hpp>
#include <PinOps.hpp>
#include "timers.h"
static uint16_t timer_frequency[TIMER_COUNT];
void MarlinHAL::set_pwm_duty(const pin_t pin, const uint16_t value, const uint16_t scale, const bool invert) {
// Calculate duty cycle based on inversion flag
const uint16_t duty = invert ? scale - value : value;
// Check if the pin supports PWM
if (PWM_PIN(pin)) {
// Get the timer peripheral base associated with the pin
const auto timer_base = getPinOpsPeripheralBase<TIMERPinOps, timer::TIMER_Base>(TIMER_PinOps, static_cast<pin_size_t>(pin));
// Initialize the timer instance
auto& TimerInstance = GeneralTimer::get_instance(timer_base);
// Get channel and previous channel mode
const auto channel = getPackedPinChannel(getPackedPinOps(TIMER_PinOps, static_cast<pin_size_t>(pin)));
const InputOutputMode previous = TimerInstance.getChannelMode(channel);
if (timer_frequency[static_cast<size_t>(timer_base)] == 0) {
set_pwm_frequency(pin, PWM_FREQUENCY);
}
// Set the PWM duty cycle
TimerInstance.setCaptureCompare(channel, duty, CCFormat::B8);
// Configure pin as PWM output
pinOpsPinout(TIMER_PinOps, static_cast<pin_size_t>(pin));
// Set channel mode if not already set and start timer
if (previous != InputOutputMode::PWM0) {
TimerInstance.setChannelMode(channel, InputOutputMode::PWM0, static_cast<pin_size_t>(pin));
TimerInstance.start();
}
} else {
pinMode(pin, OUTPUT);
digitalWrite(pin, duty < scale / 2 ? LOW : HIGH);
}
}
void MarlinHAL::set_pwm_frequency(const pin_t pin, const uint16_t f_desired) {
// Check if the pin supports PWM
if (!PWM_PIN(pin)) return;
// Get the timer peripheral base associated with the pin
const auto timer_base = getPinOpsPeripheralBase<TIMERPinOps, timer::TIMER_Base>(TIMER_PinOps, static_cast<pin_size_t>(pin));
// Guard against modifying protected timers
#ifdef STEP_TIMER
if (timer_base == static_cast<timer::TIMER_Base>(STEP_TIMER)) return;
#endif
#ifdef TEMP_TIMER
if (timer_base == static_cast<timer::TIMER_Base>(TEMP_TIMER)) return;
#endif
#if defined(PULSE_TIMER) && MF_TIMER_PULSE != MF_TIMER_STEP
if (timer_base == static_cast<timer::TIMER_Base>(PULSE_TIMER)) return;
#endif
// Initialize the timer instance
auto& TimerInstance = GeneralTimer::get_instance(timer_base);
TimerInstance.setRolloverValue(f_desired, TimerFormat::HERTZ);
timer_frequency[timer_base_to_index(timer_base)] = f_desired;
}
#endif // ARDUINO_ARCH_MFL

View file

@ -0,0 +1,86 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 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
// Fast I/O interfaces for GD32
#include <GPIO.hpp>
#include <variant.h>
#include <PinOps.hpp>
#include <PinOpsMap.hpp>
template<typename T>
FORCE_INLINE static void fast_write_pin_wrapper(pin_size_t IO, T V) {
const PortPinPair& pp = port_pin_map[IO];
gpio::fast_write_pin(pp.port, pp.pin, static_cast<bool>(V));
}
FORCE_INLINE static auto fast_read_pin_wrapper(pin_size_t IO) -> bool {
const PortPinPair& pp = port_pin_map[IO];
return gpio::fast_read_pin(pp.port, pp.pin);
}
FORCE_INLINE static void fast_toggle_pin_wrapper(pin_size_t IO) {
const PortPinPair& pp = port_pin_map[IO];
gpio::fast_toggle_pin(pp.port, pp.pin);
}
// ------------------------
// Defines
// ------------------------
#ifndef PWM
#define PWM OUTPUT
#endif
#define _WRITE(IO, V) fast_write_pin_wrapper(IO, V)
#define _READ(IO) fast_read_pin_wrapper(IO)
#define _TOGGLE(IO) fast_toggle_pin_wrapper(IO)
#define _GET_MODE(IO)
#define _SET_MODE(IO, M) pinMode((IO), (M))
#define _SET_OUTPUT(IO) pinMode((IO), OUTPUT)
#define _SET_OUTPUT_OD(IO) pinMode((IO), OUTPUT_OPEN_DRAIN)
#define WRITE(IO, V) _WRITE((IO), (V))
#define READ(IO) _READ(IO)
#define TOGGLE(IO) _TOGGLE(IO)
#define OUT_WRITE(IO, V) do { _SET_OUTPUT(IO); WRITE((IO), (V)); } while (0)
#define OUT_WRITE_OD(IO, V) do { _SET_OUTPUT_OD(IO); WRITE((IO), (V)); } while (0)
#define SET_INPUT(IO) _SET_MODE((IO), INPUT)
#define SET_INPUT_PULLUP(IO) _SET_MODE((IO), INPUT_PULLUP)
#define SET_INPUT_PULLDOWN(IO) _SET_MODE((IO), INPUT_PULLDOWN)
#define SET_OUTPUT(IO) OUT_WRITE((IO), LOW)
#define SET_OUTPUT_OD(IO) OUT_WRITE_OD((IO), LOW)
#define SET_PWM(IO) _SET_MODE((IO), PWM)
#define IS_INPUT(IO)
#define IS_OUTPUT(IO)
#define PWM_PIN(P) isPinInPinOps(TIMER_PinOps, P)
#define NO_COMPILE_TIME_PWM
// Wrappers for digitalRead and digitalWrite
#define extDigitalRead(IO) digitalRead(IO)
#define extDigitalWrite(IO, V) digitalWrite((IO), (V))

View file

@ -0,0 +1,26 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 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
#if ALL(HAS_MARLINUI_U8GLIB, FORCE_SOFT_SPI)
#define U8G_SW_SPI_MFL 1
#endif

View file

@ -0,0 +1,26 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 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
#if ALL(HAS_MEDIA, USBD_USE_CDC_MSC)
#define HAS_SD_HOST_DRIVE 1
#endif

View file

@ -0,0 +1,29 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 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
// If no real or emulated EEPROM selected, fall back to SD emulation
#if USE_FALLBACK_EEPROM
#define SDCARD_EEPROM_EMULATION
#elif ANY(I2C_EEPROM, SPI_EEPROM)
#define USE_SHARED_EEPROM 1
#endif

View file

@ -0,0 +1,22 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 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

View file

@ -0,0 +1,97 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 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
// Test MFL GD32 specific configuration values for errors at compile-time.
#if ENABLED(SDCARD_EEPROM_EMULATION) && !HAS_MEDIA
#undef SDCARD_EEPROM_EMULATION // avoid additional error noise
#if USE_FALLBACK_EEPROM
#warning "EEPROM type not specified. Fallback is SDCARD_EEPROM_EMULATION."
#endif
#error "SDCARD_EEPROM_EMULATION requires SDSUPPORT. Enable SDSUPPORT or choose another EEPROM emulation."
#endif
#if ENABLED(FLASH_EEPROM_LEVELING)
#error "FLASH_EEPROM_LEVELING is not supported on GD32."
#endif
#if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
#error "SERIAL_STATS_MAX_RX_QUEUED is not supported on GD32."
#elif ENABLED(SERIAL_STATS_DROPPED_RX)
#error "SERIAL_STATS_DROPPED_RX is not supported on GD32."
#endif
#if TEMP_SENSOR_SOC && defined(ATEMP) && TEMP_SOC_PIN != ATEMP
#error "TEMP_SENSOR_SOC requires 'TEMP_SOC_PIN ATEMP' on GD32"
#endif
// Check for common serial pin conflicts
#define _CHECK_SERIAL_PIN(N) (( \
BTN_EN1 == N || BTN_EN2 == N || DOGLCD_CS == N || HEATER_BED_PIN == N || FAN0_PIN == N || \
SDIO_D2_PIN == N || SDIO_D3_PIN == N || SDIO_CK_PIN == N || SDIO_CMD_PIN == N || \
Y_STEP_PIN == N || Y_ENABLE_PIN == N || E0_ENABLE_PIN == N || POWER_LOSS_PIN == N \
))
#define CHECK_SERIAL_PIN(T, N) defined(UART##N##_##T##_PIN) && _CHECK_SERIAL_PIN(UART##N##_##T##_PIN)
#if SERIAL_IN_USE(0)
#if CHECK_SERIAL_PIN(TX, 0)
#error "Serial Port 0 TX IO pins conflict with another pin on the board."
#endif
#if CHECK_SERIAL_PIN(RX, 0)
#error "Serial Port 0 RX IO pins conflict with another pin on the board."
#endif
#endif
#if SERIAL_IN_USE(1)
#if CHECK_SERIAL_PIN(TX, 1)
#error "Serial Port 1 TX IO pins conflict with another pin on the board."
#endif
#if CHECK_SERIAL_PIN(RX, 1)
#error "Serial Port 1 RX IO pins conflict with another pin on the board."
#endif
#endif
#if SERIAL_IN_USE(2)
#if CHECK_SERIAL_PIN(TX, 2)
#error "Serial Port 2 TX IO pins conflict with another pin on the board."
#endif
#if CHECK_SERIAL_PIN(RX, 2)
#error "Serial Port 2 RX IO pins conflict with another pin on the board."
#endif
#endif
#if SERIAL_IN_USE(3)
#if CHECK_SERIAL_PIN(TX, 3)
#error "Serial Port 3 TX IO pins conflict with another pin on the board."
#endif
#if CHECK_SERIAL_PIN(RX, 3)
#error "Serial Port 3 RX IO pins conflict with another pin on the board."
#endif
#endif
#if SERIAL_IN_USE(4)
#if CHECK_SERIAL_PIN(TX, 4)
#error "Serial Port 4 TX IO pins conflict with another pin on the board."
#endif
#if CHECK_SERIAL_PIN(RX, 4)
#error "Serial Port 4 RX IO pins conflict with another pin on the board."
#endif
#endif
#undef CHECK_SERIAL_PIN
#undef _CHECK_SERIAL_PIN

View file

@ -0,0 +1,104 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 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
/**
* Pins Debugging for GD32
*
* - NUMBER_PINS_TOTAL
* - MULTI_NAME_PAD
* - getPinByIndex(index)
* - printPinNameByIndex(index)
* - getPinIsDigitalByIndex(index)
* - digitalPinToAnalogIndex(pin)
* - getValidPinMode(pin)
* - isValidPin(pin)
* - isAnalogPin(pin)
* - digitalRead_mod(pin)
* - pwm_status(pin)
* - printPinPWM(pin)
* - printPinPort(pin)
* - printPinNumber(pin)
* - printPinAnalog(pin)
*/
#include "../../inc/MarlinConfig.h"
#include <Arduino.h>
#include <PinOps.hpp>
#include <Analog.h>
#ifndef TOTAL_PIN_COUNT
#error "Expected TOTAL_PIN_COUNT not found."
#endif
#define NUM_DIGITAL_PINS TOTAL_PIN_COUNT
#define NUMBER_PINS_TOTAL TOTAL_PIN_COUNT
#define getPinByIndex(x) pin_t(pin_array[x].pin)
#define isValidPin(P) WITHIN(P, 0, (NUM_DIGITAL_PINS - 1))
#define digitalRead_mod(P) extDigitalRead(P)
#define printPinNumber(P) do { sprintf_P(buffer, PSTR("%3hd "), pin_t(P)); SERIAL_ECHO(buffer); } while (0)
#define printPinAnalog(P) do { sprintf_P(buffer, PSTR(" (A%2d) "), pin_t(getAdcChannelFromPin(P))); SERIAL_ECHO(buffer); } while (0)
#define printPinNameByIndex(x) do { sprintf_P(buffer, PSTR("%-" STRINGIFY(MAX_NAME_LENGTH) "s"), pin_array[x].name); SERIAL_ECHO(buffer); } while (0)
#define MULTI_NAME_PAD 21 // Space needed to be pretty if not first name assigned to a pin
#ifndef M43_NEVER_TOUCH
#define M43_NEVER_TOUCH(x) WITHIN(x, 9, 10) // SERIAL pins: PA9(TX) PA10(RX)
#endif
bool isAnalogPin(const pin_t pin) {
if (!isValidPin(pin)) return false;
if (getAdcChannel(pin) != adc::ADC_Channel::INVALID) {
const PortPinPair& pp = port_pin_map[pin];
auto& instance = gpio::GPIO::get_instance(pp.port).value();
return instance.get_pin_mode(pp.pin) == gpio::Pin_Mode::ANALOG && !M43_NEVER_TOUCH(pin);
}
return false;
}
bool getValidPinMode(const pin_t pin) {
if (!isValidPin(pin)) return false;
const PortPinPair& pp = port_pin_map[pin];
auto& instance = gpio::GPIO::get_instance(pp.port).value();
gpio::Pin_Mode mode = instance.get_pin_mode(pp.pin);
return mode != gpio::Pin_Mode::ANALOG && mode != gpio::Pin_Mode::INPUT_FLOATING &&
mode != gpio::Pin_Mode::INPUT_PULLUP && mode != gpio::Pin_Mode::INPUT_PULLDOWN;
}
bool getPinIsDigitalByIndex(const int16_t index) {
const pin_t pin = getPinByIndex(index);
return (!isAnalogPin(pin));
}
int8_t digitalPinToAnalogIndex(const pin_t pin) {
if (!isValidPin(pin) || !isAnalogPin(pin)) return -1;
return pin; // Analog and digital pin indexes are shared
}
bool pwm_status(const pin_t pin) { return false; }
void printPinPWM(const pin_t pin) { /* TODO */ }
void printPinPort(const pin_t pin) { /* TODO */ }

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,222 @@
//
// MFL gd32f30x SDCARD using DMA through SDIO in C++
//
// Copyright (C) 2025 B. Mourit <bnmguy@gmail.com>
//
// This software is free software: you can redistribute it and/or modify it under the terms of the
// GNU Lesser General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License along with this software.
// If not, see <https://www.gnu.org/licenses/>.
//
#pragma once
#include "../../../inc/MarlinConfig.h"
#include <SDIO.hpp>
namespace sdio {
class DMA;
class CardDMA {
public:
static auto get_instance() -> CardDMA&;
// Initialization
auto init() -> SDIO_Error_Type;
auto card_init() -> SDIO_Error_Type;
// Startup and shutdown procedures
auto begin_startup_procedure() -> SDIO_Error_Type;
void begin_shutdown_procedure();
// Configuration
auto set_hardware_bus_width(Bus_Width width) -> SDIO_Error_Type;
auto send_bus_width_command(uint32_t width_value) -> SDIO_Error_Type;
// Main read/write/erase functions
auto read(uint8_t* buf, uint32_t address, uint32_t count) -> SDIO_Error_Type;
auto write(uint8_t* buf, uint32_t address, uint32_t count) -> SDIO_Error_Type;
auto erase(uint32_t address_start, uint32_t address_end) -> SDIO_Error_Type;
// Card select
auto select_deselect() -> SDIO_Error_Type;
// Status and state
auto get_card_interface_status(uint32_t* status) -> SDIO_Error_Type;
auto get_sdcard_status(uint32_t* status) -> SDIO_Error_Type;
auto get_transfer_state() -> Transfer_State;
auto get_card_state(Card_State* card_state) -> SDIO_Error_Type;
auto check_sdio_status(Command_Index index = Command_Index::INVALID, bool check_index = false, bool ignore_crc = false) -> SDIO_Error_Type;
// DMA
void set_dma_parameters(uint8_t* buf, uint32_t count, bool is_write);
void check_dma_complete();
// Stop transfer
auto stop_transfer() -> SDIO_Error_Type;
// Card information
auto get_card_specific_data(Card_Info* info) -> SDIO_Error_Type;
constexpr auto get_data_block_size_index(uint16_t size) -> Block_Size;
[[nodiscard]] auto get_card_capacity() const -> uint32_t;
// SDIO configuration
void sdio_configure(const SDIO_Config config) { sdio_.init(config); }
// Interrupt handler
void handle_interrupts();
// Variable stored parameters
auto get_scr(uint16_t rca, uint32_t* scr) -> SDIO_Error_Type;
auto store_cid() -> SDIO_Error_Type;
auto store_csd() -> SDIO_Error_Type;
// Inlined accessor methods
auto get_config() -> SDIO_Config& { return config_; }
auto get_dma_instance() -> dma::DMA& { return dma_; }
void set_data_end_interrupt() { sdio_.set_interrupt_enable(Interrupt_Type::DTENDIE, true); }
void set_sdio_dma_enable(bool enable) { sdio_.set_dma_enable(enable); }
auto get_is_sdio_rx() -> bool { return is_rx_; }
void clear_sdio_data_flags() { sdio_.clear_multiple_interrupt_flags(clear_data_flags); }
void clear_sdio_cmd_flags() { sdio_.clear_multiple_interrupt_flags(clear_command_flags); }
void clear_sdio_common_flags() { sdio_.clear_multiple_interrupt_flags(clear_common_flags); }
auto get_state() -> Operational_State { return current_state_; }
void set_state(Operational_State state) { current_state_ = state; }
void set_transfer_error(SDIO_Error_Type error) { transfer_error_ = error; }
void set_transfer_end(bool end) { transfer_end_ = end; };
auto set_desired_clock(uint32_t desired_clock, bool wide_bus, bool low_power) -> SDIO_Error_Type {
sdio_.init(SDIO_Config{
.desired_clock = desired_clock,
.enable_bypass = false,
.enable_powersave = low_power,
.enable_hwclock = false,
.clock_edge = Clock_Edge::RISING_EDGE,
.width = wide_bus ? Bus_Width::WIDTH_4BIT : Bus_Width::WIDTH_1BIT
});
sync_domains();
desired_clock_ = desired_clock;
return SDIO_Error_Type::OK;
}
private:
CardDMA();
// Prevent copying or assigning
CardDMA(const CardDMA&) = delete;
auto operator=(const CardDMA&) -> CardDMA& = delete;
// Helper function
auto wait_for_card_ready() -> SDIO_Error_Type;
// Member variables
alignas(4) uint32_t sdcard_csd_[4];
alignas(4) uint32_t sdcard_cid_[4];
alignas(4) uint32_t sdcard_scr_[2];
uint32_t desired_clock_;
uint32_t total_bytes_;
SDIO& sdio_;
SDIO_Config& config_;
const dma::DMA_Base dmaBase_;
const dma::DMA_Channel dmaChannel_;
dma::DMA& dma_;
uint16_t sdcard_rca_;
SDIO_Error_Type transfer_error_;
Interface_Version interface_version_;
Card_Type card_type_;
Operational_State current_state_;
bool transfer_end_;
bool multiblock_;
bool is_rx_;
// Private helper methods
auto validate_voltage() -> SDIO_Error_Type;
auto get_command_sent_result() -> SDIO_Error_Type;
auto get_r1_result(Command_Index index) -> SDIO_Error_Type;
auto get_r6_result(Command_Index index, uint16_t* rca) -> SDIO_Error_Type;
auto get_r7_result() -> SDIO_Error_Type { return check_sdio_status(Command_Index::INVALID, false, false); };
void sync_domains() { delayMicroseconds(8); }
auto validate_transfer_params(uint32_t* buf, uint16_t size) -> bool {
if (buf == nullptr) return false;
// Size must be > 0, <= 2048 and power of 2
return size > 0U && size <= 2048U && !(size & (size - 1U));
}
void process_sdsc_specific_csd(Card_Info* info, const uint8_t* csd_bytes) {
const uint32_t device_size = ((csd_bytes[6] & 0x3U) << 10) |
(csd_bytes[7] << 2) |
((csd_bytes[8] >> 6) & 0x3U);
const uint8_t device_size_multiplier = ((csd_bytes[9] & 0x3U) << 1) |
((csd_bytes[10] >> 7) & 0x1U);
// Store calculated values
info->csd.device_size = device_size;
info->csd.device_size_multiplier = device_size_multiplier;
// Calculate block size and capacity
info->block_size = 1U << info->csd.read_block_length;
info->capacity = (device_size + 1U) *
(1U << (device_size_multiplier + 2U)) *
info->block_size;
}
void process_sdhc_specific_csd(Card_Info* info, const uint8_t* csd_bytes) {
info->csd.device_size = static_cast<uint32_t>((csd_bytes[7] & 0x3FU) << 16) |
static_cast<uint32_t>((csd_bytes[8]) << 8) |
static_cast<uint32_t>(csd_bytes[9]);
// Set block size and calculate capacity
info->block_size = BLOCK_SIZE;
info->capacity = static_cast<uint32_t>((info->csd.device_size + 1U) *
BLOCK_SIZE * KILOBYTE);
}
void process_common_csd_tail(Card_Info* info, const uint8_t* csd_bytes) {
// Calculate sector_size
info->csd.sector_size = static_cast<uint8_t>(((csd_bytes[9] & 0x3FU) << 1) |
(csd_bytes[10] & 0x80U) >> 7);
// Calculate speed_factor and write_block_length
info->csd.speed_factor = static_cast<uint8_t>((csd_bytes[11] & 0x1CU) >> 2);
info->csd.write_block_length = static_cast<uint8_t>(((csd_bytes[11] & 0x3U) << 2) |
((csd_bytes[12] & 0xC0U) >> 6));
// Calculate checksum
info->csd.checksum = static_cast<uint8_t>((csd_bytes[15] & 0xFEU) >> 1);
}
void disable_all_interrupts() {
sdio_.set_interrupt_enable(Interrupt_Type::DTCRCERRIE, false);
sdio_.set_interrupt_enable(Interrupt_Type::DTTMOUTIE, false);
sdio_.set_interrupt_enable(Interrupt_Type::DTENDIE, false);
sdio_.set_interrupt_enable(Interrupt_Type::STBITEIE, false);
sdio_.set_interrupt_enable(Interrupt_Type::TFHIE, false);
sdio_.set_interrupt_enable(Interrupt_Type::RFHIE, false);
sdio_.set_interrupt_enable(Interrupt_Type::TXUREIE, false);
sdio_.set_interrupt_enable(Interrupt_Type::RXOREIE, false);
}
template <typename CheckFunc>
auto send_command_and_check(Command_Index command, uint32_t argument,
Command_Response response, Wait_Type type, CheckFunc check_result) -> SDIO_Error_Type {
sdio_.set_command_state_machine(command, argument, response, type);
sync_domains();
sdio_.set_command_state_machine_enable(true);
return check_result();
}
};
} // namespace sdio
extern sdio::CardDMA& CardDMA_I;

View file

@ -0,0 +1,231 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 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/>.
*
*/
#include "../../platforms.h"
#ifdef ARDUINO_ARCH_MFL
#include "../../../inc/MarlinConfig.h"
#if ENABLED(ONBOARD_SDIO)
#include <PinOpsMap.hpp>
#include <PinOps.hpp>
#include "SDCard.h"
#include "sdio.h"
using namespace sdio;
#define TARGET_CLOCK 6000000U
#define BLOCK_SIZE 512U
#define CARD_TIMEOUT 500 // ms
#define READ_RETRIES 3U
inline constexpr uint32_t TARGET_SDIO_CLOCK = TARGET_CLOCK;
inline constexpr uint32_t SDIO_BLOCK_SIZE = BLOCK_SIZE;
inline constexpr uint32_t SD_TIMEOUT = CARD_TIMEOUT;
inline constexpr uint8_t SDIO_READ_RETRIES = READ_RETRIES;
Card_State cardState = Card_State::READY;
auto SDIO_SetBusWidth(Bus_Width width) -> bool {
return (CardDMA_I.set_hardware_bus_width(width) == SDIO_Error_Type::OK);
}
void mfl_sdio_init() {
pinOpsPinout(SD_CMD_PinOps, static_cast<pin_size_t>(SDIO_CMD_PIN));
pinOpsPinout(SD_CK_PinOps, static_cast<pin_size_t>(SDIO_CK_PIN));
pinOpsPinout(SD_DATA0_PinOps, static_cast<pin_size_t>(SDIO_D0_PIN));
pinOpsPinout(SD_DATA1_PinOps, static_cast<pin_size_t>(SDIO_D1_PIN));
pinOpsPinout(SD_DATA2_PinOps, static_cast<pin_size_t>(SDIO_D2_PIN));
pinOpsPinout(SD_DATA3_PinOps, static_cast<pin_size_t>(SDIO_D3_PIN));
NVIC_EnableIRQ(DMA1_Channel3_4_IRQn);
NVIC_EnableIRQ(SDIO_IRQn);
}
bool SDIO_Init() {
SDIO_Error_Type result = SDIO_Error_Type::OK;
uint8_t retryCount = SDIO_READ_RETRIES;
mfl_sdio_init();
uint8_t retries = retryCount;
for (;;) {
hal.watchdog_refresh();
result = CardDMA_I.init();
if (result == SDIO_Error_Type::OK) break;
if (!--retries) return false;
}
CardDMA_I.set_desired_clock(TARGET_SDIO_CLOCK, false, false);
retries = retryCount;
for (;;) {
hal.watchdog_refresh();
if (SDIO_SetBusWidth(Bus_Width::WIDTH_4BIT)) break;
if (!--retries) break;
}
CardDMA_I.set_desired_clock(TARGET_SDIO_CLOCK, true, true);
// Fallback
if (!retries) {
mfl_sdio_init();
retries = retryCount;
for (;;) {
hal.watchdog_refresh();
result = CardDMA_I.init();
if (result == SDIO_Error_Type::OK) break;
if (!--retries) return false;
}
CardDMA_I.set_desired_clock(TARGET_SDIO_CLOCK, false, true);
}
return true;
}
static bool SDIO_ReadWriteBlock_DMA(uint32_t block, const uint8_t* src, uint8_t* dst) {
hal.watchdog_refresh();
SDIO_Error_Type result = SDIO_Error_Type::OK;
// Write
if (src) {
result = CardDMA_I.write(reinterpret_cast<uint8_t*>(const_cast<uint8_t*>(src)), block, 1);
}
// Read
else {
result = CardDMA_I.read(dst, block, 1);
}
if (result != SDIO_Error_Type::OK) {
return false;
}
millis_t timeout = millis() + SD_TIMEOUT;
while (CardDMA_I.get_state() != sdio::Operational_State::READY) {
if (ELAPSED(millis(), timeout)) {
return false;
}
}
CardDMA_I.check_dma_complete();
timeout = millis() + SD_TIMEOUT;
do {
result = CardDMA_I.get_card_state(&cardState);
if (ELAPSED(millis(), timeout)) {
return false;
}
} while (result == SDIO_Error_Type::OK && cardState != sdio::Card_State::TRANSFER);
return true;
}
bool SDIO_ReadBlock(uint32_t block, uint8_t* dst) {
// Check if the address is aligned to 4 bytes
if (reinterpret_cast<uint32_t>(dst) & 0x03) {
return false;
}
uint8_t retries = SDIO_READ_RETRIES;
while (retries--) {
if (SDIO_ReadWriteBlock_DMA(block, nullptr, dst)) {
return true;
}
}
return false;
}
bool SDIO_WriteBlock(uint32_t block, const uint8_t* src) {
// Check if the address is aligned to 4 bytes
if (reinterpret_cast<uint32_t>(src) & 0x03) {
return false;
}
uint8_t retries = SDIO_READ_RETRIES;
while (retries--) {
if (SDIO_ReadWriteBlock_DMA(block, src, nullptr)) {
return true;
delay(10);
}
}
return false;
}
bool SDIO_IsReady() {
return (CardDMA_I.get_state() == sdio::Operational_State::READY);
}
uint32_t SDIO_GetCardSize() {
return CardDMA_I.get_card_capacity();
}
// DMA interrupt handler
void DMA1_IRQHandler() {
auto& dma_instance = CardDMA_I.get_dma_instance();
bool is_receive = CardDMA_I.get_is_sdio_rx();
// Check for Transfer Complete Interrupt
if (dma_instance.get_interrupt_flag(dma::Interrupt_Flags::INTR_FLAG_FTFIF)) {
dma_instance.set_interrupt_enable(dma::Interrupt_Type::INTR_FTFIE, false);
dma_instance.set_interrupt_enable(dma::Interrupt_Type::INTR_ERRIE, false);
dma_instance.clear_interrupt_flag(dma::Interrupt_Flags::INTR_FLAG_FTFIF);
if (is_receive) {
CardDMA_I.set_sdio_dma_enable(false);
CardDMA_I.clear_sdio_data_flags();
CardDMA_I.set_state(sdio::Operational_State::READY);
} else {
CardDMA_I.set_data_end_interrupt();
}
// Signal that transfer is complete
CardDMA_I.set_transfer_end(true);
}
else if (dma_instance.get_interrupt_flag(dma::Interrupt_Flags::INTR_FLAG_ERRIF)) {
dma_instance.set_interrupt_enable(dma::Interrupt_Type::INTR_HTFIE, false);
dma_instance.set_interrupt_enable(dma::Interrupt_Type::INTR_ERRIE, false);
dma_instance.set_interrupt_enable(dma::Interrupt_Type::INTR_FTFIE, false);
// Clear all flags
dma_instance.clear_interrupt_flag(dma::Interrupt_Flags::INTR_FLAG_GIF);
// Signal that an error occurred
CardDMA_I.set_transfer_error(SDIO_Error_Type::ERROR);
CardDMA_I.set_state(sdio::Operational_State::READY);
}
}
extern "C" {
void SDIO_IRQHandler(void) {
CardDMA_I.handle_interrupts();
}
void DMA1_Channel3_4_IRQHandler(void) {
DMA1_IRQHandler();
}
} // extern "C"
#endif // ONBOARD_SDIO
#endif // ARDUINO_ARCH_MFL

View file

@ -0,0 +1,36 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 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 <SDIO.hpp>
#include <DMA.hpp>
#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
void sdio_mfl_init();
auto SDIO_SetBusWidth(sdio::Bus_Width width) -> bool;
void DMA1_IRQHandler(dma::DMA_Channel channel);

View file

@ -0,0 +1,32 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 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
// Define SPI Pins: SCK, MISO, MOSI
#ifndef SD_SCK_PIN
#define SD_SCK_PIN PIN_SPI_SCK
#endif
#ifndef SD_MISO_PIN
#define SD_MISO_PIN PIN_SPI_MISO
#endif
#ifndef SD_MOSI_PIN
#define SD_MOSI_PIN PIN_SPI_MOSI
#endif

View file

@ -0,0 +1,29 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 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
#define TS_TYPICAL_V 1.405
#define TS_TYPICAL_TEMP 25
#define TS_TYPICAL_SLOPE 4.5
// TODO: Implement voltage scaling (calibrated Vrefint) and ADC resolution scaling (when applicable)
#define TEMP_SOC_SENSOR(RAW) ((TS_TYPICAL_V - (RAW) / float(OVERSAMPLENR) / float(HAL_ADC_RANGE) * (float(ADC_VREF_MV) / 1000.0f)) / ((TS_TYPICAL_SLOPE) / 1000.0f) + TS_TYPICAL_TEMP)

View file

@ -0,0 +1,240 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 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/>.
*
*/
#include "../platforms.h"
#ifdef ARDUINO_ARCH_MFL
#include "../../inc/MarlinConfig.h"
#include "timers.h"
// ------------------------
// Local defines
// ------------------------
#define SWSERIAL_TIMER_IRQ_PRIORITY_DEFAULT 1 // Requires tight bit timing to communicate reliably with TMC drivers
#define SERVO_TIMER_IRQ_PRIORITY_DEFAULT 1 // Requires tight PWM timing to control a BLTouch reliably
#define STEP_TIMER_IRQ_PRIORITY_DEFAULT 2
#define TEMP_TIMER_IRQ_PRIORITY_DEFAULT 14 // Low priority avoids interference with other hardware and timers
#ifndef TIMER_IRQ_PRIORITY
#define TIMER_IRQ_PRIORITY 12
#endif
#ifndef STEP_TIMER_IRQ_PRIORITY
#define STEP_TIMER_IRQ_PRIORITY STEP_TIMER_IRQ_PRIORITY_DEFAULT
#endif
#ifndef TEMP_TIMER_IRQ_PRIORITY
#define TEMP_TIMER_IRQ_PRIORITY TEMP_TIMER_IRQ_PRIORITY_DEFAULT
#endif
#if HAS_TMC_SW_SERIAL
#include <SoftwareSerial.h>
#ifndef SWSERIAL_TIMER_IRQ_PRIORITY
#define SWSERIAL_TIMER_IRQ_PRIORITY SWSERIAL_TIMER_IRQ_PRIORITY_DEFAULT
#endif
#endif
#if HAS_SERVOS
#include "Servo.h"
#ifndef SERVO_TIMER_IRQ_PRIORITY
#define SERVO_TIMER_IRQ_PRIORITY SERVO_TIMER_IRQ_PRIORITY_DEFAULT
#endif
#endif
#if ENABLED(SPEAKER)
// The MFL framework default timer priority is 12. The TEMP timer must have lower priority
// than this due to the long running temperature ISR, and STEP timer should higher priority.
#if !(TIMER_IRQ_PRIORITY > STEP_TIMER_IRQ_PRIORITY && TIMER_IRQ_PRIORITY < TEMP_TIMER_IRQ_PRIORITY)
#error "Default timer interrupt priority is unspecified or set to a value which may degrade performance."
#endif
#endif
#ifndef HAL_TIMER_RATE
#define HAL_TIMER_RATE GetStepperTimerClkFreq()
#endif
#ifndef STEP_TIMER
#define STEP_TIMER MF_TIMER_STEP
#endif
#ifndef TEMP_TIMER
#define TEMP_TIMER MF_TIMER_TEMP
#endif
GeneralTimer& Step_Timer = GeneralTimer::get_instance(static_cast<timer::TIMER_Base>(STEP_TIMER));
GeneralTimer& Temp_Timer = GeneralTimer::get_instance(static_cast<timer::TIMER_Base>(TEMP_TIMER));
bool is_step_timer_initialized = false;
bool is_temp_timer_initialized = false;
// ------------------------
// Public functions
// ------------------------
// Retrieves the clock frequency of the stepper timer
uint32_t GetStepperTimerClkFreq() {
// Cache result
static uint32_t clkFreq = Step_Timer.getTimerClockFrequency();
return clkFreq;
}
/**
* @brief Starts a hardware timer
*
* If the timer is not already initialized, this function will initialize it with the given frequency.
* The timer is started immediately after initialization
*
* @param timer The timer base index to start
* @param frequency The frequency at which the timer should run
* @return None
*/
void HAL_timer_start(const uint8_t timer_number, const uint32_t frequency) {
if (HAL_timer_initialized(timer_number) || (timer_number != MF_TIMER_STEP && timer_number != MF_TIMER_TEMP))
return;
const bool is_step = (timer_number == MF_TIMER_STEP);
const uint8_t priority = is_step ?
static_cast<uint8_t>(STEP_TIMER_IRQ_PRIORITY) :
static_cast<uint8_t>(TEMP_TIMER_IRQ_PRIORITY);
// Get the reference of the timer instance
GeneralTimer& timer = is_step ? Step_Timer : Temp_Timer;
if (is_step) {
timer.setPrescaler(STEPPER_TIMER_PRESCALE);
timer.setRolloverValue(_MIN(static_cast<hal_timer_t>(HAL_TIMER_TYPE_MAX),
(HAL_TIMER_RATE) / (STEPPER_TIMER_PRESCALE)),
TimerFormat::TICK);
is_step_timer_initialized = true;
}
else {
timer.setRolloverValue(frequency, TimerFormat::HERTZ);
is_temp_timer_initialized = true;
}
timer.setAutoReloadEnable(false);
timer.setInterruptPriority(priority, 0U);
HAL_timer_enable_interrupt(timer_number);
timer.start();
}
/**
* @brief Enables the interrupt for the specified timer
*
* @param handle The timer handle for which to enable the interrupt
* @return None
*/
void HAL_timer_enable_interrupt(const uint8_t timer_number) {
if (!HAL_timer_initialized(timer_number)) return;
GeneralTimer& timer = (timer_number == MF_TIMER_STEP) ? Step_Timer : Temp_Timer;
if (timer_number == MF_TIMER_STEP && !timer.hasInterrupt())
timer.attachInterrupt(Step_Handler);
else if (timer_number == MF_TIMER_TEMP && !timer.hasInterrupt())
timer.attachInterrupt(Temp_Handler);
}
/**
* @brief Disables the interrupt for the specified timer
*
* @param handle The timer handle for which to disable the interrupt
* @return None
*/
void HAL_timer_disable_interrupt(const uint8_t timer_number) {
if (!HAL_timer_initialized(timer_number)) return;
GeneralTimer& timer = (timer_number == MF_TIMER_STEP) ? Step_Timer : Temp_Timer;
if (timer_number == MF_TIMER_STEP || timer_number == MF_TIMER_TEMP)
timer.detachInterrupt();
}
/**
* @brief Checks if the interrupt is enabled for the specified timer
*
* @param handle The timer handle to check
* @return True if the interrupt is enabled, false otherwise
*/
bool HAL_timer_interrupt_enabled(const uint8_t timer_number) {
if (!HAL_timer_initialized(timer_number)) return false;
GeneralTimer& timer = (timer_number == MF_TIMER_STEP) ? Step_Timer : Temp_Timer;
return (timer_number == MF_TIMER_STEP || timer_number == MF_TIMER_TEMP)
? timer.hasInterrupt()
: false;
}
// Sets the interrupt priorities for timers used by TMC SW serial and servos.
void SetTimerInterruptPriorities() {
TERN_(HAS_TMC_SW_SERIAL, SoftwareSerial::setInterruptPriority(SWSERIAL_TIMER_IRQ_PRIORITY, 0));
TERN_(HAS_SERVOS, libServo::setInterruptPriority(SERVO_TIMER_IRQ_PRIORITY, 0));
}
// ------------------------
// Detect timer conflicts
// ------------------------
TERN_(HAS_TMC_SW_SERIAL, static constexpr timer::TIMER_Base timer_serial[] = {static_cast<timer::TIMER_Base>(TIMER_SERIAL)});
TERN_(SPEAKER, static constexpr timer::TIMER_Base timer_tone[] = {static_cast<timer::TIMER_Base>(TIMER_TONE)});
TERN_(HAS_SERVOS, static constexpr timer::TIMER_Base timer_servo[] = {static_cast<timer::TIMER_Base>(TIMER_SERVO)});
enum TimerPurpose {
PURPOSE_SERIAL,
PURPOSE_TONE,
PURPOSE_SERVO,
PURPOSE_STEP,
PURPOSE_TEMP
};
// List of timers to check for conflicts
// Includes the timer purpose to ease debugging when evaluating at build-time
// This cannot yet account for timers used for PWM output, such as for fans
static constexpr struct { TimerPurpose p; int t; } timers_in_use[] = {
#if HAS_TMC_SW_SERIAL
{ PURPOSE_SERIAL, timer_base_to_index(timer_serial[0]) }, // Set in variant.h
#endif
#if ENABLED(SPEAKER)
{ PURPOSE_TONE, timer_base_to_index(timer_tone[0]) }, // Set in variant.h
#endif
#if HAS_SERVOS
{ PURPOSE_SERVO, timer_base_to_index(timer_servo[0]) }, // Set in variant.h
#endif
{ PURPOSE_STEP, MF_TIMER_STEP },
{ PURPOSE_TEMP, MF_TIMER_TEMP },
};
// Verifies if there are any timer conflicts in the timers_in_use array
static constexpr bool verify_no_timer_conflicts() {
for (uint8_t i = 0; i < COUNT(timers_in_use); i++)
for (uint8_t j = i + 1; j < COUNT(timers_in_use); j++)
if (timers_in_use[i].t == timers_in_use[j].t)
return false;
return true;
}
// If this assertion fails at compile time, review the timers_in_use array.
// If default_envs is defined properly in platformio.ini, VSCode can evaluate the array
// when hovering over it, making it easy to identify the conflicting timers
static_assert(verify_no_timer_conflicts(), "One or more timer conflict detected. Examine \"timers_in_use\" to help identify conflict.");
#endif // ARDUINO_ARCH_MFL

View file

@ -0,0 +1,145 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 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"
#include <GeneralTimer.h>
// ------------------------
// Defines
// ------------------------
// Timer configuration constants
#define STEPPER_TIMER_RATE 2000000
#define TEMP_TIMER_FREQUENCY 1000
// Timer instance definitions
#define MF_TIMER_STEP 3
#define MF_TIMER_TEMP 1
#define MF_TIMER_PULSE MF_TIMER_STEP
#define hal_timer_t uint32_t
#define HAL_TIMER_TYPE_MAX UINT16_MAX
extern uint32_t GetStepperTimerClkFreq();
// Timer prescaler calculations
#define STEPPER_TIMER_PRESCALE (GetStepperTimerClkFreq() / STEPPER_TIMER_RATE) // Prescaler = 30
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // Stepper timer ticks per µs
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
// Timer interrupt priorities
#define STEP_TIMER_IRQ_PRIORITY 2
#define TEMP_TIMER_IRQ_PRIORITY 14
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_STEP)
#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(MF_TIMER_STEP)
#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_TEMP)
#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_TEMP)
extern void Step_Handler();
extern void Temp_Handler();
#ifndef HAL_STEP_TIMER_ISR
#define HAL_STEP_TIMER_ISR() void Step_Handler()
#endif
#ifndef HAL_TEMP_TIMER_ISR
#define HAL_TEMP_TIMER_ISR() void Temp_Handler()
#endif
extern GeneralTimer& Step_Timer;
extern GeneralTimer& Temp_Timer;
extern bool is_step_timer_initialized;
extern bool is_temp_timer_initialized;
// Build-time mapping between timer base and index. Used in timers.cpp and fast_pwm.cpp
static inline constexpr struct {timer::TIMER_Base base; uint8_t timer_number;} base_to_index[] = {
{ timer::TIMER_Base::TIMER0_BASE, 0 },
{ timer::TIMER_Base::TIMER1_BASE, 1 },
{ timer::TIMER_Base::TIMER2_BASE, 2 },
{ timer::TIMER_Base::TIMER3_BASE, 3 },
{ timer::TIMER_Base::TIMER4_BASE, 4 },
{ timer::TIMER_Base::TIMER5_BASE, 5 },
{ timer::TIMER_Base::TIMER6_BASE, 6 },
{ timer::TIMER_Base::TIMER7_BASE, 7 }
};
// Converts a timer base to an integer timer index.
constexpr auto timer_base_to_index(timer::TIMER_Base base) -> int {
for (const auto& timer : base_to_index) {
if (timer.base == base) {
return static_cast<int>(timer.timer_number);
}
}
return -1;
}
// ------------------------
// Public functions
// ------------------------
void HAL_timer_start(const uint8_t timer, const uint32_t frequency);
void HAL_timer_enable_interrupt(const uint8_t timer);
void HAL_timer_disable_interrupt(const uint8_t timer);
bool HAL_timer_interrupt_enabled(const uint8_t timer);
// Configure timer priorities for peripherals such as Software Serial or Servos.
// Exposed here to allow all timer priority information to reside in timers.cpp
void SetTimerInterruptPriorities();
// FORCE_INLINE because these are used in performance-critical situations
FORCE_INLINE bool HAL_timer_initialized(const uint8_t timer_number) {
return (timer_number == MF_TIMER_STEP) ? is_step_timer_initialized :
(timer_number == MF_TIMER_TEMP) ? is_temp_timer_initialized :
false;
}
FORCE_INLINE static hal_timer_t HAL_timer_get_count(const uint8_t timer_number) {
if (!HAL_timer_initialized(timer_number)) return 0U;
GeneralTimer& timer = (timer_number == MF_TIMER_STEP) ? Step_Timer : Temp_Timer;
return (timer_number == MF_TIMER_STEP || timer_number == MF_TIMER_TEMP)
? timer.getCounter(TimerFormat::TICK)
: 0U;
}
FORCE_INLINE static void HAL_timer_set_compare(const uint8_t timer_number, const hal_timer_t value) {
if (!HAL_timer_initialized(timer_number)) return;
const auto new_value = static_cast<uint32_t>(value + 1U);
GeneralTimer& timer = (timer_number == MF_TIMER_STEP) ? Step_Timer : Temp_Timer;
if (timer_number == MF_TIMER_STEP || timer_number == MF_TIMER_TEMP) {
timer.setRolloverValue(new_value, TimerFormat::TICK);
if (value < static_cast<hal_timer_t>(timer.getCounter(TimerFormat::TICK)))
timer.refresh();
}
}
#define HAL_timer_isr_prologue(T) NOOP
#define HAL_timer_isr_epilogue(T) NOOP

View file

@ -0,0 +1,26 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 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
// MFL LCD-specific defines
uint8_t u8g_com_HAL_MFL_sw_spi_fn(u8g_t* u8g, uint8_t msg, uint8_t arg_val, void* arg_ptr); // u8g_com_mfl_swspi.cpp
#define U8G_COM_HAL_SW_SPI_FN u8g_com_HAL_MFL_sw_spi_fn

View file

@ -27,7 +27,7 @@
#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#endif
#include HAL_PATH(..,HAL.h)
#include HAL_PATH(.., HAL.h)
extern MarlinHAL hal;
#define HAL_ADC_RANGE _BV(HAL_ADC_RESOLUTION)

View file

@ -26,12 +26,12 @@
*/
#ifdef ARDUINO_ARCH_HC32
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if ENABLED(IIC_BL24CXX_EEPROM)
#include "../shared/eeprom_api.h"
#include "../shared/eeprom_if.h"
#include "../../shared/eeprom_api.h"
#include "../../shared/eeprom_if.h"
#ifndef MARLIN_EEPROM_SIZE
#error "MARLIN_EEPROM_SIZE is required for IIC_BL24CXX_EEPROM."

View file

@ -26,12 +26,12 @@
*/
#ifdef ARDUINO_ARCH_HC32
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if ENABLED(IIC_BL24CXX_EEPROM)
#include "../../libs/BL24CXX.h"
#include "../shared/eeprom_if.h"
#include "../../../libs/BL24CXX.h"
#include "../../shared/eeprom_if.h"
void eeprom_init() {
BL24CXX::init();
@ -39,7 +39,7 @@ void eeprom_init() {
void eeprom_write_byte(uint8_t *pos, unsigned char value) {
const unsigned eeprom_address = (unsigned)pos;
return BL24CXX::writeOneByte(eeprom_address, value);
BL24CXX::writeOneByte(eeprom_address, value);
}
uint8_t eeprom_read_byte(uint8_t *pos) {

View file

@ -25,12 +25,12 @@
*/
#ifdef ARDUINO_ARCH_HC32
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if ENABLED(SDCARD_EEPROM_EMULATION)
#include "../shared/eeprom_api.h"
#include "../../sd/cardreader.h"
#include "../../shared/eeprom_api.h"
#include "../../../sd/cardreader.h"
#define EEPROM_FILENAME "eeprom.dat"
@ -53,7 +53,7 @@ bool PersistentStore::access_start() {
int bytes_read = file.read(HAL_eeprom_data, MARLIN_EEPROM_SIZE);
if (bytes_read < 0) return false;
for (; bytes_read < MARLIN_EEPROM_SIZE; bytes_read++)
for (; bytes_read < long(MARLIN_EEPROM_SIZE); bytes_read++)
HAL_eeprom_data[bytes_read] = 0xFF;
file.close();

View file

@ -2,6 +2,9 @@
* Marlin 3D Printer Firmware
* Copyright (c) 2023 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
@ -18,7 +21,7 @@
*/
#ifdef ARDUINO_ARCH_HC32
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if USE_WIRED_EEPROM
@ -29,8 +32,8 @@
* with simple implementations supplied by Marlin.
*/
#include "../shared/eeprom_if.h"
#include "../shared/eeprom_api.h"
#include "../../shared/eeprom_if.h"
#include "../../shared/eeprom_api.h"
#ifndef MARLIN_EEPROM_SIZE
#error "MARLIN_EEPROM_SIZE is required for I2C / SPI EEPROM."

View file

@ -2,6 +2,9 @@
* Marlin 3D Printer Firmware
* Copyright (c) 2023 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

View file

@ -2,6 +2,9 @@
* Marlin 3D Printer Firmware
* Copyright (c) 2023 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

View file

@ -49,7 +49,7 @@ extern Timer0 step_timer;
* See https://github.com/MarlinFirmware/Marlin/pull/27099 for more information.
*
* NOTE: If the 'constexpr' requirement is ever lifted, TIMER0_BASE_FREQUENCY could
* be used instead. Tho this would probably not make any noticable difference.
* be used instead. Tho this would probably not make any noticeable difference.
*/
#define HAL_TIMER_RATE F_PCLK1

View file

@ -124,7 +124,7 @@ public:
static void isr_on() {}
static void isr_off() {}
static void delay_ms(const int ms) { _delay_ms(ms); }
static void delay_ms(const int ms) { delay(ms); }
// Tasks, called from idle()
static void idletask() {}

View file

@ -31,10 +31,8 @@ void cli() { } // Disable
void sei() { } // Enable
// Time functions
void _delay_ms(const int ms) { delay(ms); }
uint32_t millis() {
return (uint32_t)Clock::millis();
unsigned long millis() {
return (unsigned long)Clock::millis();
}
// This is required for some Arduino libraries we are using

View file

@ -45,7 +45,7 @@ bool PersistentStore::access_start() {
fseek(eeprom_file, 0L, SEEK_END);
std::size_t file_size = ftell(eeprom_file);
if (file_size < MARLIN_EEPROM_SIZE) {
if (file_size < long(MARLIN_EEPROM_SIZE)) {
memset(buffer + file_size, eeprom_erase_value, MARLIN_EEPROM_SIZE - file_size);
}
else {

View file

@ -74,11 +74,10 @@ extern "C" {
// Time functions
extern "C" void delay(const int ms);
void _delay_ms(const int ms);
void delayMicroseconds(unsigned long);
uint32_t millis();
unsigned long millis();
//IO functions
// IO functions
void pinMode(const pin_t, const uint8_t);
void digitalWrite(pin_t, uint8_t);
bool digitalRead(pin_t);

View file

@ -173,13 +173,8 @@ void MarlinHAL::init() {
// HAL idle task
void MarlinHAL::idletask() {
#if HAS_SHARED_MEDIA
// If Marlin is using the SD card we need to lock it to prevent access from
// a PC via USB.
// Other HALs use IS_SD_PRINTING() and IS_SD_FILE_OPEN() to check for access but
// this will not reliably detect delete operations. To be safe we will lock
// the disk if Marlin has it mounted. Unfortunately there is currently no way
// to unmount the disk from the LCD menu.
// if (IS_SD_PRINTING() || IS_SD_FILE_OPEN())
// When Marlin is using the SD Card it must be locked to prevent PC access via USB.
// For maximum safety we lock the disk if Marlin has it mounted for any reason.
if (card.isMounted())
MSC_Aquire_Lock();
else

View file

@ -36,11 +36,11 @@
* 16Kb I/O buffers (intended to hold DMA USB and Ethernet data, but currently
* unused).
*/
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if ENABLED(FLASH_EEPROM_EMULATION)
#include "../shared/eeprom_api.h"
#include "../../shared/eeprom_api.h"
extern "C" {
#include <lpc17xx_iap.h>
@ -74,7 +74,7 @@ bool PersistentStore::access_start() {
if (status == CMD_SUCCESS) {
// sector is blank so nothing stored yet
for (int i = 0; i < MARLIN_EEPROM_SIZE; i++) ram_eeprom[i] = EEPROM_ERASE;
for (int i = 0; i < long(MARLIN_EEPROM_SIZE); i++) ram_eeprom[i] = EEPROM_ERASE;
current_slot = EEPROM_SLOTS;
}
else {
@ -82,7 +82,7 @@ bool PersistentStore::access_start() {
current_slot = first_nblank_loc / (MARLIN_EEPROM_SIZE);
uint8_t *eeprom_data = SLOT_ADDRESS(EEPROM_SECTOR, current_slot);
// load current settings
for (int i = 0; i < MARLIN_EEPROM_SIZE; i++) ram_eeprom[i] = eeprom_data[i];
for (int i = 0; i < long(MARLIN_EEPROM_SIZE); i++) ram_eeprom[i] = eeprom_data[i];
}
eeprom_dirty = false;

View file

@ -26,13 +26,13 @@
#ifdef TARGET_LPC1768
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if ENABLED(SDCARD_EEPROM_EMULATION)
//#define DEBUG_SD_EEPROM_EMULATION
#include "../shared/eeprom_api.h"
#include "../../shared/eeprom_api.h"
#include <chanfs/diskio.h>
#include <chanfs/ff.h>
@ -52,7 +52,6 @@ bool eeprom_file_open = false;
size_t PersistentStore::capacity() { return MARLIN_EEPROM_SIZE - eeprom_exclude_size; }
bool PersistentStore::access_start() {
const char eeprom_erase_value = 0xFF;
MSC_Aquire_Lock();
if (f_mount(&fat_fs, "", 1)) {
MSC_Release_Lock();
@ -65,6 +64,7 @@ bool PersistentStore::access_start() {
UINT bytes_written;
FSIZE_t file_size = f_size(&eeprom_file);
f_lseek(&eeprom_file, file_size);
const char eeprom_erase_value = 0xFF;
while (file_size < capacity() && res == FR_OK) {
res = f_write(&eeprom_file, &eeprom_erase_value, 1, &bytes_written);
file_size++;

View file

@ -21,7 +21,7 @@
*/
#ifdef TARGET_LPC1768
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if USE_WIRED_EEPROM
@ -30,8 +30,8 @@
* with implementations supplied by the framework.
*/
#include "../shared/eeprom_if.h"
#include "../shared/eeprom_api.h"
#include "../../shared/eeprom_if.h"
#include "../../shared/eeprom_api.h"
#ifndef MARLIN_EEPROM_SIZE
#define MARLIN_EEPROM_SIZE 0x8000 // 32K

View file

@ -29,6 +29,6 @@
// LPC1768 boards seem to lose steps when saving to EEPROM during print (issue #20785)
// TODO: Which other boards are incompatible?
#if defined(MCU_LPC1768) && ENABLED(FLASH_EEPROM_EMULATION) && PRINTCOUNTER_SAVE_INTERVAL > 0
#if ALL(MCU_LPC1768, FLASH_EEPROM_EMULATION) && PRINTCOUNTER_SAVE_INTERVAL > 0
#define PRINTCOUNTER_SYNC
#endif

View file

@ -28,7 +28,7 @@
#include "../include/i2c_util.h"
#include "../../../core/millis_t.h"
extern int millis();
uint32_t millis();
#ifdef __cplusplus
extern "C" {

View file

@ -54,18 +54,25 @@ if pioutil.is_pio_build():
final_drive_name = drive + ':'
# print ('disc check: {}'.format(final_drive_name))
try:
volume_info = str(subprocess.check_output('cmd /C dir ' + final_drive_name, stderr=subprocess.STDOUT))
volume_info = str(subprocess.check_output('cmd /C vol ' + final_drive_name, stderr=subprocess.STDOUT))
except Exception as e:
print ('error:{}'.format(e))
continue
else:
if target_drive in volume_info and not target_file_found: # set upload if not found target file yet
target_drive_found = True
if target_drive in volume_info: # set upload
upload_disk = PureWindowsPath(final_drive_name)
if target_filename in volume_info:
if not target_file_found:
target_drive_found = True
break
try:
dir_info = str(subprocess.check_output('cmd /C dir ' + final_drive_name, stderr=subprocess.STDOUT))
except Exception as e:
print ('error:{}'.format(e))
continue
else:
if target_filename in dir_info:
upload_disk = PureWindowsPath(final_drive_name)
target_file_found = True
target_file_found = True
break
elif current_OS == 'Linux':
#

View file

@ -52,7 +52,9 @@ uint8_t _getc();
// ------------------------
#define CPU_32_BIT
#define SHARED_SERVOS HAS_SERVOS // Use shared/servos.cpp
class Servo;
typedef Servo hal_servo_t;
#define F_CPU 100000000
#define SystemCoreClock F_CPU
@ -193,7 +195,7 @@ public:
static void isr_on() {}
static void isr_off() {}
static void delay_ms(const int ms) { _delay_ms(ms); }
static void delay_ms(const int ms) { delay(ms); }
// Tasks, called from idle()
static void idletask();
@ -232,8 +234,10 @@ public:
* No option to invert the duty cycle [default = false]
* No option to change the scale of the provided value to enable finer PWM duty control [default = 255]
*/
static void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t=255, const bool=false) {
analogWrite(pin, v);
static void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255, const bool invert=false) {
auto value = map(v, 0, v_size, 0, UINT16_MAX);
value = invert ? UINT16_MAX - value : value;
analogWrite(pin, value);
}
static void set_pwm_frequency(const pin_t, int) {}

View file

@ -0,0 +1,104 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 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/>.
*
*/
#include "../platforms.h"
#ifdef __PLAT_NATIVE_SIM__
#include "../../inc/MarlinConfig.h"
#if HAS_SERVOS
#include "Servo.h"
//#define DEBUG_SERVOS
#define DEBUG_OUT ENABLED(DEBUG_SERVOS)
#include "../../../core/debug_out.h"
uint8_t ServoCount = 0; // the total number of attached servos
Servo::Servo() {
// Constructor stub
DEBUG_ECHOLNPGM("Debug Servo: constructor");
this->servoIndex = ServoCount++; // assign a servo index to this instance
}
uint8_t Servo::attach(int pin) {
// Attach stub
DEBUG_ECHOLNPGM("Debug Servo: attach to pin ", pin, " servo index ", this->servoIndex);
return attach(pin, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
}
uint8_t Servo::attach(int pin, int min, int max) {
// Attach with min and max stub
DEBUG_ECHOLNPGM("Debug Servo: attach to pin ", pin, " with min ", min, " and max ", max);
if (pin > 0) servo_pin = pin;
return this->servoIndex;
}
void Servo::detach() {
// Detach stub
DEBUG_ECHOLNPGM("Debug Servo: detach");
}
// If value is < 200 it is treated as an angle, otherwise as pulse width in microseconds
void Servo::write(int value) {
if (value < MIN_PULSE_WIDTH) { // treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)
value = map(constrain(value, 0, 180), 0, 180, SERVO_MIN_US(min), SERVO_MAX_US(max));
}
writeMicroseconds(value);
DEBUG_ECHOLNPGM("Debug Servo: write ", value);
}
void Servo::writeMicroseconds(int value) {
// Simulate the servo movement
this->value = value;
hal.set_pwm_duty(pin_t(this->servo_pin), (float(value) / 20000) * UINT16_MAX, UINT16_MAX);
DEBUG_ECHOLNPGM("Debug Servo: write microseconds ", value);
}
int Servo::read() {
// Read stub
DEBUG_ECHOLNPGM("Debug Servo: read ", this->value);
return this->value;
}
int Servo::readMicroseconds() {
// Read microseconds stub
DEBUG_ECHOLNPGM("Debug Servo: read microseconds");
return 0;
}
bool Servo::attached() {
// Attached stub
DEBUG_ECHOLNPGM("Debug Servo: attached");
return false;
}
int Servo::move(const unsigned char cmd) {
// Move stub
DEBUG_ECHOLNPGM("Debug Servo: move ", cmd);
write(cmd);
return 0;
}
#endif // HAS_SERVOS
#endif // __PLAT_NATIVE_SIM__

View file

@ -0,0 +1,48 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 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
#define MIN_PULSE_WIDTH 544 // the shortest pulse sent to a servo
#define MAX_PULSE_WIDTH 2400 // the longest pulse sent to a servo
#define DEFAULT_PULSE_WIDTH 1500 // default pulse width when servo is attached
#define SERVO_MIN_US(v) (MIN_PULSE_WIDTH - (v) * 4) // minimum value in uS for this servo
#define SERVO_MAX_US(v) (MAX_PULSE_WIDTH - (v) * 4) // maximum value in uS for this servo
class Servo {
public:
Servo();
uint8_t attach(int pin); // Attach the given pin to the next free channel, set pinMode, return channel number or INVALID_SERVO if failure
uint8_t attach(int pin, int min, int max); // As above but also set min and max values for writes.
void detach();
void write(int value); // If value is < 200 it's treated as an angle, otherwise as pulse width in microseconds
void writeMicroseconds(int value); // Write pulse width in microseconds
int read(); // Return current pulse width as an angle between 0 and 180 degrees
int readMicroseconds(); // Return current pulse width in microseconds for this servo
bool attached(); // Return true if this servo is attached, otherwise false
int move (const unsigned char cmd);
private:
uint8_t servoIndex; // Index into the channel data for this servo
int8_t min; // Minimum is this value times 4 added to MIN_PULSE_WIDTH
int8_t max; // Maximum is this value times 4 added to MAX_PULSE_WIDTH
int value; // Pulse width in microseconds for this servo
int servo_pin = 0; // pin number for this servo
};

View file

@ -0,0 +1,30 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 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
#error "ENDSTOP_INTERRUPTS_FEATURE is not supported in this simulation environment."
void setup_endstop_interrupts() {
// This function is a stub for setting up endstop interrupts.
// Since this is a simulation environment, actual hardware interrupts
// are not applicable. Add any necessary simulation-specific logic here.
}

View file

@ -1,79 +0,0 @@
/**
* 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
/**
* servo.h - Interrupt driven Servo library for Arduino using 16 bit timers- Version 2
* Copyright (c) 2009 Michael Margolis. All right reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* Based on "servo.h - Interrupt driven Servo library for Arduino using 16 bit timers -
* Version 2 Copyright (c) 2009 Michael Margolis. All right reserved.
*
* The only modification was to update/delete macros to match the LPC176x.
*
*/
#include <stdint.h>
// Macros
//values in microseconds
#define MIN_PULSE_WIDTH 544 // the shortest pulse sent to a servo
#define MAX_PULSE_WIDTH 2400 // the longest pulse sent to a servo
#define DEFAULT_PULSE_WIDTH 1500 // default pulse width when servo is attached
#define REFRESH_INTERVAL 20000 // minimum time to refresh servos in microseconds
#define MAX_SERVOS 4
#define INVALID_SERVO 255 // flag indicating an invalid servo index
// Types
typedef struct {
uint8_t nbr : 8 ; // a pin number from 0 to 254 (255 signals invalid pin)
uint8_t isActive : 1 ; // true if this channel is enabled, pin not pulsed if false
} ServoPin_t;
typedef struct {
ServoPin_t Pin;
unsigned int pulse_width; // pulse width in microseconds
} ServoInfo_t;
// Global variables
extern uint8_t ServoCount;
extern ServoInfo_t servo_info[MAX_SERVOS];

View file

@ -71,13 +71,13 @@ static uint8_t SPI_speed = 0;
static uint8_t swSpiTransfer(uint8_t b, const uint8_t spi_speed, const pin_t sck_pin, const pin_t miso_pin, const pin_t mosi_pin) {
for (uint8_t i = 0; i < 8; i++) {
WRITE_PIN(mosi_pin, !!(b & 0x80));
WRITE_PIN(sck_pin, TERN(U8G_SPI_USE_MODE_3, LOW, HIGH));
DELAY_CYCLES(SPI_SPEED);
WRITE_PIN(sck_pin, HIGH);
WRITE_PIN(mosi_pin, !!(b & 0x80));
DELAY_CYCLES(SPI_SPEED);
b <<= 1;
if (miso_pin >= 0 && READ_PIN(miso_pin)) b |= 1;
WRITE_PIN(sck_pin, LOW);
WRITE_PIN(sck_pin, TERN(U8G_SPI_USE_MODE_3, HIGH, LOW));
DELAY_CYCLES(SPI_SPEED);
}
return b;
@ -85,7 +85,7 @@ static uint8_t swSpiTransfer(uint8_t b, const uint8_t spi_speed, const pin_t sck
static uint8_t swSpiInit(const uint8_t spiRate, const pin_t sck_pin, const pin_t mosi_pin) {
WRITE_PIN(mosi_pin, HIGH);
WRITE_PIN(sck_pin, LOW);
WRITE_PIN(sck_pin, TERN(U8G_SPI_USE_MODE_3, HIGH, LOW));
return spiRate;
}
@ -93,11 +93,11 @@ static void u8g_com_st7920_write_byte_sw_spi(uint8_t rs, uint8_t val) {
static uint8_t rs_last_state = 255;
if (rs != rs_last_state) {
// Transfer Data (FA) or Command (F8)
swSpiTransfer(rs ? 0x0FA : 0x0F8, SPI_speed, SCK_pin_ST7920_HAL, -1, MOSI_pin_ST7920_HAL_HAL);
swSpiTransfer(rs ? 0xFA : 0xF8, SPI_speed, SCK_pin_ST7920_HAL, -1, MOSI_pin_ST7920_HAL_HAL);
rs_last_state = rs;
DELAY_US(40); // Give the controller time to process the data: 20 is bad, 30 is OK, 40 is safe
}
swSpiTransfer(val & 0x0F0, SPI_speed, SCK_pin_ST7920_HAL, -1, MOSI_pin_ST7920_HAL_HAL);
swSpiTransfer(val & 0xF0, SPI_speed, SCK_pin_ST7920_HAL, -1, MOSI_pin_ST7920_HAL_HAL);
swSpiTransfer(val << 4, SPI_speed, SCK_pin_ST7920_HAL, -1, MOSI_pin_ST7920_HAL_HAL);
}
@ -169,5 +169,32 @@ uint8_t u8g_com_ST7920_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void
}
#endif
#if ENABLED(LIGHTWEIGHT_UI)
#define ST7920_CS() { WRITE(LCD_PINS_RS, HIGH); }
#define ST7920_NCS() { WRITE(LCD_PINS_RS, LOW); }
#define ST7920_SET_CMD() { ST7920_SWSPI_SND_8BIT(0xF8); }
#define ST7920_SET_DAT() { ST7920_SWSPI_SND_8BIT(0xFA); }
#define ST7920_WRITE_BYTE(a) { ST7920_SWSPI_SND_8BIT((uint8_t)((a)&0xF0u)); ST7920_SWSPI_SND_8BIT((uint8_t)((a)<<4U)); }
#define ST7920_DAT(V) !!((V) & 0x80)
#define ST7920_SND_BIT(...) do{ \
WRITE(LCD_PINS_D4, LOW); \
WRITE(LCD_PINS_EN, ST7920_DAT(val)); \
WRITE(LCD_PINS_D4, HIGH); \
val <<= 1; }while(0);
void ST7920_SWSPI_SND_8BIT(uint8_t val) {
REPEAT(8, ST7920_SND_BIT);
}
void ST7920_cs() { ST7920_CS(); }
void ST7920_ncs() { ST7920_NCS(); }
void ST7920_set_cmd() { ST7920_SET_CMD(); }
void ST7920_set_dat() { ST7920_SET_DAT(); }
void ST7920_write_byte(const uint8_t val) { ST7920_WRITE_BYTE(val); }
#endif // LIGHTWEIGHT_UI
#endif // IS_U8GLIB_ST7920
#endif // __PLAT_NATIVE_SIM__

View file

@ -127,7 +127,7 @@ uint8_t swSpiTransfer_mode_3(uint8_t b, const uint8_t spi_speed, const pin_t sck
static uint8_t SPI_speed = 0;
static uint8_t swSpiInit(const uint8_t spi_speed, const uint8_t clk_pin, const uint8_t mosi_pin) {
return spi_speed;
return spi_speed;
}
static void u8g_sw_spi_shift_out(uint8_t dataPin, uint8_t clockPin, uint8_t val) {

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