Compare commits

..

2 Commits

Author SHA1 Message Date
Scott Lahteine f7406e233a Only subtract home offsets for machine-centric XY 2022-07-17 15:18:57 -05:00
InsanityAutomation 8a12d0155c Use raw positions for G34 probing to honor M206 offsets 2022-05-29 18:49:20 -04:00
656 changed files with 17580 additions and 23559 deletions
+1 -5
View File
@@ -14,10 +14,6 @@ end_of_line = lf
indent_style = space
indent_size = 2
[{*.py}]
indent_style = space
indent_size = 4
[{*.conf,*.sublime-project}]
[{*.py,*.conf,*.sublime-project}]
indent_style = tab
indent_size = 4
+17 -26
View File
@@ -14,13 +14,13 @@ body:
## Before Reporting a Bug
- Read and understand Marlin's [Code of Conduct](https://github.com/MarlinFirmware/Marlin/blob/bugfix-2.1.x/.github/code_of_conduct.md). You are expected to comply with it, including treating everyone with respect.
- Read and understand Marlin's [Code of Conduct](https://github.com/MarlinFirmware/Marlin/blob/bugfix-2.0.x/.github/code_of_conduct.md). You are expected to comply with it, including treating everyone with respect.
- Test with the [`bugfix-2.1.x` branch](https://github.com/MarlinFirmware/Marlin/archive/bugfix-2.1.x.zip) to see whether the issue still exists.
- Test with the [`bugfix-2.0.x` branch](https://github.com/MarlinFirmware/Marlin/archive/bugfix-2.0.x.zip) to see whether the issue still exists.
## Instructions
Please follow the instructions below. Failure to do so may result in your issue being closed. See [Contributing to Marlin](https://github.com/MarlinFirmware/Marlin/blob/bugfix-2.1.x/.github/contributing.md) for additional guidelines.
Please follow the instructions below. Failure to do so may result in your issue being closed. See [Contributing to Marlin](https://github.com/MarlinFirmware/Marlin/blob/bugfix-2.0.x/.github/contributing.md) for additional guidelines.
1. Provide a good title starting with [BUG].
2. Fill out all sections of this bug report form.
@@ -28,10 +28,10 @@ body:
- type: dropdown
attributes:
label: Did you test the latest `bugfix-2.1.x` code?
label: Did you test the latest `bugfix-2.0.x` code?
description: >-
Always try the latest code to make sure the issue you are reporting is not already fixed. To download
the latest code just [click this link](https://github.com/MarlinFirmware/Marlin/archive/bugfix-2.1.x.zip).
the latest code just [click this link](https://github.com/MarlinFirmware/Marlin/archive/bugfix-2.0.x.zip).
options:
- Yes, and the problem still exists.
- No, but I will test it now!
@@ -50,8 +50,6 @@ body:
Describe the bug in this section. Tell us what you were trying to do and what
happened that you did not expect. Provide a clear and concise description of the
problem and include as many details as possible.
When pasting formatted text don't forget to put ` ``` ` (on its own line) before and after to make it readable.
placeholder: |
Marlin doesn't work.
validations:
@@ -151,28 +149,21 @@ body:
- type: markdown
attributes:
value: |
# Attachments
value: >-
## Other things to include
- type: checkboxes
attributes:
label: Don't forget to include
options:
- label: A ZIP file containing your `Configuration.h` and `Configuration_adv.h`.
required: true
Please also be sure to include these items to help with troubleshooting:
- type: markdown
attributes:
value: |
### Optional items to include:
- 'Log output from the host. (`M111 S247` for maximum logging.)'
- Images or videos demonstrating the problem, if it helps to make it clear.
- A G-Code file that exposes the problem, if not affecting _all_ G-code.
* **A ZIP file** containing your `Configuration.h` and `Configuration_adv.h`.
(Please don't paste lengthy configuration text here.)
* **Log output** from the host. (`M111 S247` for maximum logging.)
* **Images or videos** demonstrating the problem, if it helps to make it clear.
* **A G-Code file** that exposes the problem, if not affecting _all_ G-code.
If you've made any other modifications to the firmware, please describe them in detail in the space provided.
When pasting formatted text into the box below don't forget to put ` ``` ` (on its own line) before and after to make it readable.
- type: textarea
attributes:
label: Additional information & file uploads
description: >-
If you've made any other modifications to the firmware, please describe them in detail.
When pasting formatted text don't forget to put ` ``` ` (on its own line) before and after to make it readable.
+1 -1
View File
@@ -17,7 +17,7 @@ body:
- Read and understand Marlin's [Code of Conduct](https://github.com/MarlinFirmware/Marlin/blob/master/.github/code_of_conduct.md). You are expected to comply with it, including treating everyone with respect.
- Check the latest [`bugfix-2.1.x` branch](https://github.com/MarlinFirmware/Marlin/archive/bugfix-2.1.x.zip) to see if the feature already exists.
- Check the latest [`bugfix-2.0.x` branch](https://github.com/MarlinFirmware/Marlin/archive/bugfix-2.0.x.zip) to see if the feature already exists.
- Before you proceed with your request, please consider if it is necessary to make it into a firmware feature, or if it may be better suited for a slicer or host feature.
+3 -6
View File
@@ -34,11 +34,8 @@ This project and everyone participating in it is governed by the [Marlin Code of
We have a Message Board and a Facebook group where our knowledgable user community can provide helpful advice if you have questions.
- [Marlin Documentation](https://marlinfw.org) - Official Marlin documentation
- Facebook Group ["Marlin Firmware"](https://www.facebook.com/groups/1049718498464482/)
- RepRap.org [Marlin Forum](https://forums.reprap.org/list.php?415)
- Facebook Group ["Marlin Firmware for 3D Printers"](https://www.facebook.com/groups/3Dtechtalk/)
- [Marlin Configuration](https://www.youtube.com/results?search_query=marlin+configuration) on YouTube
* [Marlin RepRap forum](https://reprap.org/forum/list.php?415)
* [MarlinFirmware on Facebook](https://www.facebook.com/groups/1049718498464482/)
If chat is more your speed, you can join the MarlinFirmware Discord server:
@@ -119,7 +116,7 @@ Unsure where to begin contributing to Marlin? You can start by looking through t
### Pull Requests
Pull Requests should always be targeted to working branches (e.g., `bugfix-2.1.x` and/or `bugfix-1.1.x`) and never to release branches (e.g., `2.0.x` and/or `1.1.x`). If this is your first Pull Request, please read our [Guide to Pull Requests](https://marlinfw.org/docs/development/getting_started_pull_requests.html) and Github's [Pull Request](https://help.github.com/articles/creating-a-pull-request/) documentation.
Pull Requests should always be targeted to working branches (e.g., `bugfix-2.0.x` and/or `bugfix-1.1.x`) and never to release branches (e.g., `2.0.x` and/or `1.1.x`). If this is your first Pull Request, please read our [Guide to Pull Requests](https://marlinfw.org/docs/development/getting_started_pull_requests.html) and Github's [Pull Request](https://help.github.com/articles/creating-a-pull-request/) documentation.
* Fill in [the required template](pull_request_template.md).
* Don't include issue numbers in the PR title.
+3 -23
View File
@@ -18,32 +18,12 @@ jobs:
steps:
- name: Check out bugfix-2.1.x
- name: Check out bugfix-2.0.x
uses: actions/checkout@v2
with:
ref: bugfix-2.1.x
ref: bugfix-2.0.x
- name: Bump Date (bugfix-2.0.x)
run: |
# Inline Bump Script
if [[ ! "$( git log -1 --pretty=%B )" =~ ^\[cron\] ]]; then
DIST=$( date +"%Y-%m-%d" )
eval "sed -E -i 's/(#define +STRING_DISTRIBUTION_DATE) .*$/\1 \"$DIST\"/g' Marlin/src/inc/Version.h" && \
eval "sed -E -i 's/(#define +STRING_DISTRIBUTION_DATE) .*$/\1 \"$DIST\"/g' Marlin/Version.h" && \
git config user.name "${GITHUB_ACTOR}" && \
git config user.email "${GITHUB_ACTOR}@users.noreply.github.com" && \
git add . && \
git commit -m "[cron] Bump distribution date ($DIST)" && \
git push
fi
exit 0
- name: Check out bugfix-2.1.x
uses: actions/checkout@v2
with:
ref: bugfix-2.1.x
- name: Bump Date (bugfix-2.1.x)
- name: Bump Distribution Date
run: |
# Inline Bump Script
if [[ ! "$( git log -1 --pretty=%B )" =~ ^\[cron\] ]]; then
+2 -3
View File
@@ -12,7 +12,6 @@ on:
- 1.0.x
- 1.1.x
- 2.0.x
- 2.1.x
jobs:
bad_target:
@@ -27,8 +26,8 @@ jobs:
comment: >
Thanks for your contribution! Unfortunately we can't accept PRs directed at release branches. We make patches to the bugfix branches and only later do we push them out as releases.
Please redo this PR starting with the `bugfix-2.1.x` branch and be careful to target `bugfix-2.1.x` when resubmitting the PR. Patches may also target `bugfix-2.0.x` if they are specifically for 2.0.9.x.
Please redo this PR starting with the `bugfix-2.0.x` branch and be careful to target `bugfix-2.0.x` when resubmitting the PR.
It may help to set your fork's default branch to `bugfix-2.0.x`.
See [this page](https://marlinfw.org/docs/development/getting_started_pull_requests.html) for full instructions.
See [this page](http://marlinfw.org/docs/development/getting_started_pull_requests.html) for full instructions.
+1 -1
View File
@@ -25,4 +25,4 @@ jobs:
days-before-close: 10
stale-issue-label: 'stale-closing-soon'
exempt-all-assignees: true
exempt-issue-labels: 'Bug: Confirmed !,T: Feature Request,Needs: More Data,Needs: Discussion,Needs: Documentation,Needs: Patch,Needs: Work,Needs: Testing,help wanted,no-locking'
exempt-issue-labels: 'Bug: Confirmed !,T: Feature Request,Needs: Discussion,Needs: Documentation,Needs: Patch,Needs: Work,Needs: Testing,help wanted,no-locking'
+6 -11
View File
@@ -8,7 +8,7 @@ name: CI
on:
pull_request:
branches:
- bugfix-2.1.x
- bugfix-2.0.x
paths-ignore:
- config/**
- data/**
@@ -16,7 +16,7 @@ on:
- '**/*.md'
push:
branches:
- bugfix-2.1.x
- bugfix-2.0.x
paths-ignore:
- config/**
- data/**
@@ -45,7 +45,6 @@ jobs:
- teensy35
- teensy41
- SAMD51_grandcentral_m4
- PANDA_PI_V29
# Extended AVR Environments
@@ -66,7 +65,7 @@ jobs:
#- mks_robin_maple
- mks_robin_lite_maple
- mks_robin_pro_maple
#- mks_robin_nano_v1v2_maple
#- mks_robin_nano35_maple
#- STM32F103RE_creality_maple
- STM32F103VE_ZM3E4V2_USB_maple
@@ -80,6 +79,7 @@ jobs:
- STM32F401RC_creality
- STM32F103VE_longer
- STM32F407VE_black
- STM32F401VE_STEVAL
- BIGTREE_BTT002
- BIGTREE_SKR_PRO
- BIGTREE_GTR_V1_0
@@ -93,17 +93,12 @@ jobs:
- rumba32
- LERDGEX
- LERDGEK
- mks_robin_nano_v1v2
#- mks_robin_nano_v1v2_usbmod
#- mks_robin_nano_v1_3_f4_usbmod
- mks_robin_nano35
- NUCLEO_F767ZI
- REMRAM_V1
- BTT_SKR_SE_BX
- chitu_f103
- Opulo_Lumen_REV3
# ESP32 environments
- mks_tinybee
- Index_Mobo_Rev03
# Put lengthy tests last
-1
View File
@@ -147,7 +147,6 @@ vc-fileutils.settings
imgui.ini
eeprom.dat
spi_flash.bin
fs.img
#cmake
CMakeLists.txt
+2 -2
View File
@@ -27,7 +27,7 @@ tests-single-ci:
tests-single-local:
@if ! test -n "$(TEST_TARGET)" ; then echo "***ERROR*** Set TEST_TARGET=<your-module> or use make tests-all-local" ; return 1; fi
export PATH="./buildroot/bin/:./buildroot/tests/:${PATH}" \
export PATH=./buildroot/bin/:./buildroot/tests/:${PATH} \
&& export VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) \
&& run_tests . $(TEST_TARGET) "$(ONLY_TEST)"
.PHONY: tests-single-local
@@ -38,7 +38,7 @@ tests-single-local-docker:
.PHONY: tests-single-local-docker
tests-all-local:
export PATH="./buildroot/bin/:./buildroot/tests/:${PATH}" \
export PATH=./buildroot/bin/:./buildroot/tests/:${PATH} \
&& export VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) \
&& for TEST_TARGET in $$(./get_test_targets.py) ; do echo "Running tests for $$TEST_TARGET" ; run_tests . $$TEST_TARGET ; done
.PHONY: tests-all-local
+74 -333
View File
@@ -35,7 +35,7 @@
*
* Advanced settings can be found in Configuration_adv.h
*/
#define CONFIGURATION_H_VERSION 02010200
#define CONFIGURATION_H_VERSION 02010000
//===========================================================================
//============================= Getting Started =============================
@@ -57,6 +57,15 @@
* https://www.thingiverse.com/thing:1278865
*/
//===========================================================================
//========================== DELTA / SCARA / TPARA ==========================
//===========================================================================
//
// Download configurations from the link above and customize for your machine.
// Examples are located in config/examples/delta, .../SCARA, and .../TPARA.
//
//===========================================================================
// @section info
// Author info of this build printed to the host during boot and M115
@@ -112,7 +121,6 @@
* :[2400, 9600, 19200, 38400, 57600, 115200, 250000, 500000, 1000000]
*/
#define BAUDRATE 250000
//#define BAUD_RATE_GCODE // Enable G-code M575 to set the baud rate
/**
@@ -121,7 +129,7 @@
* :[-2, -1, 0, 1, 2, 3, 4, 5, 6, 7]
*/
//#define SERIAL_PORT_2 -1
//#define BAUDRATE_2 250000 // :[2400, 9600, 19200, 38400, 57600, 115200, 250000, 500000, 1000000] Enable to override BAUDRATE
//#define BAUDRATE_2 250000 // Enable to override BAUDRATE
/**
* Select a third serial port on the board to use for communication with the host.
@@ -129,7 +137,7 @@
* :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
*/
//#define SERIAL_PORT_3 1
//#define BAUDRATE_3 250000 // :[2400, 9600, 19200, 38400, 57600, 115200, 250000, 500000, 1000000] Enable to override BAUDRATE
//#define BAUDRATE_3 250000 // Enable to override BAUDRATE
// Enable the Bluetooth serial interface on AT90USB devices
//#define BLUETOOTH
@@ -141,8 +149,6 @@
// Choose your own or use a service like https://www.uuidgenerator.net/version4
//#define MACHINE_UUID "00000000-0000-0000-0000-000000000000"
// @section stepper drivers
/**
* Stepper Drivers
*
@@ -151,12 +157,13 @@
*
* Use TMC2208/TMC2208_STANDALONE for TMC2225 drivers and TMC2209/TMC2209_STANDALONE for TMC2226 drivers.
*
* Options: A4988, A5984, DRV8825, LV8729, TB6560, TB6600, TMC2100,
* Options: A4988, A5984, DRV8825, LV8729, L6470, L6474, POWERSTEP01,
* TB6560, TB6600, TMC2100,
* TMC2130, TMC2130_STANDALONE, TMC2160, TMC2160_STANDALONE,
* TMC2208, TMC2208_STANDALONE, TMC2209, TMC2209_STANDALONE,
* TMC26X, TMC26X_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', 'TMC26X', 'TMC26X_STANDALONE', 'TMC2660', 'TMC2660_STANDALONE', 'TMC5130', 'TMC5130_STANDALONE', 'TMC5160', 'TMC5160_STANDALONE']
* :['A4988', 'A5984', 'DRV8825', 'LV8729', 'L6470', 'L6474', 'POWERSTEP01', 'TB6560', 'TB6600', 'TMC2100', 'TMC2130', 'TMC2130_STANDALONE', 'TMC2160', 'TMC2160_STANDALONE', 'TMC2208', 'TMC2208_STANDALONE', 'TMC2209', 'TMC2209_STANDALONE', 'TMC26X', 'TMC26X_STANDALONE', 'TMC2660', 'TMC2660_STANDALONE', 'TMC5130', 'TMC5130_STANDALONE', 'TMC5160', 'TMC5160_STANDALONE']
*/
#define X_DRIVER_TYPE A4988
#define Y_DRIVER_TYPE A4988
@@ -242,8 +249,6 @@
//#define SINGLENOZZLE_STANDBY_FAN
#endif
// @section multi-material
/**
* Multi-Material Unit
* Set to one of these predefined models:
@@ -256,7 +261,6 @@
*
* Requires NOZZLE_PARK_FEATURE to park print head in case MMU unit fails.
* See additional options in Configuration_adv.h.
* :["PRUSA_MMU1", "PRUSA_MMU2", "PRUSA_MMU2S", "EXTENDABLE_EMU_MMU2", "EXTENDABLE_EMU_MMU2S"]
*/
//#define MMU_MODEL PRUSA_MMU2
@@ -276,7 +280,6 @@
#define SWITCHING_NOZZLE_SERVO_NR 0
//#define SWITCHING_NOZZLE_E1_SERVO_NR 1 // If two servos are used, the index of the second
#define SWITCHING_NOZZLE_SERVO_ANGLES { 0, 90 } // Angles for E0, E1 (single servo) or lowered/raised (dual servo)
#define SWITCHING_NOZZLE_SERVO_DWELL 2500 // Dwell time to wait for servo to make physical move
#endif
/**
@@ -393,7 +396,7 @@
//#define HOTEND_OFFSET_Y { 0.0, 5.00 } // (mm) relative Y-offset for each nozzle
//#define HOTEND_OFFSET_Z { 0.0, 0.00 } // (mm) relative Z-offset for each nozzle
// @section psu control
// @section machine
/**
* Power Supply Control
@@ -496,7 +499,7 @@
* 30 : 100kΩ Kis3d Silicone heating mat 200W/300W with 6mm precision cast plate (EN AW 5083) NTC100K - beta 3950
* 60 : 100kΩ Maker's Tool Works Kapton Bed Thermistor - beta 3950
* 61 : 100kΩ Formbot/Vivedino 350°C Thermistor - beta 3950
* 66 : 4.7MΩ Dyze Design / Trianglelab T-D500 500°C High Temperature Thermistor
* 66 : 4.7MΩ Dyze Design High Temperature Thermistor
* 67 : 500kΩ SliceEngineering 450°C Thermistor
* 68 : PT100 amplifier board from Dyze Design
* 70 : 100kΩ bq Hephestos 2
@@ -518,7 +521,6 @@
* 110 : Pt100 with 1kΩ pullup (atypical)
* 147 : Pt100 with 4.7kΩ pullup
* 1010 : Pt1000 with 1kΩ pullup (atypical)
* 1022 : Pt1000 with 2.2kΩ pullup
* 1047 : Pt1000 with 4.7kΩ pullup (E3D)
* 20 : Pt100 with circuit in the Ultimainboard V2.x with mainboard ADC reference voltage = INA826 amplifier-board supply voltage.
* NOTE: (1) Must use an ADC input with no pullup. (2) Some INA826 amplifiers are unreliable at 3.3V so consider using sensor 147, 110, or 21.
@@ -556,32 +558,22 @@
#define DUMMY_THERMISTOR_999_VALUE 100
// Resistor values when using MAX31865 sensors (-5) on TEMP_SENSOR_0 / 1
#if TEMP_SENSOR_IS_MAX_TC(0)
#define MAX31865_SENSOR_OHMS_0 100 // (Ω) Typically 100 or 1000 (PT100 or PT1000)
#define MAX31865_CALIBRATION_OHMS_0 430 // (Ω) Typically 430 for Adafruit PT100; 4300 for Adafruit PT1000
#endif
#if TEMP_SENSOR_IS_MAX_TC(1)
#define MAX31865_SENSOR_OHMS_1 100
#define MAX31865_CALIBRATION_OHMS_1 430
#endif
//#define MAX31865_SENSOR_OHMS_0 100 // (Ω) Typically 100 or 1000 (PT100 or PT1000)
//#define MAX31865_CALIBRATION_OHMS_0 430 // (Ω) Typically 430 for Adafruit PT100; 4300 for Adafruit PT1000
//#define MAX31865_SENSOR_OHMS_1 100
//#define MAX31865_CALIBRATION_OHMS_1 430
#if HAS_E_TEMP_SENSOR
#define TEMP_RESIDENCY_TIME 10 // (seconds) Time to wait for hotend to "settle" in M109
#define TEMP_WINDOW 1 // (°C) Temperature proximity for the "temperature reached" timer
#define TEMP_HYSTERESIS 3 // (°C) Temperature proximity considered "close enough" to the target
#endif
#define TEMP_RESIDENCY_TIME 10 // (seconds) Time to wait for hotend to "settle" in M109
#define TEMP_WINDOW 1 // (°C) Temperature proximity for the "temperature reached" timer
#define TEMP_HYSTERESIS 3 // (°C) Temperature proximity considered "close enough" to the target
#if TEMP_SENSOR_BED
#define TEMP_BED_RESIDENCY_TIME 10 // (seconds) Time to wait for bed to "settle" in M190
#define TEMP_BED_WINDOW 1 // (°C) Temperature proximity for the "temperature reached" timer
#define TEMP_BED_HYSTERESIS 3 // (°C) Temperature proximity considered "close enough" to the target
#endif
#define TEMP_BED_RESIDENCY_TIME 10 // (seconds) Time to wait for bed to "settle" in M190
#define TEMP_BED_WINDOW 1 // (°C) Temperature proximity for the "temperature reached" timer
#define TEMP_BED_HYSTERESIS 3 // (°C) Temperature proximity considered "close enough" to the target
#if TEMP_SENSOR_CHAMBER
#define TEMP_CHAMBER_RESIDENCY_TIME 10 // (seconds) Time to wait for chamber to "settle" in M191
#define TEMP_CHAMBER_WINDOW 1 // (°C) Temperature proximity for the "temperature reached" timer
#define TEMP_CHAMBER_HYSTERESIS 3 // (°C) Temperature proximity considered "close enough" to the target
#endif
#define TEMP_CHAMBER_RESIDENCY_TIME 10 // (seconds) Time to wait for chamber to "settle" in M191
#define TEMP_CHAMBER_WINDOW 1 // (°C) Temperature proximity for the "temperature reached" timer
#define TEMP_CHAMBER_HYSTERESIS 3 // (°C) Temperature proximity considered "close enough" to the target
/**
* Redundant Temperature Sensor (TEMP_SENSOR_REDUNDANT)
@@ -640,8 +632,6 @@
//============================= PID Settings ================================
//===========================================================================
// @section hotend temp
// Enable PIDTEMP for PID control or MPCTEMP for Predictive Model.
// temperature control. Disable both for bang-bang heating.
#define PIDTEMP // See the PID Tuning Guide at https://reprap.org/wiki/PID_Tuning
@@ -652,9 +642,8 @@
#define PID_K1 0.95 // Smoothing factor within any PID loop
#if ENABLED(PIDTEMP)
//#define PID_DEBUG // Print PID debug data to the serial port. Use 'M303 D' to toggle activation.
//#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]
//#define PID_PARAMS_PER_HOTEND // Uses separate PID parameters for each extruder (useful for mismatched extruders)
// Set/get with gcode: M301 E[extruder number, 0-2]
#if ENABLED(PID_PARAMS_PER_HOTEND)
// Specify up to one value per hotend here, according to your setup.
@@ -674,8 +663,7 @@
*
* Use a physical model of the hotend to control temperature. When configured correctly
* this gives better responsiveness and stability than PID and it also removes the need
* for PID_EXTRUSION_SCALING and PID_FAN_SCALING. Use M306 T to autotune the model.
* @section mpctemp
* for PID_EXTRUSION_SCALING and PID_FAN_SCALING. Use M306 to autotune the model.
*/
#if ENABLED(MPCTEMP)
//#define MPC_EDIT_MENU // Add MPC editing to the "Advanced Settings" menu. (~1300 bytes of flash)
@@ -728,7 +716,6 @@
* impact FET heating. This also works fine on a Fotek SSR-10DA Solid State Relay into a 250W
* heater. If your configuration is significantly different than this and you don't understand
* the issues involved, don't use bed PID until someone else verifies that your hardware works.
* @section bed temp
*/
//#define PIDTEMPBED
@@ -744,7 +731,7 @@
#if ENABLED(PIDTEMPBED)
//#define MIN_BED_POWER 0
//#define PID_BED_DEBUG // Print Bed PID debug data to the serial port.
//#define PID_BED_DEBUG // Sends debug data to the serial port.
// 120V 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)
// from FOPDT model - kp=.39 Tp=405 Tdead=66, Tc set to 79.2, aggressive factor of .15 (vs .1, 1, 10)
@@ -772,7 +759,6 @@
* impact FET heating. This also works fine on a Fotek SSR-10DA Solid State Relay into a 200W
* heater. If your configuration is significantly different than this and you don't understand
* the issues involved, don't use chamber PID until someone else verifies that your hardware works.
* @section chamber temp
*/
//#define PIDTEMPCHAMBER
//#define CHAMBER_LIMIT_SWITCHING
@@ -787,7 +773,7 @@
#if ENABLED(PIDTEMPCHAMBER)
#define MIN_CHAMBER_POWER 0
//#define PID_CHAMBER_DEBUG // Print Chamber PID debug data to the serial port.
//#define PID_CHAMBER_DEBUG // Sends debug data to the serial port.
// 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.
@@ -801,6 +787,7 @@
#endif // PIDTEMPCHAMBER
#if ANY(PIDTEMP, PIDTEMPBED, PIDTEMPCHAMBER)
//#define PID_DEBUG // Sends debug data to the serial port. Use 'M303 D' to toggle activation.
//#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
@@ -810,7 +797,7 @@
//#define PID_AUTOTUNE_MENU // Add PID auto-tuning to the "Advanced Settings" menu. (~250 bytes of flash)
#endif
// @section safety
// @section extruder
/**
* Prevent extrusion if the temperature is below EXTRUDE_MINTEMP.
@@ -878,154 +865,11 @@
#define POLAR_SEGMENTS_PER_SECOND 5
#endif
// @section delta
// Enable for DELTA kinematics and configure below
//#define DELTA
#if ENABLED(DELTA)
// Make delta curves from many straight lines (linear interpolation).
// This is a trade-off between visible corners (not enough segments)
// and processor overload (too many expensive sqrt calls).
#define DELTA_SEGMENTS_PER_SECOND 200
// After homing move down to a height where XY movement is unconstrained
//#define DELTA_HOME_TO_SAFE_ZONE
// Delta calibration menu
// uncomment to add three points calibration menu option.
// See http://minow.blogspot.com/index.html#4918805519571907051
//#define DELTA_CALIBRATION_MENU
// uncomment to add G33 Delta Auto-Calibration (Enable EEPROM_SETTINGS to store results)
//#define DELTA_AUTO_CALIBRATION
// NOTE NB all values for DELTA_* values MUST be floating point, so always have a decimal point in them
#if ENABLED(DELTA_AUTO_CALIBRATION)
// set the default number of probe points : n*n (1 -> 7)
#define DELTA_CALIBRATION_DEFAULT_POINTS 4
#endif
#if EITHER(DELTA_AUTO_CALIBRATION, DELTA_CALIBRATION_MENU)
// Set the steprate for papertest probing
#define PROBE_MANUALLY_STEP 0.05 // (mm)
#endif
// Print surface diameter/2 minus unreachable space (avoid collisions with vertical towers).
#define DELTA_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)
// Distance between bed and nozzle Z home position
#define DELTA_HEIGHT 250.00 // (mm) Get this value from G33 auto calibrate
#define DELTA_ENDSTOP_ADJ { 0.0, 0.0, 0.0 } // Get these values from G33 auto calibrate
// Horizontal distance bridged by diagonal push rods when effector is centered.
#define DELTA_RADIUS 124.0 // (mm) Get this value from G33 auto calibrate
// Trim adjustments for individual towers
// tower angle corrections for X and Y tower / rotate XYZ so Z tower angle = 0
// measured in degrees anticlockwise looking from above the printer
#define DELTA_TOWER_ANGLE_TRIM { 0.0, 0.0, 0.0 } // Get these values from G33 auto calibrate
// Delta radius and diagonal rod adjustments (mm)
//#define DELTA_RADIUS_TRIM_TOWER { 0.0, 0.0, 0.0 }
//#define DELTA_DIAGONAL_ROD_TRIM_TOWER { 0.0, 0.0, 0.0 }
#endif
// @section scara
/**
* MORGAN_SCARA was developed by QHARLEY in South Africa in 2012-2013.
* Implemented and slightly reworked by JCERNY in June, 2014.
*
* Mostly Printed SCARA is an open source design by Tyler Williams. See:
* https://www.thingiverse.com/thing:2487048
* https://www.thingiverse.com/thing:1241491
*/
//#define MORGAN_SCARA
//#define MP_SCARA
#if EITHER(MORGAN_SCARA, MP_SCARA)
// If movement is choppy try lowering this value
#define SCARA_SEGMENTS_PER_SECOND 200
// Length of inner and outer support arms. Measure arm lengths precisely.
#define SCARA_LINKAGE_1 150 // (mm)
#define SCARA_LINKAGE_2 150 // (mm)
// SCARA tower offset (position of Tower relative to bed zero position)
// This needs to be reasonably accurate as it defines the printbed position in the SCARA space.
#define SCARA_OFFSET_X 100 // (mm)
#define SCARA_OFFSET_Y -56 // (mm)
#if ENABLED(MORGAN_SCARA)
//#define DEBUG_SCARA_KINEMATICS
#define SCARA_FEEDRATE_SCALING // Convert XY feedrate from mm/s to degrees/s on the fly
// Radius around the center where the arm cannot reach
#define MIDDLE_DEAD_ZONE_R 0 // (mm)
#define THETA_HOMING_OFFSET 0 // Calculated from Calibration Guide and M360 / M114. See http://reprap.harleystudio.co.za/?page_id=1073
#define PSI_HOMING_OFFSET 0 // Calculated from Calibration Guide and M364 / M114. See http://reprap.harleystudio.co.za/?page_id=1073
#elif ENABLED(MP_SCARA)
#define SCARA_OFFSET_THETA1 12 // degrees
#define SCARA_OFFSET_THETA2 131 // degrees
#endif
#endif
// @section tpara
// Enable for TPARA kinematics and configure below
//#define AXEL_TPARA
#if ENABLED(AXEL_TPARA)
#define DEBUG_ROBOT_KINEMATICS
#define ROBOT_SEGMENTS_PER_SECOND 200
// Length of inner and outer support arms. Measure arm lengths precisely.
#define ROBOT_LINKAGE_1 120 // (mm)
#define ROBOT_LINKAGE_2 120 // (mm)
// SCARA tower offset (position of Tower relative to bed zero position)
// This needs to be reasonably accurate as it defines the printbed position in the SCARA space.
#define ROBOT_OFFSET_X 0 // (mm)
#define ROBOT_OFFSET_Y 0 // (mm)
#define ROBOT_OFFSET_Z 0 // (mm)
#define SCARA_FEEDRATE_SCALING // Convert XY feedrate from mm/s to degrees/s on the fly
// Radius around the center where the arm cannot reach
#define MIDDLE_DEAD_ZONE_R 0 // (mm)
// Calculated from Calibration Guide and M360 / M114. See http://reprap.harleystudio.co.za/?page_id=1073
#define THETA_HOMING_OFFSET 0
#define PSI_HOMING_OFFSET 0
#endif
// @section machine
// Articulated robot (arm). Joints are directly mapped to axes with no kinematics.
//#define ARTICULATED_ROBOT_ARM
// For a hot wire cutter with parallel horizontal axes (X, I) where the heights of the two wire
// ends are controlled by parallel axes (Y, J). Joints are directly mapped to axes (no kinematics).
//#define FOAMCUTTER_XYUV
//===========================================================================
//============================== Endstop Settings ===========================
//===========================================================================
// @section endstops
// @section homing
// Specify here all the endstop connectors that are connected to any endstop or probe.
// Almost all printers will be using one per axis. Probes will use one or more of the
@@ -1373,27 +1217,6 @@
#define Z_PROBE_RETRACT_X X_MAX_POS
#endif
/**
* Magnetically Mounted Probe
* For probes such as Euclid, Klicky, Klackender, etc.
*/
//#define MAG_MOUNTED_PROBE
#if ENABLED(MAG_MOUNTED_PROBE)
#define PROBE_DEPLOY_FEEDRATE (133*60) // (mm/min) Probe deploy speed
#define PROBE_STOW_FEEDRATE (133*60) // (mm/min) Probe stow speed
#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
#define MAG_MOUNTED_DEPLOY_4 { PROBE_DEPLOY_FEEDRATE, { 0, 0, 0 } } // Extra move if needed
#define MAG_MOUNTED_DEPLOY_5 { PROBE_DEPLOY_FEEDRATE, { 0, 0, 0 } } // Extra move if needed
#define MAG_MOUNTED_STOW_1 { PROBE_STOW_FEEDRATE, { 245, 114, 20 } } // Move to dock
#define MAG_MOUNTED_STOW_2 { PROBE_STOW_FEEDRATE, { 245, 114, 0 } } // Place probe beside remover
#define MAG_MOUNTED_STOW_3 { PROBE_STOW_FEEDRATE, { 230, 114, 0 } } // Side move to remove probe
#define MAG_MOUNTED_STOW_4 { PROBE_STOW_FEEDRATE, { 210, 114, 20 } } // Side move to remove probe
#define MAG_MOUNTED_STOW_5 { PROBE_STOW_FEEDRATE, { 0, 0, 0 } } // Extra move if needed
#endif
// Duet Smart Effector (for delta printers) - https://bit.ly/2ul5U7J
// When the pin is defined you can use M672 to set/reset the probe sensitivity.
//#define DUET_SMART_EFFECTOR
@@ -1409,37 +1232,9 @@
*/
//#define SENSORLESS_PROBING
/**
* Allen key retractable z-probe as seen on many Kossel delta printers - https://reprap.org/wiki/Kossel#Automatic_bed_leveling_probe
* Deploys by touching z-axis belt. Retracts by pushing the probe down.
*/
//#define Z_PROBE_ALLEN_KEY
#if ENABLED(Z_PROBE_ALLEN_KEY)
// 2 or 3 sets of coordinates for deploying and retracting the spring loaded touch probe on G29,
// if servo actuated touch probe is not defined. Uncomment as appropriate for your printer/probe.
#define Z_PROBE_ALLEN_KEY_DEPLOY_1 { 30.0, DELTA_PRINTABLE_RADIUS, 100.0 }
#define Z_PROBE_ALLEN_KEY_DEPLOY_1_FEEDRATE XY_PROBE_FEEDRATE
#define Z_PROBE_ALLEN_KEY_DEPLOY_2 { 0.0, DELTA_PRINTABLE_RADIUS, 100.0 }
#define Z_PROBE_ALLEN_KEY_DEPLOY_2_FEEDRATE (XY_PROBE_FEEDRATE)/10
#define Z_PROBE_ALLEN_KEY_DEPLOY_3 { 0.0, (DELTA_PRINTABLE_RADIUS) * 0.75, 100.0 }
#define Z_PROBE_ALLEN_KEY_DEPLOY_3_FEEDRATE XY_PROBE_FEEDRATE
#define Z_PROBE_ALLEN_KEY_STOW_1 { -64.0, 56.0, 23.0 } // Move the probe into position
#define Z_PROBE_ALLEN_KEY_STOW_1_FEEDRATE XY_PROBE_FEEDRATE
#define Z_PROBE_ALLEN_KEY_STOW_2 { -64.0, 56.0, 3.0 } // Push it down
#define Z_PROBE_ALLEN_KEY_STOW_2_FEEDRATE (XY_PROBE_FEEDRATE)/10
#define Z_PROBE_ALLEN_KEY_STOW_3 { -64.0, 56.0, 50.0 } // Move it up to clear
#define Z_PROBE_ALLEN_KEY_STOW_3_FEEDRATE XY_PROBE_FEEDRATE
#define Z_PROBE_ALLEN_KEY_STOW_4 { 0.0, 0.0, 50.0 }
#define Z_PROBE_ALLEN_KEY_STOW_4_FEEDRATE XY_PROBE_FEEDRATE
#endif // Z_PROBE_ALLEN_KEY
//
// For Z_PROBE_ALLEN_KEY see the Delta example configurations.
//
/**
* Nozzle-to-Probe offsets { X, Y, Z }
@@ -1635,7 +1430,7 @@
#define DISABLE_E false // Disable the extruder when not stepping
#define DISABLE_INACTIVE_EXTRUDER // Keep only the active extruder enabled
// @section motion
// @section machine
// Invert the stepper direction. Change (or reverse the motor connector) if an axis goes the wrong way.
#define INVERT_X_DIR false
@@ -1689,7 +1484,7 @@
//#define V_HOME_DIR -1
//#define W_HOME_DIR -1
// @section geometry
// @section machine
// The size of the printable area
#define X_BED_SIZE 200
@@ -1892,15 +1687,6 @@
#define LEVELING_BED_TEMP 50
#endif
/**
* Bed Distance Sensor
*
* Measures the distance from bed to nozzle with accuracy of 0.01mm.
* For information about this sensor https://github.com/markniu/Bed_Distance_sensor
* Uses I2C port, so it requires I2C library markyue/Panda_SoftMasterI2C.
*/
//#define BD_SENSOR
/**
* Enable detailed logging of G28, G29, M48, etc.
* Turn on with the command 'M111 S32'.
@@ -2020,18 +1806,18 @@
#endif
// Add a menu item to move between bed corners for manual bed adjustment
//#define LCD_BED_TRAMMING
//#define LEVEL_BED_CORNERS
#if ENABLED(LCD_BED_TRAMMING)
#define BED_TRAMMING_INSET_LFRB { 30, 30, 30, 30 } // (mm) Left, Front, Right, Back insets
#define BED_TRAMMING_HEIGHT 0.0 // (mm) Z height of nozzle at leveling points
#define BED_TRAMMING_Z_HOP 4.0 // (mm) Z height of nozzle between leveling points
//#define BED_TRAMMING_INCLUDE_CENTER // Move to the center after the last corner
//#define BED_TRAMMING_USE_PROBE
#if ENABLED(BED_TRAMMING_USE_PROBE)
#define BED_TRAMMING_PROBE_TOLERANCE 0.1 // (mm)
#define BED_TRAMMING_VERIFY_RAISED // After adjustment triggers the probe, re-probe to verify
//#define BED_TRAMMING_AUDIO_FEEDBACK
#if ENABLED(LEVEL_BED_CORNERS)
#define LEVEL_CORNERS_INSET_LFRB { 30, 30, 30, 30 } // (mm) Left, Front, Right, Back insets
#define LEVEL_CORNERS_HEIGHT 0.0 // (mm) Z height of nozzle at leveling points
#define LEVEL_CORNERS_Z_HOP 4.0 // (mm) Z height of nozzle between leveling points
//#define LEVEL_CENTER_TOO // Move to the center after the last corner
//#define LEVEL_CORNERS_USE_PROBE
#if ENABLED(LEVEL_CORNERS_USE_PROBE)
#define LEVEL_CORNERS_PROBE_TOLERANCE 0.1
#define LEVEL_CORNERS_VERIFY_RAISED // After adjustment triggers the probe, re-probe to verify
//#define LEVEL_CORNERS_AUDIO_FEEDBACK
#endif
/**
@@ -2051,7 +1837,7 @@
* | 1 2 | | 1 4 | | 1 2 | | 2 |
* LF --------- RF LF --------- RF LF --------- RF LF --------- RF
*/
#define BED_TRAMMING_LEVELING_ORDER { LF, RF, RB, LB }
#define LEVEL_CORNERS_LEVELING_ORDER { LF, RF, RB, LB }
#endif
/**
@@ -2135,8 +1921,9 @@
#define XY_DIAG_BD 282.8427124746
#define XY_SIDE_AD 200
// Or, set the XY skew factor directly:
//#define XY_SKEW_FACTOR 0.0
// Or, set the default skew factors directly here
// to override the above measurements:
#define XY_SKEW_FACTOR 0.0
//#define SKEW_CORRECTION_FOR_Z
#if ENABLED(SKEW_CORRECTION_FOR_Z)
@@ -2145,10 +1932,8 @@
#define YZ_DIAG_AC 282.8427124746
#define YZ_DIAG_BD 282.8427124746
#define YZ_SIDE_AD 200
// Or, set the Z skew factors directly:
//#define XZ_SKEW_FACTOR 0.0
//#define YZ_SKEW_FACTOR 0.0
#define XZ_SKEW_FACTOR 0.0
#define YZ_SKEW_FACTOR 0.0
#endif
// Enable this option for M852 to set skew at runtime
@@ -2159,7 +1944,7 @@
//============================= Additional Features ===========================
//=============================================================================
// @section eeprom
// @section extras
/**
* EEPROM
@@ -2179,8 +1964,6 @@
//#define EEPROM_INIT_NOW // Init EEPROM on first boot after a new build.
#endif
// @section host
//
// Host Keepalive
//
@@ -2191,8 +1974,6 @@
#define DEFAULT_KEEPALIVE_INTERVAL 2 // Number of seconds between "busy" messages. Set with M113.
#define BUSY_WHILE_HEATING // Some hosts require "busy" messages even during heating
// @section units
//
// G20/G21 Inch mode support
//
@@ -2206,7 +1987,7 @@
// @section temperature
//
// Preheat Constants - Up to 10 are supported without changes
// Preheat Constants - Up to 6 are supported without changes
//
#define PREHEAT_1_LABEL "PLA"
#define PREHEAT_1_TEMP_HOTEND 180
@@ -2220,8 +2001,6 @@
#define PREHEAT_2_TEMP_CHAMBER 35
#define PREHEAT_2_FAN_SPEED 0 // Value from 0 to 255
// @section motion
/**
* Nozzle Park
*
@@ -2320,8 +2099,6 @@
#endif
// @section host
/**
* Print Job Timer
*
@@ -2348,8 +2125,6 @@
*/
#define PRINTJOB_TIMER_AUTOSTART
// @section stats
/**
* Print Counter
*
@@ -2364,11 +2139,9 @@
*/
//#define PRINTCOUNTER
#if ENABLED(PRINTCOUNTER)
#define PRINTCOUNTER_SAVE_INTERVAL 60 // (minutes) EEPROM save interval during print. A value of 0 will save stats at end of print.
#define PRINTCOUNTER_SAVE_INTERVAL 60 // (minutes) EEPROM save interval during print
#endif
// @section security
/**
* Password
*
@@ -2404,7 +2177,7 @@
//============================= LCD and SD support ============================
//=============================================================================
// @section interface
// @section lcd
/**
* LCD LANGUAGE
@@ -2520,16 +2293,6 @@
//
//#define REVERSE_SELECT_DIRECTION
//
// Encoder EMI Noise Filter
//
// This option increases encoder samples to filter out phantom encoder clicks caused by EMI noise.
//
//#define ENCODER_NOISE_FILTER
#if ENABLED(ENCODER_NOISE_FILTER)
#define ENCODER_SAMPLES 10
#endif
//
// Individual Axis Homing
//
@@ -2560,7 +2323,6 @@
//======================== LCD / Controller Selection =========================
//======================== (Character-based LCDs) =========================
//=============================================================================
// @section lcd
//
// RepRapDiscount Smart Controller.
@@ -2862,12 +2624,6 @@
//
//#define SILVER_GATE_GLCD_CONTROLLER
//
// eMotion Tech LCD with SD
// https://www.reprap-france.com/produit/1234568748-ecran-graphique-128-x-64-points-2-1
//
//#define EMOTION_TECH_LCD
//=============================================================================
//============================== OLED Displays ==============================
//=============================================================================
@@ -2990,7 +2746,6 @@
//#define ANYCUBIC_LCD_CHIRON
#if EITHER(ANYCUBIC_LCD_I3MEGA, ANYCUBIC_LCD_CHIRON)
//#define ANYCUBIC_LCD_DEBUG
//#define ANYCUBIC_LCD_GCODE_EXT // Add ".gcode" to menu entries for DGUS clone compatibility
#endif
//
@@ -3158,11 +2913,10 @@
//
//#define TOUCH_SCREEN
#if ENABLED(TOUCH_SCREEN)
#define BUTTON_DELAY_EDIT 50 // (ms) Button repeat delay for edit screens
#define BUTTON_DELAY_MENU 250 // (ms) Button repeat delay for menus
#define BUTTON_DELAY_EDIT 50 // (ms) Button repeat delay for edit screens
#define BUTTON_DELAY_MENU 250 // (ms) Button repeat delay for menus
//#define DISABLE_ENCODER // Disable the click encoder, if any
//#define TOUCH_IDLE_SLEEP_MINS 5 // (minutes) Display Sleep after a period of inactivity. Set with M255 S.
//#define TOUCH_IDLE_SLEEP 300 // (s) Turn off the TFT backlight if set (5mn)
#define TOUCH_SCREEN_CALIBRATION
@@ -3197,7 +2951,7 @@
//=============================== Extra Features ==============================
//=============================================================================
// @section fans
// @section extras
// Set number of user-controlled fans. Disable to use all board-defined fans.
// :[1,2,3,4,5,6,7,8]
@@ -3221,18 +2975,14 @@
// duty cycle is attained.
//#define SOFT_PWM_DITHER
// @section extras
// Support for the BariCUDA Paste Extruder
//#define BARICUDA
// @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)
//#define TEMP_STAT_LEDS
// Support for the BariCUDA Paste Extruder
//#define BARICUDA
// Support for BlinkM/CyzRgb
//#define BLINKM
@@ -3253,19 +3003,16 @@
* luminance values can be set from 0 to 255.
* For NeoPixel LED an overall brightness parameter is also available.
*
* === CAUTION ===
* *** CAUTION ***
* LED Strips require a MOSFET Chip between PWM lines and LEDs,
* as the Arduino cannot handle the current the LEDs will require.
* Failure to follow this precaution can destroy your Arduino!
*
* NOTE: A separate 5V power supply is required! The NeoPixel LED needs
* more current than the Arduino 5V linear regulator can produce.
* *** CAUTION ***
*
* Requires PWM frequency between 50 <> 100Hz (Check HAL or variant)
* Use FAST_PWM_FAN, if possible, to reduce fan noise.
* LED Type. Enable only one of the following two options.
*/
// LED Type. Enable only one of the following two options:
//#define RGB_LED
//#define RGBW_LED
@@ -3274,10 +3021,6 @@
//#define RGB_LED_G_PIN 43
//#define RGB_LED_B_PIN 35
//#define RGB_LED_W_PIN -1
//#define RGB_STARTUP_TEST // For PWM pins, fade between all colors
#if ENABLED(RGB_STARTUP_TEST)
#define RGB_STARTUP_TEST_INNER_MS 10 // (ms) Reduce or increase fading speed
#endif
#endif
// Support for Adafruit NeoPixel LED driver
@@ -3325,8 +3068,6 @@
#define PRINTER_EVENT_LEDS
#endif
// @section servos
/**
* Number of servos
*
+427 -266
View File
File diff suppressed because it is too large Load Diff
+119 -6
View File
@@ -109,7 +109,7 @@ LIQUID_TWI2 ?= 0
# This defines if Wire is needed
WIRE ?= 0
# This defines if Tone is needed (i.e., SPEAKER is defined in Configuration.h)
# This defines if Tone is needed (i.e SPEAKER is defined in Configuration.h)
# Disabling this (and SPEAKER) saves approximately 350 bytes of memory.
TONE ?= 1
@@ -317,10 +317,123 @@ else ifeq ($(HARDWARE_MOTHERBOARD),1159)
else ifeq ($(HARDWARE_MOTHERBOARD),1160)
# Longer LKx PRO / Alfawise Uxx Pro (PRO version)
else ifeq ($(HARDWARE_MOTHERBOARD),1161)
# Zonestar zrib V5.3 (Chinese RAMPS replica)
else ifeq ($(HARDWARE_MOTHERBOARD),1162)
# Pxmalion Core I3
else ifeq ($(HARDWARE_MOTHERBOARD),1163)
# 3Drag Controller
else ifeq ($(HARDWARE_MOTHERBOARD),1100)
# Velleman K8200 Controller (derived from 3Drag Controller)
else ifeq ($(HARDWARE_MOTHERBOARD),1101)
# Velleman K8400 Controller (derived from 3Drag Controller)
else ifeq ($(HARDWARE_MOTHERBOARD),1102)
# Velleman K8600 Controller (Vertex Nano)
else ifeq ($(HARDWARE_MOTHERBOARD),1103)
# Velleman K8800 Controller (Vertex Delta)
else ifeq ($(HARDWARE_MOTHERBOARD),1104)
# 2PrintBeta BAM&DICE with STK drivers
else ifeq ($(HARDWARE_MOTHERBOARD),1105)
# 2PrintBeta BAM&DICE Due with STK drivers
else ifeq ($(HARDWARE_MOTHERBOARD),1106)
# MKS BASE v1.0
else ifeq ($(HARDWARE_MOTHERBOARD),1107)
# MKS v1.4 with A4982 stepper drivers
else ifeq ($(HARDWARE_MOTHERBOARD),1108)
# MKS v1.5 with Allegro A4982 stepper drivers
else ifeq ($(HARDWARE_MOTHERBOARD),1109)
# MKS v1.6 with Allegro A4982 stepper drivers
else ifeq ($(HARDWARE_MOTHERBOARD),1110)
# MKS BASE 1.0 with Heroic HR4982 stepper drivers
else ifeq ($(HARDWARE_MOTHERBOARD),1111)
# MKS GEN v1.3 or 1.4
else ifeq ($(HARDWARE_MOTHERBOARD),1112)
# MKS GEN L
else ifeq ($(HARDWARE_MOTHERBOARD),1113)
# zrib V2.0 control board (Chinese RAMPS replica)
else ifeq ($(HARDWARE_MOTHERBOARD),1114)
# BigTreeTech or BIQU KFB2.0
else ifeq ($(HARDWARE_MOTHERBOARD),1115)
# Felix 2.0+ Electronics Board (RAMPS like)
else ifeq ($(HARDWARE_MOTHERBOARD),1116)
# Invent-A-Part RigidBoard
else ifeq ($(HARDWARE_MOTHERBOARD),1117)
# Invent-A-Part RigidBoard V2
else ifeq ($(HARDWARE_MOTHERBOARD),1118)
# Sainsmart 2-in-1 board
else ifeq ($(HARDWARE_MOTHERBOARD),1119)
# Ultimaker
else ifeq ($(HARDWARE_MOTHERBOARD),1120)
# Ultimaker (Older electronics. Pre 1.5.4. This is rare)
else ifeq ($(HARDWARE_MOTHERBOARD),1121)
MCU ?= atmega1280
PROG_MCU ?= m1280
# Azteeg X3
else ifeq ($(HARDWARE_MOTHERBOARD),1122)
# Azteeg X3 Pro
else ifeq ($(HARDWARE_MOTHERBOARD),1123)
# Ultimainboard 2.x (Uses TEMP_SENSOR 20)
else ifeq ($(HARDWARE_MOTHERBOARD),1124)
# Rumba
else ifeq ($(HARDWARE_MOTHERBOARD),1125)
# Raise3D Rumba
else ifeq ($(HARDWARE_MOTHERBOARD),1126)
# Rapide Lite RL200 Rumba
else ifeq ($(HARDWARE_MOTHERBOARD),1127)
# Formbot T-Rex 2 Plus
else ifeq ($(HARDWARE_MOTHERBOARD),1128)
# Formbot T-Rex 3
else ifeq ($(HARDWARE_MOTHERBOARD),1129)
# Formbot Raptor
else ifeq ($(HARDWARE_MOTHERBOARD),1130)
# Formbot Raptor 2
else ifeq ($(HARDWARE_MOTHERBOARD),1131)
# bq ZUM Mega 3D
else ifeq ($(HARDWARE_MOTHERBOARD),1132)
# MakeBoard Mini v2.1.2 is a control board sold by MicroMake
else ifeq ($(HARDWARE_MOTHERBOARD),1133)
# TriGorilla Anycubic version 1.3 based on RAMPS EFB
else ifeq ($(HARDWARE_MOTHERBOARD),1134)
# TriGorilla Anycubic version 1.4 based on RAMPS EFB
else ifeq ($(HARDWARE_MOTHERBOARD),1135)
# TriGorilla Anycubic version 1.4 Rev 1.1
else ifeq ($(HARDWARE_MOTHERBOARD),1136)
# Creality: Ender-4, CR-8
else ifeq ($(HARDWARE_MOTHERBOARD),1137)
# Creality: CR10S, CR20, CR-X
else ifeq ($(HARDWARE_MOTHERBOARD),1138)
# Dagoma F5
else ifeq ($(HARDWARE_MOTHERBOARD),1139)
# FYSETC F6 1.3
else ifeq ($(HARDWARE_MOTHERBOARD),1140)
# FYSETC F6 1.5
else ifeq ($(HARDWARE_MOTHERBOARD),1141)
# Duplicator i3 Plus
else ifeq ($(HARDWARE_MOTHERBOARD),1142)
# VORON
else ifeq ($(HARDWARE_MOTHERBOARD),1143)
# TRONXY V3 1.0
else ifeq ($(HARDWARE_MOTHERBOARD),1144)
# Z-Bolt X Series
else ifeq ($(HARDWARE_MOTHERBOARD),1145)
# TT OSCAR
else ifeq ($(HARDWARE_MOTHERBOARD),1146)
# Overlord/Overlord Pro
else ifeq ($(HARDWARE_MOTHERBOARD),1147)
# ADIMLab Gantry v1
else ifeq ($(HARDWARE_MOTHERBOARD),1148)
# ADIMLab Gantry v2
else ifeq ($(HARDWARE_MOTHERBOARD),1149)
# BIQU Tango V1
else ifeq ($(HARDWARE_MOTHERBOARD),1150)
# MKS GEN L V2
else ifeq ($(HARDWARE_MOTHERBOARD),1151)
# MKS GEN L V2.1
else ifeq ($(HARDWARE_MOTHERBOARD),1152)
# Copymaster 3D
else ifeq ($(HARDWARE_MOTHERBOARD),1153)
# Ortur 4
else ifeq ($(HARDWARE_MOTHERBOARD),1154)
# Tenlog D3 Hero
else ifeq ($(HARDWARE_MOTHERBOARD),1155)
#
# RAMBo and derivatives
@@ -399,7 +512,7 @@ else ifeq ($(HARDWARE_MOTHERBOARD),1324)
else ifeq ($(HARDWARE_MOTHERBOARD),1325)
# Intamsys 4.0 (Funmat HT)
else ifeq ($(HARDWARE_MOTHERBOARD),1326)
# Malyan M180 Mainboard Version 2 (no display function, direct G-code only)
# Malyan M180 Mainboard Version 2 (no display function, direct gcode only)
else ifeq ($(HARDWARE_MOTHERBOARD),1327)
# Geeetech GT2560 Rev B for A20(M/T/D)
else ifeq ($(HARDWARE_MOTHERBOARD),1328)
+2 -2
View File
@@ -28,7 +28,7 @@
/**
* Marlin release version identifier
*/
//#define SHORT_BUILD_VERSION "bugfix-2.1.x"
//#define SHORT_BUILD_VERSION "bugfix-2.0.x"
/**
* Verbose version identifier which should contain a reference to the location
@@ -41,7 +41,7 @@
* here we define this default string as the date where the latest release
* version was tagged.
*/
//#define STRING_DISTRIBUTION_DATE "2022-10-16"
//#define STRING_DISTRIBUTION_DATE "2022-05-29"
/**
* Defines a generic printer name to be output to the LCD after booting Marlin.
-211
View File
@@ -1,211 +0,0 @@
#
# Marlin Firmware
# config.ini - Options to apply before the build
#
[config:base]
ini_use_config = none
# Load all config: sections in this file
;ini_use_config = all
# Load config file relative to Marlin/
;ini_use_config = another.ini
# Download configurations from GitHub
;ini_use_config = example/Creality/Ender-5 Plus @ bugfix-2.1.x
# Download configurations from your server
;ini_use_config = https://me.myserver.com/path/to/configs
# Evaluate config:base and do a config dump
;ini_use_config = base
;config_export = 2
[config:minimal]
motherboard = BOARD_RAMPS_14_EFB
serial_port = 0
baudrate = 250000
use_watchdog = on
thermal_protection_hotends = on
thermal_protection_hysteresis = 4
thermal_protection_period = 40
bufsize = 4
block_buffer_size = 16
max_cmd_size = 96
extruders = 1
temp_sensor_0 = 1
temp_hysteresis = 3
heater_0_mintemp = 5
heater_0_maxtemp = 275
preheat_1_temp_hotend = 180
bang_max = 255
pidtemp = on
pid_k1 = 0.95
pid_max = BANG_MAX
pid_functional_range = 10
default_kp = 22.20
default_ki = 1.08
default_kd = 114.00
x_driver_type = A4988
y_driver_type = A4988
z_driver_type = A4988
e0_driver_type = A4988
x_bed_size = 200
x_min_pos = 0
x_max_pos = X_BED_SIZE
y_bed_size = 200
y_min_pos = 0
y_max_pos = Y_BED_SIZE
z_min_pos = 0
z_max_pos = 200
x_home_dir = -1
y_home_dir = -1
z_home_dir = -1
use_xmin_plug = on
use_ymin_plug = on
use_zmin_plug = on
x_min_endstop_inverting = false
y_min_endstop_inverting = false
z_min_endstop_inverting = false
default_axis_steps_per_unit = { 80, 80, 400, 500 }
axis_relative_modes = { false, false, false, false }
default_max_feedrate = { 300, 300, 5, 25 }
default_max_acceleration = { 3000, 3000, 100, 10000 }
homing_feedrate_mm_m = { (50*60), (50*60), (4*60) }
homing_bump_divisor = { 2, 2, 4 }
x_enable_on = 0
y_enable_on = 0
z_enable_on = 0
e_enable_on = 0
invert_x_dir = false
invert_y_dir = true
invert_z_dir = false
invert_e0_dir = false
invert_e_step_pin = false
invert_x_step_pin = false
invert_y_step_pin = false
invert_z_step_pin = false
disable_x = false
disable_y = false
disable_z = false
disable_e = false
proportional_font_ratio = 1.0
default_nominal_filament_dia = 1.75
junction_deviation_mm = 0.013
default_acceleration = 3000
default_travel_acceleration = 3000
default_retract_acceleration = 3000
default_minimumfeedrate = 0.0
default_mintravelfeedrate = 0.0
minimum_planner_speed = 0.05
min_steps_per_segment = 6
default_minsegmenttime = 20000
[config:basic]
bed_overshoot = 10
busy_while_heating = on
default_ejerk = 5.0
default_keepalive_interval = 2
default_leveling_fade_height = 0.0
disable_inactive_extruder = on
display_charset_hd44780 = JAPANESE
eeprom_boot_silent = on
eeprom_chitchat = on
endstoppullups = on
extrude_maxlength = 200
extrude_mintemp = 170
host_keepalive_feature = on
hotend_overshoot = 15
jd_handle_small_segments = on
lcd_info_screen_style = 0
lcd_language = en
max_bed_power = 255
mesh_inset = 0
min_software_endstops = on
max_software_endstops = on
min_software_endstop_x = on
min_software_endstop_y = on
min_software_endstop_z = on
max_software_endstop_x = on
max_software_endstop_y = on
max_software_endstop_z = on
preheat_1_fan_speed = 0
preheat_1_label = "PLA"
preheat_1_temp_bed = 70
prevent_cold_extrusion = on
prevent_lengthy_extrude = on
printjob_timer_autostart = on
probing_margin = 10
show_bootscreen = on
soft_pwm_scale = 0
string_config_h_author = "(none, default config)"
temp_bed_hysteresis = 3
temp_bed_residency_time = 10
temp_bed_window = 1
temp_residency_time = 10
temp_window = 1
validate_homing_endstops = on
xy_probe_feedrate = (133*60)
z_clearance_between_probes = 5
z_clearance_deploy_probe = 10
z_clearance_multi_probe = 5
[config:advanced]
arc_support = on
auto_report_temperatures = on
autotemp = on
autotemp_oldweight = 0.98
bed_check_interval = 5000
default_stepper_deactive_time = 120
default_volumetric_extruder_limit = 0.00
disable_inactive_e = true
disable_inactive_x = true
disable_inactive_y = true
disable_inactive_z = true
e0_auto_fan_pin = -1
encoder_100x_steps_per_sec = 80
encoder_10x_steps_per_sec = 30
encoder_rate_multiplier = on
extended_capabilities_report = on
extruder_auto_fan_speed = 255
extruder_auto_fan_temperature = 50
fanmux0_pin = -1
fanmux1_pin = -1
fanmux2_pin = -1
faster_gcode_parser = on
homing_bump_mm = { 5, 5, 2 }
max_arc_segment_mm = 1.0
min_arc_segment_mm = 0.1
min_circle_segments = 72
n_arc_correction = 25
serial_overrun_protection = on
slowdown = on
slowdown_divisor = 2
temp_sensor_bed = 0
thermal_protection_bed_hysteresis = 2
thermocouple_max_errors = 15
tx_buffer_size = 0
watch_bed_temp_increase = 2
watch_bed_temp_period = 60
watch_temp_increase = 2
watch_temp_period = 20
+92 -102
View File
@@ -66,26 +66,27 @@ static volatile int8_t Channel[_Nbr_16timers]; // counter for the s
/************ static functions common to all instances ***********************/
static inline void handle_interrupts(const timer16_Sequence_t timer, volatile uint16_t* TCNTn, volatile uint16_t* OCRnA) {
int8_t cho = Channel[timer]; // Handle the prior Channel[timer] first
if (cho < 0) // Channel -1 indicates the refresh interval completed...
*TCNTn = 0; // ...so reset the timer
else if (SERVO_INDEX(timer, cho) < ServoCount) // prior channel handled?
extDigitalWrite(SERVO(timer, cho).Pin.nbr, LOW); // pulse the prior channel LOW
static inline void handle_interrupts(timer16_Sequence_t timer, volatile uint16_t* TCNTn, volatile uint16_t* OCRnA) {
if (Channel[timer] < 0)
*TCNTn = 0; // channel set to -1 indicated that refresh interval completed so reset the timer
else {
if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && SERVO(timer, Channel[timer]).Pin.isActive)
extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, LOW); // pulse this channel low if activated
}
Channel[timer] = ++cho; // Handle the next channel (or 0)
if (cho < SERVOS_PER_TIMER && SERVO_INDEX(timer, cho) < ServoCount) {
*OCRnA = *TCNTn + SERVO(timer, cho).ticks; // set compare to current ticks plus duration
if (SERVO(timer, cho).Pin.isActive) // activated?
extDigitalWrite(SERVO(timer, cho).Pin.nbr, HIGH); // yes: pulse HIGH
Channel[timer]++; // increment to the next channel
if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) {
*OCRnA = *TCNTn + SERVO(timer, Channel[timer]).ticks;
if (SERVO(timer, Channel[timer]).Pin.isActive) // check if activated
extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, HIGH); // it's an active channel so pulse it high
}
else {
// finished all channels so wait for the refresh period to expire before starting over
const unsigned int cval = ((unsigned)*TCNTn) + 32 / (SERVO_TIMER_PRESCALER), // allow 32 cycles to ensure the next OCR1A not missed
ival = (unsigned int)usToTicks(REFRESH_INTERVAL); // at least REFRESH_INTERVAL has elapsed
*OCRnA = max(cval, ival);
Channel[timer] = -1; // reset the timer counter to 0 on the next call
if (((unsigned)*TCNTn) + 4 < usToTicks(REFRESH_INTERVAL)) // allow a few ticks to ensure the next OCR1A not missed
*OCRnA = (unsigned int)usToTicks(REFRESH_INTERVAL);
else
*OCRnA = *TCNTn + 4; // at least REFRESH_INTERVAL has elapsed
Channel[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel
}
}
@@ -122,102 +123,91 @@ static inline void handle_interrupts(const timer16_Sequence_t timer, volatile ui
/****************** end of static functions ******************************/
void initISR(const timer16_Sequence_t timer_index) {
switch (timer_index) {
default: break;
void initISR(timer16_Sequence_t timer) {
#ifdef _useTimer1
if (timer == _timer1) {
TCCR1A = 0; // normal counting mode
TCCR1B = _BV(CS11); // set prescaler of 8
TCNT1 = 0; // clear the timer count
#if defined(__AVR_ATmega8__) || defined(__AVR_ATmega128__)
SBI(TIFR, OCF1A); // clear any pending interrupts;
SBI(TIMSK, OCIE1A); // enable the output compare interrupt
#else
// here if not ATmega8 or ATmega128
SBI(TIFR1, OCF1A); // clear any pending interrupts;
SBI(TIMSK1, OCIE1A); // enable the output compare interrupt
#endif
#ifdef WIRING
timerAttach(TIMER1OUTCOMPAREA_INT, Timer1Service);
#endif
}
#endif
#ifdef _useTimer1
case _timer1:
TCCR1A = 0; // normal counting mode
TCCR1B = _BV(CS11); // set prescaler of 8
TCNT1 = 0; // clear the timer count
#if defined(__AVR_ATmega8__) || defined(__AVR_ATmega128__)
SBI(TIFR, OCF1A); // clear any pending interrupts;
SBI(TIMSK, OCIE1A); // enable the output compare interrupt
#else
// here if not ATmega8 or ATmega128
SBI(TIFR1, OCF1A); // clear any pending interrupts;
SBI(TIMSK1, OCIE1A); // enable the output compare interrupt
#endif
#ifdef WIRING
timerAttach(TIMER1OUTCOMPAREA_INT, Timer1Service);
#endif
break;
#endif
#ifdef _useTimer3
if (timer == _timer3) {
TCCR3A = 0; // normal counting mode
TCCR3B = _BV(CS31); // set prescaler of 8
TCNT3 = 0; // clear the timer count
#ifdef __AVR_ATmega128__
SBI(TIFR, OCF3A); // clear any pending interrupts;
SBI(ETIMSK, OCIE3A); // enable the output compare interrupt
#else
SBI(TIFR3, OCF3A); // clear any pending interrupts;
SBI(TIMSK3, OCIE3A); // enable the output compare interrupt
#endif
#ifdef WIRING
timerAttach(TIMER3OUTCOMPAREA_INT, Timer3Service); // for Wiring platform only
#endif
}
#endif
#ifdef _useTimer3
case _timer3:
TCCR3A = 0; // normal counting mode
TCCR3B = _BV(CS31); // set prescaler of 8
TCNT3 = 0; // clear the timer count
#ifdef __AVR_ATmega128__
SBI(TIFR, OCF3A); // clear any pending interrupts;
SBI(ETIMSK, OCIE3A); // enable the output compare interrupt
#else
SBI(TIFR3, OCF3A); // clear any pending interrupts;
SBI(TIMSK3, OCIE3A); // enable the output compare interrupt
#endif
#ifdef WIRING
timerAttach(TIMER3OUTCOMPAREA_INT, Timer3Service); // for Wiring platform only
#endif
break;
#endif
#ifdef _useTimer4
if (timer == _timer4) {
TCCR4A = 0; // normal counting mode
TCCR4B = _BV(CS41); // set prescaler of 8
TCNT4 = 0; // clear the timer count
TIFR4 = _BV(OCF4A); // clear any pending interrupts;
TIMSK4 = _BV(OCIE4A); // enable the output compare interrupt
}
#endif
#ifdef _useTimer4
case _timer4:
TCCR4A = 0; // normal counting mode
TCCR4B = _BV(CS41); // set prescaler of 8
TCNT4 = 0; // clear the timer count
TIFR4 = _BV(OCF4A); // clear any pending interrupts;
TIMSK4 = _BV(OCIE4A); // enable the output compare interrupt
break;
#endif
#ifdef _useTimer5
case _timer5:
TCCR5A = 0; // normal counting mode
TCCR5B = _BV(CS51); // set prescaler of 8
TCNT5 = 0; // clear the timer count
TIFR5 = _BV(OCF5A); // clear any pending interrupts;
TIMSK5 = _BV(OCIE5A); // enable the output compare interrupt
break;
#endif
}
#ifdef _useTimer5
if (timer == _timer5) {
TCCR5A = 0; // normal counting mode
TCCR5B = _BV(CS51); // set prescaler of 8
TCNT5 = 0; // clear the timer count
TIFR5 = _BV(OCF5A); // clear any pending interrupts;
TIMSK5 = _BV(OCIE5A); // enable the output compare interrupt
}
#endif
}
void finISR(const timer16_Sequence_t timer_index) {
void finISR(timer16_Sequence_t timer) {
// Disable use of the given timer
#ifdef WIRING
switch (timer_index) {
default: break;
case _timer1:
CBI(
#if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
TIMSK1
#else
TIMSK
#endif
, OCIE1A // disable timer 1 output compare interrupt
);
timerDetach(TIMER1OUTCOMPAREA_INT);
break;
case _timer3:
CBI(
#if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
TIMSK3
#else
ETIMSK
#endif
, OCIE3A // disable the timer3 output compare A interrupt
);
timerDetach(TIMER3OUTCOMPAREA_INT);
break;
if (timer == _timer1) {
CBI(
#if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
TIMSK1
#else
TIMSK
#endif
, OCIE1A); // disable timer 1 output compare interrupt
timerDetach(TIMER1OUTCOMPAREA_INT);
}
else if (timer == _timer3) {
CBI(
#if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
TIMSK3
#else
ETIMSK
#endif
, OCIE3A); // disable the timer3 output compare A interrupt
timerDetach(TIMER3OUTCOMPAREA_INT);
}
#else // !WIRING
// For arduino - in future: call here to a currently undefined function to reset the timer
UNUSED(timer_index);
UNUSED(timer);
#endif
}
+3 -11
View File
@@ -35,19 +35,11 @@
|| X_STEP_PIN == N || Y_STEP_PIN == N || Z_STEP_PIN == N \
|| X_DIR_PIN == N || Y_DIR_PIN == N || Z_DIR_PIN == N \
|| X_ENA_PIN == N || Y_ENA_PIN == N || Z_ENA_PIN == N \
|| BTN_EN1 == N || BTN_EN2 == N \
)
#if CONF_SERIAL_IS(0)
// D0-D1. No known conflicts.
#if CONF_SERIAL_IS(0) // D0-D1. No known conflicts.
#endif
#if NOT_TARGET(__AVR_ATmega644P__, __AVR_ATmega1284P__)
#if CONF_SERIAL_IS(1) && (CHECK_SERIAL_PIN(18) || CHECK_SERIAL_PIN(19))
#error "Serial Port 1 pin D18 and/or D19 conflicts with another pin on the board."
#endif
#else
#if CONF_SERIAL_IS(1) && (CHECK_SERIAL_PIN(10) || CHECK_SERIAL_PIN(11))
#error "Serial Port 1 pin D10 and/or D11 conflicts with another pin on the board."
#endif
#if CONF_SERIAL_IS(1) && (CHECK_SERIAL_PIN(18) || CHECK_SERIAL_PIN(19))
#error "Serial Port 1 pin D18 and/or D19 conflicts with another pin on the board."
#endif
#if CONF_SERIAL_IS(2) && (CHECK_SERIAL_PIN(16) || CHECK_SERIAL_PIN(17))
#error "Serial Port 2 pin D16 and/or D17 conflicts with another pin on the board."
+1 -1
View File
@@ -74,7 +74,7 @@
#define MULTI_NAME_PAD 26 // space needed to be pretty if not first name assigned to a pin
void PRINT_ARRAY_NAME(uint8_t x) {
PGM_P const name_mem_pointer = (PGM_P)pgm_read_ptr(&pin_array[x].name);
const char * const name_mem_pointer = (PGM_P)pgm_read_ptr(&pin_array[x].name);
LOOP_L_N(y, MAX_NAME_LENGTH) {
char temp_char = pgm_read_byte(name_mem_pointer + y);
if (temp_char != 0)
+1 -1
View File
@@ -210,7 +210,7 @@ public:
static void adc_init() {}
// Called by Temperature::init for each sensor at startup
static void adc_enable(const uint8_t /*ch*/) {}
static void adc_enable(const uint8_t ch) {}
// Begin ADC sampling on the given channel. Called from Temperature::isr!
static void adc_start(const uint8_t ch) { adc_result = analogRead(ch); }
+2 -2
View File
@@ -247,12 +247,12 @@
b <<= 1; // little setup time
WRITE(SD_SCK_PIN, HIGH);
DELAY_NS_VAR(spiDelayNS);
DELAY_NS(spiDelayNS);
b |= (READ(SD_MISO_PIN) != 0);
WRITE(SD_SCK_PIN, LOW);
DELAY_NS_VAR(spiDelayNS);
DELAY_NS(spiDelayNS);
} while (--bits);
return b;
}
+1 -1
View File
@@ -41,7 +41,7 @@
practice, we need alignment to 256 bytes to make this work in all
cases */
__attribute__ ((aligned(256)))
static DeviceVectors ram_tab[61] = { nullptr };
static DeviceVectors ram_tab = { nullptr };
/**
* This function checks if the exception/interrupt table is already in SRAM or not.
+64 -68
View File
@@ -47,12 +47,12 @@
#include "../shared/servo.h"
#include "../shared/servo_private.h"
static Flags<_Nbr_16timers> DisablePending; // ISR should disable the timer at the next timer reset
static volatile int8_t Channel[_Nbr_16timers]; // counter for the servo being pulsed for each timer (or -1 if refresh interval)
// ------------------------
/// Interrupt handler for the TC0 channel 1.
// ------------------------
void Servo_Handler(const timer16_Sequence_t, Tc*, const uint8_t);
void Servo_Handler(timer16_Sequence_t timer, Tc *pTc, uint8_t channel);
#ifdef _useTimer1
void HANDLER_FOR_TIMER1() { Servo_Handler(_timer1, TC_FOR_TIMER1, CHANNEL_FOR_TIMER1); }
@@ -70,92 +70,88 @@ void Servo_Handler(const timer16_Sequence_t, Tc*, const uint8_t);
void HANDLER_FOR_TIMER5() { Servo_Handler(_timer5, TC_FOR_TIMER5, CHANNEL_FOR_TIMER5); }
#endif
void Servo_Handler(const timer16_Sequence_t timer, Tc *tc, const uint8_t channel) {
static int8_t Channel[_Nbr_16timers]; // Servo counters to pulse (or -1 for refresh interval)
int8_t cho = Channel[timer]; // Handle the prior Channel[timer] first
if (cho < 0) { // Channel -1 indicates the refresh interval completed...
tc->TC_CHANNEL[channel].TC_CCR |= TC_CCR_SWTRG; // ...so reset the timer
if (DisablePending[timer]) {
// Disabling only after the full servo period expires prevents
// pulses being too close together if immediately re-enabled.
DisablePending.clear(timer);
TC_Stop(tc, channel);
tc->TC_CHANNEL[channel].TC_SR; // clear interrupt
return;
}
}
else if (SERVO_INDEX(timer, cho) < ServoCount) // prior channel handled?
extDigitalWrite(SERVO(timer, cho).Pin.nbr, LOW); // pulse the prior channel LOW
void Servo_Handler(timer16_Sequence_t timer, Tc *tc, uint8_t channel) {
// clear interrupt
tc->TC_CHANNEL[channel].TC_SR;
if (Channel[timer] < 0)
tc->TC_CHANNEL[channel].TC_CCR |= TC_CCR_SWTRG; // channel set to -1 indicated that refresh interval completed so reset the timer
else if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && SERVO(timer, Channel[timer]).Pin.isActive)
extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, LOW); // pulse this channel low if activated
Channel[timer] = ++cho; // go to the next channel (or 0)
if (cho < SERVOS_PER_TIMER && SERVO_INDEX(timer, cho) < ServoCount) {
tc->TC_CHANNEL[channel].TC_RA = tc->TC_CHANNEL[channel].TC_CV + SERVO(timer, cho).ticks;
if (SERVO(timer, cho).Pin.isActive) // activated?
extDigitalWrite(SERVO(timer, cho).Pin.nbr, HIGH); // yes: pulse HIGH
Channel[timer]++; // increment to the next channel
if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) {
tc->TC_CHANNEL[channel].TC_RA = tc->TC_CHANNEL[channel].TC_CV + SERVO(timer,Channel[timer]).ticks;
if (SERVO(timer,Channel[timer]).Pin.isActive) // check if activated
extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, HIGH); // its an active channel so pulse it high
}
else {
// finished all channels so wait for the refresh period to expire before starting over
const unsigned int cval = tc->TC_CHANNEL[channel].TC_CV + 128 / (SERVO_TIMER_PRESCALER), // allow 128 cycles to ensure the next CV not missed
ival = (unsigned int)usToTicks(REFRESH_INTERVAL); // at least REFRESH_INTERVAL has elapsed
tc->TC_CHANNEL[channel].TC_RA = max(cval, ival);
Channel[timer] = -1; // reset the timer CCR on the next call
tc->TC_CHANNEL[channel].TC_RA =
tc->TC_CHANNEL[channel].TC_CV < usToTicks(REFRESH_INTERVAL) - 4
? (unsigned int)usToTicks(REFRESH_INTERVAL) // allow a few ticks to ensure the next OCR1A not missed
: tc->TC_CHANNEL[channel].TC_CV + 4; // at least REFRESH_INTERVAL has elapsed
Channel[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel
}
tc->TC_CHANNEL[channel].TC_SR; // clear interrupt
}
static void _initISR(Tc *tc, uint32_t channel, uint32_t id, IRQn_Type irqn) {
pmc_enable_periph_clk(id);
TC_Configure(tc, channel,
TC_CMR_WAVE // Waveform mode
| TC_CMR_WAVSEL_UP_RC // Counter running up and reset when equal to RC
| (SERVO_TIMER_PRESCALER == 2 ? TC_CMR_TCCLKS_TIMER_CLOCK1 : 0) // MCK/2
| (SERVO_TIMER_PRESCALER == 8 ? TC_CMR_TCCLKS_TIMER_CLOCK2 : 0) // MCK/8
| (SERVO_TIMER_PRESCALER == 32 ? TC_CMR_TCCLKS_TIMER_CLOCK3 : 0) // MCK/32
| (SERVO_TIMER_PRESCALER == 128 ? TC_CMR_TCCLKS_TIMER_CLOCK4 : 0) // MCK/128
);
TC_CMR_TCCLKS_TIMER_CLOCK3 | // MCK/32
TC_CMR_WAVE | // Waveform mode
TC_CMR_WAVSEL_UP_RC ); // Counter running up and reset when equals to RC
// Wait 1ms before the first ISR
TC_SetRA(tc, channel, (F_CPU) / (SERVO_TIMER_PRESCALER) / 1000UL); // 1ms
/* 84MHz, MCK/32, for 1.5ms: 3937 */
TC_SetRA(tc, channel, 2625); // 1ms
// Configure and enable interrupt
/* Configure and enable interrupt */
NVIC_EnableIRQ(irqn);
tc->TC_CHANNEL[channel].TC_IER = TC_IER_CPAS; // TC_IER_CPAS: RA Compare
// TC_IER_CPAS: RA Compare
tc->TC_CHANNEL[channel].TC_IER = TC_IER_CPAS;
// Enables the timer clock and performs a software reset to start the counting
TC_Start(tc, channel);
}
void initISR(const timer16_Sequence_t timer_index) {
CRITICAL_SECTION_START();
const bool disable_soon = DisablePending[timer_index];
DisablePending.clear(timer_index);
CRITICAL_SECTION_END();
if (!disable_soon) switch (timer_index) {
default: break;
#ifdef _useTimer1
case _timer1: return _initISR(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1, ID_TC_FOR_TIMER1, IRQn_FOR_TIMER1);
#endif
#ifdef _useTimer2
case _timer2: return _initISR(TC_FOR_TIMER2, CHANNEL_FOR_TIMER2, ID_TC_FOR_TIMER2, IRQn_FOR_TIMER2);
#endif
#ifdef _useTimer3
case _timer3: return _initISR(TC_FOR_TIMER3, CHANNEL_FOR_TIMER3, ID_TC_FOR_TIMER3, IRQn_FOR_TIMER3);
#endif
#ifdef _useTimer4
case _timer4: return _initISR(TC_FOR_TIMER4, CHANNEL_FOR_TIMER4, ID_TC_FOR_TIMER4, IRQn_FOR_TIMER4);
#endif
#ifdef _useTimer5
case _timer5: return _initISR(TC_FOR_TIMER5, CHANNEL_FOR_TIMER5, ID_TC_FOR_TIMER5, IRQn_FOR_TIMER5);
#endif
}
void initISR(timer16_Sequence_t timer) {
#ifdef _useTimer1
if (timer == _timer1)
_initISR(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1, ID_TC_FOR_TIMER1, IRQn_FOR_TIMER1);
#endif
#ifdef _useTimer2
if (timer == _timer2)
_initISR(TC_FOR_TIMER2, CHANNEL_FOR_TIMER2, ID_TC_FOR_TIMER2, IRQn_FOR_TIMER2);
#endif
#ifdef _useTimer3
if (timer == _timer3)
_initISR(TC_FOR_TIMER3, CHANNEL_FOR_TIMER3, ID_TC_FOR_TIMER3, IRQn_FOR_TIMER3);
#endif
#ifdef _useTimer4
if (timer == _timer4)
_initISR(TC_FOR_TIMER4, CHANNEL_FOR_TIMER4, ID_TC_FOR_TIMER4, IRQn_FOR_TIMER4);
#endif
#ifdef _useTimer5
if (timer == _timer5)
_initISR(TC_FOR_TIMER5, CHANNEL_FOR_TIMER5, ID_TC_FOR_TIMER5, IRQn_FOR_TIMER5);
#endif
}
void finISR(const timer16_Sequence_t timer_index) {
// Timer is disabled from the ISR, to ensure proper final pulse length.
DisablePending.set(timer_index);
void finISR(timer16_Sequence_t) {
#ifdef _useTimer1
TC_Stop(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1);
#endif
#ifdef _useTimer2
TC_Stop(TC_FOR_TIMER2, CHANNEL_FOR_TIMER2);
#endif
#ifdef _useTimer3
TC_Stop(TC_FOR_TIMER3, CHANNEL_FOR_TIMER3);
#endif
#ifdef _useTimer4
TC_Stop(TC_FOR_TIMER4, CHANNEL_FOR_TIMER4);
#endif
#ifdef _useTimer5
TC_Stop(TC_FOR_TIMER5, CHANNEL_FOR_TIMER5);
#endif
}
#endif // HAS_SERVOS
+1 -1
View File
@@ -37,7 +37,7 @@
#define _useTimer5
#define TRIM_DURATION 2 // compensation ticks to trim adjust for digitalWrite delays
#define SERVO_TIMER_PRESCALER 2 // timer prescaler
#define SERVO_TIMER_PRESCALER 32 // timer prescaler
/*
TC0, chan 0 => TC0_Handler
+1 -1
View File
@@ -70,7 +70,7 @@
#define PRINT_PIN_ANALOG(p) do{ sprintf_P(buffer, PSTR(" (A%2d) "), DIGITAL_PIN_TO_ANALOG_PIN(pin)); SERIAL_ECHO(buffer); }while(0)
#define GET_ARRAY_PIN(p) pin_array[p].pin
#define GET_ARRAY_IS_DIGITAL(p) pin_array[p].is_digital
#define VALID_PIN(pin) (pin >= 0 && pin < int8_t(NUMBER_PINS_TOTAL))
#define VALID_PIN(pin) (pin >= 0 && pin < (int8_t)NUMBER_PINS_TOTAL ? 1 : 0)
#define DIGITAL_PIN_TO_ANALOG_PIN(p) int(p - analogInputToDigitalPin(0))
#define IS_ANALOG(P) WITHIN(P, char(analogInputToDigitalPin(0)), char(analogInputToDigitalPin(NUM_ANALOG_INPUTS - 1)))
#define pwm_status(pin) (((g_pinStatus[pin] & 0xF) == PIN_STATUS_PWM) && \
+2 -9
View File
@@ -89,17 +89,10 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
NVIC_SetPriority(irq, timer_config[timer_num].priority);
// wave mode, reset counter on match with RC,
TC_Configure(tc, channel,
TC_CMR_WAVE
| TC_CMR_WAVSEL_UP_RC
| (HAL_TIMER_PRESCALER == 2 ? TC_CMR_TCCLKS_TIMER_CLOCK1 : 0)
| (HAL_TIMER_PRESCALER == 8 ? TC_CMR_TCCLKS_TIMER_CLOCK2 : 0)
| (HAL_TIMER_PRESCALER == 32 ? TC_CMR_TCCLKS_TIMER_CLOCK3 : 0)
| (HAL_TIMER_PRESCALER == 128 ? TC_CMR_TCCLKS_TIMER_CLOCK4 : 0)
);
TC_Configure(tc, channel, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK1);
// Set compare value
TC_SetRC(tc, channel, VARIANT_MCK / (HAL_TIMER_PRESCALER) / frequency);
TC_SetRC(tc, channel, VARIANT_MCK / 2 / frequency);
// And start timer
TC_Start(tc, channel);
+1 -2
View File
@@ -35,8 +35,7 @@
typedef uint32_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX 0xFFFFFFFF
#define HAL_TIMER_PRESCALER 2
#define HAL_TIMER_RATE ((F_CPU) / (HAL_TIMER_PRESCALER)) // frequency of timers peripherals
#define HAL_TIMER_RATE ((F_CPU) / 2) // frequency of timers peripherals
#ifndef MF_TIMER_STEP
#define MF_TIMER_STEP 2 // Timer Index for Stepper
+8 -8
View File
@@ -6,14 +6,14 @@
#
import pioutil
if pioutil.is_pio_build():
import platform
current_OS = platform.system()
import platform
current_OS = platform.system()
if current_OS == 'Windows':
if current_OS == 'Windows':
Import("env")
Import("env")
# Use bossac.exe on Windows
env.Replace(
UPLOADCMD="bossac --info --unlock --write --verify --reset --erase -U false --boot $SOURCE"
)
# Use bossac.exe on Windows
env.Replace(
UPLOADCMD="bossac --info --unlock --write --verify --reset --erase -U false --boot $SOURCE"
)
+1 -1
View File
@@ -1059,7 +1059,7 @@ static inline void convert_64_bit_to_byte_array(uint64_t value, uint8_t *data)
while (val_index < 8)
{
data[val_index++] = value & 0xFF;
value >>= 8;
value = value >> 8;
}
}
+1 -1
View File
@@ -62,7 +62,7 @@ void usb_task_idle(void) {
// Attend SD card access from the USB MSD -- Prioritize access to improve speed
int delay = 2;
while (main_b_msc_enable && --delay > 0) {
if (udi_msc_process_trans()) delay = 20;
if (udi_msc_process_trans()) delay = 10000;
// Reset the watchdog, just to be sure
REG_WDT_CR = WDT_CR_WDRSTT | WDT_CR_KEY(0xA5);
+12 -38
View File
@@ -65,7 +65,6 @@ portMUX_TYPE MarlinHAL::spinlock = portMUX_INITIALIZER_UNLOCKED;
// ------------------------
uint16_t MarlinHAL::adc_result;
pwm_pin_t MarlinHAL::pwm_pin_data[MAX_EXPANDER_BITS];
// ------------------------
// Private Variables
@@ -331,46 +330,21 @@ int8_t get_pwm_channel(const pin_t pin, const uint32_t freq, const uint16_t res)
}
void MarlinHAL::set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=_BV(PWM_RESOLUTION)-1*/, const bool invert/*=false*/) {
#if ENABLED(I2S_STEPPER_STREAM)
if (pin > 127) {
const uint8_t pinlo = pin & 0x7F;
pwm_pin_t &pindata = pwm_pin_data[pinlo];
const uint32_t duty = map(invert ? v_size - v : v, 0, v_size, 0, pindata.pwm_cycle_ticks);
if (duty == 0 || duty == pindata.pwm_cycle_ticks) { // max or min (i.e., on/off)
pindata.pwm_duty_ticks = 0; // turn off PWM for this pin
duty ? SBI32(i2s_port_data, pinlo) : CBI32(i2s_port_data, pinlo); // set pin level
}
else
pindata.pwm_duty_ticks = duty; // PWM duty count = # of 4µs ticks per full PWM cycle
}
else
#endif
{
const int8_t cid = get_pwm_channel(pin, PWM_FREQUENCY, PWM_RESOLUTION);
if (cid >= 0) {
const uint32_t duty = map(invert ? v_size - v : v, 0, v_size, 0, _BV(PWM_RESOLUTION)-1);
ledcWrite(cid, duty);
}
}
const int8_t cid = get_pwm_channel(pin, PWM_FREQUENCY, PWM_RESOLUTION);
if (cid >= 0) {
uint32_t duty = map(invert ? v_size - v : v, 0, v_size, 0, _BV(PWM_RESOLUTION)-1);
ledcWrite(cid, duty);
}
}
int8_t MarlinHAL::set_pwm_frequency(const pin_t pin, const uint32_t f_desired) {
#if ENABLED(I2S_STEPPER_STREAM)
if (pin > 127) {
pwm_pin_data[pin & 0x7F].pwm_cycle_ticks = 1000000UL / f_desired / 4; // # of 4µs ticks per full PWM cycle
return 0;
}
else
#endif
{
const int8_t cid = channel_for_pin(pin);
if (cid >= 0) {
if (f_desired == ledcReadFreq(cid)) return cid; // no freq change
ledcDetachPin(chan_pin[cid]);
chan_pin[cid] = 0; // remove old freq channel
}
return get_pwm_channel(pin, f_desired, PWM_RESOLUTION); // try for new one
}
const int8_t cid = channel_for_pin(pin);
if (cid >= 0) {
if (f_desired == ledcReadFreq(cid)) return cid; // no freq change
ledcDetachPin(chan_pin[cid]);
chan_pin[cid] = 0; // remove old freq channel
}
return get_pwm_channel(pin, f_desired, PWM_RESOLUTION); // try for new one
}
// use hardware PWM if avail, if not then ISR
+2 -13
View File
@@ -60,17 +60,14 @@
#endif
#endif
#define CRITICAL_SECTION_START() portENTER_CRITICAL(&hal.spinlock)
#define CRITICAL_SECTION_END() portEXIT_CRITICAL(&hal.spinlock)
#define CRITICAL_SECTION_START() portENTER_CRITICAL(&spinlock)
#define CRITICAL_SECTION_END() portEXIT_CRITICAL(&spinlock)
#define HAL_CAN_SET_PWM_FREQ // This HAL supports PWM Frequency adjustment
#define PWM_FREQUENCY 1000u // Default PWM frequency when set_pwm_duty() is called without set_pwm_frequency()
#define PWM_RESOLUTION 10u // Default PWM bit resolution
#define CHANNEL_MAX_NUM 15u // max PWM channel # to allocate (7 to only use low speed, 15 to use low & high)
#define MAX_PWM_IOPIN 33u // hardware pwm pins < 34
#ifndef MAX_EXPANDER_BITS
#define MAX_EXPANDER_BITS 32 // I2S expander bit width (max 32)
#endif
// ------------------------
// Types
@@ -79,12 +76,6 @@
typedef double isr_float_t; // FPU ops are used for single-precision, so use double for ISRs.
typedef int16_t pin_t;
typedef struct pwm_pin {
uint32_t pwm_cycle_ticks = 1000000UL / (PWM_FREQUENCY) / 4; // # ticks per pwm cycle
uint32_t pwm_tick_count = 0; // current tick count
uint32_t pwm_duty_ticks = 0; // # of ticks for current duty cycle
} pwm_pin_t;
class Servo;
typedef Servo hal_servo_t;
@@ -206,8 +197,6 @@ public:
// Free SRAM
static int freeMemory();
static pwm_pin_t pwm_pin_data[MAX_EXPANDER_BITS];
//
// ADC Methods
//
+8 -46
View File
@@ -139,40 +139,22 @@ 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;
#endif
uint32_t remaining = 0;
for (;;) {
while (1) {
xQueueReceive(dma.queue, &dma.current, portMAX_DELAY);
dma.rw_pos = 0;
while (dma.rw_pos < DMA_SAMPLE_COUNT) {
// Fill with the port data post pulse_phase until the next step
if (nextMainISR && TERN1(LIN_ADVANCE, nextAdvanceISR))
if (remaining) {
i2s_push_sample();
// i2s_push_sample() is also called from Stepper::pulse_phase_isr() and Stepper::advance_isr()
// in a rare case where both are called, we need to double decrement the counters
const uint8_t push_count = 1 + (!nextMainISR && TERN0(LIN_ADVANCE, !nextAdvanceISR));
#if ENABLED(LIN_ADVANCE)
if (!nextAdvanceISR) {
Stepper::advance_isr();
nextAdvanceISR = Stepper::la_interval;
}
else if (nextAdvanceISR == Stepper::LA_ADV_NEVER)
nextAdvanceISR = Stepper::la_interval;
#endif
if (!nextMainISR) {
Stepper::pulse_phase_isr();
nextMainISR = Stepper::block_phase_isr();
remaining--;
}
else {
Stepper::pulse_phase_isr();
remaining = Stepper::block_phase_isr();
}
nextMainISR -= push_count;
TERN_(LIN_ADVANCE, nextAdvanceISR -= push_count);
}
}
}
@@ -355,26 +337,6 @@ uint8_t i2s_state(uint8_t pin) {
}
void i2s_push_sample() {
// Every 4µs (when space in DMA buffer) toggle each expander PWM output using
// the current duty cycle/frequency so they sync with any steps (once
// through the DMA/FIFO buffers). PWM signal inversion handled by other functions
LOOP_L_N(p, MAX_EXPANDER_BITS) {
if (hal.pwm_pin_data[p].pwm_duty_ticks > 0) { // pin has active pwm?
if (hal.pwm_pin_data[p].pwm_tick_count == 0) {
if (TEST32(i2s_port_data, p)) { // hi->lo
CBI32(i2s_port_data, p);
hal.pwm_pin_data[p].pwm_tick_count = hal.pwm_pin_data[p].pwm_cycle_ticks - hal.pwm_pin_data[p].pwm_duty_ticks;
}
else { // lo->hi
SBI32(i2s_port_data, p);
hal.pwm_pin_data[p].pwm_tick_count = hal.pwm_pin_data[p].pwm_duty_ticks;
}
}
else
hal.pwm_pin_data[p].pwm_tick_count--;
}
}
dma.current[dma.rw_pos++] = i2s_port_data;
}
@@ -20,10 +20,3 @@
*
*/
#pragma once
//
// Board-specific options need to be defined before HAL.h
//
#if MB(MKS_TINYBEE)
#define MAX_EXPANDER_BITS 24 // TinyBee has 3 x HC595
#endif
-8
View File
@@ -45,14 +45,6 @@
#error "FAST_PWM_FAN is not available on TinyBee."
#endif
#if BOTH(I2S_STEPPER_STREAM, BABYSTEPPING) && DISABLED(INTEGRATED_BABYSTEPPING)
#error "BABYSTEPPING on I2S stream requires INTEGRATED_BABYSTEPPING."
#endif
#if USING_PULLDOWNS
#error "PULLDOWN pin mode is not available on ESP32 boards."
#endif
#if BOTH(I2S_STEPPER_STREAM, LIN_ADVANCE) && DISABLED(EXPERIMENTAL_I2S_LA)
#error "I2S stream is currently incompatible with LIN_ADVANCE."
#endif
-12
View File
@@ -32,13 +32,6 @@
#include "HAL.h"
#include "SPI.h"
#if ENABLED(SDSUPPORT)
#include "../../sd/cardreader.h"
#if ENABLED(ESP3D_WIFISUPPORT)
#include "sd_ESP32.h"
#endif
#endif
static SPISettings spiConfig;
@@ -52,11 +45,6 @@ static SPISettings spiConfig;
uint8_t u8g_eps_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
static uint8_t msgInitCount = 2; // Ignore all messages until 2nd U8G_COM_MSG_INIT
#if ENABLED(PAUSE_LCD_FOR_BUSY_SD)
if (card.flag.saving || card.flag.logging || TERN0(ESP3D_WIFISUPPORT, sd_busy_lock == true)) return 0;
#endif
if (msgInitCount) {
if (msg == U8G_COM_MSG_INIT) msgInitCount--;
if (msgInitCount) return -1;
+8 -8
View File
@@ -69,12 +69,12 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
std::size_t bytes_written = 0;
for (std::size_t i = 0; i < size; i++) {
buffer[pos + i] = value[i];
bytes_written++;
buffer[pos+i] = value[i];
bytes_written ++;
}
crc16(crc, value, size);
pos += size;
pos = pos + size;
return (bytes_written != size); // return true for any error
}
@@ -82,21 +82,21 @@ bool PersistentStore::read_data(int &pos, uint8_t *value, const size_t size, uin
std::size_t bytes_read = 0;
if (writing) {
for (std::size_t i = 0; i < size; i++) {
value[i] = buffer[pos + i];
bytes_read++;
value[i] = buffer[pos+i];
bytes_read ++;
}
crc16(crc, value, size);
}
else {
uint8_t temp[size];
for (std::size_t i = 0; i < size; i++) {
temp[i] = buffer[pos + i];
bytes_read++;
temp[i] = buffer[pos+i];
bytes_read ++;
}
crc16(crc, temp, size);
}
pos += size;
pos = pos + size;
return bytes_read != size; // return true for any error
}
+2 -2
View File
@@ -26,8 +26,8 @@
struct LowpassFilter {
uint64_t data_delay = 0;
uint16_t update(uint16_t value) {
data_delay += value - (data_delay >> 6);
return uint16_t(data_delay >> 6);
data_delay = data_delay - (data_delay >> 6) + value;
return (uint16_t)(data_delay >> 6);
}
};
@@ -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 defined(MCU_LPC1768) && PRINTCOUNTER_SAVE_INTERVAL > 0
#define PRINTCOUNTER_SYNC 1
#endif
+104 -112
View File
@@ -9,127 +9,119 @@ from __future__ import print_function
import pioutil
if pioutil.is_pio_build():
target_filename = "FIRMWARE.CUR"
target_drive = "REARM"
target_filename = "FIRMWARE.CUR"
target_drive = "REARM"
import platform
import os,getpass,platform
current_OS = platform.system()
Import("env")
current_OS = platform.system()
Import("env")
def print_error(e):
print('\nUnable to find destination disk (%s)\n' \
'Please select it in platformio.ini using the upload_port keyword ' \
'(https://docs.platformio.org/en/latest/projectconf/section_env_upload.html) ' \
'or copy the firmware (.pio/build/%s/firmware.bin) manually to the appropriate disk\n' \
%(e, env.get('PIOENV')))
def print_error(e):
print('\nUnable to find destination disk (%s)\n' \
'Please select it in platformio.ini using the upload_port keyword ' \
'(https://docs.platformio.org/en/latest/projectconf/section_env_upload.html) ' \
'or copy the firmware (.pio/build/%s/firmware.bin) manually to the appropriate disk\n' \
%(e, env.get('PIOENV')))
def before_upload(source, target, env):
try:
from pathlib import Path
#
# Find a disk for upload
#
upload_disk = 'Disk not found'
target_file_found = False
target_drive_found = False
if current_OS == 'Windows':
#
# platformio.ini will accept this for a Windows upload port designation: 'upload_port = L:'
# Windows - doesn't care about the disk's name, only cares about the drive letter
import subprocess,string
from ctypes import windll
from pathlib import PureWindowsPath
def before_upload(source, target, env):
try:
#
# Find a disk for upload
#
upload_disk = 'Disk not found'
target_file_found = False
target_drive_found = False
if current_OS == 'Windows':
#
# platformio.ini will accept this for a Windows upload port designation: 'upload_port = L:'
# Windows - doesn't care about the disk's name, only cares about the drive letter
import subprocess,string
from ctypes import windll
# getting list of drives
# https://stackoverflow.com/questions/827371/is-there-a-way-to-list-all-the-available-drive-letters-in-python
drives = []
bitmask = windll.kernel32.GetLogicalDrives()
for letter in string.ascii_uppercase:
if bitmask & 1:
drives.append(letter)
bitmask >>= 1
# getting list of drives
# https://stackoverflow.com/questions/827371/is-there-a-way-to-list-all-the-available-drive-letters-in-python
drives = []
bitmask = windll.kernel32.GetLogicalDrives()
for letter in string.ascii_uppercase:
if bitmask & 1:
drives.append(letter)
bitmask >>= 1
for drive in drives:
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))
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
upload_disk = PureWindowsPath(final_drive_name)
if target_filename in volume_info:
if not target_file_found:
upload_disk = PureWindowsPath(final_drive_name)
target_file_found = True
for drive in drives:
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))
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
upload_disk = final_drive_name
if target_filename in volume_info:
if not target_file_found:
upload_disk = final_drive_name
target_file_found = True
elif current_OS == 'Linux':
#
# platformio.ini will accept this for a Linux upload port designation: 'upload_port = /media/media_name/drive'
#
import getpass
user = getpass.getuser()
mpath = Path('/media', user)
drives = [ x for x in mpath.iterdir() if x.is_dir() ]
if target_drive in drives: # If target drive is found, use it.
target_drive_found = True
upload_disk = mpath / target_drive
else:
for drive in drives:
try:
fpath = mpath / drive
filenames = [ x.name for x in fpath.iterdir() if x.is_file() ]
except:
continue
else:
if target_filename in filenames:
upload_disk = mpath / drive
target_file_found = True
break
#
# set upload_port to drive if found
#
elif current_OS == 'Linux':
#
# platformio.ini will accept this for a Linux upload port designation: 'upload_port = /media/media_name/drive'
#
drives = os.listdir(os.path.join(os.sep, 'media', getpass.getuser()))
if target_drive in drives: # If target drive is found, use it.
target_drive_found = True
upload_disk = os.path.join(os.sep, 'media', getpass.getuser(), target_drive) + os.sep
else:
for drive in drives:
try:
files = os.listdir(os.path.join(os.sep, 'media', getpass.getuser(), drive))
except:
continue
else:
if target_filename in files:
upload_disk = os.path.join(os.sep, 'media', getpass.getuser(), drive) + os.sep
target_file_found = True
break
#
# set upload_port to drive if found
#
if target_file_found or target_drive_found:
env.Replace(
UPLOAD_FLAGS="-P$UPLOAD_PORT"
)
if target_file_found or target_drive_found:
env.Replace(
UPLOAD_FLAGS="-P$UPLOAD_PORT"
)
elif current_OS == 'Darwin': # MAC
#
# platformio.ini will accept this for a OSX upload port designation: 'upload_port = /media/media_name/drive'
#
dpath = Path('/Volumes') # human readable names
drives = [ x for x in dpath.iterdir() if x.is_dir() ]
if target_drive in drives and not target_file_found: # set upload if not found target file yet
target_drive_found = True
upload_disk = dpath / target_drive
for drive in drives:
try:
fpath = dpath / drive # will get an error if the drive is protected
filenames = [ x.name for x in fpath.iterdir() if x.is_file() ]
except:
continue
else:
if target_filename in filenames:
upload_disk = dpath / drive
target_file_found = True
break
elif current_OS == 'Darwin': # MAC
#
# platformio.ini will accept this for a OSX upload port designation: 'upload_port = /media/media_name/drive'
#
drives = os.listdir('/Volumes') # human readable names
if target_drive in drives and not target_file_found: # set upload if not found target file yet
target_drive_found = True
upload_disk = '/Volumes/' + target_drive + '/'
for drive in drives:
try:
filenames = os.listdir('/Volumes/' + drive + '/') # will get an error if the drive is protected
except:
continue
else:
if target_filename in filenames:
if not target_file_found:
upload_disk = '/Volumes/' + drive + '/'
target_file_found = True
#
# Set upload_port to drive if found
#
if target_file_found or target_drive_found:
env.Replace(UPLOAD_PORT=str(upload_disk))
print('\nUpload disk: ', upload_disk, '\n')
else:
print_error('Autodetect Error')
#
# Set upload_port to drive if found
#
if target_file_found or target_drive_found:
env.Replace(UPLOAD_PORT=upload_disk)
print('\nUpload disk: ', upload_disk, '\n')
else:
print_error('Autodetect Error')
except Exception as e:
print_error(str(e))
except Exception as e:
print_error(str(e))
env.AddPreAction("upload", before_upload)
env.AddPreAction("upload", before_upload)
+1 -1
View File
@@ -44,7 +44,7 @@
*
* Now you can simply SET_OUTPUT(STEP); WRITE(STEP, HIGH); WRITE(STEP, LOW);
*
* Why double up on these macros? see https://gcc.gnu.org/onlinedocs/cpp/Stringification.html
* Why double up on these macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html
*/
/// Read a pin
+1 -1
View File
@@ -51,7 +51,7 @@ enum XPTCoordinate : uint8_t {
XPT2046_Z2 = 0x40 | XPT2046_CONTROL | XPT2046_DFR_MODE,
};
#ifndef XPT2046_Z1_THRESHOLD
#if !defined(XPT2046_Z1_THRESHOLD)
#define XPT2046_Z1_THRESHOLD 10
#endif
+1 -1
View File
@@ -598,7 +598,7 @@ void MarlinHAL::dma_init() {
void MarlinHAL::init() {
TERN_(DMA_IS_REQUIRED, dma_init());
#if ENABLED(SDSUPPORT)
#if HAS_SD_DETECT && SD_CONNECTION_IS(ONBOARD)
#if SD_CONNECTION_IS(ONBOARD) && PIN_EXISTS(SD_DETECT)
SET_INPUT_PULLUP(SD_DETECT_PIN);
#endif
OUT_WRITE(SDSS, HIGH); // Try to set SDSS inactive before any other SPI users start up
+26 -19
View File
@@ -77,8 +77,7 @@ HAL_SERVO_TIMER_ISR() {
;
const uint8_t tcChannel = TIMER_TCCHANNEL(timer);
int8_t cho = currentServoIndex[timer]; // Handle the prior servo first
if (cho < 0) { // Servo -1 indicates the refresh interval completed...
if (currentServoIndex[timer] < 0) {
#if defined(_useTimer1) && defined(_useTimer2)
if (currentServoIndex[timer ^ 1] >= 0) {
// Wait for both channels
@@ -87,37 +86,45 @@ HAL_SERVO_TIMER_ISR() {
return;
}
#endif
tc->COUNT16.COUNT.reg = TC_COUNTER_START_VAL; // ...so reset the timer
tc->COUNT16.COUNT.reg = TC_COUNTER_START_VAL;
SYNC(tc->COUNT16.SYNCBUSY.bit.COUNT);
}
else if (SERVO_INDEX(timer, cho) < ServoCount) // prior channel handled?
digitalWrite(SERVO(timer, cho).Pin.nbr, LOW); // pulse the prior channel LOW
else if (SERVO_INDEX(timer, currentServoIndex[timer]) < ServoCount && SERVO(timer, currentServoIndex[timer]).Pin.isActive)
digitalWrite(SERVO(timer, currentServoIndex[timer]).Pin.nbr, LOW); // pulse this channel low if activated
currentServoIndex[timer] = ++cho; // go to the next channel (or 0)
if (cho < SERVOS_PER_TIMER && SERVO_INDEX(timer, cho) < ServoCount) {
if (SERVO(timer, cho).Pin.isActive) // activated?
digitalWrite(SERVO(timer, cho).Pin.nbr, HIGH); // yes: pulse HIGH
// Select the next servo controlled by this timer
currentServoIndex[timer]++;
tc->COUNT16.CC[tcChannel].reg = getTimerCount() - (uint16_t)SERVO(timer, cho).ticks;
if (SERVO_INDEX(timer, currentServoIndex[timer]) < ServoCount && currentServoIndex[timer] < SERVOS_PER_TIMER) {
if (SERVO(timer, currentServoIndex[timer]).Pin.isActive) // check if activated
digitalWrite(SERVO(timer, currentServoIndex[timer]).Pin.nbr, HIGH); // it's an active channel so pulse it high
tc->COUNT16.CC[tcChannel].reg = getTimerCount() - (uint16_t)SERVO(timer, currentServoIndex[timer]).ticks;
}
else {
// finished all channels so wait for the refresh period to expire before starting over
currentServoIndex[timer] = -1; // reset the timer COUNT.reg on the next call
const uint16_t cval = getTimerCount() - 256 / (SERVO_TIMER_PRESCALER), // allow 256 cycles to ensure the next CV not missed
ival = (TC_COUNTER_START_VAL) - (uint16_t)usToTicks(REFRESH_INTERVAL); // at least REFRESH_INTERVAL has elapsed
tc->COUNT16.CC[tcChannel].reg = min(cval, ival);
currentServoIndex[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel
const uint16_t tcCounterValue = getTimerCount();
if ((TC_COUNTER_START_VAL - tcCounterValue) + 4UL < usToTicks(REFRESH_INTERVAL)) // allow a few ticks to ensure the next OCR1A not missed
tc->COUNT16.CC[tcChannel].reg = TC_COUNTER_START_VAL - (uint16_t)usToTicks(REFRESH_INTERVAL);
else
tc->COUNT16.CC[tcChannel].reg = (uint16_t)(tcCounterValue - 4UL); // at least REFRESH_INTERVAL has elapsed
}
if (tcChannel == 0) {
SYNC(tc->COUNT16.SYNCBUSY.bit.CC0);
tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC0; // Clear the interrupt
// Clear the interrupt
tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC0;
}
else {
SYNC(tc->COUNT16.SYNCBUSY.bit.CC1);
tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC1; // Clear the interrupt
// Clear the interrupt
tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC1;
}
}
void initISR(const timer16_Sequence_t timer) {
void initISR(timer16_Sequence_t timer) {
Tc * const tc = timer_config[SERVO_TC].pTc;
const uint8_t tcChannel = TIMER_TCCHANNEL(timer);
@@ -194,9 +201,9 @@ void initISR(const timer16_Sequence_t timer) {
}
}
void finISR(const timer16_Sequence_t timer_index) {
void finISR(timer16_Sequence_t timer) {
Tc * const tc = timer_config[SERVO_TC].pTc;
const uint8_t tcChannel = TIMER_TCCHANNEL(timer_index);
const uint8_t tcChannel = TIMER_TCCHANNEL(timer);
// Disable the match channel interrupt request
tc->COUNT16.INTENCLR.reg = (tcChannel == 0) ? TC_INTENCLR_MC0 : TC_INTENCLR_MC1;
+1 -1
View File
@@ -29,7 +29,7 @@
#define PRINT_PIN_ANALOG(p) do{ sprintf_P(buffer, PSTR(" (A%2d) "), DIGITAL_PIN_TO_ANALOG_PIN(pin)); SERIAL_ECHO(buffer); }while(0)
#define GET_ARRAY_PIN(p) pin_array[p].pin
#define GET_ARRAY_IS_DIGITAL(p) pin_array[p].is_digital
#define VALID_PIN(pin) (pin >= 0 && pin < int8_t(NUMBER_PINS_TOTAL))
#define VALID_PIN(pin) (pin >= 0 && pin < (int8_t)NUMBER_PINS_TOTAL)
#define DIGITAL_PIN_TO_ANALOG_PIN(p) digitalPinToAnalogInput(p)
#define IS_ANALOG(P) (DIGITAL_PIN_TO_ANALOG_PIN(P)!=-1)
#define pwm_status(pin) digitalPinHasPWM(pin)
@@ -27,8 +27,3 @@
#elif EITHER(I2C_EEPROM, SPI_EEPROM)
#define USE_SHARED_EEPROM 1
#endif
// Some STM32F4 boards may lose steps when saving to EEPROM during print (PR #17946)
#if defined(STM32F4xx) && ENABLED(FLASH_EEPROM_EMULATION) && PRINTCOUNTER_SAVE_INTERVAL > 0
#define PRINTCOUNTER_SYNC 1
#endif
+5
View File
@@ -37,6 +37,11 @@
#error "SDCARD_EEPROM_EMULATION requires SDSUPPORT. Enable SDSUPPORT or choose another EEPROM emulation."
#endif
#if defined(STM32F4xx) && BOTH(PRINTCOUNTER, FLASH_EEPROM_EMULATION)
#warning "FLASH_EEPROM_EMULATION may cause long delays when writing and should not be used while printing."
#error "Disable PRINTCOUNTER or choose another EEPROM emulation."
#endif
#if !defined(STM32F4xx) && ENABLED(FLASH_EEPROM_LEVELING)
#error "FLASH_EEPROM_LEVELING is currently only supported on STM32F4 hardware."
#endif
+7 -11
View File
@@ -102,18 +102,17 @@ const XrefInfo pin_xref[] PROGMEM = {
#define PIN_NUM_ALPHA_LEFT(P) (((P & 0x000F) < 10) ? ('0' + (P & 0x000F)) : '1')
#define PIN_NUM_ALPHA_RIGHT(P) (((P & 0x000F) > 9) ? ('0' + (P & 0x000F) - 10) : 0 )
#define PORT_NUM(P) ((P >> 4) & 0x0007)
#define PORT_ALPHA(P) ('A' + (P >> 4))
#define PORT_ALPHA(P) ('A' + (P >> 4))
/**
* Translation of routines & variables used by pinsDebug.h
*/
#if NUM_ANALOG_FIRST >= NUM_DIGITAL_PINS
#if PA0 >= NUM_DIGITAL_PINS
#define HAS_HIGH_ANALOG_PINS 1
#endif
#define NUM_ANALOG_LAST ((NUM_ANALOG_FIRST) + (NUM_ANALOG_INPUTS) - 1)
#define NUMBER_PINS_TOTAL ((NUM_DIGITAL_PINS) + TERN0(HAS_HIGH_ANALOG_PINS, NUM_ANALOG_INPUTS))
#define VALID_PIN(P) (WITHIN(P, 0, (NUM_DIGITAL_PINS) - 1) || TERN0(HAS_HIGH_ANALOG_PINS, WITHIN(P, NUM_ANALOG_FIRST, NUM_ANALOG_LAST)))
#define NUMBER_PINS_TOTAL NUM_DIGITAL_PINS + TERN0(HAS_HIGH_ANALOG_PINS, NUM_ANALOG_INPUTS)
#define VALID_PIN(ANUM) ((ANUM) >= 0 && (ANUM) < NUMBER_PINS_TOTAL)
#define digitalRead_mod(Ard_num) extDigitalRead(Ard_num) // must use Arduino pin numbers when doing reads
#define PRINT_PIN(Q)
#define PRINT_PIN_ANALOG(p) do{ sprintf_P(buffer, PSTR(" (A%2d) "), DIGITAL_PIN_TO_ANALOG_PIN(pin)); SERIAL_ECHO(buffer); }while(0)
@@ -169,7 +168,7 @@ bool GET_PINMODE(const pin_t Ard_num) {
}
int8_t digital_pin_to_analog_pin(const pin_t Ard_num) {
if (WITHIN(Ard_num, NUM_ANALOG_FIRST, NUM_ANALOG_LAST))
if (WITHIN(Ard_num, NUM_ANALOG_FIRST, NUM_ANALOG_FIRST + NUM_ANALOG_INPUTS - 1))
return Ard_num - NUM_ANALOG_FIRST;
const uint32_t ind = digitalPinToAnalogInput(Ard_num);
@@ -207,11 +206,8 @@ void port_print(const pin_t Ard_num) {
SERIAL_ECHO_SP(7);
// Print number to be used with M42
int calc_p = Ard_num;
if (Ard_num > NUM_DIGITAL_PINS) {
calc_p -= NUM_ANALOG_FIRST;
if (calc_p > 7) calc_p += 8;
}
int calc_p = Ard_num % (NUM_DIGITAL_PINS + 1);
if (Ard_num > NUM_DIGITAL_PINS && calc_p > 7) calc_p += 8;
SERIAL_ECHOPGM(" M42 P", calc_p);
SERIAL_CHAR(' ');
if (calc_p < 100) {
+204 -335
View File
@@ -33,6 +33,7 @@
#include <stdint.h>
#include <stdbool.h>
// use local drivers
#if defined(STM32F103xE) || defined(STM32F103xG)
#include <stm32f1xx_hal_rcc_ex.h>
#include <stm32f1xx_hal_sd.h>
@@ -46,397 +47,254 @@
#include <stm32f7xx_hal_dma.h>
#include <stm32f7xx_hal_gpio.h>
#include <stm32f7xx_hal_sd.h>
#elif defined(STM32H7xx)
#define SDIO_FOR_STM32H7
#include <stm32h7xx_hal_rcc.h>
#include <stm32h7xx_hal_dma.h>
#include <stm32h7xx_hal_gpio.h>
#include <stm32h7xx_hal_sd.h>
#else
#error "SDIO is only supported with STM32F103xE, STM32F103xG, STM32F4xx, STM32F7xx, and STM32H7xx."
#error "SDIO only supported with STM32F103xE, STM32F103xG, STM32F4xx, or STM32F7xx."
#endif
// SDIO Max Clock (naming from STM Manual, don't change)
#define SDIOCLK 48000000
SD_HandleTypeDef hsd; // create SDIO structure
// F4 supports one DMA for RX and another for TX, but Marlin will never
// do read and write at same time, so we use the same DMA for both.
DMA_HandleTypeDef hdma_sdio;
/*
SDIO_INIT_CLK_DIV is 118
SDIO clock frequency is 48MHz / (TRANSFER_CLOCK_DIV + 2)
SDIO init clock frequency should not exceed 400kHz = 48MHz / (118 + 2)
Default TRANSFER_CLOCK_DIV is 2 (118 / 40)
Default SDIO clock frequency is 48MHz / (2 + 2) = 12 MHz
This might be too fast for stable SDIO operations
MKS Robin board seems to have stable SDIO with BusWide 1bit and ClockDiv 8 i.e. 4.8MHz SDIO clock frequency
Additional testing is required as there are clearly some 4bit initialization problems
*/
#ifndef USBD_OK
#define USBD_OK 0
#endif
// Target Clock, configurable. Default is 18MHz, from STM32F1
#ifndef SDIO_CLOCK
#define SDIO_CLOCK 18000000 // 18 MHz
#endif
SD_HandleTypeDef hsd; // SDIO structure
// SDIO retries, configurable. Default is 3, from STM32F1
#ifndef SDIO_READ_RETRIES
#define SDIO_READ_RETRIES 3
#endif
// SDIO Max Clock (naming from STM Manual, don't change)
#define SDIOCLK 48000000
static uint32_t clock_to_divider(uint32_t clk) {
#ifdef SDIO_FOR_STM32H7
// SDMMC_CK frequency = sdmmc_ker_ck / [2 * CLKDIV].
uint32_t sdmmc_clk = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SDMMC);
return sdmmc_clk / (2U * SDIO_CLOCK) + (sdmmc_clk % (2U * SDIO_CLOCK) != 0);
#else
// limit the SDIO master clock to 8/3 of PCLK2. See STM32 Manuals
// Also limited to no more than 48Mhz (SDIOCLK).
const uint32_t pclk2 = HAL_RCC_GetPCLK2Freq();
clk = min(clk, (uint32_t)(pclk2 * 8 / 3));
clk = min(clk, (uint32_t)SDIOCLK);
// Round up divider, so we don't run the card over the speed supported,
// and subtract by 2, because STM32 will add 2, as written in the manual:
// SDIO_CK frequency = SDIOCLK / [CLKDIV + 2]
return pclk2 / clk + (pclk2 % clk != 0) - 2;
#endif
// limit the SDIO master clock to 8/3 of PCLK2. See STM32 Manuals
// Also limited to no more than 48Mhz (SDIOCLK).
const uint32_t pclk2 = HAL_RCC_GetPCLK2Freq();
clk = min(clk, (uint32_t)(pclk2 * 8 / 3));
clk = min(clk, (uint32_t)SDIOCLK);
// Round up divider, so we don't run the card over the speed supported,
// and subtract by 2, because STM32 will add 2, as written in the manual:
// SDIO_CK frequency = SDIOCLK / [CLKDIV + 2]
return pclk2 / clk + (pclk2 % clk != 0) - 2;
}
// Start the SDIO clock
void HAL_SD_MspInit(SD_HandleTypeDef *hsd) {
UNUSED(hsd);
#ifdef SDIO_FOR_STM32H7
pinmap_pinout(PC_12, PinMap_SD);
pinmap_pinout(PD_2, PinMap_SD);
pinmap_pinout(PC_8, PinMap_SD);
#if PINS_EXIST(SDIO_D1, SDIO_D2, SDIO_D3) // Define D1-D3 only for 4-bit wide SDIO bus
pinmap_pinout(PC_9, PinMap_SD);
pinmap_pinout(PC_10, PinMap_SD);
pinmap_pinout(PC_11, PinMap_SD);
#endif
__HAL_RCC_SDMMC1_CLK_ENABLE();
HAL_NVIC_EnableIRQ(SDMMC1_IRQn);
#else
__HAL_RCC_SDIO_CLK_ENABLE();
#endif
void go_to_transfer_speed() {
/* Default SDIO peripheral configuration for SD card initialization */
hsd.Init.ClockEdge = hsd.Init.ClockEdge;
hsd.Init.ClockBypass = hsd.Init.ClockBypass;
hsd.Init.ClockPowerSave = hsd.Init.ClockPowerSave;
hsd.Init.BusWide = hsd.Init.BusWide;
hsd.Init.HardwareFlowControl = hsd.Init.HardwareFlowControl;
hsd.Init.ClockDiv = clock_to_divider(SDIO_CLOCK);
/* Initialize SDIO peripheral interface with default configuration */
SDIO_Init(hsd.Instance, hsd.Init);
}
#ifdef SDIO_FOR_STM32H7
void SD_LowLevel_Init(void) {
uint32_t tempreg;
#define SD_TIMEOUT 1000 // ms
__HAL_RCC_GPIOC_CLK_ENABLE(); //enable GPIO clocks
__HAL_RCC_GPIOD_CLK_ENABLE(); //enable GPIO clocks
extern "C" void SDMMC1_IRQHandler(void) { HAL_SD_IRQHandler(&hsd); }
GPIO_InitTypeDef GPIO_InitStruct;
uint8_t waitingRxCplt = 0, waitingTxCplt = 0;
void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsdio) { waitingTxCplt = 0; }
void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsdio) { waitingRxCplt = 0; }
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = 1; //GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
void HAL_SD_MspDeInit(SD_HandleTypeDef *hsd) {
__HAL_RCC_SDMMC1_FORCE_RESET(); delay(10);
__HAL_RCC_SDMMC1_RELEASE_RESET(); delay(10);
}
bool SDIO_Init() {
HAL_StatusTypeDef sd_state = HAL_OK;
if (hsd.Instance == SDMMC1) HAL_SD_DeInit(&hsd);
// HAL SD initialization
hsd.Instance = SDMMC1;
hsd.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
hsd.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
hsd.Init.BusWide = SDMMC_BUS_WIDE_1B;
hsd.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
hsd.Init.ClockDiv = clock_to_divider(SDIO_CLOCK);
sd_state = HAL_SD_Init(&hsd);
#if PINS_EXIST(SDIO_D1, SDIO_D2, SDIO_D3)
if (sd_state == HAL_OK)
sd_state = HAL_SD_ConfigWideBusOperation(&hsd, SDMMC_BUS_WIDE_4B);
#endif
return (sd_state == HAL_OK);
}
#else // !SDIO_FOR_STM32H7
#define SD_TIMEOUT 500 // ms
// SDIO retries, configurable. Default is 3, from STM32F1
#ifndef SDIO_READ_RETRIES
#define SDIO_READ_RETRIES 3
#if DISABLED(STM32F1xx)
GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
#endif
// F4 supports one DMA for RX and another for TX, but Marlin will never
// do read and write at same time, so we use the same DMA for both.
DMA_HandleTypeDef hdma_sdio;
GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_12; // D0 & SCK
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
#ifdef STM32F1xx
#define DMA_IRQ_HANDLER DMA2_Channel4_5_IRQHandler
#elif defined(STM32F4xx)
#define DMA_IRQ_HANDLER DMA2_Stream3_IRQHandler
#else
#error "Unknown STM32 architecture."
#endif
extern "C" void SDIO_IRQHandler(void) { HAL_SD_IRQHandler(&hsd); }
extern "C" void DMA_IRQ_HANDLER(void) { HAL_DMA_IRQHandler(&hdma_sdio); }
/*
SDIO_INIT_CLK_DIV is 118
SDIO clock frequency is 48MHz / (TRANSFER_CLOCK_DIV + 2)
SDIO init clock frequency should not exceed 400kHz = 48MHz / (118 + 2)
Default TRANSFER_CLOCK_DIV is 2 (118 / 40)
Default SDIO clock frequency is 48MHz / (2 + 2) = 12 MHz
This might be too fast for stable SDIO operations
MKS Robin SDIO seems stable with BusWide 1bit and ClockDiv 8 (i.e., 4.8MHz SDIO clock frequency)
More testing is required as there are clearly some 4bit init problems.
*/
void go_to_transfer_speed() {
/* Default SDIO peripheral configuration for SD card initialization */
hsd.Init.ClockEdge = hsd.Init.ClockEdge;
hsd.Init.ClockBypass = hsd.Init.ClockBypass;
hsd.Init.ClockPowerSave = hsd.Init.ClockPowerSave;
hsd.Init.BusWide = hsd.Init.BusWide;
hsd.Init.HardwareFlowControl = hsd.Init.HardwareFlowControl;
hsd.Init.ClockDiv = clock_to_divider(SDIO_CLOCK);
/* Initialize SDIO peripheral interface with default configuration */
SDIO_Init(hsd.Instance, hsd.Init);
}
void SD_LowLevel_Init() {
uint32_t tempreg;
// Enable GPIO clocks
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = 1; // GPIO_NOPULL
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
#if DISABLED(STM32F1xx)
GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
#endif
GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_12; // D0 & SCK
#if PINS_EXIST(SDIO_D1, SDIO_D2, SDIO_D3) // define D1-D3 only if have a four bit wide SDIO bus
GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11; // D1-D3
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
#endif
#if PINS_EXIST(SDIO_D1, SDIO_D2, SDIO_D3) // define D1-D3 only if have a four bit wide SDIO bus
GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11; // D1-D3
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
#endif
// Configure PD.02 CMD line
GPIO_InitStruct.Pin = GPIO_PIN_2;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
// Configure PD.02 CMD line
GPIO_InitStruct.Pin = GPIO_PIN_2;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
// Setup DMA
#if defined(STM32F1xx)
hdma_sdio.Init.Mode = DMA_NORMAL;
hdma_sdio.Instance = DMA2_Channel4;
HAL_NVIC_EnableIRQ(DMA2_Channel4_5_IRQn);
#elif defined(STM32F4xx)
hdma_sdio.Init.Mode = DMA_PFCTRL;
hdma_sdio.Instance = DMA2_Stream3;
hdma_sdio.Init.Channel = DMA_CHANNEL_4;
hdma_sdio.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
hdma_sdio.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_sdio.Init.MemBurst = DMA_MBURST_INC4;
hdma_sdio.Init.PeriphBurst = DMA_PBURST_INC4;
HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
#endif
HAL_NVIC_EnableIRQ(SDIO_IRQn);
hdma_sdio.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_sdio.Init.MemInc = DMA_MINC_ENABLE;
hdma_sdio.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_sdio.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_sdio.Init.Priority = DMA_PRIORITY_LOW;
__HAL_LINKDMA(&hsd, hdmarx, hdma_sdio);
__HAL_LINKDMA(&hsd, hdmatx, hdma_sdio);
// Setup DMA
#ifdef STM32F1xx
hdma_sdio.Init.Mode = DMA_NORMAL;
hdma_sdio.Instance = DMA2_Channel4;
HAL_NVIC_EnableIRQ(DMA2_Channel4_5_IRQn);
#elif defined(STM32F4xx)
hdma_sdio.Init.Mode = DMA_PFCTRL;
hdma_sdio.Instance = DMA2_Stream3;
hdma_sdio.Init.Channel = DMA_CHANNEL_4;
hdma_sdio.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
hdma_sdio.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_sdio.Init.MemBurst = DMA_MBURST_INC4;
hdma_sdio.Init.PeriphBurst = DMA_PBURST_INC4;
HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
#endif
HAL_NVIC_EnableIRQ(SDIO_IRQn);
hdma_sdio.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_sdio.Init.MemInc = DMA_MINC_ENABLE;
hdma_sdio.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_sdio.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_sdio.Init.Priority = DMA_PRIORITY_LOW;
__HAL_LINKDMA(&hsd, hdmarx, hdma_sdio);
__HAL_LINKDMA(&hsd, hdmatx, hdma_sdio);
#if defined(STM32F1xx)
__HAL_RCC_SDIO_CLK_ENABLE();
__HAL_RCC_DMA2_CLK_ENABLE();
#else
__HAL_RCC_SDIO_FORCE_RESET();
delay(2);
__HAL_RCC_SDIO_RELEASE_RESET();
delay(2);
__HAL_RCC_SDIO_CLK_ENABLE();
#ifdef STM32F1xx
__HAL_RCC_SDIO_CLK_ENABLE();
__HAL_RCC_DMA2_CLK_ENABLE();
#else
__HAL_RCC_SDIO_FORCE_RESET(); delay(2);
__HAL_RCC_SDIO_RELEASE_RESET(); delay(2);
__HAL_RCC_SDIO_CLK_ENABLE();
__HAL_RCC_DMA2_FORCE_RESET();
delay(2);
__HAL_RCC_DMA2_RELEASE_RESET();
delay(2);
__HAL_RCC_DMA2_CLK_ENABLE();
#endif
__HAL_RCC_DMA2_FORCE_RESET(); delay(2);
__HAL_RCC_DMA2_RELEASE_RESET(); delay(2);
__HAL_RCC_DMA2_CLK_ENABLE();
#endif
//Initialize the SDIO (with initial <400Khz Clock)
tempreg = 0; //Reset value
tempreg |= SDIO_CLKCR_CLKEN; // Clock enabled
tempreg |= SDIO_INIT_CLK_DIV; // Clock Divider. Clock = 48000 / (118 + 2) = 400Khz
// Keep the rest at 0 => HW_Flow Disabled, Rising Clock Edge, Disable CLK ByPass, Bus Width = 0, Power save Disable
SDIO->CLKCR = tempreg;
// Initialize the SDIO (with initial <400Khz Clock)
tempreg = 0 // Reset value
| SDIO_CLKCR_CLKEN // Clock enabled
| SDIO_INIT_CLK_DIV; // Clock Divider. Clock = 48000 / (118 + 2) = 400Khz
// Keep the rest at 0 => HW_Flow Disabled, Rising Clock Edge, Disable CLK ByPass, Bus Width = 0, Power save Disable
SDIO->CLKCR = tempreg;
// Power up the SDIO
SDIO_PowerState_ON(SDIO);
hsd.Instance = SDIO;
}
// Power up the SDIO
SDIO_PowerState_ON(SDIO);
hsd.Instance = SDIO;
void HAL_SD_MspInit(SD_HandleTypeDef *hsd) { // application specific init
UNUSED(hsd); // Prevent unused argument(s) compilation warning
__HAL_RCC_SDIO_CLK_ENABLE(); // turn on SDIO clock
}
bool SDIO_Init() {
uint8_t retryCnt = SDIO_READ_RETRIES;
bool status;
hsd.Instance = SDIO;
hsd.State = HAL_SD_STATE_RESET;
SD_LowLevel_Init();
uint8_t retry_Cnt = retryCnt;
for (;;) {
hal.watchdog_refresh();
status = (bool) HAL_SD_Init(&hsd);
if (!status) break;
if (!--retry_Cnt) return false; // return failing status if retries are exhausted
}
bool SDIO_Init() {
uint8_t retryCnt = SDIO_READ_RETRIES;
go_to_transfer_speed();
bool status;
hsd.Instance = SDIO;
hsd.State = HAL_SD_STATE_RESET;
SD_LowLevel_Init();
uint8_t retry_Cnt = retryCnt;
#if PINS_EXIST(SDIO_D1, SDIO_D2, SDIO_D3) // go to 4 bit wide mode if pins are defined
retry_Cnt = retryCnt;
for (;;) {
hal.watchdog_refresh();
status = (bool) HAL_SD_Init(&hsd);
if (!status) break;
if (!--retry_Cnt) return false; // return failing status if retries are exhausted
if (!HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B)) break; // some cards are only 1 bit wide so a pass here is not required
if (!--retry_Cnt) break;
}
go_to_transfer_speed();
#if PINS_EXIST(SDIO_D1, SDIO_D2, SDIO_D3) // go to 4 bit wide mode if pins are defined
if (!retry_Cnt) { // wide bus failed, go back to one bit wide mode
hsd.State = (HAL_SD_StateTypeDef) 0; // HAL_SD_STATE_RESET
SD_LowLevel_Init();
retry_Cnt = retryCnt;
for (;;) {
hal.watchdog_refresh();
if (!HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B)) break; // some cards are only 1 bit wide so a pass here is not required
if (!--retry_Cnt) break;
status = (bool) HAL_SD_Init(&hsd);
if (!status) break;
if (!--retry_Cnt) return false; // return failing status if retries are exhausted
}
if (!retry_Cnt) { // wide bus failed, go back to one bit wide mode
hsd.State = (HAL_SD_StateTypeDef) 0; // HAL_SD_STATE_RESET
SD_LowLevel_Init();
retry_Cnt = retryCnt;
for (;;) {
hal.watchdog_refresh();
status = (bool) HAL_SD_Init(&hsd);
if (!status) break;
if (!--retry_Cnt) return false; // return failing status if retries are exhausted
}
go_to_transfer_speed();
}
#endif
go_to_transfer_speed();
}
#endif
return true;
return true;
}
static bool SDIO_ReadWriteBlock_DMA(uint32_t block, const uint8_t *src, uint8_t *dst) {
if (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER) return false;
hal.watchdog_refresh();
HAL_StatusTypeDef ret;
if (src) {
hdma_sdio.Init.Direction = DMA_MEMORY_TO_PERIPH;
HAL_DMA_Init(&hdma_sdio);
ret = HAL_SD_WriteBlocks_DMA(&hsd, (uint8_t *)src, block, 1);
}
else {
hdma_sdio.Init.Direction = DMA_PERIPH_TO_MEMORY;
HAL_DMA_Init(&hdma_sdio);
ret = HAL_SD_ReadBlocks_DMA(&hsd, (uint8_t *)dst, block, 1);
}
/**
* @brief Read or Write a block
* @details Read or Write a block with SDIO
*
* @param block The block index
* @param src The data buffer source for a write
* @param dst The data buffer destination for a read
*
* @return true on success
*/
static bool SDIO_ReadWriteBlock_DMA(uint32_t block, const uint8_t *src, uint8_t *dst) {
if (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER) return false;
if (ret != HAL_OK) {
HAL_DMA_Abort_IT(&hdma_sdio);
HAL_DMA_DeInit(&hdma_sdio);
return false;
}
hal.watchdog_refresh();
HAL_StatusTypeDef ret;
if (src) {
hdma_sdio.Init.Direction = DMA_MEMORY_TO_PERIPH;
HAL_DMA_Init(&hdma_sdio);
ret = HAL_SD_WriteBlocks_DMA(&hsd, (uint8_t*)src, block, 1);
}
else {
hdma_sdio.Init.Direction = DMA_PERIPH_TO_MEMORY;
HAL_DMA_Init(&hdma_sdio);
ret = HAL_SD_ReadBlocks_DMA(&hsd, (uint8_t*)dst, block, 1);
}
if (ret != HAL_OK) {
millis_t timeout = millis() + 500;
// Wait the transfer
while (hsd.State != HAL_SD_STATE_READY) {
if (ELAPSED(millis(), timeout)) {
HAL_DMA_Abort_IT(&hdma_sdio);
HAL_DMA_DeInit(&hdma_sdio);
return false;
}
millis_t timeout = millis() + SD_TIMEOUT;
// Wait the transfer
while (hsd.State != HAL_SD_STATE_READY) {
if (ELAPSED(millis(), timeout)) {
HAL_DMA_Abort_IT(&hdma_sdio);
HAL_DMA_DeInit(&hdma_sdio);
return false;
}
}
while (__HAL_DMA_GET_FLAG(&hdma_sdio, __HAL_DMA_GET_TC_FLAG_INDEX(&hdma_sdio)) != 0
|| __HAL_DMA_GET_FLAG(&hdma_sdio, __HAL_DMA_GET_TE_FLAG_INDEX(&hdma_sdio)) != 0) { /* nada */ }
HAL_DMA_Abort_IT(&hdma_sdio);
HAL_DMA_DeInit(&hdma_sdio);
timeout = millis() + SD_TIMEOUT;
while (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER) if (ELAPSED(millis(), timeout)) return false;
return true;
}
#endif // !SDIO_FOR_STM32H7
while (__HAL_DMA_GET_FLAG(&hdma_sdio, __HAL_DMA_GET_TC_FLAG_INDEX(&hdma_sdio)) != 0
|| __HAL_DMA_GET_FLAG(&hdma_sdio, __HAL_DMA_GET_TE_FLAG_INDEX(&hdma_sdio)) != 0) { /* nada */ }
/**
* @brief Read a block
* @details Read a block from media with SDIO
*
* @param block The block index
* @param src The block buffer
*
* @return true on success
*/
bool SDIO_ReadBlock(uint32_t block, uint8_t *dst) {
#ifdef SDIO_FOR_STM32H7
HAL_DMA_Abort_IT(&hdma_sdio);
HAL_DMA_DeInit(&hdma_sdio);
uint32_t timeout = HAL_GetTick() + SD_TIMEOUT;
timeout = millis() + 500;
while (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER) if (ELAPSED(millis(), timeout)) return false;
while (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER)
if (HAL_GetTick() >= timeout) return false;
waitingRxCplt = 1;
if (HAL_SD_ReadBlocks_DMA(&hsd, (uint8_t*)dst, block, 1) != HAL_OK)
return false;
timeout = HAL_GetTick() + SD_TIMEOUT;
while (waitingRxCplt)
if (HAL_GetTick() >= timeout) return false;
return true;
#else
uint8_t retries = SDIO_READ_RETRIES;
while (retries--) if (SDIO_ReadWriteBlock_DMA(block, nullptr, dst)) return true;
return false;
#endif
return true;
}
bool SDIO_ReadBlock(uint32_t block, uint8_t *dst) {
uint8_t retries = SDIO_READ_RETRIES;
while (retries--) if (SDIO_ReadWriteBlock_DMA(block, nullptr, dst)) return true;
return false;
}
/**
* @brief Write a block
* @details Write a block to media with SDIO
*
* @param block The block index
* @param src The block data
*
* @return true on success
*/
bool SDIO_WriteBlock(uint32_t block, const uint8_t *src) {
#ifdef SDIO_FOR_STM32H7
uint32_t timeout = HAL_GetTick() + SD_TIMEOUT;
while (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER)
if (HAL_GetTick() >= timeout) return false;
waitingTxCplt = 1;
if (HAL_SD_WriteBlocks_DMA(&hsd, (uint8_t*)src, block, 1) != HAL_OK)
return false;
timeout = HAL_GetTick() + SD_TIMEOUT;
while (waitingTxCplt)
if (HAL_GetTick() >= timeout) return false;
return true;
#else
uint8_t retries = SDIO_READ_RETRIES;
while (retries--) if (SDIO_ReadWriteBlock_DMA(block, src, nullptr)) return true;
return false;
#endif
uint8_t retries = SDIO_READ_RETRIES;
while (retries--) if (SDIO_ReadWriteBlock_DMA(block, src, nullptr)) return true;
return false;
}
bool SDIO_IsReady() {
@@ -447,5 +305,16 @@ uint32_t SDIO_GetCardSize() {
return (uint32_t)(hsd.SdCard.BlockNbr) * (hsd.SdCard.BlockSize);
}
#if defined(STM32F1xx)
#define DMA_IRQ_HANDLER DMA2_Channel4_5_IRQHandler
#elif defined(STM32F4xx)
#define DMA_IRQ_HANDLER DMA2_Stream3_IRQHandler
#else
#error "Unknown STM32 architecture."
#endif
extern "C" void SDIO_IRQHandler(void) { HAL_SD_IRQHandler(&hsd); }
extern "C" void DMA_IRQ_HANDLER(void) { HAL_DMA_IRQHandler(&hdma_sdio); }
#endif // SDIO_SUPPORT
#endif // HAL_STM32
+6 -10
View File
@@ -159,28 +159,24 @@ void GT911::read_reg(uint16_t reg, uint8_t reg_len, uint8_t* r_data, uint8_t r_l
void GT911::Init() {
OUT_WRITE(GT911_RST_PIN, LOW);
OUT_WRITE(GT911_INT_PIN, LOW);
delay(11);
WRITE(GT911_INT_PIN, HIGH);
delayMicroseconds(110);
delay(20);
WRITE(GT911_RST_PIN, HIGH);
delay(6);
WRITE(GT911_INT_PIN, LOW);
delay(55);
SET_INPUT(GT911_INT_PIN);
sw_iic.init();
uint8_t clear_reg = 0x00;
write_reg(0x814E, 2, &clear_reg, 1); // Reset to 0 for start
uint8_t clear_reg = 0x0000;
write_reg(0x814E, 2, &clear_reg, 2); // Reset to 0 for start
}
bool GT911::getFirstTouchPoint(int16_t *x, int16_t *y) {
read_reg(0x814E, 2, &reg.REG.status, 1);
if (reg.REG.status >= 0x80 && reg.REG.status <= 0x85) {
read_reg(0x8150, 2, reg.map + 2, 38);
if (reg.REG.status & 0x80) {
uint8_t clear_reg = 0x00;
write_reg(0x814E, 2, &clear_reg, 1); // Reset to 0 for start
read_reg(0x8150, 2, reg.map + 2, 8 * (reg.REG.status & 0x0F));
// First touch point
*x = ((reg.REG.point[0].xh & 0x0F) << 8) | reg.REG.point[0].xl;
*y = ((reg.REG.point[0].yh & 0x0F) << 8) | reg.REG.point[0].yl;
+1 -1
View File
@@ -23,7 +23,7 @@
#include "../../../inc/MarlinConfig.h"
#define GT911_SLAVE_ADDRESS 0x28
#define GT911_SLAVE_ADDRESS 0xBA
#if !PIN_EXISTS(GT911_RST)
#error "GT911_RST_PIN is not defined."
+1 -1
View File
@@ -147,7 +147,7 @@ uint32_t TFT_FSMC::ReadID(tft_data_t Reg) {
}
bool TFT_FSMC::isBusy() {
#ifdef STM32F1xx
#if defined(STM32F1xx)
volatile bool dmaEnabled = (DMAtx.Instance->CCR & DMA_CCR_EN) != RESET;
#elif defined(STM32F4xx)
volatile bool dmaEnabled = DMAtx.Instance->CR & DMA_SxCR_EN;
+2 -2
View File
@@ -372,9 +372,9 @@ void TFT_LTDC::TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Cou
if (MemoryIncrease == DMA_PINC_ENABLE) {
DrawImage(x_min, y_cur, x_min + width, y_cur + height, Data);
Data += width * height;
}
else
} else {
DrawRect(x_min, y_cur, x_min + width, y_cur + height, *Data);
}
y_cur += height;
}
+1 -1
View File
@@ -179,7 +179,7 @@ uint32_t TFT_SPI::ReadID(uint16_t Reg) {
}
bool TFT_SPI::isBusy() {
#ifdef STM32F1xx
#if defined(STM32F1xx)
volatile bool dmaEnabled = (DMAtx.Instance->CCR & DMA_CCR_EN) != RESET;
#elif defined(STM32F4xx)
volatile bool dmaEnabled = DMAtx.Instance->CR & DMA_SxCR_EN;
+8 -8
View File
@@ -147,17 +147,17 @@ void libServo::move(const int32_t value) {
uint16_t SR = timer_get_status(tdev);
if (SR & TIMER_SR_CC1IF) { // channel 1 off
#ifdef SERVO0_PWM_OD
OUT_WRITE_OD(SERVO0_PIN, HIGH); // off
OUT_WRITE_OD(SERVO0_PIN, 1); // off
#else
OUT_WRITE(SERVO0_PIN, LOW);
OUT_WRITE(SERVO0_PIN, 0);
#endif
timer_reset_status_bit(tdev, TIMER_SR_CC1IF_BIT);
}
if (SR & TIMER_SR_CC2IF) { // channel 2 resume
#ifdef SERVO0_PWM_OD
OUT_WRITE_OD(SERVO0_PIN, LOW); // on
OUT_WRITE_OD(SERVO0_PIN, 0); // on
#else
OUT_WRITE(SERVO0_PIN, HIGH);
OUT_WRITE(SERVO0_PIN, 1);
#endif
timer_reset_status_bit(tdev, TIMER_SR_CC2IF_BIT);
}
@@ -167,9 +167,9 @@ void libServo::move(const int32_t value) {
timer_dev *tdev = HAL_get_timer_dev(MF_TIMER_SERVO0);
if (!tdev) return false;
#ifdef SERVO0_PWM_OD
OUT_WRITE_OD(inPin, HIGH);
OUT_WRITE_OD(inPin, 1);
#else
OUT_WRITE(inPin, LOW);
OUT_WRITE(inPin, 0);
#endif
timer_pause(tdev);
@@ -200,9 +200,9 @@ void libServo::move(const int32_t value) {
timer_disable_irq(tdev, 1);
timer_disable_irq(tdev, 2);
#ifdef SERVO0_PWM_OD
OUT_WRITE_OD(pin, HIGH); // off
OUT_WRITE_OD(pin, 1); // off
#else
OUT_WRITE(pin, LOW);
OUT_WRITE(pin, 0);
#endif
}
}
+1 -1
View File
@@ -36,7 +36,7 @@
#define PRINT_PIN_ANALOG(p) do{ sprintf_P(buffer, PSTR(" (A%2d) "), DIGITAL_PIN_TO_ANALOG_PIN(pin)); SERIAL_ECHO(buffer); }while(0)
#define GET_ARRAY_PIN(p) pin_array[p].pin
#define GET_ARRAY_IS_DIGITAL(p) pin_array[p].is_digital
#define VALID_PIN(pin) (pin >= 0 && pin < int8_t(NUMBER_PINS_TOTAL))
#define VALID_PIN(pin) (pin >= 0 && pin < (int8_t)NUMBER_PINS_TOTAL ? 1 : 0)
#define DIGITAL_PIN_TO_ANALOG_PIN(p) int(p - analogInputToDigitalPin(0))
#define IS_ANALOG(P) ((P) >= analogInputToDigitalPin(0) && (P) <= analogInputToDigitalPin(13)) || ((P) >= analogInputToDigitalPin(14) && (P) <= analogInputToDigitalPin(17))
#define pwm_status(pin) HAL_pwm_status(pin)
+139
View File
@@ -0,0 +1,139 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
/**
* Software L6470 SPI functions originally from Arduino Sd2Card Library
* Copyright (c) 2009 by William Greiman
*/
#include "../../inc/MarlinConfig.h"
#if HAS_L64XX
#include "Delay.h"
#include "../../core/serial.h"
#include "../../libs/L64XX/L64XX_Marlin.h"
// Make sure GCC optimizes this file.
// Note that this line triggers a bug in GCC which is fixed by casting.
// See the note below.
#pragma GCC optimize (3)
// run at ~4Mhz
inline uint8_t L6470_SpiTransfer_Mode_0(uint8_t b) { // using Mode 0
for (uint8_t bits = 8; bits--;) {
WRITE(L6470_CHAIN_MOSI_PIN, b & 0x80);
b <<= 1; // little setup time
WRITE(L6470_CHAIN_SCK_PIN, HIGH);
DELAY_NS(125); // 10 cycles @ 84mhz
b |= (READ(L6470_CHAIN_MISO_PIN) != 0);
WRITE(L6470_CHAIN_SCK_PIN, LOW);
DELAY_NS(125); // 10 cycles @ 84mhz
}
return b;
}
inline uint8_t L6470_SpiTransfer_Mode_3(uint8_t b) { // using Mode 3
for (uint8_t bits = 8; bits--;) {
WRITE(L6470_CHAIN_SCK_PIN, LOW);
WRITE(L6470_CHAIN_MOSI_PIN, b & 0x80);
DELAY_NS(125); // 10 cycles @ 84mhz
WRITE(L6470_CHAIN_SCK_PIN, HIGH);
DELAY_NS(125); // Need more delay for fast CPUs
b <<= 1; // little setup time
b |= (READ(L6470_CHAIN_MISO_PIN) != 0);
}
DELAY_NS(125); // 10 cycles @ 84mhz
return b;
}
/**
* L64XX methods for SPI init and transfer
*/
void L64XX_Marlin::spi_init() {
OUT_WRITE(L6470_CHAIN_SS_PIN, HIGH);
OUT_WRITE(L6470_CHAIN_SCK_PIN, HIGH);
OUT_WRITE(L6470_CHAIN_MOSI_PIN, HIGH);
SET_INPUT(L6470_CHAIN_MISO_PIN);
#if PIN_EXISTS(L6470_BUSY)
SET_INPUT(L6470_BUSY_PIN);
#endif
OUT_WRITE(L6470_CHAIN_MOSI_PIN, HIGH);
}
uint8_t L64XX_Marlin::transfer_single(uint8_t data, int16_t ss_pin) {
// First device in chain has data sent last
extDigitalWrite(ss_pin, LOW);
hal.isr_off(); // Disable interrupts during SPI transfer (can't allow partial command to chips)
const uint8_t data_out = L6470_SpiTransfer_Mode_3(data);
hal.isr_on(); // Enable interrupts
extDigitalWrite(ss_pin, HIGH);
return data_out;
}
uint8_t L64XX_Marlin::transfer_chain(uint8_t data, int16_t ss_pin, uint8_t chain_position) {
uint8_t data_out = 0;
// first device in chain has data sent last
extDigitalWrite(ss_pin, LOW);
for (uint8_t i = L64XX::chain[0]; !L64xxManager.spi_abort && i >= 1; i--) { // Send data unless aborted
hal.isr_off(); // Disable interrupts during SPI transfer (can't allow partial command to chips)
const uint8_t temp = L6470_SpiTransfer_Mode_3(uint8_t(i == chain_position ? data : dSPIN_NOP));
hal.isr_on(); // Enable interrupts
if (i == chain_position) data_out = temp;
}
extDigitalWrite(ss_pin, HIGH);
return data_out;
}
/**
* Platform-supplied L6470 buffer transfer method
*/
void L64XX_Marlin::transfer(uint8_t L6470_buf[], const uint8_t length) {
// First device in chain has its data sent last
if (spi_active) { // Interrupted SPI transfer so need to
WRITE(L6470_CHAIN_SS_PIN, HIGH); // guarantee min high of 650ns
DELAY_US(1);
}
WRITE(L6470_CHAIN_SS_PIN, LOW);
for (uint8_t i = length; i >= 1; i--)
L6470_SpiTransfer_Mode_3(uint8_t(L6470_buf[i]));
WRITE(L6470_CHAIN_SS_PIN, HIGH);
}
#pragma GCC reset_options
#endif // HAS_L64XX
@@ -135,11 +135,11 @@ static UnwResult UnwTabExecuteInstructions(const UnwindCallbacks *cb, UnwTabStat
while ((instruction = UnwTabGetNextInstruction(cb, ucb)) != -1) {
if ((instruction & 0xC0) == 0x00) { // ARM_EXIDX_CMD_DATA_POP
/* vsp += (xxxxxx << 2) + 4 */
/* vsp = vsp + (xxxxxx << 2) + 4 */
ucb->vrs[13] += ((instruction & 0x3F) << 2) + 4;
}
else if ((instruction & 0xC0) == 0x40) { // ARM_EXIDX_CMD_DATA_PUSH
/* vsp -= (xxxxxx << 2) - 4 */
/* vsp = vsp - (xxxxxx << 2) - 4 */
ucb->vrs[13] -= ((instruction & 0x3F) << 2) - 4;
}
else if ((instruction & 0xF0) == 0x80) {
+6 -7
View File
@@ -65,7 +65,7 @@ uint8_t ServoCount = 0; // the total number of attached
/************ static functions common to all instances ***********************/
static bool anyTimerChannelActive(const timer16_Sequence_t timer) {
static boolean isTimerActive(timer16_Sequence_t timer) {
// returns true if any servo is active on this timer
LOOP_L_N(channel, SERVOS_PER_TIMER) {
if (SERVO(timer, channel).Pin.isActive)
@@ -101,18 +101,17 @@ int8_t Servo::attach(const int inPin, const int inMin, const int inMax) {
max = (MAX_PULSE_WIDTH - inMax) / 4;
// initialize the timer if it has not already been initialized
const timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex);
if (!anyTimerChannelActive(timer)) initISR(timer);
servo_info[servoIndex].Pin.isActive = true; // this must be set after the check for anyTimerChannelActive
timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex);
if (!isTimerActive(timer)) initISR(timer);
servo_info[servoIndex].Pin.isActive = true; // this must be set after the check for isTimerActive
return servoIndex;
}
void Servo::detach() {
servo_info[servoIndex].Pin.isActive = false;
const timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex);
if (!anyTimerChannelActive(timer)) finISR(timer);
//pinMode(servo_info[servoIndex].Pin.nbr, INPUT); // set servo pin to input
timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex);
if (!isTimerActive(timer)) finISR(timer);
}
void Servo::write(int value) {
+6 -6
View File
@@ -70,10 +70,10 @@
#define ticksToUs(_ticks) (unsigned(_ticks) * (SERVO_TIMER_PRESCALER) / clockCyclesPerMicrosecond())
// convenience macros
#define SERVO_INDEX_TO_TIMER(_servo_nbr) timer16_Sequence_t(_servo_nbr / (SERVOS_PER_TIMER)) // the timer controlling this servo
#define SERVO_INDEX_TO_CHANNEL(_servo_nbr) (_servo_nbr % (SERVOS_PER_TIMER)) // the index of the servo on this timer
#define SERVO_INDEX(_timer,_channel) ((_timer*(SERVOS_PER_TIMER)) + _channel) // servo index by timer and channel
#define SERVO(_timer,_channel) servo_info[SERVO_INDEX(_timer,_channel)] // servo class by timer and channel
#define SERVO_INDEX_TO_TIMER(_servo_nbr) ((timer16_Sequence_t)(_servo_nbr / (SERVOS_PER_TIMER))) // returns the timer controlling this servo
#define SERVO_INDEX_TO_CHANNEL(_servo_nbr) (_servo_nbr % (SERVOS_PER_TIMER)) // returns the index of the servo on this timer
#define SERVO_INDEX(_timer,_channel) ((_timer*(SERVOS_PER_TIMER)) + _channel) // macro to access servo index by timer and channel
#define SERVO(_timer,_channel) (servo_info[SERVO_INDEX(_timer,_channel)]) // macro to access servo class by timer and channel
// Types
@@ -94,5 +94,5 @@ extern ServoInfo_t servo_info[MAX_SERVOS];
// Public functions
void initISR(const timer16_Sequence_t timer_index);
void finISR(const timer16_Sequence_t timer_index);
extern void initISR(timer16_Sequence_t timer);
extern void finISR(timer16_Sequence_t timer);
+55 -64
View File
@@ -39,13 +39,17 @@
#endif
#include <math.h>
#include "module/endstops.h"
#include "core/utility.h"
#include "module/motion.h"
#include "module/planner.h"
#include "module/printcounter.h" // PrintCounter or Stopwatch
#include "module/settings.h"
#include "module/stepper.h"
#include "module/endstops.h"
#include "module/temperature.h"
#include "module/settings.h"
#include "module/printcounter.h" // PrintCounter or Stopwatch
#include "module/stepper.h"
#include "module/stepper/indirection.h"
#include "gcode/gcode.h"
#include "gcode/parser.h"
@@ -121,10 +125,6 @@
#include "feature/bltouch.h"
#endif
#if ENABLED(BD_SENSOR)
#include "feature/bedlevel/bdl/bdl.h"
#endif
#if ENABLED(POLL_JOG)
#include "feature/joystick.h"
#endif
@@ -228,6 +228,10 @@
#include "feature/mmu/mmu2.h"
#endif
#if HAS_L64XX
#include "libs/L64XX/L64XX_Marlin.h"
#endif
#if ENABLED(PASSWORD_FEATURE)
#include "feature/password/password.h"
#endif
@@ -248,10 +252,6 @@
#include "feature/easythreed_ui.h"
#endif
#if ENABLED(MARLIN_TEST_BUILD)
#include "tests/marlin_tests.h"
#endif
PGMSTR(M112_KILL_STR, "M112 Shutdown");
MarlinState marlin_state = MF_INITIALIZING;
@@ -347,7 +347,7 @@ void startOrResumeJob() {
TERN_(GCODE_REPEAT_MARKERS, repeat.reset());
TERN_(CANCEL_OBJECTS, cancelable.reset());
TERN_(LCD_SHOW_E_TOTAL, e_move_accumulator = 0);
#if ENABLED(SET_REMAINING_TIME)
#if BOTH(LCD_SET_PROGRESS_MANUALLY, USE_M73_REMAINING_TIME)
ui.reset_remaining_time();
#endif
}
@@ -423,38 +423,37 @@ inline void manage_inactivity(const bool no_stepper_sleep=false) {
kill();
}
const bool has_blocks = planner.has_blocks_queued(); // Any moves in the planner?
if (has_blocks) gcode.reset_stepper_timeout(ms); // Reset timeout for M18/M84, M85 max 'kill', and laser.
// M18 / M84 : Handle steppers inactive time timeout
#if HAS_DISABLE_INACTIVE_AXIS
if (gcode.stepper_inactive_time) {
if (gcode.stepper_inactive_time) {
static bool already_shutdown_steppers; // = false
static bool already_shutdown_steppers; // = false
if (!has_blocks && !do_reset_timeout && gcode.stepper_inactive_timeout()) {
if (!already_shutdown_steppers) {
already_shutdown_steppers = true;
// Any moves in the planner? Resets both the M18/M84
// activity timeout and the M85 max 'kill' timeout
if (planner.has_blocks_queued())
gcode.reset_stepper_timeout(ms);
else if (!do_reset_timeout && gcode.stepper_inactive_timeout()) {
if (!already_shutdown_steppers) {
already_shutdown_steppers = true; // L6470 SPI will consume 99% of free time without this
// Individual axes will be disabled if configured
TERN_(DISABLE_INACTIVE_X, stepper.disable_axis(X_AXIS));
TERN_(DISABLE_INACTIVE_Y, stepper.disable_axis(Y_AXIS));
TERN_(DISABLE_INACTIVE_Z, stepper.disable_axis(Z_AXIS));
TERN_(DISABLE_INACTIVE_I, stepper.disable_axis(I_AXIS));
TERN_(DISABLE_INACTIVE_J, stepper.disable_axis(J_AXIS));
TERN_(DISABLE_INACTIVE_K, stepper.disable_axis(K_AXIS));
TERN_(DISABLE_INACTIVE_U, stepper.disable_axis(U_AXIS));
TERN_(DISABLE_INACTIVE_V, stepper.disable_axis(V_AXIS));
TERN_(DISABLE_INACTIVE_W, stepper.disable_axis(W_AXIS));
TERN_(DISABLE_INACTIVE_E, stepper.disable_e_steppers());
// Individual axes will be disabled if configured
TERN_(DISABLE_INACTIVE_X, stepper.disable_axis(X_AXIS));
TERN_(DISABLE_INACTIVE_Y, stepper.disable_axis(Y_AXIS));
TERN_(DISABLE_INACTIVE_Z, stepper.disable_axis(Z_AXIS));
TERN_(DISABLE_INACTIVE_I, stepper.disable_axis(I_AXIS));
TERN_(DISABLE_INACTIVE_J, stepper.disable_axis(J_AXIS));
TERN_(DISABLE_INACTIVE_K, stepper.disable_axis(K_AXIS));
TERN_(DISABLE_INACTIVE_U, stepper.disable_axis(U_AXIS));
TERN_(DISABLE_INACTIVE_V, stepper.disable_axis(V_AXIS));
TERN_(DISABLE_INACTIVE_W, stepper.disable_axis(W_AXIS));
TERN_(DISABLE_INACTIVE_E, stepper.disable_e_steppers());
TERN_(AUTO_BED_LEVELING_UBL, bedlevel.steppers_were_disabled());
}
TERN_(AUTO_BED_LEVELING_UBL, bedlevel.steppers_were_disabled());
}
else
already_shutdown_steppers = false;
}
#endif
else
already_shutdown_steppers = false;
}
#if ENABLED(PHOTO_GCODE) && PIN_EXISTS(CHDK)
// Check if CHDK should be set to LOW (after M240 set it HIGH)
@@ -488,7 +487,7 @@ inline void manage_inactivity(const bool no_stepper_sleep=false) {
}
#endif
#if ENABLED(FREEZE_FEATURE)
#if HAS_FREEZE_PIN
stepper.frozen = READ(FREEZE_PIN) == FREEZE_STATE;
#endif
@@ -733,6 +732,8 @@ inline void manage_inactivity(const bool no_stepper_sleep=false) {
TERN_(MONITOR_DRIVER_STATUS, monitor_tmc_drivers());
TERN_(MONITOR_L6470_DRIVER_STATUS, L64xxManager.monitor_driver());
// Limit check_axes_activity frequency to 10Hz
static millis_t next_check_axes_ms = 0;
if (ELAPSED(ms, next_check_axes_ms)) {
@@ -774,23 +775,16 @@ inline void manage_inactivity(const bool no_stepper_sleep=false) {
* - Handle Joystick jogging
*/
void idle(bool no_stepper_sleep/*=false*/) {
#ifdef MAX7219_DEBUG_PROFILE
CodeProfiler idle_profiler;
#endif
#if ENABLED(MARLIN_DEV_MODE)
static uint16_t idle_depth = 0;
if (++idle_depth > 5) SERIAL_ECHOLNPGM("idle() call depth: ", idle_depth);
#endif
// Bed Distance Sensor task
TERN_(BD_SENSOR, bdl.process());
// Core Marlin activities
manage_inactivity(no_stepper_sleep);
// Manage Heaters (and Watchdog)
thermalManager.task();
thermalManager.manage_heater();
// Max7219 heartbeat, animation, etc
TERN_(MAX7219_DEBUG, max7219.idle_tasks());
@@ -1065,6 +1059,7 @@ inline void tmc_standby_setup() {
* • TMC220x Stepper Drivers (Serial)
* • PSU control
* • Power-loss Recovery
* • L64XX Stepper Drivers (SPI)
* • Stepper Driver Reset: DISABLE
* • TMC Stepper Drivers (SPI)
* • Run hal.init_board() for additional pins setup
@@ -1227,10 +1222,10 @@ void setup() {
SETUP_RUN(hal.init());
// Init and disable SPI thermocouples; this is still needed
#if TEMP_SENSOR_IS_MAX_TC(0) || (TEMP_SENSOR_IS_MAX_TC(REDUNDANT) && REDUNDANT_TEMP_MATCH(SOURCE, E0))
#if TEMP_SENSOR_0_IS_MAX_TC || (TEMP_SENSOR_REDUNDANT_IS_MAX_TC && REDUNDANT_TEMP_MATCH(SOURCE, E0))
OUT_WRITE(TEMP_0_CS_PIN, HIGH); // Disable
#endif
#if TEMP_SENSOR_IS_MAX_TC(1) || (TEMP_SENSOR_IS_MAX_TC(REDUNDANT) && REDUNDANT_TEMP_MATCH(SOURCE, E1))
#if TEMP_SENSOR_1_IS_MAX_TC || (TEMP_SENSOR_REDUNDANT_IS_MAX_TC && REDUNDANT_TEMP_MATCH(SOURCE, E1))
OUT_WRITE(TEMP_1_CS_PIN, HIGH);
#endif
@@ -1246,13 +1241,6 @@ void setup() {
SETUP_RUN(tmc_serial_begin());
#endif
#if HAS_TMC_SPI
#if DISABLED(TMC_USE_SW_SPI)
SETUP_RUN(SPI.begin());
#endif
SETUP_RUN(tmc_init_cs_pins());
#endif
#if ENABLED(PSU_CONTROL)
SETUP_LOG("PSU_CONTROL");
powerManager.init();
@@ -1262,10 +1250,21 @@ void setup() {
SETUP_RUN(recovery.setup());
#endif
#if HAS_L64XX
SETUP_RUN(L64xxManager.init()); // Set up SPI, init drivers
#endif
#if HAS_STEPPER_RESET
SETUP_RUN(disableStepperDrivers());
#endif
#if HAS_TMC_SPI
#if DISABLED(TMC_USE_SW_SPI)
SETUP_RUN(SPI.begin());
#endif
SETUP_RUN(tmc_init_cs_pins());
#endif
SETUP_RUN(hal.init_board());
SETUP_RUN(esp_wifi_init());
@@ -1639,15 +1638,9 @@ void setup() {
SETUP_RUN(test_tmc_connection());
#endif
#if ENABLED(BD_SENSOR)
SETUP_RUN(bdl.init(I2C_BD_SDA_PIN, I2C_BD_SCL_PIN, I2C_BD_DELAY));
#endif
marlin_state = MF_RUNNING;
SETUP_LOG("setup() completed.");
TERN_(MARLIN_TEST_BUILD, runStartupTests());
}
/**
@@ -1682,7 +1675,5 @@ void loop() {
TERN_(HAS_TFT_LVGL_UI, printer_state_polling());
TERN_(MARLIN_TEST_BUILD, runPeriodicTests());
} while (ENABLED(__AVR__)); // Loop forever on slower (AVR) boards
}
+67 -77
View File
@@ -161,7 +161,7 @@
#define BOARD_PICA_REVB 1324 // PICA Shield (original version)
#define BOARD_PICA 1325 // PICA Shield (rev C or later)
#define BOARD_INTAMSYS40 1326 // Intamsys 4.0 (Funmat HT)
#define BOARD_MALYAN_M180 1327 // Malyan M180 Mainboard Version 2 (no display function, direct G-code only)
#define BOARD_MALYAN_M180 1327 // Malyan M180 Mainboard Version 2 (no display function, direct gcode only)
#define BOARD_GT2560_V4_A20 1328 // Geeetech GT2560 Rev B for A20(M/T/D)
#define BOARD_PROTONEER_CNC_SHIELD_V3 1329 // Mega controller & Protoneer CNC Shield V3.00
#define BOARD_WEEDO_62A 1330 // WEEDO 62A board (TINA2, Monoprice Cadet, etc.)
@@ -238,7 +238,6 @@
#define BOARD_BTT_SKR_V1_1 2012 // BigTreeTech SKR v1.1
#define BOARD_BTT_SKR_V1_3 2013 // BigTreeTech SKR v1.3
#define BOARD_BTT_SKR_V1_4 2014 // BigTreeTech SKR v1.4
#define BOARD_EMOTRONIC 2015 // eMotion-Tech eMotronic
//
// LPC1769 ARM Cortex M3
@@ -329,47 +328,44 @@
#define BOARD_BTT_SKR_MINI_E3_V1_2 4025 // BigTreeTech SKR Mini E3 V1.2 (STM32F103RC)
#define BOARD_BTT_SKR_MINI_E3_V2_0 4026 // BigTreeTech SKR Mini E3 V2.0 (STM32F103RC / STM32F103RE)
#define BOARD_BTT_SKR_MINI_E3_V3_0 4027 // BigTreeTech SKR Mini E3 V3.0 (STM32G0B1RE)
#define BOARD_BTT_SKR_MINI_E3_V3_0_1 4028 // BigTreeTech SKR Mini E3 V3.0.1 (STM32F401RC)
#define BOARD_BTT_SKR_MINI_MZ_V1_0 4029 // BigTreeTech SKR Mini MZ V1.0 (STM32F103RC)
#define BOARD_BTT_SKR_E3_DIP 4030 // BigTreeTech SKR E3 DIP V1.0 (STM32F103RC / STM32F103RE)
#define BOARD_BTT_SKR_CR6 4031 // BigTreeTech SKR CR6 v1.0 (STM32F103RE)
#define BOARD_JGAURORA_A5S_A1 4032 // JGAurora A5S A1 (STM32F103ZE)
#define BOARD_FYSETC_AIO_II 4033 // FYSETC AIO_II (STM32F103RC)
#define BOARD_FYSETC_CHEETAH 4034 // FYSETC Cheetah (STM32F103RC)
#define BOARD_FYSETC_CHEETAH_V12 4035 // FYSETC Cheetah V1.2 (STM32F103RC)
#define BOARD_LONGER3D_LK 4036 // Longer3D LK1/2 - Alfawise U20/U20+/U30 (STM32F103VE)
#define BOARD_CCROBOT_MEEB_3DP 4037 // ccrobot-online.com MEEB_3DP (STM32F103RC)
#define BOARD_CHITU3D_V5 4038 // Chitu3D TronXY X5SA V5 Board (STM32F103ZE)
#define BOARD_CHITU3D_V6 4039 // Chitu3D TronXY X5SA V6 Board (STM32F103ZE)
#define BOARD_CHITU3D_V9 4040 // Chitu3D TronXY X5SA V9 Board (STM32F103ZE)
#define BOARD_CREALITY_V4 4041 // Creality v4.x (STM32F103RC / STM32F103RE)
#define BOARD_CREALITY_V422 4042 // Creality v4.2.2 (STM32F103RC / STM32F103RE)
#define BOARD_CREALITY_V423 4043 // Creality v4.2.3 (STM32F103RC / STM32F103RE)
#define BOARD_CREALITY_V425 4044 // Creality v4.2.5 (STM32F103RC / STM32F103RE)
#define BOARD_CREALITY_V427 4045 // Creality v4.2.7 (STM32F103RC / STM32F103RE)
#define BOARD_CREALITY_V4210 4046 // Creality v4.2.10 (STM32F103RC / STM32F103RE) as found in the CR-30
#define BOARD_CREALITY_V431 4047 // Creality v4.3.1 (STM32F103RC / STM32F103RE)
#define BOARD_CREALITY_V431_A 4048 // Creality v4.3.1a (STM32F103RC / STM32F103RE)
#define BOARD_CREALITY_V431_B 4049 // Creality v4.3.1b (STM32F103RC / STM32F103RE)
#define BOARD_CREALITY_V431_C 4050 // Creality v4.3.1c (STM32F103RC / STM32F103RE)
#define BOARD_CREALITY_V431_D 4051 // Creality v4.3.1d (STM32F103RC / STM32F103RE)
#define BOARD_CREALITY_V452 4052 // Creality v4.5.2 (STM32F103RC / STM32F103RE)
#define BOARD_CREALITY_V453 4053 // Creality v4.5.3 (STM32F103RC / STM32F103RE)
#define BOARD_CREALITY_V521 4054 // Creality v5.2.1 (STM32F103VE) as found in the SV04
#define BOARD_CREALITY_V24S1 4055 // Creality v2.4.S1 (STM32F103RC / STM32F103RE) v101 as found in the Ender-7
#define BOARD_CREALITY_V24S1_301 4056 // Creality v2.4.S1_301 (STM32F103RC / STM32F103RE) v301 as found in the Ender-3 S1
#define BOARD_CREALITY_V25S1 4057 // Creality v2.5.S1 (STM32F103RE) as found in the CR-10 Smart Pro
#define BOARD_TRIGORILLA_PRO 4058 // Trigorilla Pro (STM32F103ZE)
#define BOARD_FLY_MINI 4059 // FLYmaker FLY MINI (STM32F103RC)
#define BOARD_FLSUN_HISPEED 4060 // FLSUN HiSpeedV1 (STM32F103VE)
#define BOARD_BEAST 4061 // STM32F103RE Libmaple-based controller
#define BOARD_MINGDA_MPX_ARM_MINI 4062 // STM32F103ZE Mingda MD-16
#define BOARD_GTM32_PRO_VD 4063 // STM32F103VE controller
#define BOARD_ZONESTAR_ZM3E2 4064 // Zonestar ZM3E2 (STM32F103RC)
#define BOARD_ZONESTAR_ZM3E4 4065 // Zonestar ZM3E4 V1 (STM32F103VC)
#define BOARD_ZONESTAR_ZM3E4V2 4066 // Zonestar ZM3E4 V2 (STM32F103VC)
#define BOARD_ERYONE_ERY32_MINI 4067 // Eryone Ery32 mini (STM32F103VE)
#define BOARD_PANDA_PI_V29 4068 // Panda Pi V2.9 - Standalone (STM32F103RC)
#define BOARD_BTT_SKR_MINI_MZ_V1_0 4028 // BigTreeTech SKR Mini MZ V1.0 (STM32F103RC)
#define BOARD_BTT_SKR_E3_DIP 4029 // BigTreeTech SKR E3 DIP V1.0 (STM32F103RC / STM32F103RE)
#define BOARD_BTT_SKR_CR6 4030 // BigTreeTech SKR CR6 v1.0 (STM32F103RE)
#define BOARD_JGAURORA_A5S_A1 4031 // JGAurora A5S A1 (STM32F103ZE)
#define BOARD_FYSETC_AIO_II 4032 // FYSETC AIO_II
#define BOARD_FYSETC_CHEETAH 4033 // FYSETC Cheetah
#define BOARD_FYSETC_CHEETAH_V12 4034 // FYSETC Cheetah V1.2
#define BOARD_LONGER3D_LK 4035 // Alfawise U20/U20+/U30 (Longer3D LK1/2) / STM32F103VE
#define BOARD_CCROBOT_MEEB_3DP 4036 // ccrobot-online.com MEEB_3DP (STM32F103RC)
#define BOARD_CHITU3D_V5 4037 // Chitu3D TronXY X5SA V5 Board
#define BOARD_CHITU3D_V6 4038 // Chitu3D TronXY X5SA V6 Board
#define BOARD_CHITU3D_V9 4039 // Chitu3D TronXY X5SA V9 Board
#define BOARD_CREALITY_V4 4040 // Creality v4.x (STM32F103RC / STM32F103RE)
#define BOARD_CREALITY_V422 4041 // Creality v4.2.2 (STM32F103RC / STM32F103RE)
#define BOARD_CREALITY_V423 4042 // Creality v4.2.3 (STM32F103RC / STM32F103RE)
#define BOARD_CREALITY_V427 4043 // Creality v4.2.7 (STM32F103RC / STM32F103RE)
#define BOARD_CREALITY_V4210 4044 // Creality v4.2.10 (STM32F103RC / STM32F103RE) as found in the CR-30
#define BOARD_CREALITY_V431 4045 // Creality v4.3.1 (STM32F103RC / STM32F103RE)
#define BOARD_CREALITY_V431_A 4046 // Creality v4.3.1a (STM32F103RC / STM32F103RE)
#define BOARD_CREALITY_V431_B 4047 // Creality v4.3.1b (STM32F103RC / STM32F103RE)
#define BOARD_CREALITY_V431_C 4048 // Creality v4.3.1c (STM32F103RC / STM32F103RE)
#define BOARD_CREALITY_V431_D 4049 // Creality v4.3.1d (STM32F103RC / STM32F103RE)
#define BOARD_CREALITY_V452 4050 // Creality v4.5.2 (STM32F103RC / STM32F103RE)
#define BOARD_CREALITY_V453 4051 // Creality v4.5.3 (STM32F103RC / STM32F103RE)
#define BOARD_CREALITY_V24S1 4052 // Creality v2.4.S1 (STM32F103RC / STM32F103RE) v101 as found in the Ender-7
#define BOARD_CREALITY_V24S1_301 4053 // Creality v2.4.S1_301 (STM32F103RC / STM32F103RE) v301 as found in the Ender-3 S1
#define BOARD_CREALITY_V25S1 4054 // Creality v2.5.S1 (STM32F103RE) as found in the CR-10 Smart Pro
#define BOARD_TRIGORILLA_PRO 4055 // Trigorilla Pro (STM32F103ZE)
#define BOARD_FLY_MINI 4056 // FLYmaker FLY MINI (STM32F103RC)
#define BOARD_FLSUN_HISPEED 4057 // FLSUN HiSpeedV1 (STM32F103VE)
#define BOARD_BEAST 4058 // STM32F103RE Libmaple-based controller
#define BOARD_MINGDA_MPX_ARM_MINI 4059 // STM32F103ZE Mingda MD-16
#define BOARD_GTM32_PRO_VD 4060 // STM32F103VE controller
#define BOARD_ZONESTAR_ZM3E2 4061 // Zonestar ZM3E2 (STM32F103RC)
#define BOARD_ZONESTAR_ZM3E4 4062 // Zonestar ZM3E4 V1 (STM32F103VC)
#define BOARD_ZONESTAR_ZM3E4V2 4063 // Zonestar ZM3E4 V2 (STM32F103VC)
#define BOARD_ERYONE_ERY32_MINI 4064 // Eryone Ery32 mini (STM32F103VE)
#define BOARD_PANDA_PI_V29 4065 // Panda Pi V2.9 - Standalone (STM32F103RC)
//
// ARM Cortex-M4F
@@ -389,43 +385,40 @@
#define BOARD_RUMBA32_BTT 4204 // RUMBA32 STM32F446VE based controller from BIGTREETECH
#define BOARD_BLACK_STM32F407VE 4205 // BLACK_STM32F407VE
#define BOARD_BLACK_STM32F407ZE 4206 // BLACK_STM32F407ZE
#define BOARD_BTT_SKR_PRO_V1_1 4207 // BigTreeTech SKR Pro v1.1 (STM32F407ZG)
#define BOARD_BTT_SKR_PRO_V1_2 4208 // BigTreeTech SKR Pro v1.2 (STM32F407ZG)
#define BOARD_BTT_BTT002_V1_0 4209 // BigTreeTech BTT002 v1.0 (STM32F407VG)
#define BOARD_BTT_E3_RRF 4210 // BigTreeTech E3 RRF (STM32F407VG)
#define BOARD_BTT_SKR_V2_0_REV_A 4211 // BigTreeTech SKR v2.0 Rev A (STM32F407VG)
#define BOARD_BTT_SKR_V2_0_REV_B 4212 // BigTreeTech SKR v2.0 Rev B (STM32F407VG/STM32F429VG)
#define BOARD_BTT_GTR_V1_0 4213 // BigTreeTech GTR v1.0 (STM32F407IGT)
#define BOARD_BTT_OCTOPUS_V1_0 4214 // BigTreeTech Octopus v1.0 (STM32F446ZE)
#define BOARD_BTT_OCTOPUS_V1_1 4215 // BigTreeTech Octopus v1.1 (STM32F446ZE)
#define BOARD_BTT_OCTOPUS_PRO_V1_0 4216 // BigTreeTech Octopus Pro v1.0 (STM32F446ZE / STM32F429ZG)
#define BOARD_LERDGE_K 4217 // Lerdge K (STM32F407ZG)
#define BOARD_LERDGE_S 4218 // Lerdge S (STM32F407VE)
#define BOARD_LERDGE_X 4219 // Lerdge X (STM32F407VE)
#define BOARD_VAKE403D 4220 // VAkE 403D (STM32F446VE)
#define BOARD_FYSETC_S6 4221 // FYSETC S6 (STM32F446VE)
#define BOARD_FYSETC_S6_V2_0 4222 // FYSETC S6 v2.0 (STM32F446VE)
#define BOARD_FYSETC_SPIDER 4223 // FYSETC Spider (STM32F446VE)
#define BOARD_FLYF407ZG 4224 // FLYmaker FLYF407ZG (STM32F407ZG)
#define BOARD_MKS_ROBIN2 4225 // MKS_ROBIN2 (STM32F407ZE)
#define BOARD_MKS_ROBIN_PRO_V2 4226 // MKS Robin Pro V2 (STM32F407VE)
#define BOARD_MKS_ROBIN_NANO_V3 4227 // MKS Robin Nano V3 (STM32F407VG)
#define BOARD_MKS_ROBIN_NANO_V3_1 4228 // MKS Robin Nano V3.1 (STM32F407VE)
#define BOARD_MKS_MONSTER8_V1 4229 // MKS Monster8 V1 (STM32F407VE)
#define BOARD_MKS_MONSTER8_V2 4230 // MKS Monster8 V2 (STM32F407VE)
#define BOARD_STEVAL_3DP001V1 4207 // STEVAL-3DP001V1 3D PRINTER BOARD
#define BOARD_BTT_SKR_PRO_V1_1 4208 // BigTreeTech SKR Pro v1.1 (STM32F407ZG)
#define BOARD_BTT_SKR_PRO_V1_2 4209 // BigTreeTech SKR Pro v1.2 (STM32F407ZG)
#define BOARD_BTT_BTT002_V1_0 4210 // BigTreeTech BTT002 v1.0 (STM32F407VG)
#define BOARD_BTT_E3_RRF 4211 // BigTreeTech E3 RRF (STM32F407VG)
#define BOARD_BTT_SKR_V2_0_REV_A 4212 // BigTreeTech SKR v2.0 Rev A (STM32F407VG)
#define BOARD_BTT_SKR_V2_0_REV_B 4213 // BigTreeTech SKR v2.0 Rev B (STM32F407VG/STM32F429VG)
#define BOARD_BTT_GTR_V1_0 4214 // BigTreeTech GTR v1.0 (STM32F407IGT)
#define BOARD_BTT_OCTOPUS_V1_0 4215 // BigTreeTech Octopus v1.0 (STM32F446ZE)
#define BOARD_BTT_OCTOPUS_V1_1 4216 // BigTreeTech Octopus v1.1 (STM32F446ZE)
#define BOARD_BTT_OCTOPUS_PRO_V1_0 4217 // BigTreeTech Octopus Pro v1.0 (STM32F446ZE/STM32F429ZG)
#define BOARD_LERDGE_K 4218 // Lerdge K (STM32F407ZG)
#define BOARD_LERDGE_S 4219 // Lerdge S (STM32F407VE)
#define BOARD_LERDGE_X 4220 // Lerdge X (STM32F407VE)
#define BOARD_VAKE403D 4221 // VAkE 403D (STM32F446VE)
#define BOARD_FYSETC_S6 4222 // FYSETC S6 (STM32F446VE)
#define BOARD_FYSETC_S6_V2_0 4223 // FYSETC S6 v2.0 (STM32F446VE)
#define BOARD_FYSETC_SPIDER 4224 // FYSETC Spider (STM32F446VE)
#define BOARD_FLYF407ZG 4225 // FLYmaker FLYF407ZG (STM32F407ZG)
#define BOARD_MKS_ROBIN2 4226 // MKS_ROBIN2 (STM32F407ZE)
#define BOARD_MKS_ROBIN_PRO_V2 4227 // MKS Robin Pro V2 (STM32F407VE)
#define BOARD_MKS_ROBIN_NANO_V3 4228 // MKS Robin Nano V3 (STM32F407VG)
#define BOARD_MKS_ROBIN_NANO_V3_1 4229 // MKS Robin Nano V3.1 (STM32F407VE)
#define BOARD_MKS_MONSTER8 4230 // MKS Monster8 (STM32F407VG)
#define BOARD_ANET_ET4 4231 // ANET ET4 V1.x (STM32F407VG)
#define BOARD_ANET_ET4P 4232 // ANET ET4P V1.x (STM32F407VG)
#define BOARD_FYSETC_CHEETAH_V20 4233 // FYSETC Cheetah V2.0 (STM32F401RC)
#define BOARD_TH3D_EZBOARD_V2 4234 // TH3D EZBoard v2.0 (STM32F405RG)
#define BOARD_OPULO_LUMEN_REV3 4235 // Opulo Lumen PnP Controller REV3 (STM32F407VE / STM32F407VG)
#define BOARD_FYSETC_CHEETAH_V20 4233 // FYSETC Cheetah V2.0
#define BOARD_TH3D_EZBOARD_V2 4234 // TH3D EZBoard v2.0
#define BOARD_INDEX_REV03 4235 // Index PnP Controller REV03 (STM32F407VE/VG)
#define BOARD_MKS_ROBIN_NANO_V1_3_F4 4236 // MKS Robin Nano V1.3 and MKS Robin Nano-S V1.3 (STM32F407VE)
#define BOARD_MKS_EAGLE 4237 // MKS Eagle (STM32F407VE)
#define BOARD_ARTILLERY_RUBY 4238 // Artillery Ruby (STM32F401RC)
#define BOARD_FYSETC_SPIDER_V2_2 4239 // FYSETC Spider V2.2 (STM32F446VE)
#define BOARD_CREALITY_V24S1_301F4 4240 // Creality v2.4.S1_301F4 (STM32F401RC) as found in the Ender-3 S1 F4
#define BOARD_OPULO_LUMEN_REV4 4241 // Opulo Lumen PnP Controller REV4 (STM32F407VE / STM32F407VG)
#define BOARD_FYSETC_SPIDER_KING407 4242 // FYSETC Spider King407 (STM32F407ZG)
#define BOARD_MKS_SKIPR_V1 4243 // MKS SKIPR v1.0 all-in-one board (STM32F407VE)
//
// ARM Cortex M7
@@ -435,10 +428,7 @@
#define BOARD_TEENSY41 5001 // Teensy 4.1
#define BOARD_T41U5XBB 5002 // T41U5XBB Teensy 4.1 breakout board
#define BOARD_NUCLEO_F767ZI 5003 // ST NUCLEO-F767ZI Dev Board
#define BOARD_BTT_SKR_SE_BX_V2 5004 // BigTreeTech SKR SE BX V2.0 (STM32H743II)
#define BOARD_BTT_SKR_SE_BX_V3 5005 // BigTreeTech SKR SE BX V3.0 (STM32H743II)
#define BOARD_BTT_SKR_V3_0 5006 // BigTreeTech SKR V3.0 (STM32H743VG)
#define BOARD_BTT_SKR_V3_0_EZ 5007 // BigTreeTech SKR V3.0 EZ (STM32H743VG)
#define BOARD_BTT_SKR_SE_BX 5004 // BigTreeTech SKR SE BX (STM32H743II)
//
// Espressif ESP32 WiFi
+17
View File
@@ -30,6 +30,10 @@
#define _A5984 0x5984
#define _DRV8825 0x8825
#define _LV8729 0x8729
#define _L6470 0x6470
#define _L6474 0x6474
#define _L6480 0x6480
#define _POWERSTEP01 0xF00D
#define _TB6560 0x6560
#define _TB6600 0x6600
#define _TMC2100 0x2100
@@ -189,3 +193,16 @@
#if HAS_DRIVER(TMC26X)
#define HAS_TMC26X 1
#endif
//
// L64XX Stepper Drivers
//
#if HAS_DRIVER(L6470) || HAS_DRIVER(L6474) || HAS_DRIVER(L6480) || HAS_DRIVER(POWERSTEP01)
#define HAS_L64XX 1
#endif
#if HAS_L64XX && !HAS_DRIVER(L6474)
#define HAS_L64XX_NOT_L6474 1
#endif
#define AXIS_IS_L64XX(A) (AXIS_DRIVER_TYPE_##A(L6470) || AXIS_DRIVER_TYPE_##A(L6474) || AXIS_DRIVER_TYPE_##A(L6480) || AXIS_DRIVER_TYPE_##A(POWERSTEP01))
+4 -1
View File
@@ -174,7 +174,6 @@
#define STR_SD_VOL_INIT_FAIL "volume.init failed"
#define STR_SD_OPENROOT_FAIL "openRoot failed"
#define STR_SD_CARD_OK "SD card ok"
#define STR_SD_CARD_RELEASED "SD card released"
#define STR_SD_WORKDIR_FAIL "workDir open failed"
#define STR_SD_OPEN_FILE_FAIL "open failed, File: "
#define STR_SD_FILE_OPENED "File opened: "
@@ -228,6 +227,10 @@
#define STR_PID_DEBUG " PID_DEBUG "
#define STR_PID_DEBUG_INPUT ": Input "
#define STR_PID_DEBUG_OUTPUT " Output "
#define STR_PID_DEBUG_PTERM " pTerm "
#define STR_PID_DEBUG_ITERM " iTerm "
#define STR_PID_DEBUG_DTERM " dTerm "
#define STR_PID_DEBUG_CTERM " cTerm "
#define STR_INVALID_EXTRUDER_NUM " - Invalid extruder number !"
#define STR_MPC_AUTOTUNE "MPC Autotune"
#define STR_MPC_AUTOTUNE_START " start for " STR_E
+4 -15
View File
@@ -21,7 +21,7 @@
*/
#pragma once
#ifndef __has_include
#if !defined(__has_include)
#define __has_include(...) 1
#endif
@@ -338,12 +338,6 @@
#define GANG_N_1(N,K) _GANG_N(N,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K)
// Macros for initializing arrays
#define LIST_26(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,...) A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z
#define LIST_25(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,...) A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y
#define LIST_24(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,...) A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X
#define LIST_23(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,...) A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W
#define LIST_22(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,...) A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V
#define LIST_21(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,...) A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U
#define LIST_20(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,...) A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T
#define LIST_19(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,...) A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S
#define LIST_18(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,...) A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R
@@ -650,8 +644,8 @@
#define IS_PROBE(V...) SECOND(V, 0) // Get the second item passed, or 0
#define PROBE() ~, 1 // Second item will be 1 if this is passed
#define _NOT_0 PROBE()
#define NOT(x) IS_PROBE(_CAT(_NOT_, x)) // NOT('0') gets '1'. Anything else gets '0'.
#define _BOOL(x) NOT(NOT(x)) // _BOOL('0') gets '0'. Anything else gets '1'.
#define NOT(x) IS_PROBE(_CAT(_NOT_, x)) // NOT('0') gets '1'. Anything else gets '0'.
#define _BOOL(x) NOT(NOT(x)) // NOT('0') gets '0'. Anything else gets '1'.
#define IF_ELSE(TF) _IF_ELSE(_BOOL(TF))
#define _IF_ELSE(TF) _CAT(_IF_, TF)
@@ -665,6 +659,7 @@
#define HAS_ARGS(V...) _BOOL(FIRST(_END_OF_ARGUMENTS_ V)())
#define _END_OF_ARGUMENTS_() 0
// Simple Inline IF Macros, friendly to use in other macro definitions
#define IF(O, A, B) ((O) ? (A) : (B))
#define IF_0(O, A) IF(O, A, 0)
@@ -736,9 +731,3 @@
#define __MAPLIST() _MAPLIST
#define MAPLIST(OP,V...) EVAL(_MAPLIST(OP,V))
// Temperature Sensor Config
#define TEMP_SENSOR(N) TEMP_SENSOR_##N
#define _HAS_E_TEMP(N) || TEMP_SENSOR(N)
#define HAS_E_TEMP_SENSOR (0 REPEAT(EXTRUDERS, _HAS_E_TEMP))
#define TEMP_SENSOR_IS_MAX_TC(T) (TEMP_SENSOR(T) == -5 || TEMP_SENSOR(T) == -3 || TEMP_SENSOR(T) == -2)
+3 -3
View File
@@ -35,7 +35,7 @@ PGMSTR(SP_P_STR, " P"); PGMSTR(SP_T_STR, " T"); PGMSTR(NUL_STR, "");
#define _N_STR(N) PGMSTR(N##_STR, STR_##N);
#define _N_LBL(N) PGMSTR(N##_LBL, STR_##N ":");
#define _SP_N_STR(N) PGMSTR(SP_##N##_STR, " " STR_##N);
#define _SP_N_STR(N) PGMSTR(SP_##N##_STR, STR_##N ":");
#define _SP_N_LBL(N) PGMSTR(SP_##N##_LBL, " " STR_##N ":");
MAP(_N_STR, LOGICAL_AXIS_NAMES); MAP(_SP_N_STR, LOGICAL_AXIS_NAMES);
MAP(_N_LBL, LOGICAL_AXIS_NAMES); MAP(_SP_N_LBL, LOGICAL_AXIS_NAMES);
@@ -72,8 +72,8 @@ void serial_print_P(PGM_P str) {
while (const char c = pgm_read_byte(str++)) SERIAL_CHAR(c);
}
void serial_echo_start() { serial_print(F("echo:")); }
void serial_error_start() { serial_print(F("Error:")); }
void serial_echo_start() { static PGMSTR(echomagic, "echo:"); serial_print_P(echomagic); }
void serial_error_start() { static PGMSTR(errormagic, "Error:"); serial_print_P(errormagic); }
void serial_spaces(uint8_t count) { count *= (PROPORTIONAL_FONT_RATIO); while (count--) SERIAL_CHAR(' '); }
+113 -117
View File
@@ -113,8 +113,8 @@ struct Flags<1> {
void set(const int) { b = true; }
void clear(const int) { b = false; }
bool test(const int) const { return b; }
bool& operator[](const int) { return b; }
bool operator[](const int) const { return b; }
bool operator[](const int) { return b; }
bool operator[](const int) const { return b; }
int size() const { return sizeof(b); }
};
@@ -226,8 +226,8 @@ typedef const_float_t const_celsius_float_t;
// Helpers
#define _RECIP(N) ((N) ? 1.0f / static_cast<float>(N) : 0.0f)
#define _ABS(N) ((N) < 0 ? -(N) : (N))
#define _LS(N) (N = (T)(uint32_t(N) << p))
#define _RS(N) (N = (T)(uint32_t(N) >> p))
#define _LS(N) (N = (T)(uint32_t(N) << v))
#define _RS(N) (N = (T)(uint32_t(N) >> v))
#define FI FORCE_INLINE
// Forward declarations
@@ -347,10 +347,6 @@ struct XYval {
FI operator T* () { return pos; }
// If any element is true then it's true
FI operator bool() { return x || y; }
// Smallest element
FI T small() const { return _MIN(x, y); }
// Largest element
FI T large() const { return _MAX(x, y); }
// Explicit copy and copies with conversion
FI XYval<T> copy() const { return *this; }
@@ -409,18 +405,18 @@ struct XYval {
FI XYval<T> operator* (const XYZEval<T> &rs) { XYval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; return ls; }
FI XYval<T> operator/ (const XYZEval<T> &rs) const { XYval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; return ls; }
FI XYval<T> operator/ (const XYZEval<T> &rs) { XYval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; return ls; }
FI XYval<T> operator* (const float &p) const { XYval<T> ls = *this; ls.x *= p; ls.y *= p; return ls; }
FI XYval<T> operator* (const float &p) { XYval<T> ls = *this; ls.x *= p; ls.y *= p; return ls; }
FI XYval<T> operator* (const int &p) const { XYval<T> ls = *this; ls.x *= p; ls.y *= p; return ls; }
FI XYval<T> operator* (const int &p) { XYval<T> ls = *this; ls.x *= p; ls.y *= p; return ls; }
FI XYval<T> operator/ (const float &p) const { XYval<T> ls = *this; ls.x /= p; ls.y /= p; return ls; }
FI XYval<T> operator/ (const float &p) { XYval<T> ls = *this; ls.x /= p; ls.y /= p; return ls; }
FI XYval<T> operator/ (const int &p) const { XYval<T> ls = *this; ls.x /= p; ls.y /= p; return ls; }
FI XYval<T> operator/ (const int &p) { XYval<T> ls = *this; ls.x /= p; ls.y /= p; return ls; }
FI XYval<T> operator>>(const int &p) const { XYval<T> ls = *this; _RS(ls.x); _RS(ls.y); return ls; }
FI XYval<T> operator>>(const int &p) { XYval<T> ls = *this; _RS(ls.x); _RS(ls.y); return ls; }
FI XYval<T> operator<<(const int &p) const { XYval<T> ls = *this; _LS(ls.x); _LS(ls.y); return ls; }
FI XYval<T> operator<<(const int &p) { XYval<T> ls = *this; _LS(ls.x); _LS(ls.y); return ls; }
FI XYval<T> operator* (const float &v) const { XYval<T> ls = *this; ls.x *= v; ls.y *= v; return ls; }
FI XYval<T> operator* (const float &v) { XYval<T> ls = *this; ls.x *= v; ls.y *= v; return ls; }
FI XYval<T> operator* (const int &v) const { XYval<T> ls = *this; ls.x *= v; ls.y *= v; return ls; }
FI XYval<T> operator* (const int &v) { XYval<T> ls = *this; ls.x *= v; ls.y *= v; return ls; }
FI XYval<T> operator/ (const float &v) const { XYval<T> ls = *this; ls.x /= v; ls.y /= v; return ls; }
FI XYval<T> operator/ (const float &v) { XYval<T> ls = *this; ls.x /= v; ls.y /= v; return ls; }
FI XYval<T> operator/ (const int &v) const { XYval<T> ls = *this; ls.x /= v; ls.y /= v; return ls; }
FI XYval<T> operator/ (const int &v) { XYval<T> ls = *this; ls.x /= v; ls.y /= v; return ls; }
FI XYval<T> operator>>(const int &v) const { XYval<T> ls = *this; _RS(ls.x); _RS(ls.y); return ls; }
FI XYval<T> operator>>(const int &v) { XYval<T> ls = *this; _RS(ls.x); _RS(ls.y); return ls; }
FI XYval<T> operator<<(const int &v) const { XYval<T> ls = *this; _LS(ls.x); _LS(ls.y); return ls; }
FI XYval<T> operator<<(const int &v) { XYval<T> ls = *this; _LS(ls.x); _LS(ls.y); return ls; }
FI const XYval<T> operator-() const { XYval<T> o = *this; o.x = -x; o.y = -y; return o; }
FI XYval<T> operator-() { XYval<T> o = *this; o.x = -x; o.y = -y; return o; }
@@ -434,15 +430,21 @@ struct XYval {
FI XYval<T>& operator+=(const XYZEval<T> &rs) { x += rs.x; y += rs.y; return *this; }
FI XYval<T>& operator-=(const XYZEval<T> &rs) { x -= rs.x; y -= rs.y; return *this; }
FI XYval<T>& operator*=(const XYZEval<T> &rs) { x *= rs.x; y *= rs.y; return *this; }
FI XYval<T>& operator*=(const float &p) { x *= p; y *= p; return *this; }
FI XYval<T>& operator*=(const int &p) { x *= p; y *= p; return *this; }
FI XYval<T>& operator>>=(const int &p) { _RS(x); _RS(y); return *this; }
FI XYval<T>& operator<<=(const int &p) { _LS(x); _LS(y); return *this; }
FI XYval<T>& operator*=(const float &v) { x *= v; y *= v; return *this; }
FI XYval<T>& operator*=(const int &v) { x *= v; y *= v; return *this; }
FI XYval<T>& operator>>=(const int &v) { _RS(x); _RS(y); return *this; }
FI XYval<T>& operator<<=(const int &v) { _LS(x); _LS(y); return *this; }
// Exact comparisons. For floats a "NEAR" operation may be better.
FI bool operator==(const XYval<T> &rs) { return x == rs.x && y == rs.y; }
FI bool operator==(const XYZval<T> &rs) { return x == rs.x && y == rs.y; }
FI bool operator==(const XYZEval<T> &rs) { return x == rs.x && y == rs.y; }
FI bool operator==(const XYval<T> &rs) const { return x == rs.x && y == rs.y; }
FI bool operator==(const XYZval<T> &rs) const { return x == rs.x && y == rs.y; }
FI bool operator==(const XYZEval<T> &rs) const { return x == rs.x && y == rs.y; }
FI bool operator!=(const XYval<T> &rs) { return !operator==(rs); }
FI bool operator!=(const XYZval<T> &rs) { return !operator==(rs); }
FI bool operator!=(const XYZEval<T> &rs) { return !operator==(rs); }
FI bool operator!=(const XYval<T> &rs) const { return !operator==(rs); }
FI bool operator!=(const XYZval<T> &rs) const { return !operator==(rs); }
FI bool operator!=(const XYZEval<T> &rs) const { return !operator==(rs); }
@@ -492,10 +494,10 @@ struct XYZval {
FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; }
#endif
#if HAS_V_AXIS
FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pu) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; u = pu; }
FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pm) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; u = pu; }
#endif
#if HAS_W_AXIS
FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pu, const T pv) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; u = pu; v = pv; }
FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pm, const T po) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; u = pu; v = pv; }
#endif
// Length reduced to one dimension
@@ -504,10 +506,6 @@ struct XYZval {
FI operator T* () { return pos; }
// If any element is true then it's true
FI operator bool() { return NUM_AXIS_GANG(x, || y, || z, || i, || j, || k, || u, || v, || w); }
// Smallest element
FI T small() const { return _MIN(NUM_AXIS_LIST(x, y, z, i, j, k, u, v, w)); }
// Largest element
FI T large() const { return _MAX(NUM_AXIS_LIST(x, y, z, i, j, k, u, v, w)); }
// Explicit copy and copies with conversion
FI XYZval<T> copy() const { XYZval<T> o = *this; return o; }
@@ -567,18 +565,18 @@ struct XYZval {
FI XYZval<T> operator* (const XYZEval<T> &rs) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k, ls.u *= rs.u, ls.v *= rs.v, ls.w *= rs.w); return ls; }
FI XYZval<T> operator/ (const XYZEval<T> &rs) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k, ls.u /= rs.u, ls.v /= rs.v, ls.w /= rs.w); return ls; }
FI XYZval<T> operator/ (const XYZEval<T> &rs) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k, ls.u /= rs.u, ls.v /= rs.v, ls.w /= rs.w); return ls; }
FI XYZval<T> operator* (const float &p) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x *= p, ls.y *= p, ls.z *= p, ls.i *= p, ls.j *= p, ls.k *= p, ls.u *= p, ls.v *= p, ls.w *= p ); return ls; }
FI XYZval<T> operator* (const float &p) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x *= p, ls.y *= p, ls.z *= p, ls.i *= p, ls.j *= p, ls.k *= p, ls.u *= p, ls.v *= p, ls.w *= p ); return ls; }
FI XYZval<T> operator* (const int &p) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x *= p, ls.y *= p, ls.z *= p, ls.i *= p, ls.j *= p, ls.k *= p, ls.u *= p, ls.v *= p, ls.w *= p ); return ls; }
FI XYZval<T> operator* (const int &p) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x *= p, ls.y *= p, ls.z *= p, ls.i *= p, ls.j *= p, ls.k *= p, ls.u *= p, ls.v *= p, ls.w *= p ); return ls; }
FI XYZval<T> operator/ (const float &p) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x /= p, ls.y /= p, ls.z /= p, ls.i /= p, ls.j /= p, ls.k /= p, ls.u /= p, ls.v /= p, ls.w /= p ); return ls; }
FI XYZval<T> operator/ (const float &p) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x /= p, ls.y /= p, ls.z /= p, ls.i /= p, ls.j /= p, ls.k /= p, ls.u /= p, ls.v /= p, ls.w /= p ); return ls; }
FI XYZval<T> operator/ (const int &p) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x /= p, ls.y /= p, ls.z /= p, ls.i /= p, ls.j /= p, ls.k /= p, ls.u /= p, ls.v /= p, ls.w /= p ); return ls; }
FI XYZval<T> operator/ (const int &p) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x /= p, ls.y /= p, ls.z /= p, ls.i /= p, ls.j /= p, ls.k /= p, ls.u /= p, ls.v /= p, ls.w /= p ); return ls; }
FI XYZval<T> operator>>(const int &p) const { XYZval<T> ls = *this; NUM_AXIS_CODE(_RS(ls.x), _RS(ls.y), _RS(ls.z), _RS(ls.i), _RS(ls.j), _RS(ls.k), _RS(ls.u), _RS(ls.v), _RS(ls.w) ); return ls; }
FI XYZval<T> operator>>(const int &p) { XYZval<T> ls = *this; NUM_AXIS_CODE(_RS(ls.x), _RS(ls.y), _RS(ls.z), _RS(ls.i), _RS(ls.j), _RS(ls.k), _RS(ls.u), _RS(ls.v), _RS(ls.w) ); return ls; }
FI XYZval<T> operator<<(const int &p) const { XYZval<T> ls = *this; NUM_AXIS_CODE(_LS(ls.x), _LS(ls.y), _LS(ls.z), _LS(ls.i), _LS(ls.j), _LS(ls.k), _LS(ls.u), _LS(ls.v), _LS(ls.w) ); return ls; }
FI XYZval<T> operator<<(const int &p) { XYZval<T> ls = *this; NUM_AXIS_CODE(_LS(ls.x), _LS(ls.y), _LS(ls.z), _LS(ls.i), _LS(ls.j), _LS(ls.k), _LS(ls.u), _LS(ls.v), _LS(ls.w) ); return ls; }
FI XYZval<T> operator* (const float &v) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v, ls.u *= v, ls.v *= v, ls.w *= v ); return ls; }
FI XYZval<T> operator* (const float &v) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v, ls.u *= v, ls.v *= v, ls.w *= v ); return ls; }
FI XYZval<T> operator* (const int &v) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v, ls.u *= v, ls.v *= v, ls.w *= v ); return ls; }
FI XYZval<T> operator* (const int &v) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v, ls.u *= v, ls.v *= v, ls.w *= v ); return ls; }
FI XYZval<T> operator/ (const float &v) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v, ls.u /= v, ls.v /= v, ls.w /= v ); return ls; }
FI XYZval<T> operator/ (const float &v) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v, ls.u /= v, ls.v /= v, ls.w /= v ); return ls; }
FI XYZval<T> operator/ (const int &v) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v, ls.u /= v, ls.v /= v, ls.w /= v ); return ls; }
FI XYZval<T> operator/ (const int &v) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v, ls.u /= v, ls.v /= v, ls.w /= v ); return ls; }
FI XYZval<T> operator>>(const int &v) const { XYZval<T> ls = *this; NUM_AXIS_CODE(_RS(ls.x), _RS(ls.y), _RS(ls.z), _RS(ls.i), _RS(ls.j), _RS(ls.k), _RS(ls.u), _RS(ls.v), _RS(ls.w) ); return ls; }
FI XYZval<T> operator>>(const int &v) { XYZval<T> ls = *this; NUM_AXIS_CODE(_RS(ls.x), _RS(ls.y), _RS(ls.z), _RS(ls.i), _RS(ls.j), _RS(ls.k), _RS(ls.u), _RS(ls.v), _RS(ls.w) ); return ls; }
FI XYZval<T> operator<<(const int &v) const { XYZval<T> ls = *this; NUM_AXIS_CODE(_LS(ls.x), _LS(ls.y), _LS(ls.z), _LS(ls.i), _LS(ls.j), _LS(ls.k), _LS(ls.u), _LS(ls.v), _LS(ls.w) ); return ls; }
FI XYZval<T> operator<<(const int &v) { XYZval<T> ls = *this; NUM_AXIS_CODE(_LS(ls.x), _LS(ls.y), _LS(ls.z), _LS(ls.i), _LS(ls.j), _LS(ls.k), _LS(ls.u), _LS(ls.v), _LS(ls.w) ); return ls; }
FI const XYZval<T> operator-() const { XYZval<T> o = *this; NUM_AXIS_CODE(o.x = -x, o.y = -y, o.z = -z, o.i = -i, o.j = -j, o.k = -k, o.u = -u, o.v = -v, o.w = -w); return o; }
FI XYZval<T> operator-() { XYZval<T> o = *this; NUM_AXIS_CODE(o.x = -x, o.y = -y, o.z = -z, o.i = -i, o.j = -j, o.k = -k, o.u = -u, o.v = -v, o.w = -w); return o; }
@@ -595,13 +593,15 @@ struct XYZval {
FI XYZval<T>& operator-=(const XYZEval<T> &rs) { NUM_AXIS_CODE(x -= rs.x, y -= rs.y, z -= rs.z, i -= rs.i, j -= rs.j, k -= rs.k, u -= rs.u, v -= rs.v, w -= rs.w); return *this; }
FI XYZval<T>& operator*=(const XYZEval<T> &rs) { NUM_AXIS_CODE(x *= rs.x, y *= rs.y, z *= rs.z, i *= rs.i, j *= rs.j, k *= rs.k, u *= rs.u, v *= rs.v, w *= rs.w); return *this; }
FI XYZval<T>& operator/=(const XYZEval<T> &rs) { NUM_AXIS_CODE(x /= rs.x, y /= rs.y, z /= rs.z, i /= rs.i, j /= rs.j, k /= rs.k, u /= rs.u, v /= rs.v, w /= rs.w); return *this; }
FI XYZval<T>& operator*=(const float &p) { NUM_AXIS_CODE(x *= p, y *= p, z *= p, i *= p, j *= p, k *= p, u *= p, v *= p, w *= p); return *this; }
FI XYZval<T>& operator*=(const int &p) { NUM_AXIS_CODE(x *= p, y *= p, z *= p, i *= p, j *= p, k *= p, u *= p, v *= p, w *= p); return *this; }
FI XYZval<T>& operator>>=(const int &p) { NUM_AXIS_CODE(_RS(x), _RS(y), _RS(z), _RS(i), _RS(j), _RS(k), _RS(u), _RS(v), _RS(w)); return *this; }
FI XYZval<T>& operator<<=(const int &p) { NUM_AXIS_CODE(_LS(x), _LS(y), _LS(z), _LS(i), _LS(j), _LS(k), _LS(u), _LS(v), _LS(w)); return *this; }
FI XYZval<T>& operator*=(const float &v) { NUM_AXIS_CODE(x *= v, y *= v, z *= v, i *= v, j *= v, k *= v, u *= v, v *= v, w *= v); return *this; }
FI XYZval<T>& operator*=(const int &v) { NUM_AXIS_CODE(x *= v, y *= v, z *= v, i *= v, j *= v, k *= v, u *= v, v *= v, w *= v); return *this; }
FI XYZval<T>& operator>>=(const int &v) { NUM_AXIS_CODE(_RS(x), _RS(y), _RS(z), _RS(i), _RS(j), _RS(k), _RS(u), _RS(v), _RS(w)); return *this; }
FI XYZval<T>& operator<<=(const int &v) { NUM_AXIS_CODE(_LS(x), _LS(y), _LS(z), _LS(i), _LS(j), _LS(k), _LS(u), _LS(v), _LS(w)); return *this; }
// Exact comparisons. For floats a "NEAR" operation may be better.
FI bool operator==(const XYZEval<T> &rs) { return true NUM_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k, && u == rs.u, && v == rs.v, && w == rs.w); }
FI bool operator==(const XYZEval<T> &rs) const { return true NUM_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k, && u == rs.u, && v == rs.v, && w == rs.w); }
FI bool operator!=(const XYZEval<T> &rs) { return !operator==(rs); }
FI bool operator!=(const XYZEval<T> &rs) const { return !operator==(rs); }
};
@@ -634,10 +634,10 @@ struct XYZEval {
FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; }
#endif
#if HAS_V_AXIS
FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pu) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; u = pu; }
FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pm) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; u = pu; }
#endif
#if HAS_W_AXIS
FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pu, const T pv) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; u = pu; v = pv; }
FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pm, const T po) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; u = pm; v = pv; }
#endif
// Setters taking struct types and arrays
@@ -654,15 +654,11 @@ struct XYZEval {
#endif
// Length reduced to one dimension
FI T magnitude() const { return (T)sqrtf(LOGICAL_AXIS_GANG(+ e*e, + x*x, + y*y, + z*z, + i*i, + j*j, + k*k, + u*u, + v*v, + w*w)); }
FI T magnitude() const { return (T)sqrtf(LOGICAL_AXIS_GANG(+ e*e, + x*x, + y*y, + z*z, + i*i, + j*j, + k*k, + u*u, + v*v, + w*w)); }
// Pointer to the data as a simple array
FI operator T* () { return pos; }
FI operator T* () { return pos; }
// If any element is true then it's true
FI operator bool() { return 0 LOGICAL_AXIS_GANG(|| e, || x, || y, || z, || i, || j, || k, || u, || v, || w); }
// Smallest element
FI T small() const { return _MIN(LOGICAL_AXIS_LIST(e, x, y, z, i, j, k, u, v, w)); }
// Largest element
FI T large() const { return _MAX(LOGICAL_AXIS_LIST(e, x, y, z, i, j, k, u, v, w)); }
FI operator bool() { return 0 LOGICAL_AXIS_GANG(|| e, || x, || y, || z, || i, || j, || k, || u, || v, || w); }
// Explicit copy and copies with conversion
FI XYZEval<T> copy() const { XYZEval<T> v = *this; return v; }
@@ -688,76 +684,76 @@ struct XYZEval {
FI operator const XYZval<T>&() const { return *(const XYZval<T>*)this; }
// Accessor via an AxisEnum (or any integer) [index]
FI T& operator[](const int n) { return pos[n]; }
FI const T& operator[](const int n) const { return pos[n]; }
FI T& operator[](const int n) { return pos[n]; }
FI const T& operator[](const int n) const { return pos[n]; }
// Assignment operator overrides do the expected thing
FI XYZEval<T>& operator= (const T v) { set(LOGICAL_AXIS_LIST_1(v)); return *this; }
FI XYZEval<T>& operator= (const XYval<T> &rs) { set(rs.x, rs.y); return *this; }
FI XYZEval<T>& operator= (const XYZval<T> &rs) { set(NUM_AXIS_ELEM(rs)); return *this; }
FI XYZEval<T>& operator= (const T v) { set(LIST_N_1(NUM_AXES, v)); return *this; }
FI XYZEval<T>& operator= (const XYval<T> &rs) { set(rs.x, rs.y); return *this; }
FI XYZEval<T>& operator= (const XYZval<T> &rs) { set(NUM_AXIS_ELEM(rs)); return *this; }
// Override other operators to get intuitive behaviors
FI XYZEval<T> operator+ (const XYval<T> &rs) const { XYZEval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; return ls; }
FI XYZEval<T> operator+ (const XYval<T> &rs) { XYZEval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; return ls; }
FI XYZEval<T> operator- (const XYval<T> &rs) const { XYZEval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; return ls; }
FI XYZEval<T> operator- (const XYval<T> &rs) { XYZEval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; return ls; }
FI XYZEval<T> operator* (const XYval<T> &rs) const { XYZEval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; return ls; }
FI XYZEval<T> operator* (const XYval<T> &rs) { XYZEval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; return ls; }
FI XYZEval<T> operator/ (const XYval<T> &rs) const { XYZEval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; return ls; }
FI XYZEval<T> operator/ (const XYval<T> &rs) { XYZEval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; return ls; }
FI XYZEval<T> operator+ (const XYZval<T> &rs) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k, ls.u += rs.u, ls.v += rs.v, ls.w += rs.w); return ls; }
FI XYZEval<T> operator+ (const XYZval<T> &rs) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k, ls.u += rs.u, ls.v += rs.v, ls.w += rs.w); return ls; }
FI XYZEval<T> operator- (const XYZval<T> &rs) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k, ls.u -= rs.u, ls.v -= rs.v, ls.w -= rs.w); return ls; }
FI XYZEval<T> operator- (const XYZval<T> &rs) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k, ls.u -= rs.u, ls.v -= rs.v, ls.w -= rs.w); return ls; }
FI XYZEval<T> operator* (const XYZval<T> &rs) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k, ls.u *= rs.u, ls.v *= rs.v, ls.w *= rs.w); return ls; }
FI XYZEval<T> operator* (const XYZval<T> &rs) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k, ls.u *= rs.u, ls.v *= rs.v, ls.w *= rs.w); return ls; }
FI XYZEval<T> operator/ (const XYZval<T> &rs) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k, ls.u /= rs.u, ls.v /= rs.v, ls.w /= rs.w); return ls; }
FI XYZEval<T> operator/ (const XYZval<T> &rs) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k, ls.u /= rs.u, ls.v /= rs.v, ls.w /= rs.w); return ls; }
FI XYZEval<T> operator+ (const XYZEval<T> &rs) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e += rs.e, ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k, ls.u += rs.u, ls.v += rs.v, ls.w += rs.w); return ls; }
FI XYZEval<T> operator+ (const XYZEval<T> &rs) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e += rs.e, ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k, ls.u += rs.u, ls.v += rs.v, ls.w += rs.w); return ls; }
FI XYZEval<T> operator- (const XYZEval<T> &rs) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e -= rs.e, ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k, ls.u -= rs.u, ls.v -= rs.v, ls.w -= rs.w); return ls; }
FI XYZEval<T> operator- (const XYZEval<T> &rs) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e -= rs.e, ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k, ls.u -= rs.u, ls.v -= rs.v, ls.w -= rs.w); return ls; }
FI XYZEval<T> operator* (const XYZEval<T> &rs) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e *= rs.e, ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k, ls.u *= rs.u, ls.v *= rs.v, ls.w *= rs.w); return ls; }
FI XYZEval<T> operator* (const XYZEval<T> &rs) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e *= rs.e, ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k, ls.u *= rs.u, ls.v *= rs.v, ls.w *= rs.w); return ls; }
FI XYZEval<T> operator/ (const XYZEval<T> &rs) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e /= rs.e, ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k, ls.u /= rs.u, ls.v /= rs.v, ls.w /= rs.w); return ls; }
FI XYZEval<T> operator/ (const XYZEval<T> &rs) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e /= rs.e, ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k, ls.u /= rs.u, ls.v /= rs.v, ls.w /= rs.w); return ls; }
FI XYZEval<T> operator* (const float &p) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e *= p, ls.x *= p, ls.y *= p, ls.z *= p, ls.i *= p, ls.j *= p, ls.k *= p, ls.u *= p, ls.v *= p, ls.w *= p ); return ls; }
FI XYZEval<T> operator* (const float &p) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e *= p, ls.x *= p, ls.y *= p, ls.z *= p, ls.i *= p, ls.j *= p, ls.k *= p, ls.u *= p, ls.v *= p, ls.w *= p ); return ls; }
FI XYZEval<T> operator* (const int &p) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e *= p, ls.x *= p, ls.y *= p, ls.z *= p, ls.i *= p, ls.j *= p, ls.k *= p, ls.u *= p, ls.v *= p, ls.w *= p ); return ls; }
FI XYZEval<T> operator* (const int &p) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e *= p, ls.x *= p, ls.y *= p, ls.z *= p, ls.i *= p, ls.j *= p, ls.k *= p, ls.u *= p, ls.v *= p, ls.w *= p ); return ls; }
FI XYZEval<T> operator/ (const float &p) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e /= p, ls.x /= p, ls.y /= p, ls.z /= p, ls.i /= p, ls.j /= p, ls.k /= p, ls.u /= p, ls.v /= p, ls.w /= p ); return ls; }
FI XYZEval<T> operator/ (const float &p) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e /= p, ls.x /= p, ls.y /= p, ls.z /= p, ls.i /= p, ls.j /= p, ls.k /= p, ls.u /= p, ls.v /= p, ls.w /= p ); return ls; }
FI XYZEval<T> operator/ (const int &p) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e /= p, ls.x /= p, ls.y /= p, ls.z /= p, ls.i /= p, ls.j /= p, ls.k /= p, ls.u /= p, ls.v /= p, ls.w /= p ); return ls; }
FI XYZEval<T> operator/ (const int &p) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e /= p, ls.x /= p, ls.y /= p, ls.z /= p, ls.i /= p, ls.j /= p, ls.k /= p, ls.u /= p, ls.v /= p, ls.w /= p ); return ls; }
FI XYZEval<T> operator>>(const int &p) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(_RS(ls.e), _RS(ls.x), _RS(ls.y), _RS(ls.z), _RS(ls.i), _RS(ls.j), _RS(ls.k), _RS(ls.u), _RS(ls.v), _RS(ls.w) ); return ls; }
FI XYZEval<T> operator>>(const int &p) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(_RS(ls.e), _RS(ls.x), _RS(ls.y), _RS(ls.z), _RS(ls.i), _RS(ls.j), _RS(ls.k), _RS(ls.u), _RS(ls.v), _RS(ls.w) ); return ls; }
FI XYZEval<T> operator<<(const int &p) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(_LS(ls.e), _LS(ls.x), _LS(ls.y), _LS(ls.z), _LS(ls.i), _LS(ls.j), _LS(ls.k), _LS(ls.u), _LS(ls.v), _LS(ls.w) ); return ls; }
FI XYZEval<T> operator<<(const int &p) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(_LS(ls.e), _LS(ls.x), _LS(ls.y), _LS(ls.z), _LS(ls.i), _LS(ls.j), _LS(ls.k), _LS(ls.u), _LS(ls.v), _LS(ls.w) ); return ls; }
FI const XYZEval<T> operator-() const { return LOGICAL_AXIS_ARRAY(-e, -x, -y, -z, -i, -j, -k, -u, -v, -w); }
FI XYZEval<T> operator-() { return LOGICAL_AXIS_ARRAY(-e, -x, -y, -z, -i, -j, -k, -u, -v, -w); }
FI XYZEval<T> operator+ (const XYval<T> &rs) const { XYZEval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; return ls; }
FI XYZEval<T> operator+ (const XYval<T> &rs) { XYZEval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; return ls; }
FI XYZEval<T> operator- (const XYval<T> &rs) const { XYZEval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; return ls; }
FI XYZEval<T> operator- (const XYval<T> &rs) { XYZEval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; return ls; }
FI XYZEval<T> operator* (const XYval<T> &rs) const { XYZEval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; return ls; }
FI XYZEval<T> operator* (const XYval<T> &rs) { XYZEval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; return ls; }
FI XYZEval<T> operator/ (const XYval<T> &rs) const { XYZEval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; return ls; }
FI XYZEval<T> operator/ (const XYval<T> &rs) { XYZEval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; return ls; }
FI XYZEval<T> operator+ (const XYZval<T> &rs) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k, ls.u += rs.u, ls.v += rs.v, ls.w += rs.w); return ls; }
FI XYZEval<T> operator+ (const XYZval<T> &rs) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k, ls.u += rs.u, ls.v += rs.v, ls.w += rs.w); return ls; }
FI XYZEval<T> operator- (const XYZval<T> &rs) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k, ls.u -= rs.u, ls.v -= rs.v, ls.w -= rs.w); return ls; }
FI XYZEval<T> operator- (const XYZval<T> &rs) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k, ls.u -= rs.u, ls.v -= rs.v, ls.w -= rs.w); return ls; }
FI XYZEval<T> operator* (const XYZval<T> &rs) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k, ls.u *= rs.u, ls.v *= rs.v, ls.w *= rs.w); return ls; }
FI XYZEval<T> operator* (const XYZval<T> &rs) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k, ls.u *= rs.u, ls.v *= rs.v, ls.w *= rs.w); return ls; }
FI XYZEval<T> operator/ (const XYZval<T> &rs) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k, ls.u /= rs.u, ls.v /= rs.v, ls.w /= rs.w); return ls; }
FI XYZEval<T> operator/ (const XYZval<T> &rs) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k, ls.u /= rs.u, ls.v /= rs.v, ls.w /= rs.w); return ls; }
FI XYZEval<T> operator+ (const XYZEval<T> &rs) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e += rs.e, ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k, ls.u += rs.u, ls.v += rs.v, ls.w += rs.w); return ls; }
FI XYZEval<T> operator+ (const XYZEval<T> &rs) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e += rs.e, ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k, ls.u += rs.u, ls.v += rs.v, ls.w += rs.w); return ls; }
FI XYZEval<T> operator- (const XYZEval<T> &rs) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e -= rs.e, ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k, ls.u -= rs.u, ls.v -= rs.v, ls.w -= rs.w); return ls; }
FI XYZEval<T> operator- (const XYZEval<T> &rs) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e -= rs.e, ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k, ls.u -= rs.u, ls.v -= rs.v, ls.w -= rs.w); return ls; }
FI XYZEval<T> operator* (const XYZEval<T> &rs) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e *= rs.e, ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k, ls.u *= rs.u, ls.v *= rs.v, ls.w *= rs.w); return ls; }
FI XYZEval<T> operator* (const XYZEval<T> &rs) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e *= rs.e, ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k, ls.u *= rs.u, ls.v *= rs.v, ls.w *= rs.w); return ls; }
FI XYZEval<T> operator/ (const XYZEval<T> &rs) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e /= rs.e, ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k, ls.u /= rs.u, ls.v /= rs.v, ls.w /= rs.w); return ls; }
FI XYZEval<T> operator/ (const XYZEval<T> &rs) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e /= rs.e, ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k, ls.u /= rs.u, ls.v /= rs.v, ls.w /= rs.w); return ls; }
FI XYZEval<T> operator* (const float &v) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e *= v, ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v, ls.u *= v, ls.v *= v, ls.w *= v ); return ls; }
FI XYZEval<T> operator* (const float &v) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e *= v, ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v, ls.u *= v, ls.v *= v, ls.w *= v ); return ls; }
FI XYZEval<T> operator* (const int &v) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e *= v, ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v, ls.u *= v, ls.v *= v, ls.w *= v ); return ls; }
FI XYZEval<T> operator* (const int &v) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e *= v, ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v, ls.u *= v, ls.v *= v, ls.w *= v ); return ls; }
FI XYZEval<T> operator/ (const float &v) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e /= v, ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v, ls.u /= v, ls.v /= v, ls.w /= v ); return ls; }
FI XYZEval<T> operator/ (const float &v) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e /= v, ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v, ls.u /= v, ls.v /= v, ls.w /= v ); return ls; }
FI XYZEval<T> operator/ (const int &v) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e /= v, ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v, ls.u /= v, ls.v /= v, ls.w /= v ); return ls; }
FI XYZEval<T> operator/ (const int &v) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e /= v, ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v, ls.u /= v, ls.v /= v, ls.w /= v ); return ls; }
FI XYZEval<T> operator>>(const int &v) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(_RS(ls.e), _RS(ls.x), _RS(ls.y), _RS(ls.z), _RS(ls.i), _RS(ls.j), _RS(ls.k), _RS(ls.u), _RS(ls.v), _RS(ls.w) ); return ls; }
FI XYZEval<T> operator>>(const int &v) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(_RS(ls.e), _RS(ls.x), _RS(ls.y), _RS(ls.z), _RS(ls.i), _RS(ls.j), _RS(ls.k), _RS(ls.u), _RS(ls.v), _RS(ls.w) ); return ls; }
FI XYZEval<T> operator<<(const int &v) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(_LS(ls.e), _LS(ls.x), _LS(ls.y), _LS(ls.z), _LS(ls.i), _LS(ls.j), _LS(ls.k), _LS(ls.u), _LS(ls.v), _LS(ls.w) ); return ls; }
FI XYZEval<T> operator<<(const int &v) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(_LS(ls.e), _LS(ls.x), _LS(ls.y), _LS(ls.z), _LS(ls.i), _LS(ls.j), _LS(ls.k), _LS(ls.u), _LS(ls.v), _LS(ls.w) ); return ls; }
FI const XYZEval<T> operator-() const { return LOGICAL_AXIS_ARRAY(-e, -x, -y, -z, -i, -j, -k, -u, -v, -w); }
FI XYZEval<T> operator-() { return LOGICAL_AXIS_ARRAY(-e, -x, -y, -z, -i, -j, -k, -u, -v, -w); }
// Modifier operators
FI XYZEval<T>& operator+=(const XYval<T> &rs) { x += rs.x; y += rs.y; return *this; }
FI XYZEval<T>& operator-=(const XYval<T> &rs) { x -= rs.x; y -= rs.y; return *this; }
FI XYZEval<T>& operator*=(const XYval<T> &rs) { x *= rs.x; y *= rs.y; return *this; }
FI XYZEval<T>& operator/=(const XYval<T> &rs) { x /= rs.x; y /= rs.y; return *this; }
FI XYZEval<T>& operator+=(const XYZval<T> &rs) { NUM_AXIS_CODE(x += rs.x, y += rs.y, z += rs.z, i += rs.i, j += rs.j, k += rs.k, u += rs.u, v += rs.v, w += rs.w); return *this; }
FI XYZEval<T>& operator-=(const XYZval<T> &rs) { NUM_AXIS_CODE(x -= rs.x, y -= rs.y, z -= rs.z, i -= rs.i, j -= rs.j, k -= rs.k, u -= rs.u, v -= rs.v, w -= rs.w); return *this; }
FI XYZEval<T>& operator*=(const XYZval<T> &rs) { NUM_AXIS_CODE(x *= rs.x, y *= rs.y, z *= rs.z, i *= rs.i, j *= rs.j, k *= rs.k, u *= rs.u, v *= rs.v, w *= rs.w); return *this; }
FI XYZEval<T>& operator/=(const XYZval<T> &rs) { NUM_AXIS_CODE(x /= rs.x, y /= rs.y, z /= rs.z, i /= rs.i, j /= rs.j, k /= rs.k, u /= rs.u, v /= rs.v, w /= rs.w); return *this; }
FI XYZEval<T>& operator+=(const XYZEval<T> &rs) { LOGICAL_AXIS_CODE(e += rs.e, x += rs.x, y += rs.y, z += rs.z, i += rs.i, j += rs.j, k += rs.k, u += rs.u, v += rs.v, w += rs.w); return *this; }
FI XYZEval<T>& operator-=(const XYZEval<T> &rs) { LOGICAL_AXIS_CODE(e -= rs.e, x -= rs.x, y -= rs.y, z -= rs.z, i -= rs.i, j -= rs.j, k -= rs.k, u -= rs.u, v -= rs.v, w -= rs.w); return *this; }
FI XYZEval<T>& operator*=(const XYZEval<T> &rs) { LOGICAL_AXIS_CODE(e *= rs.e, x *= rs.x, y *= rs.y, z *= rs.z, i *= rs.i, j *= rs.j, k *= rs.k, u *= rs.u, v *= rs.v, w *= rs.w); return *this; }
FI XYZEval<T>& operator/=(const XYZEval<T> &rs) { LOGICAL_AXIS_CODE(e /= rs.e, x /= rs.x, y /= rs.y, z /= rs.z, i /= rs.i, j /= rs.j, k /= rs.k, u /= rs.u, v /= rs.v, w /= rs.w); return *this; }
FI XYZEval<T>& operator*=(const T &p) { LOGICAL_AXIS_CODE(e *= p, x *= p, y *= p, z *= p, i *= p, j *= p, k *= p, u *= p, v *= p, w *= p); return *this; }
FI XYZEval<T>& operator>>=(const int &p) { LOGICAL_AXIS_CODE(_RS(e), _RS(x), _RS(y), _RS(z), _RS(i), _RS(j), _RS(k), _RS(u), _RS(v), _RS(w)); return *this; }
FI XYZEval<T>& operator<<=(const int &p) { LOGICAL_AXIS_CODE(_LS(e), _LS(x), _LS(y), _LS(z), _LS(i), _LS(j), _LS(k), _LS(u), _LS(v), _LS(w)); return *this; }
FI XYZEval<T>& operator+=(const XYval<T> &rs) { x += rs.x; y += rs.y; return *this; }
FI XYZEval<T>& operator-=(const XYval<T> &rs) { x -= rs.x; y -= rs.y; return *this; }
FI XYZEval<T>& operator*=(const XYval<T> &rs) { x *= rs.x; y *= rs.y; return *this; }
FI XYZEval<T>& operator/=(const XYval<T> &rs) { x /= rs.x; y /= rs.y; return *this; }
FI XYZEval<T>& operator+=(const XYZval<T> &rs) { NUM_AXIS_CODE(x += rs.x, y += rs.y, z += rs.z, i += rs.i, j += rs.j, k += rs.k, u += rs.u, v += rs.v, w += rs.w); return *this; }
FI XYZEval<T>& operator-=(const XYZval<T> &rs) { NUM_AXIS_CODE(x -= rs.x, y -= rs.y, z -= rs.z, i -= rs.i, j -= rs.j, k -= rs.k, u -= rs.u, v -= rs.v, w -= rs.w); return *this; }
FI XYZEval<T>& operator*=(const XYZval<T> &rs) { NUM_AXIS_CODE(x *= rs.x, y *= rs.y, z *= rs.z, i *= rs.i, j *= rs.j, k *= rs.k, u *= rs.u, v *= rs.v, w *= rs.w); return *this; }
FI XYZEval<T>& operator/=(const XYZval<T> &rs) { NUM_AXIS_CODE(x /= rs.x, y /= rs.y, z /= rs.z, i /= rs.i, j /= rs.j, k /= rs.k, u /= rs.u, v /= rs.v, w /= rs.w); return *this; }
FI XYZEval<T>& operator+=(const XYZEval<T> &rs) { LOGICAL_AXIS_CODE(e += rs.e, x += rs.x, y += rs.y, z += rs.z, i += rs.i, j += rs.j, k += rs.k, u += rs.u, v += rs.v, w += rs.w); return *this; }
FI XYZEval<T>& operator-=(const XYZEval<T> &rs) { LOGICAL_AXIS_CODE(e -= rs.e, x -= rs.x, y -= rs.y, z -= rs.z, i -= rs.i, j -= rs.j, k -= rs.k, u -= rs.u, v -= rs.v, w -= rs.w); return *this; }
FI XYZEval<T>& operator*=(const XYZEval<T> &rs) { LOGICAL_AXIS_CODE(e *= rs.e, x *= rs.x, y *= rs.y, z *= rs.z, i *= rs.i, j *= rs.j, k *= rs.k, u *= rs.u, v *= rs.v, w *= rs.w); return *this; }
FI XYZEval<T>& operator/=(const XYZEval<T> &rs) { LOGICAL_AXIS_CODE(e /= rs.e, x /= rs.x, y /= rs.y, z /= rs.z, i /= rs.i, j /= rs.j, k /= rs.k, u /= rs.u, v /= rs.v, w /= rs.w); return *this; }
FI XYZEval<T>& operator*=(const T &v) { LOGICAL_AXIS_CODE(e *= v, x *= v, y *= v, z *= v, i *= v, j *= v, k *= v, u *= v, v *= v, w *= v); return *this; }
FI XYZEval<T>& operator>>=(const int &v) { LOGICAL_AXIS_CODE(_RS(e), _RS(x), _RS(y), _RS(z), _RS(i), _RS(j), _RS(k), _RS(u), _RS(v), _RS(w)); return *this; }
FI XYZEval<T>& operator<<=(const int &v) { LOGICAL_AXIS_CODE(_LS(e), _LS(x), _LS(y), _LS(z), _LS(i), _LS(j), _LS(k), _LS(u), _LS(v), _LS(w)); return *this; }
// Exact comparisons. For floats a "NEAR" operation may be better.
FI bool operator==(const XYZval<T> &rs) const { return true NUM_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k, && u == rs.u, && v == rs.v, && w == rs.w); }
FI bool operator==(const XYZEval<T> &rs) const { return true LOGICAL_AXIS_GANG(&& e == rs.e, && x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k, && u == rs.u, && v == rs.v, && w == rs.w); }
FI bool operator!=(const XYZval<T> &rs) const { return !operator==(rs); }
FI bool operator!=(const XYZEval<T> &rs) const { return !operator==(rs); }
FI bool operator==(const XYZval<T> &rs) { return true NUM_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k, && u == rs.u, && v == rs.v, && w == rs.w); }
FI bool operator==(const XYZval<T> &rs) const { return true NUM_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k, && u == rs.u, && v == rs.v, && w == rs.w); }
FI bool operator!=(const XYZval<T> &rs) { return !operator==(rs); }
FI bool operator!=(const XYZval<T> &rs) const { return !operator==(rs); }
};
#undef _RECIP
+7 -9
View File
@@ -29,10 +29,10 @@ void safe_delay(millis_t ms) {
while (ms > 50) {
ms -= 50;
delay(50);
thermalManager.task();
thermalManager.manage_heater();
}
delay(ms);
thermalManager.task(); // This keeps us safe if too many small safe_delay() calls are made
thermalManager.manage_heater(); // This keeps us safe if too many small safe_delay() calls are made
}
// A delay to provide brittle hosts time to receive bytes
@@ -51,7 +51,7 @@ void safe_delay(millis_t ms) {
#include "../module/probe.h"
#include "../module/motion.h"
#include "../module/planner.h"
#include "../module/stepper.h"
#include "../libs/numtostr.h"
#include "../feature/bedlevel/bedlevel.h"
@@ -70,7 +70,6 @@ void safe_delay(millis_t ms) {
TERN_(NOZZLE_AS_PROBE, "NOZZLE_AS_PROBE")
TERN_(FIX_MOUNTED_PROBE, "FIX_MOUNTED_PROBE")
TERN_(HAS_Z_SERVO_PROBE, TERN(BLTOUCH, "BLTOUCH", "SERVO PROBE"))
TERN_(BD_SENSOR, "BD_SENSOR")
TERN_(TOUCH_MI_PROBE, "TOUCH_MI_PROBE")
TERN_(Z_PROBE_SLED, "Z_PROBE_SLED")
TERN_(Z_PROBE_ALLEN_KEY, "Z_PROBE_ALLEN_KEY")
@@ -133,10 +132,11 @@ void safe_delay(millis_t ms) {
#else
#if ENABLED(AUTO_BED_LEVELING_UBL)
SERIAL_ECHOPGM("UBL Adjustment Z");
const float rz = bedlevel.get_z_correction(current_position);
#elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
SERIAL_ECHOPGM("ABL Adjustment Z");
const float rz = bedlevel.get_z_correction(current_position);
#endif
const float rz = bedlevel.get_z_correction(current_position);
SERIAL_ECHO(ftostr43sign(rz, '+'));
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
if (planner.z_fade_height) {
@@ -156,13 +156,11 @@ void safe_delay(millis_t ms) {
SERIAL_ECHOPGM("Mesh Bed Leveling");
if (planner.leveling_active) {
SERIAL_ECHOLNPGM(" (enabled)");
const float z_offset = bedlevel.get_z_offset(),
z_correction = bedlevel.get_z_correction(current_position);
SERIAL_ECHOPGM("MBL Adjustment Z", ftostr43sign(z_offset + z_correction, '+'));
SERIAL_ECHOPGM("MBL Adjustment Z", ftostr43sign(bedlevel.get_z(current_position), '+'));
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
if (planner.z_fade_height) {
SERIAL_ECHOPGM(" (", ftostr43sign(
z_offset + z_correction * planner.fade_scaling_factor_for_z(current_position.z), '+'
bedlevel.get_z(current_position, planner.fade_scaling_factor_for_z(current_position.z)), '+'
));
SERIAL_CHAR(')');
}
-5
View File
@@ -59,11 +59,6 @@ void safe_delay(millis_t ms); // Delay ensuring that temperatures are
#define log_machine_info() NOOP
#endif
/**
* A restorer instance remembers a variable's value before setting a
* new value, then restores the old value when it goes out of scope.
* Put operator= on your type to get extended behavior on value change.
*/
template<typename T>
class restorer {
T& ref_;
-12
View File
@@ -54,18 +54,6 @@ void Babystep::add_mm(const AxisEnum axis, const_float_t mm) {
add_steps(axis, mm * planner.settings.axis_steps_per_mm[axis]);
}
#if ENABLED(BD_SENSOR)
void Babystep::set_mm(const AxisEnum axis, const_float_t mm) {
//if (DISABLED(BABYSTEP_WITHOUT_HOMING) && axes_should_home(_BV(axis))) return;
const int16_t distance = mm * planner.settings.axis_steps_per_mm[axis];
accum = distance; // Count up babysteps for the UI
steps[BS_AXIS_IND(axis)] = distance;
TERN_(BABYSTEP_DISPLAY_TOTAL, axis_total[BS_TOTAL_IND(axis)] = distance);
TERN_(BABYSTEP_ALWAYS_AVAILABLE, gcode.reset_stepper_timeout());
TERN_(INTEGRATED_BABYSTEPPING, if (has_steps()) stepper.initiateBabystepping());
}
#endif
void Babystep::add_steps(const AxisEnum axis, const int16_t distance) {
if (DISABLED(BABYSTEP_WITHOUT_HOMING) && axes_should_home(_BV(axis))) return;
-4
View File
@@ -63,10 +63,6 @@ public:
static void add_steps(const AxisEnum axis, const int16_t distance);
static void add_mm(const AxisEnum axis, const_float_t mm);
#if ENABLED(BD_SENSOR)
static void set_mm(const AxisEnum axis, const_float_t mm);
#endif
static bool has_steps() {
return steps[BS_AXIS_IND(X_AXIS)] || steps[BS_AXIS_IND(Y_AXIS)] || steps[BS_AXIS_IND(Z_AXIS)];
}
-196
View File
@@ -1,196 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2022 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 "../../../inc/MarlinConfig.h"
#if ENABLED(BD_SENSOR)
#include "../../../MarlinCore.h"
#include "../../../gcode/gcode.h"
#include "../../../module/settings.h"
#include "../../../module/motion.h"
#include "../../../module/planner.h"
#include "../../../module/stepper.h"
#include "../../../module/probe.h"
#include "../../../module/temperature.h"
#include "../../../module/endstops.h"
#include "../../babystep.h"
// I2C software Master library for segment bed heating and bed distance sensor
#include <Panda_segmentBed_I2C.h>
#include "bdl.h"
BDS_Leveling bdl;
//#define DEBUG_OUT_BD
// M102 S-5 Read raw Calibrate data
// M102 S-6 Start Calibrate
// M102 S4 Set the adjustable Z height value (e.g., 'M102 S4' means it will do adjusting while the Z height <= 0.4mm , disable with 'M102 S0'.)
// M102 S-1 Read sensor information
#define MAX_BD_HEIGHT 4.0f
#define CMD_START_READ_CALIBRATE_DATA 1017
#define CMD_END_READ_CALIBRATE_DATA 1018
#define CMD_START_CALIBRATE 1019
#define CMD_END_CALIBRATE 1021
#define CMD_READ_VERSION 1016
I2C_SegmentBED BD_I2C_SENSOR;
#define BD_SENSOR_I2C_ADDR 0x3C
int8_t BDS_Leveling::config_state;
uint8_t BDS_Leveling::homing;
void BDS_Leveling::echo_name() { SERIAL_ECHOPGM("Bed Distance Leveling"); }
void BDS_Leveling::init(uint8_t _sda, uint8_t _scl, uint16_t delay_s) {
int ret = BD_I2C_SENSOR.i2c_init(_sda, _scl, BD_SENSOR_I2C_ADDR, delay_s);
if (ret != 1) SERIAL_ECHOLNPGM("BD_I2C_SENSOR Init Fail return code:", ret);
config_state = 0;
}
float BDS_Leveling::read() {
const uint16_t tmp = BD_I2C_SENSOR.BD_i2c_read();
float BD_z = NAN;
if (BD_I2C_SENSOR.BD_Check_OddEven(tmp) && (tmp & 0x3FF) < 1020)
BD_z = (tmp & 0x3FF) / 100.0f;
return BD_z;
}
void BDS_Leveling::process() {
//if (config_state == 0) return;
static millis_t next_check_ms = 0; // starting at T=0
static float z_pose = 0.0f;
const millis_t ms = millis();
if (ELAPSED(ms, next_check_ms)) { // timed out (or first run)
next_check_ms = ms + (config_state < 0 ? 1000 : 100); // check at 1Hz or 10Hz
unsigned short tmp = 0;
const float cur_z = planner.get_axis_position_mm(Z_AXIS); //current_position.z
static float old_cur_z = cur_z,
old_buf_z = current_position.z;
tmp = BD_I2C_SENSOR.BD_i2c_read();
if (BD_I2C_SENSOR.BD_Check_OddEven(tmp) && (tmp & 0x3FF) < 1020) {
const float z_sensor = (tmp & 0x3FF) / 100.0f;
if (cur_z < 0) config_state = 0;
//float abs_z = current_position.z > cur_z ? (current_position.z - cur_z) : (cur_z - current_position.z);
#if ENABLED(BABYSTEPPING)
if (cur_z < config_state * 0.1f
&& config_state > 0
&& old_cur_z == cur_z
&& old_buf_z == current_position.z
&& z_sensor < (MAX_BD_HEIGHT)
) {
babystep.set_mm(Z_AXIS, cur_z - z_sensor);
#if ENABLED(DEBUG_OUT_BD)
SERIAL_ECHOLNPGM("BD:", z_sensor, ", Z:", cur_z, "|", current_position.z);
#endif
}
else {
babystep.set_mm(Z_AXIS, 0); //if (old_cur_z <= cur_z) Z_DIR_WRITE(!INVERT_Z_DIR);
stepper.set_directions();
}
#endif
old_cur_z = cur_z;
old_buf_z = current_position.z;
endstops.bdp_state_update(z_sensor <= 0.01f);
//endstops.update();
}
else
stepper.set_directions();
#if ENABLED(DEBUG_OUT_BD)
SERIAL_ECHOLNPGM("BD:", tmp & 0x3FF, ", Z:", cur_z, "|", current_position.z);
if (BD_I2C_SENSOR.BD_Check_OddEven(tmp) == 0) SERIAL_ECHOLNPGM("errorCRC");
#endif
if ((tmp & 0x3FF) > 1020) {
BD_I2C_SENSOR.BD_i2c_stop();
safe_delay(10);
}
// read raw calibrate data
if (config_state == -5) {
BD_I2C_SENSOR.BD_i2c_write(CMD_START_READ_CALIBRATE_DATA);
safe_delay(1000);
for (int i = 0; i < MAX_BD_HEIGHT * 10; i++) {
tmp = BD_I2C_SENSOR.BD_i2c_read();
SERIAL_ECHOLNPGM("Calibrate data:", i, ",", tmp & 0x3FF, ", check:", BD_I2C_SENSOR.BD_Check_OddEven(tmp));
safe_delay(500);
}
config_state = 0;
BD_I2C_SENSOR.BD_i2c_write(CMD_END_READ_CALIBRATE_DATA);
safe_delay(500);
}
else if (config_state <= -6) { // Start Calibrate
safe_delay(100);
if (config_state == -6) {
//BD_I2C_SENSOR.BD_i2c_write(1019); // begin calibrate
//delay(1000);
gcode.stepper_inactive_time = SEC_TO_MS(60 * 5);
gcode.process_subcommands_now(F("M17 Z"));
gcode.process_subcommands_now(F("G1 Z0.0"));
z_pose = 0;
safe_delay(1000);
BD_I2C_SENSOR.BD_i2c_write(CMD_START_CALIBRATE); // Begin calibrate
SERIAL_ECHOLNPGM("Begin calibrate");
safe_delay(2000);
config_state = -7;
}
else if (planner.get_axis_position_mm(Z_AXIS) < 10.0f) {
if (z_pose >= MAX_BD_HEIGHT) {
BD_I2C_SENSOR.BD_i2c_write(CMD_END_CALIBRATE); // End calibrate
SERIAL_ECHOLNPGM("End calibrate data");
z_pose = 7;
config_state = 0;
safe_delay(1000);
}
else {
float tmp_k = 0;
char tmp_1[30];
sprintf_P(tmp_1, PSTR("G1 Z%d.%d"), int(z_pose), int(int(z_pose * 10) % 10));
gcode.process_subcommands_now(tmp_1);
SERIAL_ECHO(tmp_1);
SERIAL_ECHOLNPGM(" ,Z:", current_position.z);
while (tmp_k < (z_pose - 0.1f)) {
tmp_k = planner.get_axis_position_mm(Z_AXIS);
safe_delay(1);
}
safe_delay(800);
tmp = (z_pose + 0.0001f) * 10;
BD_I2C_SENSOR.BD_i2c_write(tmp);
SERIAL_ECHOLNPGM("w:", tmp, ",Zpose:", z_pose);
z_pose += 0.1001f;
//queue.enqueue_now_P(PSTR("G90"));
}
}
}
}
}
#endif // BD_SENSOR
-36
View File
@@ -1,36 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2022 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 <stdint.h>
class BDS_Leveling {
public:
static int8_t config_state;
static uint8_t homing;
static void echo_name();
static void init(uint8_t _sda, uint8_t _scl, uint16_t delay_s);
static void process();
static float read();
};
extern BDS_Leveling bdl;
+4 -4
View File
@@ -75,9 +75,9 @@ void set_bed_leveling_enabled(const bool enable/*=true*/) {
planner.synchronize();
// Get the corrected leveled / unleveled position
planner.apply_modifiers(current_position, true); // Physical position with all modifiers
planner.leveling_active ^= true; // Toggle leveling between apply and unapply
planner.unapply_modifiers(current_position, true); // Logical position with modifiers removed
planner.apply_modifiers(current_position); // Physical position with all modifiers
planner.leveling_active ^= true; // Toggle leveling between apply and unapply
planner.unapply_modifiers(current_position); // Logical position with modifiers removed
sync_plan_position();
_report_leveling();
@@ -154,7 +154,7 @@ void reset_bed_level() {
#endif
LOOP_L_N(x, sx) {
SERIAL_CHAR(' ');
const float offset = values[x * sy + y];
const float offset = values[x * sx + y];
if (!isnan(offset)) {
if (offset >= 0) SERIAL_CHAR('+');
SERIAL_ECHO_F(offset, int(precision));
+2 -1
View File
@@ -31,6 +31,7 @@
#include "../../../libs/hex_print.h"
#include "../../../module/settings.h"
#include "../../../lcd/marlinui.h"
#include "../../../module/stepper.h"
#include "../../../module/planner.h"
#include "../../../module/motion.h"
#include "../../../module/probe.h"
@@ -407,7 +408,7 @@ void unified_bed_leveling::G29() {
z_values[x][x2] += 9.999f; // We want the altered line several mesh points thick
#if ENABLED(EXTENSIBLE_UI)
ExtUI::onMeshUpdate(x, x, z_values[x][x]);
ExtUI::onMeshUpdate(x, x2, z_values[x][x2]);
ExtUI::onMeshUpdate(x, (x2), z_values[x][x2]);
#endif
}
break;
+17 -29
View File
@@ -26,6 +26,7 @@
#include "../bedlevel.h"
#include "../../../module/planner.h"
#include "../../../module/stepper.h"
#include "../../../module/motion.h"
#if ENABLED(DELTA)
@@ -35,18 +36,8 @@
#include "../../../MarlinCore.h"
#include <math.h>
//#define DEBUG_UBL_MOTION
#define DEBUG_OUT ENABLED(DEBUG_UBL_MOTION)
#include "../../../core/debug_out.h"
#if !UBL_SEGMENTED
// TODO: The first and last parts of a move might result in very short segment(s)
// after getting split on the cell boundary, so moves like that should not
// get split. This will be most common for moves that start/end near the
// corners of cells. To fix the issue, simply check if the start/end of the line
// is very close to a cell boundary in advance and don't split the line there.
void unified_bed_leveling::line_to_destination_cartesian(const_feedRate_t scaled_fr_mm_s, const uint8_t extruder) {
/**
* Much of the nozzle movement will be within the same cell. So we will do as little computation
@@ -185,9 +176,7 @@
dest.z += z0;
planner.buffer_segment(dest, scaled_fr_mm_s, extruder);
}
else
DEBUG_ECHOLNPGM("[ubl] skip Y segment");
} //else printf("FIRST MOVE PRUNED ");
}
// At the final destination? Usually not, but when on a Y Mesh Line it's completed.
@@ -236,9 +225,7 @@
dest.z += z0;
if (!planner.buffer_segment(dest, scaled_fr_mm_s, extruder)) break;
}
else
DEBUG_ECHOLNPGM("[ubl] skip Y segment");
} //else printf("FIRST MOVE PRUNED ");
}
if (xy_pos_t(current_position) != xy_pos_t(end))
@@ -373,12 +360,11 @@
#endif
NOLESS(segments, 1U); // Must have at least one segment
const float inv_segments = 1.0f / segments; // Reciprocal to save calculation
const float inv_segments = 1.0f / segments, // Reciprocal to save calculation
segment_xyz_mm = SQRT(cart_xy_mm_2 + sq(total.z)) * inv_segments; // Length of each segment
// Add hints to help optimize the move
PlannerHints hints(SQRT(cart_xy_mm_2 + sq(total.z)) * inv_segments); // Length of each segment
#if ENABLED(SCARA_FEEDRATE_SCALING)
hints.inv_duration = scaled_fr_mm_s / hints.millimeters;
const float inv_duration = scaled_fr_mm_s / segment_xyz_mm;
#endif
xyze_float_t diff = total * inv_segments;
@@ -392,9 +378,13 @@
if (!planner.leveling_active || !planner.leveling_active_at_z(destination.z)) {
while (--segments) {
raw += diff;
planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, hints);
planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, segment_xyz_mm
OPTARG(SCARA_FEEDRATE_SCALING, inv_duration)
);
}
planner.buffer_line(destination, scaled_fr_mm_s, active_extruder, hints);
planner.buffer_line(destination, scaled_fr_mm_s, active_extruder, segment_xyz_mm
OPTARG(SCARA_FEEDRATE_SCALING, inv_duration)
);
return false; // Did not set current from destination
}
@@ -423,12 +413,10 @@
LIMIT(icell.x, 0, GRID_MAX_CELLS_X);
LIMIT(icell.y, 0, GRID_MAX_CELLS_Y);
const int8_t ncellx = _MIN(icell.x+1, GRID_MAX_CELLS_X),
ncelly = _MIN(icell.y+1, GRID_MAX_CELLS_Y);
float z_x0y0 = z_values[icell.x][icell.y], // z at lower left corner
z_x1y0 = z_values[ncellx ][icell.y], // z at upper left corner
z_x0y1 = z_values[icell.x][ncelly ], // z at lower right corner
z_x1y1 = z_values[ncellx ][ncelly ]; // z at upper right corner
float z_x0y0 = z_values[icell.x ][icell.y ], // z at lower left corner
z_x1y0 = z_values[icell.x+1][icell.y ], // z at upper left corner
z_x0y1 = z_values[icell.x ][icell.y+1], // z at lower right corner
z_x1y1 = z_values[icell.x+1][icell.y+1]; // z at upper right corner
if (isnan(z_x0y0)) z_x0y0 = 0; // ideally activating planner.leveling_active (G29 A)
if (isnan(z_x1y0)) z_x1y0 = 0; // should refuse if any invalid mesh points
@@ -465,7 +453,7 @@
TERN_(ENABLE_LEVELING_FADE_HEIGHT, * fade_scaling_factor); // apply fade factor to interpolated height
const float oldz = raw.z; raw.z += z_cxcy;
planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, hints);
planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, segment_xyz_mm OPTARG(SCARA_FEEDRATE_SCALING, inv_duration) );
raw.z = oldz;
if (segments == 0) // done with last segment
+1 -1
View File
@@ -45,7 +45,7 @@ void stop();
bool BLTouch::command(const BLTCommand cmd, const millis_t &ms) {
if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("BLTouch Command :", cmd);
servo[Z_PROBE_SERVO_NR].move(cmd);
MOVE_SERVO(Z_PROBE_SERVO_NR, cmd);
safe_delay(_MAX(ms, (uint32_t)BLTOUCH_DELAY)); // BLTOUCH_DELAY is also the *minimum* delay
return triggered();
}
@@ -11,6 +11,7 @@
#include "dac_dac084s085.h"
#include "../../MarlinCore.h"
#include "../../module/stepper.h"
#include "../../HAL/shared/Delay.h"
dac084s085::dac084s085() { }
+1
View File
@@ -29,6 +29,7 @@
#if HAS_MOTOR_CURRENT_DAC
#include "stepper_dac.h"
#include "../../MarlinCore.h" // for SP_X_LBL...
bool dac_present = false;
constexpr xyze_uint8_t dac_order = DAC_STEPPER_ORDER;
+9 -10
View File
@@ -143,16 +143,14 @@ namespace DirectStepping {
// special case for 8-bit, check if rolled back to 0
if (Cfg::DIRECTIONAL || !write_page_size) { // full 256 bytes
if (write_byte_idx) return true;
} else {
if (write_byte_idx < write_page_size) return true;
}
else if (write_byte_idx < write_page_size)
return true;
} else if (Cfg::DIRECTIONAL) {
if (write_byte_idx != Cfg::PAGE_SIZE) return true;
} else {
if (write_byte_idx < write_page_size) return true;
}
else if (Cfg::DIRECTIONAL) {
if (write_byte_idx != Cfg::PAGE_SIZE)
return true;
}
else if (write_byte_idx < write_page_size)
return true;
state = State::CHECKSUM;
return true;
@@ -163,10 +161,11 @@ namespace DirectStepping {
return true;
}
case State::UNFAIL:
if (c == 0)
if (c == 0) {
set_page_state(write_page_idx, PageState::FREE);
else
} else {
fatal_error = true;
}
state = State::MONITOR;
return true;
}
-3
View File
@@ -33,9 +33,6 @@
// Static data members
bool EmergencyParser::killed_by_M112, // = false
EmergencyParser::quickstop_by_M410,
#if ENABLED(SDSUPPORT)
EmergencyParser::sd_abort_by_M524,
#endif
EmergencyParser::enabled;
#if ENABLED(HOST_PROMPT_SUPPORT)
+1 -19
View File
@@ -49,7 +49,7 @@ class EmergencyParser {
public:
// Currently looking for: M108, M112, M410, M524, M876 S[0-9], S000, P000, R000
// Currently looking for: M108, M112, M410, M876 S[0-9], S000, P000, R000
enum State : uint8_t {
EP_RESET,
EP_N,
@@ -58,9 +58,6 @@ public:
EP_M10, EP_M108,
EP_M11, EP_M112,
EP_M4, EP_M41, EP_M410,
#if ENABLED(SDSUPPORT)
EP_M5, EP_M52, EP_M524,
#endif
#if ENABLED(HOST_PROMPT_SUPPORT)
EP_M8, EP_M87, EP_M876, EP_M876S, EP_M876SN,
#endif
@@ -79,10 +76,6 @@ public:
static bool killed_by_M112;
static bool quickstop_by_M410;
#if ENABLED(SDSUPPORT)
static bool sd_abort_by_M524;
#endif
#if ENABLED(HOST_PROMPT_SUPPORT)
static uint8_t M876_reason;
#endif
@@ -152,9 +145,6 @@ public:
case ' ': break;
case '1': state = EP_M1; break;
case '4': state = EP_M4; break;
#if ENABLED(SDSUPPORT)
case '5': state = EP_M5; break;
#endif
#if ENABLED(HOST_PROMPT_SUPPORT)
case '8': state = EP_M8; break;
#endif
@@ -175,11 +165,6 @@ public:
case EP_M4: state = (c == '1') ? EP_M41 : EP_IGNORE; break;
case EP_M41: state = (c == '0') ? EP_M410 : EP_IGNORE; break;
#if ENABLED(SDSUPPORT)
case EP_M5: state = (c == '2') ? EP_M52 : EP_IGNORE; break;
case EP_M52: state = (c == '4') ? EP_M524 : EP_IGNORE; break;
#endif
#if ENABLED(HOST_PROMPT_SUPPORT)
case EP_M8: state = (c == '7') ? EP_M87 : EP_IGNORE; break;
@@ -215,9 +200,6 @@ public:
case EP_M108: wait_for_user = wait_for_heatup = false; break;
case EP_M112: killed_by_M112 = true; break;
case EP_M410: quickstop_by_M410 = true; break;
#if ENABLED(SDSUPPORT)
case EP_M524: sd_abort_by_M524 = true; break;
#endif
#if ENABLED(HOST_PROMPT_SUPPORT)
case EP_M876SN: hostui.handle_response(M876_reason); break;
#endif
+1
View File
@@ -34,6 +34,7 @@ FWRetract fwretract; // Single instance - this calls the constructor
#include "../module/motion.h"
#include "../module/planner.h"
#include "../module/stepper.h"
#include "../gcode/gcode.h"
+3 -24
View File
@@ -111,29 +111,20 @@ void HostUI::action(FSTR_P const fstr, const bool eol) {
if (eol) SERIAL_EOL();
}
void HostUI::prompt_plus(const bool pgm, FSTR_P const ptype, const char * const str, const char extra_char/*='\0'*/) {
void HostUI::prompt_plus(FSTR_P const ptype, FSTR_P const fstr, const char extra_char/*='\0'*/) {
prompt(ptype, false);
PORT_REDIRECT(SerialMask::All);
SERIAL_CHAR(' ');
if (pgm)
SERIAL_ECHOPGM_P(str);
else
SERIAL_ECHO(str);
SERIAL_ECHOF(fstr);
if (extra_char != '\0') SERIAL_CHAR(extra_char);
SERIAL_EOL();
}
void HostUI::prompt_begin(const PromptReason reason, FSTR_P const fstr, const char extra_char/*='\0'*/) {
prompt_end();
host_prompt_reason = reason;
prompt_plus(F("begin"), fstr, extra_char);
}
void HostUI::prompt_begin(const PromptReason reason, const char * const cstr, const char extra_char/*='\0'*/) {
prompt_end();
host_prompt_reason = reason;
prompt_plus(F("begin"), cstr, extra_char);
}
void HostUI::prompt_button(FSTR_P const fstr) { prompt_plus(F("button"), fstr); }
void HostUI::prompt_end() { prompt(F("end")); }
void HostUI::prompt_show() { prompt(F("show")); }
@@ -142,26 +133,14 @@ void HostUI::action(FSTR_P const fstr, const bool eol) {
if (btn2) prompt_button(btn2);
prompt_show();
}
void HostUI::prompt_button(FSTR_P const fstr) { prompt_plus(F("button"), fstr); }
void HostUI::prompt_button(const char * const cstr) { prompt_plus(F("button"), cstr); }
void HostUI::prompt_do(const PromptReason reason, FSTR_P const fstr, FSTR_P const btn1/*=nullptr*/, FSTR_P const btn2/*=nullptr*/) {
prompt_begin(reason, fstr);
_prompt_show(btn1, btn2);
}
void HostUI::prompt_do(const PromptReason reason, const char * const cstr, FSTR_P const btn1/*=nullptr*/, FSTR_P const btn2/*=nullptr*/) {
prompt_begin(reason, cstr);
_prompt_show(btn1, btn2);
}
void HostUI::prompt_do(const PromptReason reason, FSTR_P const fstr, const char extra_char, FSTR_P const btn1/*=nullptr*/, FSTR_P const btn2/*=nullptr*/) {
prompt_begin(reason, fstr, extra_char);
_prompt_show(btn1, btn2);
}
void HostUI::prompt_do(const PromptReason reason, const char * const cstr, const char extra_char, FSTR_P const btn1/*=nullptr*/, FSTR_P const btn2/*=nullptr*/) {
prompt_begin(reason, cstr, extra_char);
_prompt_show(btn1, btn2);
}
#if ENABLED(ADVANCED_PAUSE_FEATURE)
void HostUI::filament_load_prompt() {
+2 -16
View File
@@ -79,14 +79,7 @@ class HostUI {
#if ENABLED(HOST_PROMPT_SUPPORT)
private:
static void prompt(FSTR_P const ptype, const bool eol=true);
static void prompt_plus(const bool pgm, FSTR_P const ptype, const char * const str, const char extra_char='\0');
static void prompt_plus(FSTR_P const ptype, FSTR_P const fstr, const char extra_char='\0') {
prompt_plus(true, ptype, FTOP(fstr), extra_char);
}
static void prompt_plus(FSTR_P const ptype, const char * const cstr, const char extra_char='\0') {
prompt_plus(false, ptype, cstr, extra_char);
}
static void prompt_plus(FSTR_P const ptype, FSTR_P const fstr, const char extra_char='\0');
static void prompt_show();
static void _prompt_show(FSTR_P const btn1, FSTR_P const btn2);
@@ -100,17 +93,10 @@ class HostUI {
static void notify(const char * const message);
static void prompt_begin(const PromptReason reason, FSTR_P const fstr, const char extra_char='\0');
static void prompt_begin(const PromptReason reason, const char * const cstr, const char extra_char='\0');
static void prompt_end();
static void prompt_button(FSTR_P const fstr);
static void prompt_button(const char * const cstr);
static void prompt_end();
static void prompt_do(const PromptReason reason, FSTR_P const pstr, FSTR_P const btn1=nullptr, FSTR_P const btn2=nullptr);
static void prompt_do(const PromptReason reason, const char * const cstr, FSTR_P const btn1=nullptr, FSTR_P const btn2=nullptr);
static void prompt_do(const PromptReason reason, FSTR_P const pstr, const char extra_char, FSTR_P const btn1=nullptr, FSTR_P const btn2=nullptr);
static void prompt_do(const PromptReason reason, const char * const cstr, const char extra_char, FSTR_P const btn1=nullptr, FSTR_P const btn2=nullptr);
static void prompt_open(const PromptReason reason, FSTR_P const pstr, FSTR_P const btn1=nullptr, FSTR_P const btn2=nullptr) {
if (host_prompt_reason == PROMPT_NOT_DEFINED) prompt_do(reason, pstr, btn1, btn2);
}
+1 -2
View File
@@ -172,9 +172,8 @@ Joystick joystick;
current_position += move_dist;
apply_motion_limits(current_position);
const float length = sqrt(hypot2);
PlannerHints hints(length);
injecting_now = true;
planner.buffer_line(current_position, length / seg_time, active_extruder, hints);
planner.buffer_line(current_position, length / seg_time, active_extruder, length);
injecting_now = false;
}
}
-38
View File
@@ -69,44 +69,6 @@ void LEDLights::setup() {
#if ENABLED(RGBW_LED)
if (PWM_PIN(RGB_LED_W_PIN)) SET_PWM(RGB_LED_W_PIN); else SET_OUTPUT(RGB_LED_W_PIN);
#endif
#if ENABLED(RGB_STARTUP_TEST)
int8_t led_pin_count = 0;
if (PWM_PIN(RGB_LED_R_PIN) && PWM_PIN(RGB_LED_G_PIN) && PWM_PIN(RGB_LED_B_PIN)) led_pin_count = 3;
#if ENABLED(RGBW_LED)
if (PWM_PIN(RGB_LED_W_PIN) && led_pin_count) led_pin_count++;
#endif
// Startup animation
if (led_pin_count) {
// blackout
if (PWM_PIN(RGB_LED_R_PIN)) hal.set_pwm_duty(pin_t(RGB_LED_R_PIN), 0); else WRITE(RGB_LED_R_PIN, LOW);
if (PWM_PIN(RGB_LED_G_PIN)) hal.set_pwm_duty(pin_t(RGB_LED_G_PIN), 0); else WRITE(RGB_LED_G_PIN, LOW);
if (PWM_PIN(RGB_LED_B_PIN)) hal.set_pwm_duty(pin_t(RGB_LED_B_PIN), 0); else WRITE(RGB_LED_B_PIN, LOW);
#if ENABLED(RGBW_LED)
if (PWM_PIN(RGB_LED_W_PIN)) hal.set_pwm_duty(pin_t(RGB_LED_W_PIN), 0);
else WRITE(RGB_LED_W_PIN, LOW);
#endif
delay(200);
LOOP_L_N(i, led_pin_count) {
LOOP_LE_N(b, 200) {
const uint16_t led_pwm = b <= 100 ? b : 200 - b;
if (i == 0 && PWM_PIN(RGB_LED_R_PIN)) hal.set_pwm_duty(pin_t(RGB_LED_R_PIN), led_pwm); else WRITE(RGB_LED_R_PIN, b < 100 ? HIGH : LOW);
if (i == 1 && PWM_PIN(RGB_LED_G_PIN)) hal.set_pwm_duty(pin_t(RGB_LED_G_PIN), led_pwm); else WRITE(RGB_LED_G_PIN, b < 100 ? HIGH : LOW);
if (i == 2 && PWM_PIN(RGB_LED_B_PIN)) hal.set_pwm_duty(pin_t(RGB_LED_B_PIN), led_pwm); else WRITE(RGB_LED_B_PIN, b < 100 ? HIGH : LOW);
#if ENABLED(RGBW_LED)
if (i == 3){
if (PWM_PIN(RGB_LED_W_PIN)) hal.set_pwm_duty(pin_t(RGB_LED_W_PIN), led_pwm);
else WRITE(RGB_LED_W_PIN, b < 100 ? HIGH : LOW);
delay(RGB_STARTUP_TEST_INNER_MS);//More slowing for ending
}
#endif
delay(RGB_STARTUP_TEST_INNER_MS);
}
}
delay(500);
}
#endif // RGB_STARTUP_TEST
#endif
TERN_(NEOPIXEL_LED, neo.init());
TERN_(PCA9533, PCA9533_init());
-8
View File
@@ -131,13 +131,6 @@ public:
// Accessors
static uint16_t pixels() { return adaneo1.numPixels() * TERN1(NEOPIXEL2_INSERIES, 2); }
static uint32_t pixel_color(const uint16_t n) {
#if ENABLED(NEOPIXEL2_INSERIES)
if (n >= NEOPIXEL_PIXELS) return adaneo2.getPixelColor(n - (NEOPIXEL_PIXELS));
#endif
return adaneo1.getPixelColor(n);
}
static uint8_t brightness() { return adaneo1.getBrightness(); }
static uint32_t Color(uint8_t r, uint8_t g, uint8_t b OPTARG(HAS_WHITE_LED, uint8_t w)) {
@@ -181,7 +174,6 @@ extern Marlin_NeoPixel neo;
// Accessors
static uint16_t pixels() { return adaneo.numPixels();}
static uint32_t pixel_color(const uint16_t n) { return adaneo.getPixelColor(n); }
static uint8_t brightness() { return adaneo.getBrightness(); }
static uint32_t Color(uint8_t r, uint8_t g, uint8_t b OPTARG(HAS_WHITE_LED2, uint8_t w)) {
return adaneo.Color(r, g, b OPTARG(HAS_WHITE_LED2, w));
+37 -77
View File
@@ -44,6 +44,7 @@
#include "max7219.h"
#include "../module/planner.h"
#include "../module/stepper.h"
#include "../MarlinCore.h"
#include "../HAL/shared/Delay.h"
@@ -51,7 +52,6 @@
#define HAS_SIDE_BY_SIDE 1
#endif
#define _ROT ((MAX7219_ROTATE + 360) % 360)
#if _ROT == 0 || _ROT == 180
#define MAX7219_X_LEDS TERN(HAS_SIDE_BY_SIDE, 8, MAX7219_LINES)
#define MAX7219_Y_LEDS TERN(HAS_SIDE_BY_SIDE, MAX7219_LINES, 8)
@@ -62,15 +62,6 @@
#error "MAX7219_ROTATE must be a multiple of +/- 90°."
#endif
#ifdef MAX7219_DEBUG_PROFILE
CodeProfiler::Mode CodeProfiler::mode = ACCUMULATE_AVERAGE;
uint8_t CodeProfiler::instance_count = 0;
uint32_t CodeProfiler::last_calc_time = micros();
uint8_t CodeProfiler::time_fraction = 0;
uint32_t CodeProfiler::total_time = 0;
uint16_t CodeProfiler::call_count = 0;
#endif
Max7219 max7219;
uint8_t Max7219::led_line[MAX7219_LINES]; // = { 0 };
@@ -78,7 +69,7 @@ uint8_t Max7219::suspended; // = 0;
#define LINE_REG(Q) (max7219_reg_digit0 + ((Q) & 0x7))
#if (_ROT == 0 || _ROT == 270) == DISABLED(MAX7219_REVERSE_EACH)
#if _ROT == 0 || _ROT == 270
#define _LED_BIT(Q) (7 - ((Q) & 0x7))
#else
#define _LED_BIT(Q) ((Q) & 0x7)
@@ -275,27 +266,26 @@ void Max7219::set(const uint8_t line, const uint8_t bits) {
#endif // MAX7219_NUMERIC
// Modify a single LED bit and send the changed line
void Max7219::led_set(const uint8_t x, const uint8_t y, const bool on, uint8_t * const rcm/*=nullptr*/) {
void Max7219::led_set(const uint8_t x, const uint8_t y, const bool on) {
if (x >= MAX7219_X_LEDS || y >= MAX7219_Y_LEDS) return error(F("led_set"), x, y);
if (BIT_7219(x, y) == on) return;
XOR_7219(x, y);
refresh_unit_line(LED_IND(x, y));
if (rcm != nullptr) *rcm |= _BV(LED_IND(x, y) & 0x07);
}
void Max7219::led_on(const uint8_t x, const uint8_t y, uint8_t * const rcm/*=nullptr*/) {
void Max7219::led_on(const uint8_t x, const uint8_t y) {
if (x >= MAX7219_X_LEDS || y >= MAX7219_Y_LEDS) return error(F("led_on"), x, y);
led_set(x, y, true, rcm);
led_set(x, y, true);
}
void Max7219::led_off(const uint8_t x, const uint8_t y, uint8_t * const rcm/*=nullptr*/) {
void Max7219::led_off(const uint8_t x, const uint8_t y) {
if (x >= MAX7219_X_LEDS || y >= MAX7219_Y_LEDS) return error(F("led_off"), x, y);
led_set(x, y, false, rcm);
led_set(x, y, false);
}
void Max7219::led_toggle(const uint8_t x, const uint8_t y, uint8_t * const rcm/*=nullptr*/) {
void Max7219::led_toggle(const uint8_t x, const uint8_t y) {
if (x >= MAX7219_X_LEDS || y >= MAX7219_Y_LEDS) return error(F("led_toggle"), x, y);
led_set(x, y, !BIT_7219(x, y), rcm);
led_set(x, y, !BIT_7219(x, y));
}
void Max7219::send_row(const uint8_t row) {
@@ -458,7 +448,7 @@ void Max7219::register_setup() {
pulse_load(); // Tell the chips to load the clocked out data
}
#if MAX7219_INIT_TEST
#ifdef MAX7219_INIT_TEST
uint8_t test_mode = 0;
millis_t next_patt_ms;
@@ -546,9 +536,13 @@ void Max7219::init() {
register_setup();
clear();
LOOP_LE_N(i, 7) { // Empty registers to turn all LEDs off
led_line[i] = 0x00;
send(max7219_reg_digit0 + i, 0);
pulse_load(); // Tell the chips to load the clocked out data
}
#if MAX7219_INIT_TEST
#ifdef MAX7219_INIT_TEST
start_test_pattern();
#endif
}
@@ -560,55 +554,41 @@ void Max7219::init() {
*/
// Apply changes to update a marker
void Max7219::mark16(const uint8_t pos, const uint8_t v1, const uint8_t v2, uint8_t * const rcm/*=nullptr*/) {
void Max7219::mark16(const uint8_t pos, const uint8_t v1, const uint8_t v2) {
#if MAX7219_X_LEDS > 8 // At least 16 LEDs on the X-Axis. Use single line.
led_off(v1 & 0xF, pos, rcm);
led_on(v2 & 0xF, pos, rcm);
led_off(v1 & 0xF, pos);
led_on(v2 & 0xF, pos);
#elif MAX7219_Y_LEDS > 8 // At least 16 LEDs on the Y-Axis. Use a single column.
led_off(pos, v1 & 0xF, rcm);
led_on(pos, v2 & 0xF, rcm);
led_off(pos, v1 & 0xF);
led_on(pos, v2 & 0xF);
#else // Single 8x8 LED matrix. Use two lines to get 16 LEDs.
led_off(v1 & 0x7, pos + (v1 >= 8), rcm);
led_on(v2 & 0x7, pos + (v2 >= 8), rcm);
led_off(v1 & 0x7, pos + (v1 >= 8));
led_on(v2 & 0x7, pos + (v2 >= 8));
#endif
}
// Apply changes to update a tail-to-head range
void Max7219::range16(const uint8_t y, const uint8_t ot, const uint8_t nt, const uint8_t oh,
const uint8_t nh, uint8_t * const rcm/*=nullptr*/) {
void Max7219::range16(const uint8_t y, const uint8_t ot, const uint8_t nt, const uint8_t oh, const uint8_t nh) {
#if MAX7219_X_LEDS > 8 // At least 16 LEDs on the X-Axis. Use single line.
if (ot != nt) for (uint8_t n = ot & 0xF; n != (nt & 0xF) && n != (nh & 0xF); n = (n + 1) & 0xF)
led_off(n & 0xF, y, rcm);
led_off(n & 0xF, y);
if (oh != nh) for (uint8_t n = (oh + 1) & 0xF; n != ((nh + 1) & 0xF); n = (n + 1) & 0xF)
led_on(n & 0xF, y, rcm);
led_on(n & 0xF, y);
#elif MAX7219_Y_LEDS > 8 // At least 16 LEDs on the Y-Axis. Use a single column.
if (ot != nt) for (uint8_t n = ot & 0xF; n != (nt & 0xF) && n != (nh & 0xF); n = (n + 1) & 0xF)
led_off(y, n & 0xF, rcm);
led_off(y, n & 0xF);
if (oh != nh) for (uint8_t n = (oh + 1) & 0xF; n != ((nh + 1) & 0xF); n = (n + 1) & 0xF)
led_on(y, n & 0xF, rcm);
led_on(y, n & 0xF);
#else // Single 8x8 LED matrix. Use two lines to get 16 LEDs.
if (ot != nt) for (uint8_t n = ot & 0xF; n != (nt & 0xF) && n != (nh & 0xF); n = (n + 1) & 0xF)
led_off(n & 0x7, y + (n >= 8), rcm);
led_off(n & 0x7, y + (n >= 8));
if (oh != nh) for (uint8_t n = (oh + 1) & 0xF; n != ((nh + 1) & 0xF); n = (n + 1) & 0xF)
led_on(n & 0x7, y + (n >= 8), rcm);
led_on(n & 0x7, y + (n >= 8));
#endif
}
// Apply changes to update a quantity
void Max7219::quantity(const uint8_t pos, const uint8_t ov, const uint8_t nv, uint8_t * const rcm/*=nullptr*/) {
for (uint8_t i = _MIN(nv, ov); i < _MAX(nv, ov); i++)
led_set(
#if MAX7219_X_LEDS >= MAX7219_Y_LEDS
i, pos // Single matrix or multiple matrices in Landscape
#else
pos, i // Multiple matrices in Portrait
#endif
, nv >= ov
, rcm
);
}
void Max7219::quantity16(const uint8_t pos, const uint8_t ov, const uint8_t nv, uint8_t * const rcm/*=nullptr*/) {
void Max7219::quantity16(const uint8_t pos, const uint8_t ov, const uint8_t nv) {
for (uint8_t i = _MIN(nv, ov); i < _MAX(nv, ov); i++)
led_set(
#if MAX7219_X_LEDS > 8 // At least 16 LEDs on the X-Axis. Use single line.
@@ -619,7 +599,6 @@ void Max7219::quantity16(const uint8_t pos, const uint8_t ov, const uint8_t nv,
i >> 1, pos + (i & 1)
#endif
, nv >= ov
, rcm
);
}
@@ -657,20 +636,16 @@ void Max7219::idle_tasks() {
register_setup();
}
#if MAX7219_INIT_TEST
#ifdef MAX7219_INIT_TEST
if (test_mode) {
run_test_pattern();
return;
}
#endif
// suspend updates and record which lines have changed for batching later
suspended++;
uint8_t row_change_mask = 0x00;
#if ENABLED(MAX7219_DEBUG_PRINTER_ALIVE)
if (do_blink) {
led_toggle(MAX7219_X_LEDS - 1, MAX7219_Y_LEDS - 1, &row_change_mask);
led_toggle(MAX7219_X_LEDS - 1, MAX7219_Y_LEDS - 1);
next_blink = ms + 1000;
}
#endif
@@ -680,7 +655,7 @@ void Max7219::idle_tasks() {
static int16_t last_head_cnt = 0xF, last_tail_cnt = 0xF;
if (last_head_cnt != head || last_tail_cnt != tail) {
range16(MAX7219_DEBUG_PLANNER_HEAD, last_tail_cnt, tail, last_head_cnt, head, &row_change_mask);
range16(MAX7219_DEBUG_PLANNER_HEAD, last_tail_cnt, tail, last_head_cnt, head);
last_head_cnt = head;
last_tail_cnt = tail;
}
@@ -690,7 +665,7 @@ void Max7219::idle_tasks() {
#ifdef MAX7219_DEBUG_PLANNER_HEAD
static int16_t last_head_cnt = 0x1;
if (last_head_cnt != head) {
mark16(MAX7219_DEBUG_PLANNER_HEAD, last_head_cnt, head, &row_change_mask);
mark16(MAX7219_DEBUG_PLANNER_HEAD, last_head_cnt, head);
last_head_cnt = head;
}
#endif
@@ -698,7 +673,7 @@ void Max7219::idle_tasks() {
#ifdef MAX7219_DEBUG_PLANNER_TAIL
static int16_t last_tail_cnt = 0x1;
if (last_tail_cnt != tail) {
mark16(MAX7219_DEBUG_PLANNER_TAIL, last_tail_cnt, tail, &row_change_mask);
mark16(MAX7219_DEBUG_PLANNER_TAIL, last_tail_cnt, tail);
last_tail_cnt = tail;
}
#endif
@@ -709,26 +684,11 @@ void Max7219::idle_tasks() {
static int16_t last_depth = 0;
const int16_t current_depth = (head - tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1) & 0xF;
if (current_depth != last_depth) {
quantity16(MAX7219_DEBUG_PLANNER_QUEUE, last_depth, current_depth, &row_change_mask);
quantity16(MAX7219_DEBUG_PLANNER_QUEUE, last_depth, current_depth);
last_depth = current_depth;
}
#endif
#ifdef MAX7219_DEBUG_PROFILE
static uint8_t last_time_fraction = 0;
const uint8_t current_time_fraction = (uint16_t(CodeProfiler::get_time_fraction()) * MAX7219_NUMBER_UNITS + 8) / 16;
if (current_time_fraction != last_time_fraction) {
quantity(MAX7219_DEBUG_PROFILE, last_time_fraction, current_time_fraction, &row_change_mask);
last_time_fraction = current_time_fraction;
}
#endif
// batch line updates
suspended--;
if (!suspended)
LOOP_L_N(i, 8) if (row_change_mask & _BV(i))
refresh_line(i);
// After resume() automatically do a refresh()
if (suspended == 0x80) {
suspended = 0;
+9 -70
View File
@@ -47,6 +47,7 @@
#ifndef MAX7219_ROTATE
#define MAX7219_ROTATE 0
#endif
#define _ROT ((MAX7219_ROTATE + 360) % 360)
#ifndef MAX7219_NUMBER_UNITS
#define MAX7219_NUMBER_UNITS 1
@@ -72,67 +73,6 @@
#define max7219_reg_shutdown 0x0C
#define max7219_reg_displayTest 0x0F
#ifdef MAX7219_DEBUG_PROFILE
// This class sums up the amount of time for which its instances exist.
// By default there is one instantiated for the duration of the idle()
// function. But an instance can be created in any code block to measure
// the time spent from the point of instantiation until the CPU leaves
// block. Be careful about having multiple instances of CodeProfiler as
// it does not guard against double counting. In general mixing ISR and
// non-ISR use will require critical sections but note that mode setting
// is atomic so the total or average times can safely be read if you set
// mode to FREEZE first.
class CodeProfiler {
public:
enum Mode : uint8_t { ACCUMULATE_AVERAGE, ACCUMULATE_TOTAL, FREEZE };
private:
static Mode mode;
static uint8_t instance_count;
static uint32_t last_calc_time;
static uint32_t total_time;
static uint8_t time_fraction;
static uint16_t call_count;
uint32_t start_time;
public:
CodeProfiler() : start_time(micros()) { instance_count++; }
~CodeProfiler() {
instance_count--;
if (mode == FREEZE) return;
call_count++;
const uint32_t now = micros();
total_time += now - start_time;
if (mode == ACCUMULATE_TOTAL) return;
// update time_fraction every hundred milliseconds
if (instance_count == 0 && ELAPSED(now, last_calc_time + 100000)) {
time_fraction = total_time * 128 / (now - last_calc_time);
last_calc_time = now;
total_time = 0;
}
}
static void set_mode(Mode _mode) { mode = _mode; }
static void reset() {
time_fraction = 0;
last_calc_time = micros();
total_time = 0;
call_count = 0;
}
// returns fraction of total time which was measured, scaled from 0 to 128
static uint8_t get_time_fraction() { return time_fraction; }
// returns total time in microseconds
static uint32_t get_total_time() { return total_time; }
static uint16_t get_call_count() { return call_count; }
};
#endif
class Max7219 {
public:
static uint8_t led_line[MAX7219_LINES];
@@ -170,10 +110,10 @@ public:
#endif
// Set a single LED by XY coordinate
static void led_set(const uint8_t x, const uint8_t y, const bool on, uint8_t * const rcm=nullptr);
static void led_on(const uint8_t x, const uint8_t y, uint8_t * const rcm=nullptr);
static void led_off(const uint8_t x, const uint8_t y, uint8_t * const rcm=nullptr);
static void led_toggle(const uint8_t x, const uint8_t y, uint8_t * const rcm=nullptr);
static void led_set(const uint8_t x, const uint8_t y, const bool on);
static void led_on(const uint8_t x, const uint8_t y);
static void led_off(const uint8_t x, const uint8_t y);
static void led_toggle(const uint8_t x, const uint8_t y);
// Set all LEDs in a single column
static void set_column(const uint8_t col, const uint32_t val);
@@ -207,12 +147,11 @@ private:
static void set(const uint8_t line, const uint8_t bits);
static void send_row(const uint8_t row);
static void send_column(const uint8_t col);
static void mark16(const uint8_t y, const uint8_t v1, const uint8_t v2, uint8_t * const rcm=nullptr);
static void range16(const uint8_t y, const uint8_t ot, const uint8_t nt, const uint8_t oh, const uint8_t nh, uint8_t * const rcm=nullptr);
static void quantity(const uint8_t y, const uint8_t ov, const uint8_t nv, uint8_t * const rcm=nullptr);
static void quantity16(const uint8_t y, const uint8_t ov, const uint8_t nv, uint8_t * const rcm=nullptr);
static void mark16(const uint8_t y, const uint8_t v1, const uint8_t v2);
static void range16(const uint8_t y, const uint8_t ot, const uint8_t nt, const uint8_t oh, const uint8_t nh);
static void quantity16(const uint8_t y, const uint8_t ov, const uint8_t nv);
#if MAX7219_INIT_TEST
#ifdef MAX7219_INIT_TEST
static void test_pattern();
static void run_test_pattern();
static void start_test_pattern();
+1 -1
View File
@@ -26,7 +26,7 @@
* Algorithm & Implementation: Scott Mudge - mail@scottmudge.com
* Date: Dec. 2020
*
* Character Frequencies from ~30 MB of comment-stripped G-code:
* Character Frequencies from ~30 MB of comment-stripped gcode:
* '1' -> 4451136 '4' -> 1353273 '\n' -> 1087683 '-' -> 90242
* '0' -> 4253577 '9' -> 1352147 'G' -> 1075806 'Z' -> 34109
* ' ' -> 3053297 '3' -> 1262929 'X' -> 975742 'M' -> 11879
+2 -2
View File
@@ -29,7 +29,7 @@
* Specifically optimized for 3D printing G-Code, this is a zero-cost data compression method
* which packs ~180-190% more data into the same amount of bytes going to the CNC controller.
* As a majority of G-Code can be represented by a restricted alphabet, I performed histogram
* analysis on a wide variety of 3D printing G-code samples, and found ~93% of all G-code could
* analysis on a wide variety of 3D printing gcode samples, and found ~93% of all gcode could
* be represented by the same 15-character alphabet.
*
* This allowed me to design a system of packing 2 8-bit characters into a single byte, assuming
@@ -38,7 +38,7 @@
*
* Combined with some logic to allow commingling of full-width characters outside of this 15-
* character alphabet (at the cost of an extra 8-bits per full-width character), and by stripping
* out unnecessary comments, the end result is G-code which is roughly half the original size.
* out unnecessary comments, the end result is gcode which is roughly half the original size.
*
* Why did I do this? I noticed micro-stuttering and other data-bottleneck issues while printing
* objects with high curvature, especially at high speeds. There is also the issue of the limited
@@ -51,7 +51,7 @@ When done, the MMU sends
- MMU => 'ok\n'
We don't wait for a response here but immediately continue with the next G-code which should
We don't wait for a response here but immediately continue with the next gcode which should
be one or more extruder moves to feed the filament into the hotend.
+32 -45
View File
@@ -54,8 +54,7 @@ MMU2 mmu2;
#define MMU_CMD_TIMEOUT 45000UL // 45s timeout for mmu commands (except P0)
#define MMU_P0_TIMEOUT 3000UL // Timeout for P0 command: 3seconds
#define MMU2_SEND(S) tx_str(F(S "\n"))
#define MMU2_RECV(S) rx_str(F(S "\n"))
#define MMU2_COMMAND(S) tx_str(F(S "\n"))
#if ENABLED(MMU_EXTRUDER_SENSOR)
uint8_t mmu_idl_sens = 0;
@@ -132,7 +131,7 @@ void MMU2::reset() {
safe_delay(20);
WRITE(MMU2_RST_PIN, HIGH);
#else
MMU2_SEND("X0"); // Send soft reset
MMU2_COMMAND("X0"); // Send soft reset
#endif
}
@@ -158,9 +157,11 @@ void MMU2::mmu_loop() {
case -1:
if (rx_start()) {
prev_P0_request = millis(); // Initialize finda sensor timeout
DEBUG_ECHOLNPGM("MMU => 'start'");
DEBUG_ECHOLNPGM("MMU <= 'S1'");
MMU2_SEND("S1"); // Read Version
MMU2_COMMAND("S1"); // Read Version
state = -2;
}
else if (millis() > 30000) { // 30sec after reset disable MMU
@@ -172,8 +173,10 @@ void MMU2::mmu_loop() {
case -2:
if (rx_ok()) {
sscanf(rx_buffer, "%huok\n", &version);
DEBUG_ECHOLNPGM("MMU => ", version, "\nMMU <= 'S2'");
MMU2_SEND("S2"); // Read Build Number
MMU2_COMMAND("S2"); // Read Build Number
state = -3;
}
break;
@@ -188,12 +191,14 @@ void MMU2::mmu_loop() {
#if ENABLED(MMU2_MODE_12V)
DEBUG_ECHOLNPGM("MMU <= 'M1'");
MMU2_SEND("M1"); // Stealth Mode
MMU2_COMMAND("M1"); // Stealth Mode
state = -5;
#else
DEBUG_ECHOLNPGM("MMU <= 'P0'");
MMU2_SEND("P0"); // Read FINDA
MMU2_COMMAND("P0"); // Read FINDA
state = -4;
#endif
}
@@ -204,8 +209,10 @@ void MMU2::mmu_loop() {
// response to M1
if (rx_ok()) {
DEBUG_ECHOLNPGM("MMU => ok");
DEBUG_ECHOLNPGM("MMU <= 'P0'");
MMU2_SEND("P0"); // Read FINDA
MMU2_COMMAND("P0"); // Read FINDA
state = -4;
}
break;
@@ -243,13 +250,14 @@ void MMU2::mmu_loop() {
else if (cmd == MMU_CMD_C0) {
// continue loading
DEBUG_ECHOLNPGM("MMU <= 'C0'");
MMU2_SEND("C0");
MMU2_COMMAND("C0");
state = 3; // wait for response
}
else if (cmd == MMU_CMD_U0) {
// unload current
DEBUG_ECHOLNPGM("MMU <= 'U0'");
MMU2_SEND("U0");
MMU2_COMMAND("U0");
state = 3; // wait for response
}
else if (WITHIN(cmd, MMU_CMD_E0, MMU_CMD_E0 + EXTRUDERS - 1)) {
@@ -262,7 +270,7 @@ void MMU2::mmu_loop() {
else if (cmd == MMU_CMD_R0) {
// recover after eject
DEBUG_ECHOLNPGM("MMU <= 'R0'");
MMU2_SEND("R0");
MMU2_COMMAND("R0");
state = 3; // wait for response
}
else if (WITHIN(cmd, MMU_CMD_F0, MMU_CMD_F0 + EXTRUDERS - 1)) {
@@ -277,7 +285,7 @@ void MMU2::mmu_loop() {
cmd = MMU_CMD_NONE;
}
else if (ELAPSED(millis(), prev_P0_request + 300)) {
MMU2_SEND("P0"); // Read FINDA
MMU2_COMMAND("P0"); // Read FINDA
state = 2; // wait for response
}
@@ -306,7 +314,7 @@ void MMU2::mmu_loop() {
if (mmu_idl_sens) {
if (FILAMENT_PRESENT() && mmu_loading_flag) {
DEBUG_ECHOLNPGM("MMU <= 'A'");
MMU2_SEND("A"); // send 'abort' request
MMU2_COMMAND("A"); // send 'abort' request
mmu_idl_sens = 0;
DEBUG_ECHOLNPGM("MMU IDLER_SENSOR = 0 - ABORT");
}
@@ -319,9 +327,9 @@ void MMU2::mmu_loop() {
const bool keep_trying = !mmu2s_triggered && last_cmd == MMU_CMD_C0;
if (keep_trying) {
// MMU ok received but filament sensor not triggered, retrying...
DEBUG_ECHOLNPGM("MMU => 'ok' (no filament in gears)");
DEBUG_ECHOLNPGM("MMU => 'ok' (filament not present in gears)");
DEBUG_ECHOLNPGM("MMU <= 'C0' (keep trying)");
MMU2_SEND("C0");
MMU2_COMMAND("C0");
}
#else
constexpr bool keep_trying = false;
@@ -353,7 +361,7 @@ void MMU2::mmu_loop() {
*/
bool MMU2::rx_start() {
// check for start message
return MMU2_RECV("start");
return rx_str(F("start\n"));
}
/**
@@ -432,7 +440,7 @@ void MMU2::clear_rx_buffer() {
* Check if we received 'ok' from MMU
*/
bool MMU2::rx_ok() {
if (MMU2_RECV("ok")) {
if (rx_str(F("ok\n"))) {
prev_P0_request = millis();
return true;
}
@@ -577,7 +585,7 @@ static void mmu2_not_responding() {
command(MMU_CMD_T0 + index);
manage_response(true, true);
mmu_continue_loading();
//command(MMU_CMD_C0);
command(MMU_CMD_C0);
extruder = index;
active_extruder = 0;
@@ -645,34 +653,13 @@ static void mmu2_not_responding() {
}
void MMU2::mmu_continue_loading() {
// Try to load the filament a limited number of times
bool fil_present = 0;
for (uint8_t i = 0; i < MMU_LOADING_ATTEMPTS_NR; i++) {
DEBUG_ECHOLNPGM("Load attempt #", i + 1);
// Done as soon as filament is present
fil_present = FILAMENT_PRESENT();
if (fil_present) break;
// Attempt to load the filament, 1mm at a time, for 3s
DEBUG_ECHOLNPGM("Additional load attempt #", i);
if (FILAMENT_PRESENT()) break;
command(MMU_CMD_C0);
stepper.enable_extruder();
const millis_t expire_ms = millis() + 3000;
do {
current_position.e += 1;
line_to_current_position(MMU_LOAD_FEEDRATE);
planner.synchronize();
// When (T0 rx->ok) load is ready, but in fact it did not load
// successfully or an overload created pressure in the extruder.
// Send (C0) to load more and move E_AXIS a little to release pressure.
if ((fil_present = FILAMENT_PRESENT())) MMU2_SEND("A");
} while (!fil_present && PENDING(millis(), expire_ms));
stepper.disable_extruder();
manage_response(true, true);
}
// Was the filament still missing in the last check?
if (!fil_present) {
if (!FILAMENT_PRESENT()) {
DEBUG_ECHOLNPGM("Filament never reached sensor, runout");
filament_runout();
}
@@ -695,7 +682,7 @@ static void mmu2_not_responding() {
command(MMU_CMD_T0 + index);
manage_response(true, true);
command(MMU_CMD_C0);
extruder = index; // Filament change is finished
extruder = index; //filament change is finished
active_extruder = 0;
stepper.enable_extruder();
SERIAL_ECHO_MSG(STR_ACTIVE_EXTRUDER, extruder);
@@ -874,7 +861,7 @@ void MMU2::filament_runout() {
if (cmd == MMU_CMD_NONE && last_cmd == MMU_CMD_C0) {
if (present && !mmu2s_triggered) {
DEBUG_ECHOLNPGM("MMU <= 'A'");
MMU2_SEND("A");
tx_str(F("A\n"));
}
// Slowly spin the extruder during C0
else {
@@ -952,7 +939,7 @@ bool MMU2::load_filament_to_nozzle(const uint8_t index) {
* Load filament to nozzle of multimaterial printer
*
* This function is used only after T? (user select filament) and M600 (change filament).
* It is not used after T0 .. T4 command (select filament), in such case, G-code is responsible for loading
* It is not used after T0 .. T4 command (select filament), in such case, gcode is responsible for loading
* filament to nozzle.
*/
void MMU2::load_to_nozzle() {
-1
View File
@@ -86,7 +86,6 @@ private:
#endif
#if ENABLED(MMU_EXTRUDER_SENSOR)
#define MMU_LOAD_FEEDRATE 19.02f // (mm/s)
static void mmu_continue_loading();
#endif
+6 -13
View File
@@ -35,13 +35,10 @@
#include "../gcode/gcode.h"
#include "../module/motion.h"
#include "../module/planner.h"
#include "../module/stepper.h"
#include "../module/printcounter.h"
#include "../module/temperature.h"
#if HAS_EXTRUDERS
#include "../module/stepper.h"
#endif
#if ENABLED(AUTO_BED_LEVELING_UBL)
#include "bedlevel/bedlevel.h"
#endif
@@ -66,7 +63,7 @@
#include "../lcd/marlinui.h"
#if HAS_SOUND
#if HAS_BUZZER
#include "../libs/buzzer.h"
#endif
@@ -101,7 +98,7 @@ fil_change_settings_t fc_settings[EXTRUDERS];
#define _PMSG(L) L##_LCD
#endif
#if HAS_SOUND
#if HAS_BUZZER
static void impatient_beep(const int8_t max_beep_count, const bool restart=false) {
if (TERN0(HAS_MARLINUI_MENU, pause_mode == PAUSE_MODE_PAUSE_PRINT)) return;
@@ -714,13 +711,9 @@ void resume_print(const_float_t slow_load_length/*=0*/, const_float_t fast_load_
TERN_(HAS_FILAMENT_SENSOR, runout.reset());
#if ENABLED(DWIN_LCD_PROUI)
DWIN_Print_Resume();
HMI_ReturnScreen();
#else
ui.reset_status();
ui.return_to_status();
#endif
TERN(DWIN_LCD_PROUI, DWIN_Print_Resume(), ui.reset_status());
TERN_(HAS_MARLINUI_MENU, ui.return_to_status());
TERN_(DWIN_LCD_PROUI, HMI_ReturnScreen());
}
#endif // ADVANCED_PAUSE_FEATURE
+1 -2
View File
@@ -30,7 +30,7 @@
#include "power.h"
#include "../module/planner.h"
#include "../module/stepper/indirection.h" // for restore_stepper_drivers
#include "../module/stepper.h"
#include "../module/temperature.h"
#include "../MarlinCore.h"
@@ -46,7 +46,6 @@ Power powerManager;
bool Power::psu_on;
#if ENABLED(AUTO_POWER_CONTROL)
#include "../module/stepper.h"
#include "../module/temperature.h"
#if BOTH(USE_CONTROLLER_FAN, AUTO_POWER_CONTROLLERFAN)
+3 -3
View File
@@ -53,7 +53,7 @@ PowerMonitor power_monitor; // Single instance - this calls the constructor
void PowerMonitor::draw_current() {
const float amps = getAmps();
lcd_put_u8str(amps < 100 ? ftostr31ns(amps) : ui16tostr4rj((uint16_t)amps));
lcd_put_lchar('A');
lcd_put_wchar('A');
}
#endif
@@ -61,7 +61,7 @@ PowerMonitor power_monitor; // Single instance - this calls the constructor
void PowerMonitor::draw_voltage() {
const float volts = getVolts();
lcd_put_u8str(volts < 100 ? ftostr31ns(volts) : ui16tostr4rj((uint16_t)volts));
lcd_put_lchar('V');
lcd_put_wchar('V');
}
#endif
@@ -69,7 +69,7 @@ PowerMonitor power_monitor; // Single instance - this calls the constructor
void PowerMonitor::draw_power() {
const float power = getPower();
lcd_put_u8str(power < 100 ? ftostr31ns(power) : ui16tostr4rj((uint16_t)power));
lcd_put_lchar('W');
lcd_put_wchar('W');
}
#endif
+1 -1
View File
@@ -32,7 +32,7 @@ struct pm_lpf_t {
uint32_t filter_buf;
float value;
void add_sample(const uint16_t sample) {
filter_buf += (uint32_t(sample) << K_SCALE) - (filter_buf >> K_VALUE);
filter_buf = filter_buf - (filter_buf >> K_VALUE) + (uint32_t(sample) << K_SCALE);
}
void capture() {
value = filter_buf * (SCALE * (1.0f / (1UL << (PM_K_VALUE + PM_K_SCALE))));
+42 -60
View File
@@ -39,26 +39,17 @@
#endif
SpindleLaser cutter;
bool SpindleLaser::enable_state; // Virtual enable state, controls enable pin if present and or apply power if > 0
uint8_t SpindleLaser::power, // Actual power output 0-255 ocr or "0 = off" > 0 = "on"
SpindleLaser::last_power_applied; // = 0 // Basic power state tracking
uint8_t SpindleLaser::power;
#if ENABLED(LASER_FEATURE)
cutter_test_pulse_t SpindleLaser::testPulse = 50; // (ms) Test fire pulse default duration
uint8_t SpindleLaser::last_block_power; // = 0 // Track power changes for dynamic inline power
feedRate_t SpindleLaser::feedrate_mm_m = 1500,
SpindleLaser::last_feedrate_mm_m; // = 0 // (mm/min) Track feedrate changes for dynamic power
cutter_test_pulse_t SpindleLaser::testPulse = 50; // Test fire Pulse time ms value.
#endif
bool SpindleLaser::isReady; // Ready to apply power setting from the UI to OCR
cutter_power_t SpindleLaser::menuPower, // Power set via LCD menu in PWM, PERCENT, or RPM
SpindleLaser::unitPower; // LCD status power in PWM, PERCENT, or RPM
bool SpindleLaser::isReadyForUI = false; // Ready to apply power setting from the UI to OCR
CutterMode SpindleLaser::cutter_mode = CUTTER_MODE_STANDARD; // Default is standard mode
constexpr cutter_cpower_t SpindleLaser::power_floor;
cutter_power_t SpindleLaser::menuPower = 0, // Power value via LCD menu in PWM, PERCENT, or RPM based on configured format set by CUTTER_POWER_UNIT.
SpindleLaser::unitPower = 0; // Unit power is in PWM, PERCENT, or RPM based on CUTTER_POWER_UNIT.
cutter_frequency_t SpindleLaser::frequency; // PWM frequency setting; range: 2K - 50K
#if ENABLED(MARLIN_DEV_MODE)
cutter_frequency_t SpindleLaser::frequency; // PWM frequency setting; range: 2K - 50K
#endif
#define SPINDLE_LASER_PWM_OFF TERN(SPINDLE_LASER_PWM_INVERT, 255, 0)
/**
@@ -66,21 +57,21 @@ cutter_frequency_t SpindleLaser::frequency; // PWM fre
*/
void SpindleLaser::init() {
#if ENABLED(SPINDLE_SERVO)
servo[SPINDLE_SERVO_NR].move(SPINDLE_SERVO_MIN);
#elif PIN_EXISTS(SPINDLE_LASER_ENA)
MOVE_SERVO(SPINDLE_SERVO_NR, SPINDLE_SERVO_MIN);
#else
OUT_WRITE(SPINDLE_LASER_ENA_PIN, !SPINDLE_LASER_ACTIVE_STATE); // Init spindle to off
#endif
#if ENABLED(SPINDLE_CHANGE_DIR)
OUT_WRITE(SPINDLE_DIR_PIN, SPINDLE_INVERT_DIR); // Init rotation to clockwise (M3)
#endif
#if ENABLED(HAL_CAN_SET_PWM_FREQ) && SPINDLE_LASER_FREQUENCY
frequency = SPINDLE_LASER_FREQUENCY;
hal.set_pwm_frequency(pin_t(SPINDLE_LASER_PWM_PIN), SPINDLE_LASER_FREQUENCY);
#endif
#if ENABLED(SPINDLE_LASER_USE_PWM)
SET_PWM(SPINDLE_LASER_PWM_PIN);
hal.set_pwm_duty(pin_t(SPINDLE_LASER_PWM_PIN), SPINDLE_LASER_PWM_OFF); // Set to lowest speed
#endif
#if ENABLED(HAL_CAN_SET_PWM_FREQ) && SPINDLE_LASER_FREQUENCY
hal.set_pwm_frequency(pin_t(SPINDLE_LASER_PWM_PIN), SPINDLE_LASER_FREQUENCY);
TERN_(MARLIN_DEV_MODE, frequency = SPINDLE_LASER_FREQUENCY);
#endif
#if ENABLED(AIR_EVACUATION)
OUT_WRITE(AIR_EVACUATION_PIN, !AIR_EVACUATION_ACTIVE); // Init Vacuum/Blower OFF
#endif
@@ -98,62 +89,53 @@ void SpindleLaser::init() {
*/
void SpindleLaser::_set_ocr(const uint8_t ocr) {
#if ENABLED(HAL_CAN_SET_PWM_FREQ) && SPINDLE_LASER_FREQUENCY
hal.set_pwm_frequency(pin_t(SPINDLE_LASER_PWM_PIN), frequency);
hal.set_pwm_frequency(pin_t(SPINDLE_LASER_PWM_PIN), TERN(MARLIN_DEV_MODE, frequency, SPINDLE_LASER_FREQUENCY));
#endif
hal.set_pwm_duty(pin_t(SPINDLE_LASER_PWM_PIN), ocr ^ SPINDLE_LASER_PWM_OFF);
}
void SpindleLaser::set_ocr(const uint8_t ocr) {
#if PIN_EXISTS(SPINDLE_LASER_ENA)
WRITE(SPINDLE_LASER_ENA_PIN, SPINDLE_LASER_ACTIVE_STATE); // Cutter ON
#endif
WRITE(SPINDLE_LASER_ENA_PIN, SPINDLE_LASER_ACTIVE_STATE); // Cutter ON
_set_ocr(ocr);
}
void SpindleLaser::ocr_off() {
#if PIN_EXISTS(SPINDLE_LASER_ENA)
WRITE(SPINDLE_LASER_ENA_PIN, !SPINDLE_LASER_ACTIVE_STATE); // Cutter OFF
#endif
WRITE(SPINDLE_LASER_ENA_PIN, !SPINDLE_LASER_ACTIVE_STATE); // Cutter OFF
_set_ocr(0);
}
#endif // SPINDLE_LASER_USE_PWM
/**
* Apply power for Laser or Spindle
* Apply power for laser/spindle
*
* Apply cutter power value for PWM, Servo, and on/off pin.
*
* @param opwr Power value. Range 0 to MAX.
* @param opwr Power value. Range 0 to MAX. When 0 disable spindle/laser.
*/
void SpindleLaser::apply_power(const uint8_t opwr) {
if (enabled() || opwr == 0) { // 0 check allows us to disable where no ENA pin exists
// Test and set the last power used to improve performance
if (opwr == last_power_applied) return;
last_power_applied = opwr;
// Handle PWM driven or just simple on/off
#if ENABLED(SPINDLE_LASER_USE_PWM)
if (CUTTER_UNIT_IS(RPM) && unitPower == 0)
ocr_off();
else if (ENABLED(CUTTER_POWER_RELATIVE) || enabled() || opwr == 0) {
set_ocr(opwr);
isReadyForUI = true;
}
else
ocr_off();
#elif ENABLED(SPINDLE_SERVO)
MOVE_SERVO(SPINDLE_SERVO_NR, power);
#else
WRITE(SPINDLE_LASER_ENA_PIN, enabled() ? SPINDLE_LASER_ACTIVE_STATE : !SPINDLE_LASER_ACTIVE_STATE);
isReadyForUI = true;
#endif
}
else {
#if PIN_EXISTS(SPINDLE_LASER_ENA)
WRITE(SPINDLE_LASER_ENA_PIN, !SPINDLE_LASER_ACTIVE_STATE);
#endif
isReadyForUI = false; // Only used for UI display updates.
TERN_(SPINDLE_LASER_USE_PWM, ocr_off());
}
static uint8_t last_power_applied = 0;
if (opwr == last_power_applied) return;
last_power_applied = opwr;
power = opwr;
#if ENABLED(SPINDLE_LASER_USE_PWM)
if (cutter.unitPower == 0 && CUTTER_UNIT_IS(RPM)) {
ocr_off();
isReady = false;
}
else if (ENABLED(CUTTER_POWER_RELATIVE) || enabled()) {
set_ocr(power);
isReady = true;
}
else {
ocr_off();
isReady = false;
}
#elif ENABLED(SPINDLE_SERVO)
MOVE_SERVO(SPINDLE_SERVO_NR, power);
#else
WRITE(SPINDLE_LASER_ENA_PIN, enabled() ? SPINDLE_LASER_ACTIVE_STATE : !SPINDLE_LASER_ACTIVE_STATE);
isReady = true;
#endif
}
#if ENABLED(SPINDLE_CHANGE_DIR)
+179 -166
View File
@@ -34,98 +34,84 @@
#include "../libs/buzzer.h"
#endif
// Inline laser power
#include "../module/planner.h"
#if ENABLED(LASER_POWER_INLINE)
#include "../module/planner.h"
#endif
#define PCT_TO_PWM(X) ((X) * 255 / 100)
#define PCT_TO_SERVO(X) ((X) * 180 / 100)
// Laser/Cutter operation mode
enum CutterMode : int8_t {
CUTTER_MODE_ERROR = -1,
CUTTER_MODE_STANDARD, // M3 power is applied directly and waits for planner moves to sync.
CUTTER_MODE_CONTINUOUS, // M3 or G1/2/3 move power is controlled within planner blocks, set with 'M3 I', cleared with 'M5 I'.
CUTTER_MODE_DYNAMIC // M4 laser power is proportional to the feed rate, set with 'M4 I', cleared with 'M5 I'.
};
class SpindleLaser {
public:
static CutterMode cutter_mode;
static constexpr uint8_t pct_to_ocr(const_float_t pct) { return uint8_t(PCT_TO_PWM(pct)); }
static const inline uint8_t pct_to_ocr(const_float_t pct) { return uint8_t(PCT_TO_PWM(pct)); }
// cpower = configured values (e.g., SPEED_POWER_MAX)
// Convert configured power range to a percentage
static constexpr cutter_cpower_t power_floor = TERN(CUTTER_POWER_RELATIVE, SPEED_POWER_MIN, 0);
static constexpr uint8_t cpwr_to_pct(const cutter_cpower_t cpwr) {
return cpwr ? round(100.0f * (cpwr - power_floor) / (SPEED_POWER_MAX - power_floor)) : 0;
static const inline uint8_t cpwr_to_pct(const cutter_cpower_t cpwr) {
constexpr cutter_cpower_t power_floor = TERN(CUTTER_POWER_RELATIVE, SPEED_POWER_MIN, 0),
power_range = SPEED_POWER_MAX - power_floor;
return cpwr ? round(100.0f * (cpwr - power_floor) / power_range) : 0;
}
// Convert config defines from RPM to %, angle or PWM when in Spindle mode
// and convert from PERCENT to PWM when in Laser mode
static constexpr cutter_power_t cpwr_to_upwr(const cutter_cpower_t cpwr) { // STARTUP power to Unit power
return (
// Convert a cpower (e.g., SPEED_POWER_STARTUP) to unit power (upwr, upower),
// which can be PWM, Percent, Servo angle, or RPM (rel/abs).
static const inline cutter_power_t cpwr_to_upwr(const cutter_cpower_t cpwr) { // STARTUP power to Unit power
const cutter_power_t upwr = (
#if ENABLED(SPINDLE_FEATURE)
// Spindle configured define values are in RPM
// Spindle configured values are in RPM
#if CUTTER_UNIT_IS(RPM)
cpwr // to same
#elif CUTTER_UNIT_IS(PERCENT)
cpwr_to_pct(cpwr) // to Percent
#elif CUTTER_UNIT_IS(SERVO)
PCT_TO_SERVO(cpwr_to_pct(cpwr)) // to SERVO angle
#else
PCT_TO_PWM(cpwr_to_pct(cpwr)) // to PWM
cpwr // to RPM
#elif CUTTER_UNIT_IS(PERCENT) // to PCT
cpwr_to_pct(cpwr)
#elif CUTTER_UNIT_IS(SERVO) // to SERVO angle
PCT_TO_SERVO(cpwr_to_pct(cpwr))
#else // to PWM
PCT_TO_PWM(cpwr_to_pct(cpwr))
#endif
#else
// Laser configured define values are in Percent
// Laser configured values are in PCT
#if CUTTER_UNIT_IS(PWM255)
PCT_TO_PWM(cpwr) // to PWM
PCT_TO_PWM(cpwr)
#else
cpwr // to same
cpwr // to RPM/PCT
#endif
#endif
);
return upwr;
}
static constexpr cutter_power_t mpower_min() { return cpwr_to_upwr(SPEED_POWER_MIN); }
static constexpr cutter_power_t mpower_max() { return cpwr_to_upwr(SPEED_POWER_MAX); }
static const cutter_power_t mpower_min() { return cpwr_to_upwr(SPEED_POWER_MIN); }
static const cutter_power_t mpower_max() { return cpwr_to_upwr(SPEED_POWER_MAX); }
#if ENABLED(LASER_FEATURE)
static cutter_test_pulse_t testPulse; // (ms) Test fire pulse duration
static uint8_t last_block_power; // Track power changes for dynamic power
static feedRate_t feedrate_mm_m, last_feedrate_mm_m; // (mm/min) Track feedrate changes for dynamic power
static bool laser_feedrate_changed() {
const bool changed = last_feedrate_mm_m != feedrate_mm_m;
if (changed) last_feedrate_mm_m = feedrate_mm_m;
return changed;
}
static cutter_test_pulse_t testPulse; // Test fire Pulse ms value
#endif
static bool isReadyForUI; // Ready to apply power setting from the UI to OCR
static bool enable_state;
static uint8_t power,
last_power_applied; // Basic power state tracking
static bool isReady; // Ready to apply power setting from the UI to OCR
static uint8_t power;
static cutter_frequency_t frequency; // Set PWM frequency; range: 2K-50K
#if ENABLED(MARLIN_DEV_MODE)
static cutter_frequency_t frequency; // Set PWM frequency; range: 2K-50K
#endif
static cutter_power_t menuPower, // Power as set via LCD menu in PWM, Percentage or RPM
unitPower; // Power as displayed status in PWM, Percentage or RPM
static void init();
#if ENABLED(HAL_CAN_SET_PWM_FREQ) && SPINDLE_LASER_FREQUENCY
#if ENABLED(MARLIN_DEV_MODE)
static void refresh_frequency() { hal.set_pwm_frequency(pin_t(SPINDLE_LASER_PWM_PIN), frequency); }
#endif
// Modifying this function should update everywhere
static bool enabled(const cutter_power_t opwr) { return opwr > 0; }
static bool enabled() { return enable_state; }
static bool enabled() { return enabled(power); }
static void apply_power(const uint8_t inpow);
FORCE_INLINE static void refresh() { apply_power(power); }
FORCE_INLINE static void set_power(const uint8_t upwr) { power = upwr; refresh(); }
#if ENABLED(SPINDLE_LASER_USE_PWM)
@@ -136,6 +122,7 @@ public:
public:
static void set_ocr(const uint8_t ocr);
static void ocr_set_power(const uint8_t ocr) { power = ocr; set_ocr(ocr); }
static void ocr_off();
/**
@@ -153,76 +140,78 @@ public:
);
}
/**
* Correct power to configured range
*/
static cutter_power_t power_to_range(const cutter_power_t pwr) {
return power_to_range(pwr, _CUTTER_POWER(CUTTER_POWER_UNIT));
}
static cutter_power_t power_to_range(const cutter_power_t pwr, const uint8_t pwrUnit) {
static constexpr float
min_pct = TERN(CUTTER_POWER_RELATIVE, 0, TERN(SPINDLE_FEATURE, round(100.0f * (SPEED_POWER_MIN) / (SPEED_POWER_MAX)), SPEED_POWER_MIN)),
max_pct = TERN(SPINDLE_FEATURE, 100, SPEED_POWER_MAX);
if (pwr <= 0) return 0;
cutter_power_t upwr;
switch (pwrUnit) {
case _CUTTER_POWER_PWM255:
upwr = cutter_power_t(
(pwr < pct_to_ocr(min_pct)) ? pct_to_ocr(min_pct) // Use minimum if set below
: (pwr > pct_to_ocr(max_pct)) ? pct_to_ocr(max_pct) // Use maximum if set above
: pwr
);
break;
case _CUTTER_POWER_PERCENT:
upwr = cutter_power_t(
(pwr < min_pct) ? min_pct // Use minimum if set below
: (pwr > max_pct) ? max_pct // Use maximum if set above
: pwr // PCT
);
break;
case _CUTTER_POWER_RPM:
upwr = cutter_power_t(
(pwr < SPEED_POWER_MIN) ? SPEED_POWER_MIN // Use minimum if set below
: (pwr > SPEED_POWER_MAX) ? SPEED_POWER_MAX // Use maximum if set above
: pwr // Calculate OCR value
);
break;
default: break;
}
return upwr;
}
#endif // SPINDLE_LASER_USE_PWM
/**
* Correct power to configured range
* Enable/Disable spindle/laser
* @param enable true = enable; false = disable
*/
static cutter_power_t power_to_range(const cutter_power_t pwr, const uint8_t pwrUnit=_CUTTER_POWER(CUTTER_POWER_UNIT)) {
static constexpr float
min_pct = TERN(CUTTER_POWER_RELATIVE, 0, TERN(SPINDLE_FEATURE, round(100.0f * (SPEED_POWER_MIN) / (SPEED_POWER_MAX)), SPEED_POWER_MIN)),
max_pct = TERN(SPINDLE_FEATURE, 100, SPEED_POWER_MAX);
if (pwr <= 0) return 0;
cutter_power_t upwr;
switch (pwrUnit) {
case _CUTTER_POWER_PWM255: { // PWM
const uint8_t pmin = pct_to_ocr(min_pct), pmax = pct_to_ocr(max_pct);
upwr = cutter_power_t(constrain(pwr, pmin, pmax));
} break;
case _CUTTER_POWER_PERCENT: // Percent
upwr = cutter_power_t(constrain(pwr, min_pct, max_pct));
break;
case _CUTTER_POWER_RPM: // Calculate OCR value
upwr = cutter_power_t(constrain(pwr, SPEED_POWER_MIN, SPEED_POWER_MAX));
break;
default: break;
static void set_enabled(const bool enable) {
uint8_t value = 0;
if (enable) {
#if ENABLED(SPINDLE_LASER_USE_PWM)
if (power)
value = power;
else if (unitPower)
value = upower_to_ocr(cpwr_to_upwr(SPEED_POWER_STARTUP));
#else
value = 255;
#endif
}
return upwr;
set_power(value);
}
static void disable() { isReady = false; set_enabled(false); }
/**
* Enable Laser or Spindle output.
* It's important to prevent changing the power output value during inline cutter operation.
* Inline power is adjusted in the planner to support LASER_TRAP_POWER and CUTTER_MODE_DYNAMIC mode.
* Wait for spindle to spin up or spin down
*
* This method accepts one of the following control states:
*
* - For CUTTER_MODE_STANDARD the cutter power is either full on/off or ocr-based and it will apply
* SPEED_POWER_STARTUP if no value is assigned.
*
* - For CUTTER_MODE_CONTINUOUS inline and power remains where last set and the cutter output enable flag is set.
*
* - CUTTER_MODE_DYNAMIC is also inline-based and it just sets the enable output flag.
*
* - For CUTTER_MODE_ERROR set the output enable_state flag directly and set power to 0 for any mode.
* This mode allows a global power shutdown action to occur.
* @param on true = state to on; false = state to off.
*/
static void set_enabled(bool enable) {
switch (cutter_mode) {
case CUTTER_MODE_STANDARD:
apply_power(enable ? TERN(SPINDLE_LASER_USE_PWM, (power ?: (unitPower ? upower_to_ocr(cpwr_to_upwr(SPEED_POWER_STARTUP)) : 0)), 255) : 0);
break;
case CUTTER_MODE_CONTINUOUS:
TERN_(LASER_FEATURE, set_inline_enabled(enable));
break;
case CUTTER_MODE_DYNAMIC:
TERN_(LASER_FEATURE, set_inline_enabled(enable));
break;
case CUTTER_MODE_ERROR: // Error mode, no enable and kill power.
enable = false;
apply_power(0);
}
#if SPINDLE_LASER_ENA_PIN
WRITE(SPINDLE_LASER_ENA_PIN, enable ? SPINDLE_LASER_ACTIVE_STATE : !SPINDLE_LASER_ACTIVE_STATE);
#endif
enable_state = enable;
}
static void disable() { isReadyForUI = false; set_enabled(false); }
// Wait for spindle/laser to startup or shutdown
static void power_delay(const bool on) {
safe_delay(on ? SPINDLE_LASER_POWERUP_DELAY : SPINDLE_LASER_POWERDOWN_DELAY);
#if DISABLED(LASER_POWER_INLINE)
safe_delay(on ? SPINDLE_LASER_POWERUP_DELAY : SPINDLE_LASER_POWERDOWN_DELAY);
#endif
}
#if ENABLED(SPINDLE_CHANGE_DIR)
@@ -234,98 +223,122 @@ public:
#endif
#if ENABLED(AIR_EVACUATION)
static void air_evac_enable(); // Turn On Cutter Vacuum or Laser Blower motor
static void air_evac_disable(); // Turn Off Cutter Vacuum or Laser Blower motor
static void air_evac_toggle(); // Toggle Cutter Vacuum or Laser Blower motor
static bool air_evac_state() { // Get current state
static void air_evac_enable(); // Turn On Cutter Vacuum or Laser Blower motor
static void air_evac_disable(); // Turn Off Cutter Vacuum or Laser Blower motor
static void air_evac_toggle(); // Toggle Cutter Vacuum or Laser Blower motor
static bool air_evac_state() { // Get current state
return (READ(AIR_EVACUATION_PIN) == AIR_EVACUATION_ACTIVE);
}
#endif
#if ENABLED(AIR_ASSIST)
static void air_assist_enable(); // Turn on air assist
static void air_assist_disable(); // Turn off air assist
static void air_assist_toggle(); // Toggle air assist
static bool air_assist_state() { // Get current state
static void air_assist_enable(); // Turn on air assist
static void air_assist_disable(); // Turn off air assist
static void air_assist_toggle(); // Toggle air assist
static bool air_assist_state() { // Get current state
return (READ(AIR_ASSIST_PIN) == AIR_ASSIST_ACTIVE);
}
#endif
#if HAS_MARLINUI_MENU
#if ENABLED(SPINDLE_FEATURE)
static void enable_with_dir(const bool reverse) {
isReadyForUI = true;
const uint8_t ocr = TERN(SPINDLE_LASER_USE_PWM, upower_to_ocr(menuPower), 255);
if (menuPower)
power = ocr;
else
menuPower = cpwr_to_upwr(SPEED_POWER_STARTUP);
unitPower = menuPower;
set_reverse(reverse);
set_enabled(true);
}
FORCE_INLINE static void enable_forward() { enable_with_dir(false); }
FORCE_INLINE static void enable_reverse() { enable_with_dir(true); }
FORCE_INLINE static void enable_same_dir() { enable_with_dir(is_reverse()); }
#endif // SPINDLE_FEATURE
static void enable_with_dir(const bool reverse) {
isReady = true;
const uint8_t ocr = TERN(SPINDLE_LASER_USE_PWM, upower_to_ocr(menuPower), 255);
if (menuPower)
power = ocr;
else
menuPower = cpwr_to_upwr(SPEED_POWER_STARTUP);
unitPower = menuPower;
set_reverse(reverse);
set_enabled(true);
}
FORCE_INLINE static void enable_forward() { enable_with_dir(false); }
FORCE_INLINE static void enable_reverse() { enable_with_dir(true); }
FORCE_INLINE static void enable_same_dir() { enable_with_dir(is_reverse()); }
#if ENABLED(SPINDLE_LASER_USE_PWM)
static void update_from_mpower() {
if (isReadyForUI) power = upower_to_ocr(menuPower);
if (isReady) power = upower_to_ocr(menuPower);
unitPower = menuPower;
}
#endif
#if ENABLED(LASER_FEATURE)
// Toggle the laser on/off with menuPower. Apply SPEED_POWER_STARTUP if it was 0 on entry.
static void menu_set_enabled(const bool state) {
set_enabled(state);
if (state) {
if (!menuPower) menuPower = cpwr_to_upwr(SPEED_POWER_STARTUP);
power = upower_to_ocr(menuPower);
apply_power(power);
} else
apply_power(0);
}
/**
* Test fire the laser using the testPulse ms duration
* Also fires with any PWM power that was previous set
* If not set defaults to 80% power
*/
static void test_fire_pulse() {
BUZZ(30, 3000);
cutter_mode = CUTTER_MODE_STANDARD; // Menu needs standard mode.
menu_set_enabled(true); // Laser On
delay(testPulse); // Delay for time set by user in pulse ms menu screen.
menu_set_enabled(false); // Laser Off
TERN_(HAS_BEEPER, buzzer.tone(30, 3000));
enable_forward(); // Turn Laser on (Spindle speak but same funct)
delay(testPulse); // Delay for time set by user in pulse ms menu screen.
disable(); // Turn laser off
}
#endif // LASER_FEATURE
#endif
#endif // HAS_MARLINUI_MENU
#if ENABLED(LASER_FEATURE)
#if ENABLED(LASER_POWER_INLINE)
/**
* Inline power adds extra fields to the planner block
* to handle laser power and scale to movement speed.
*/
// Dynamic mode rate calculation
static uint8_t calc_dynamic_power() {
if (feedrate_mm_m > 65535) return 255; // Too fast, go always on
uint16_t rate = uint16_t(feedrate_mm_m); // 16 bits from the G-code parser float input
rate >>= 8; // Take the G-code input e.g. F40000 and shift off the lower bits to get an OCR value from 1-255
return uint8_t(rate);
// Force disengage planner power control
static void inline_disable() {
isReady = false;
unitPower = 0;
planner.laser_inline.status.isPlanned = false;
planner.laser_inline.status.isEnabled = false;
planner.laser_inline.power = 0;
}
// Inline modes of all other functions; all enable planner inline power control
static void set_inline_enabled(const bool enable) { planner.laser_inline.status.isEnabled = enable; }
// Set the power for subsequent movement blocks
static void inline_power(const cutter_power_t cpwr) {
TERN(SPINDLE_LASER_USE_PWM, power = planner.laser_inline.power = cpwr, planner.laser_inline.power = cpwr > 0 ? 255 : 0);
static void set_inline_enabled(const bool enable) {
if (enable)
inline_power(255);
else {
isReady = false;
unitPower = menuPower = 0;
planner.laser_inline.status.isPlanned = false;
TERN(SPINDLE_LASER_USE_PWM, inline_ocr_power, inline_power)(0);
}
}
#endif // LASER_FEATURE
// Set the power for subsequent movement blocks
static void inline_power(const cutter_power_t upwr) {
unitPower = menuPower = upwr;
#if ENABLED(SPINDLE_LASER_USE_PWM)
#if ENABLED(SPEED_POWER_RELATIVE) && !CUTTER_UNIT_IS(RPM) // relative mode does not turn laser off at 0, except for RPM
planner.laser_inline.status.isEnabled = true;
planner.laser_inline.power = upower_to_ocr(upwr);
isReady = true;
#else
inline_ocr_power(upower_to_ocr(upwr));
#endif
#else
planner.laser_inline.status.isEnabled = enabled(upwr);
planner.laser_inline.power = upwr;
isReady = enabled(upwr);
#endif
}
static void kill() { disable(); }
static void inline_direction(const bool) { /* never */ }
#if ENABLED(SPINDLE_LASER_USE_PWM)
static void inline_ocr_power(const uint8_t ocrpwr) {
isReady = ocrpwr > 0;
planner.laser_inline.status.isEnabled = ocrpwr > 0;
planner.laser_inline.power = ocrpwr;
}
#endif
#endif // LASER_POWER_INLINE
static void kill() {
TERN_(LASER_POWER_INLINE, inline_disable());
disable();
}
};
extern SpindleLaser cutter;

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