Compare commits
138 Commits
Ender-3_Pr
...
bugfix-2.0
Author | SHA1 | Date | |
---|---|---|---|
|
70c5bca8c2 | ||
|
bb4a01c4f9 | ||
|
06a6708220 | ||
|
e3d1bd6d97 | ||
|
031bc6adb9 | ||
|
a6cc7a4f35 | ||
|
4f9fbcee2b | ||
|
d1211b9f90 | ||
|
d5699dd5c0 | ||
|
79bd1a68c7 | ||
|
0922702504 | ||
|
2bf631c6cc | ||
|
9a0d0e7ef1 | ||
|
3fab4898e4 | ||
|
eee8f11849 | ||
|
096bea208e | ||
|
daa7ee6c6a | ||
|
09cc5473b5 | ||
|
5ccaf1d233 | ||
|
78789ee11d | ||
|
39f6ae0e3c | ||
|
3441e917bc | ||
|
9ba4c58595 | ||
|
a720b1a335 | ||
|
799b8fccaf | ||
|
69a1c539fb | ||
|
6904e31e54 | ||
|
407c32563b | ||
|
0281459093 | ||
|
0ef496df2b | ||
|
9c2d0f47fb | ||
|
cd9a23c4d0 | ||
|
ab346f24ca | ||
|
5ee7e3ffa4 | ||
|
32765c600a | ||
|
602e14704b | ||
|
0ad83e0af5 | ||
|
9bd39749d7 | ||
|
ce5497218a | ||
|
ca06ec9abb | ||
|
cf1e4df51b | ||
|
38391eb116 | ||
|
03b50354cb | ||
|
ceeb6c646b | ||
|
20f79e290f | ||
|
5ecf3f876c | ||
|
dee41990cc | ||
|
94a8b70ce3 | ||
|
b2101b9928 | ||
|
976ac28be5 | ||
|
b0b340aab9 | ||
|
1ceac4a9fe | ||
|
a8046d2a95 | ||
|
c6f2be637c | ||
|
30da489f1c | ||
|
a540c58a2d | ||
|
e52298db35 | ||
|
31c350d55e | ||
|
d50a3129e2 | ||
|
614f54622a | ||
|
f89bb65220 | ||
|
284b35d120 | ||
|
fe5e941d92 | ||
|
80cc5f0413 | ||
|
0595a55700 | ||
|
2535ce2a26 | ||
|
777af4b6c4 | ||
|
b1162d97eb | ||
|
e70c350b3d | ||
|
ff516e257b | ||
|
41269e9c2b | ||
|
091b0f9664 | ||
|
dc04f61adc | ||
|
eb25530ba8 | ||
|
6133ca2d68 | ||
|
5a46b900d8 | ||
|
b09997d137 | ||
|
7dc3cfa1a6 | ||
|
93144f1e7d | ||
|
5e215fa3c4 | ||
|
2bdc5a78ad | ||
|
cd06d5f34f | ||
|
72f341b4bc | ||
|
9a4cfe4940 | ||
|
4a9ecdd70b | ||
|
160762742a | ||
|
95b0ee2fbf | ||
|
505ae61b8d | ||
|
5660c3b189 | ||
|
470512dd50 | ||
|
310a76444d | ||
|
ea630bbed7 | ||
|
15915ede53 | ||
|
a68aa255bc | ||
|
b3fe059f6c | ||
|
b938d99b32 | ||
|
b01caf0afe | ||
|
088fa84b7f | ||
|
74339bfefc | ||
|
40fa85b92e | ||
|
1c3d5827e6 | ||
|
0567d613ba | ||
|
3bf100301a | ||
|
f1483e76a1 | ||
|
9efccbf23e | ||
|
fe86ff2d53 | ||
|
f6e248df6e | ||
|
6d1ce46dd1 | ||
|
341bf27d1d | ||
|
0698fcb005 | ||
|
d725998340 | ||
|
2f814079d8 | ||
|
a3876c5896 | ||
|
7497890f04 | ||
|
b16a32e7ce | ||
|
052a64052b | ||
|
4648ade0e6 | ||
|
a67dd76db4 | ||
|
47b8671836 | ||
|
f04efa85cd | ||
|
5b2b08d048 | ||
|
3f9869a6c1 | ||
|
65490f27c4 | ||
|
1afb80d45d | ||
|
6a20b1271d | ||
|
733e5f3957 | ||
|
031633cde6 | ||
|
5149eed13c | ||
|
2ecaebeab2 | ||
|
047ecc5995 | ||
|
2268e1417b | ||
|
3fa767f533 | ||
|
9860580bed | ||
|
6df193a5d1 | ||
|
e5fb6ace4c | ||
|
b659bb2a52 | ||
|
7e27f06364 | ||
|
72346e80fa |
@@ -14,6 +14,10 @@ end_of_line = lf
|
|||||||
indent_style = space
|
indent_style = space
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
|
||||||
[{*.py,*.conf,*.sublime-project}]
|
[{*.py}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[{*.conf,*.sublime-project}]
|
||||||
indent_style = tab
|
indent_style = tab
|
||||||
indent_size = 4
|
indent_size = 4
|
||||||
|
7
.github/contributing.md
vendored
7
.github/contributing.md
vendored
@@ -34,8 +34,11 @@ 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.
|
We have a Message Board and a Facebook group where our knowledgable user community can provide helpful advice if you have questions.
|
||||||
|
|
||||||
* [Marlin RepRap forum](https://reprap.org/forum/list.php?415)
|
- [Marlin Documentation](https://marlinfw.org) - Official Marlin documentation
|
||||||
* [MarlinFirmware on Facebook](https://www.facebook.com/groups/1049718498464482/)
|
- 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
|
||||||
|
|
||||||
If chat is more your speed, you can join the MarlinFirmware Discord server:
|
If chat is more your speed, you can join the MarlinFirmware Discord server:
|
||||||
|
|
||||||
|
147
.github/workflows/test-builds.yml
vendored
Normal file
147
.github/workflows/test-builds.yml
vendored
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
#
|
||||||
|
# test-builds.yml
|
||||||
|
# Do test builds to catch compile errors
|
||||||
|
#
|
||||||
|
|
||||||
|
name: CI - bugfix-2.0.x
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- bugfix-2.0.x
|
||||||
|
paths-ignore:
|
||||||
|
- config/**
|
||||||
|
- data/**
|
||||||
|
- docs/**
|
||||||
|
- '**/*.md'
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- bugfix-2.0.x
|
||||||
|
paths-ignore:
|
||||||
|
- config/**
|
||||||
|
- data/**
|
||||||
|
- docs/**
|
||||||
|
- '**/*.md'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test_builds:
|
||||||
|
name: Run All Tests
|
||||||
|
if: github.repository == 'MarlinFirmware/Marlin'
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
test-platform:
|
||||||
|
# Base Environments
|
||||||
|
|
||||||
|
- DUE
|
||||||
|
- DUE_archim
|
||||||
|
- esp32
|
||||||
|
- linux_native
|
||||||
|
- mega2560
|
||||||
|
- at90usb1286_dfu
|
||||||
|
- teensy31
|
||||||
|
- teensy35
|
||||||
|
- teensy41
|
||||||
|
- SAMD51_grandcentral_m4
|
||||||
|
|
||||||
|
# Extended AVR Environments
|
||||||
|
|
||||||
|
- FYSETC_F6
|
||||||
|
- mega1280
|
||||||
|
- rambo
|
||||||
|
- sanguino1284p
|
||||||
|
- sanguino644p
|
||||||
|
|
||||||
|
# STM32F1 (Maple) Environments
|
||||||
|
|
||||||
|
#- STM32F103RC_btt_maple
|
||||||
|
- STM32F103RC_btt_USB_maple
|
||||||
|
- STM32F103RC_fysetc_maple
|
||||||
|
- STM32F103RC_meeb_maple
|
||||||
|
- jgaurora_a5s_a1_maple
|
||||||
|
- STM32F103VE_longer_maple
|
||||||
|
#- mks_robin_maple
|
||||||
|
- mks_robin_lite_maple
|
||||||
|
- mks_robin_pro_maple
|
||||||
|
#- mks_robin_nano35_maple
|
||||||
|
#- STM32F103RE_creality_maple
|
||||||
|
- STM32F103VE_ZM3E4V2_USB_maple
|
||||||
|
|
||||||
|
# STM32 (ST) Environments
|
||||||
|
|
||||||
|
- STM32F103RC_btt
|
||||||
|
#- STM32F103RC_btt_USB
|
||||||
|
- STM32F103RE_btt
|
||||||
|
- STM32F103RE_btt_USB
|
||||||
|
- STM32F103RE_creality
|
||||||
|
- STM32F401RC_creality
|
||||||
|
- STM32F103VE_longer
|
||||||
|
- STM32F407VE_black
|
||||||
|
- STM32F401VE_STEVAL
|
||||||
|
- BIGTREE_BTT002
|
||||||
|
- BIGTREE_SKR_PRO
|
||||||
|
- BIGTREE_GTR_V1_0
|
||||||
|
- mks_robin
|
||||||
|
- ARMED
|
||||||
|
- FYSETC_S6
|
||||||
|
- STM32F070CB_malyan
|
||||||
|
- STM32F070RB_malyan
|
||||||
|
- malyan_M300
|
||||||
|
- FLYF407ZG
|
||||||
|
- rumba32
|
||||||
|
- LERDGEX
|
||||||
|
- LERDGEK
|
||||||
|
- mks_robin_nano35
|
||||||
|
- NUCLEO_F767ZI
|
||||||
|
- REMRAM_V1
|
||||||
|
- BTT_SKR_SE_BX
|
||||||
|
- chitu_f103
|
||||||
|
- Opulo_Lumen_REV3
|
||||||
|
|
||||||
|
# Put lengthy tests last
|
||||||
|
|
||||||
|
- LPC1768
|
||||||
|
- LPC1769
|
||||||
|
|
||||||
|
# Non-working environment tests
|
||||||
|
#- at90usb1286_cdc
|
||||||
|
#- STM32F103CB_malyan
|
||||||
|
#- STM32F103RE
|
||||||
|
#- mks_robin_mini
|
||||||
|
|
||||||
|
steps:
|
||||||
|
|
||||||
|
- name: Check out the PR
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Cache pip
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: ~/.cache/pip
|
||||||
|
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-pip-
|
||||||
|
|
||||||
|
- name: Cache PlatformIO
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: ~/.platformio
|
||||||
|
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
|
||||||
|
|
||||||
|
- name: Select Python 3.7
|
||||||
|
uses: actions/setup-python@v3
|
||||||
|
with:
|
||||||
|
python-version: '3.7' # Version range or exact version of a Python version to use, using semvers version range syntax.
|
||||||
|
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
|
||||||
|
|
||||||
|
- name: Install PlatformIO
|
||||||
|
run: |
|
||||||
|
pip install -U platformio
|
||||||
|
pio upgrade --dev
|
||||||
|
pio pkg update --global
|
||||||
|
|
||||||
|
- name: Run ${{ matrix.test-platform }} Tests
|
||||||
|
run: |
|
||||||
|
make tests-single-ci TEST_TARGET=${{ matrix.test-platform }}
|
@@ -35,7 +35,7 @@
|
|||||||
*
|
*
|
||||||
* Advanced settings can be found in Configuration_adv.h
|
* Advanced settings can be found in Configuration_adv.h
|
||||||
*/
|
*/
|
||||||
#define CONFIGURATION_H_VERSION 02000904
|
#define CONFIGURATION_H_VERSION 02000905
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//============================= Getting Started =============================
|
//============================= Getting Started =============================
|
||||||
@@ -57,15 +57,6 @@
|
|||||||
* https://www.thingiverse.com/thing:1278865
|
* 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
|
// @section info
|
||||||
|
|
||||||
// Author info of this build printed to the host during boot and M115
|
// Author info of this build printed to the host during boot and M115
|
||||||
@@ -186,28 +177,27 @@
|
|||||||
//#define E7_DRIVER_TYPE A4988
|
//#define E7_DRIVER_TYPE A4988
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Axis codes for additional axes:
|
* Additional Axis Settings
|
||||||
* This defines the axis code that is used in G-code commands to
|
*
|
||||||
* reference a specific axis.
|
* AXISn_NAME defines the letter used to refer to the axis in (most) G-code commands.
|
||||||
* 'A' for rotational axis parallel to X
|
* By convention the names and roles are typically:
|
||||||
* 'B' for rotational axis parallel to Y
|
* 'A' : Rotational axis parallel to X
|
||||||
* 'C' for rotational axis parallel to Z
|
* 'B' : Rotational axis parallel to Y
|
||||||
* 'U' for secondary linear axis parallel to X
|
* 'C' : Rotational axis parallel to Z
|
||||||
* 'V' for secondary linear axis parallel to Y
|
* 'U' : Secondary linear axis parallel to X
|
||||||
* 'W' for secondary linear axis parallel to Z
|
* 'V' : Secondary linear axis parallel to Y
|
||||||
* Regardless of the settings, firmware-internal axis IDs are
|
* 'W' : Secondary linear axis parallel to Z
|
||||||
* I (AXIS4), J (AXIS5), K (AXIS6).
|
*
|
||||||
|
* Regardless of these settings the axes are internally named I, J, K.
|
||||||
*/
|
*/
|
||||||
#ifdef I_DRIVER_TYPE
|
#ifdef I_DRIVER_TYPE
|
||||||
#define AXIS4_NAME 'A' // :['A', 'B', 'C', 'U', 'V', 'W']
|
#define AXIS4_NAME 'A' // :['A', 'B', 'C', 'U', 'V', 'W']
|
||||||
#endif
|
#endif
|
||||||
#ifdef J_DRIVER_TYPE
|
#ifdef J_DRIVER_TYPE
|
||||||
#define AXIS5_NAME 'B' // :['B', 'C', 'U', 'V', 'W']
|
#define AXIS5_NAME 'B' // :['B', 'C', 'U', 'V', 'W']
|
||||||
#define AXIS5_ROTATES
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef K_DRIVER_TYPE
|
#ifdef K_DRIVER_TYPE
|
||||||
#define AXIS6_NAME 'C' // :['C', 'U', 'V', 'W']
|
#define AXIS6_NAME 'C' // :['C', 'U', 'V', 'W']
|
||||||
#define AXIS6_ROTATES
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// @section extruder
|
// @section extruder
|
||||||
@@ -643,7 +633,7 @@
|
|||||||
*
|
*
|
||||||
* Use a physical model of the hotend to control temperature. When configured correctly
|
* 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
|
* this gives better responsiveness and stability than PID and it also removes the need
|
||||||
* for PID_EXTRUSION_SCALING and PID_FAN_SCALING. Use M306 to autotune the model.
|
* for PID_EXTRUSION_SCALING and PID_FAN_SCALING. Use M306 T to autotune the model.
|
||||||
*/
|
*/
|
||||||
#if ENABLED(MPCTEMP)
|
#if ENABLED(MPCTEMP)
|
||||||
//#define MPC_EDIT_MENU // Add MPC editing to the "Advanced Settings" menu. (~1300 bytes of flash)
|
//#define MPC_EDIT_MENU // Add MPC editing to the "Advanced Settings" menu. (~1300 bytes of flash)
|
||||||
@@ -845,6 +835,134 @@
|
|||||||
#define POLAR_SEGMENTS_PER_SECOND 5
|
#define POLAR_SEGMENTS_PER_SECOND 5
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//============================== Endstop Settings ===========================
|
//============================== Endstop Settings ===========================
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
@@ -1001,9 +1119,9 @@
|
|||||||
* M204 R Retract Acceleration
|
* M204 R Retract Acceleration
|
||||||
* M204 T Travel Acceleration
|
* M204 T Travel Acceleration
|
||||||
*/
|
*/
|
||||||
#define DEFAULT_ACCELERATION 3000 // X, Y, Z and E acceleration for printing moves
|
#define DEFAULT_ACCELERATION 3000 // X, Y, Z ... and E acceleration for printing moves
|
||||||
#define DEFAULT_RETRACT_ACCELERATION 3000 // E acceleration for retracts
|
#define DEFAULT_RETRACT_ACCELERATION 3000 // E acceleration for retracts
|
||||||
#define DEFAULT_TRAVEL_ACCELERATION 3000 // X, Y, Z acceleration for travel (non printing) moves
|
#define DEFAULT_TRAVEL_ACCELERATION 3000 // X, Y, Z ... acceleration for travel (non printing) moves
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default Jerk limits (mm/s)
|
* Default Jerk limits (mm/s)
|
||||||
@@ -1185,9 +1303,37 @@
|
|||||||
*/
|
*/
|
||||||
//#define SENSORLESS_PROBING
|
//#define SENSORLESS_PROBING
|
||||||
|
|
||||||
//
|
/**
|
||||||
// For Z_PROBE_ALLEN_KEY see the Delta example configurations.
|
* 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
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Nozzle-to-Probe offsets { X, Y, Z }
|
* Nozzle-to-Probe offsets { X, Y, Z }
|
||||||
|
@@ -30,7 +30,7 @@
|
|||||||
*
|
*
|
||||||
* Basic settings can be found in Configuration.h
|
* Basic settings can be found in Configuration.h
|
||||||
*/
|
*/
|
||||||
#define CONFIGURATION_ADV_H_VERSION 02000904
|
#define CONFIGURATION_ADV_H_VERSION 02000905
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//============================= Thermal Settings ============================
|
//============================= Thermal Settings ============================
|
||||||
@@ -923,9 +923,12 @@
|
|||||||
*/
|
*/
|
||||||
//#define Z_STEPPER_AUTO_ALIGN
|
//#define Z_STEPPER_AUTO_ALIGN
|
||||||
#if ENABLED(Z_STEPPER_AUTO_ALIGN)
|
#if ENABLED(Z_STEPPER_AUTO_ALIGN)
|
||||||
// Define probe X and Y positions for Z1, Z2 [, Z3 [, Z4]]
|
/**
|
||||||
// If not defined, probe limits will be used.
|
* Define probe X and Y positions for Z1, Z2 [, Z3 [, Z4]]
|
||||||
// Override with 'M422 S<index> X<pos> Y<pos>'
|
* These positions are machine-relative and do not shift with the M206 home offset!
|
||||||
|
* If not defined, probe limits will be used.
|
||||||
|
* Override with 'M422 S<index> X<pos> Y<pos>'.
|
||||||
|
*/
|
||||||
//#define Z_STEPPER_ALIGN_XY { { 10, 190 }, { 100, 10 }, { 190, 190 } }
|
//#define Z_STEPPER_ALIGN_XY { { 10, 190 }, { 100, 10 }, { 190, 190 } }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -3472,6 +3475,9 @@
|
|||||||
#if ENABLED(SPINDLE_LASER_USE_PWM)
|
#if ENABLED(SPINDLE_LASER_USE_PWM)
|
||||||
#define SPINDLE_LASER_PWM_INVERT false // Set to "true" if the speed/power goes up when you want it to go slower
|
#define SPINDLE_LASER_PWM_INVERT false // Set to "true" if the speed/power goes up when you want it to go slower
|
||||||
#define SPINDLE_LASER_FREQUENCY 2500 // (Hz) Spindle/laser frequency (only on supported HALs: AVR, ESP32, and LPC)
|
#define SPINDLE_LASER_FREQUENCY 2500 // (Hz) Spindle/laser frequency (only on supported HALs: AVR, ESP32, and LPC)
|
||||||
|
// ESP32: If SPINDLE_LASER_PWM_PIN is onboard then <=78125Hz. For I2S expander
|
||||||
|
// the frequency determines the PWM resolution. 2500Hz = 0-100, 977Hz = 0-255, ...
|
||||||
|
// (250000 / SPINDLE_LASER_FREQUENCY) = max value.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//#define AIR_EVACUATION // Cutter Vacuum / Laser Blower motor control with G-codes M10-M11
|
//#define AIR_EVACUATION // Cutter Vacuum / Laser Blower motor control with G-codes M10-M11
|
||||||
@@ -3545,8 +3551,11 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Define the minimum and maximum test pulse time values for a laser test fire function
|
// Define the minimum and maximum test pulse time values for a laser test fire function
|
||||||
#define LASER_TEST_PULSE_MIN 1 // Used with Laser Control Menu
|
#define LASER_TEST_PULSE_MIN 1 // (ms) Used with Laser Control Menu
|
||||||
#define LASER_TEST_PULSE_MAX 999 // Caution: Menu may not show more than 3 characters
|
#define LASER_TEST_PULSE_MAX 999 // (ms) Caution: Menu may not show more than 3 characters
|
||||||
|
|
||||||
|
#define SPINDLE_LASER_POWERUP_DELAY 50 // (ms) Delay to allow the spindle/laser to come up to speed/power
|
||||||
|
#define SPINDLE_LASER_POWERDOWN_DELAY 50 // (ms) Delay to allow the spindle to stop
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Laser Safety Timeout
|
* Laser Safety Timeout
|
||||||
@@ -3559,16 +3568,30 @@
|
|||||||
#define LASER_SAFETY_TIMEOUT_MS 1000 // (ms)
|
#define LASER_SAFETY_TIMEOUT_MS 1000 // (ms)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable inline laser power to be handled in the planner / stepper routines.
|
* Any M3 or G1/2/3/5 command with the 'I' parameter enables continuous inline power mode.
|
||||||
* Inline power is specified by the I (inline) flag in an M3 command (e.g., M3 S20 I)
|
|
||||||
* or by the 'S' parameter in G0/G1/G2/G3 moves (see LASER_MOVE_POWER).
|
|
||||||
*
|
*
|
||||||
* This allows the laser to keep in perfect sync with the planner and removes
|
* e.g., 'M3 I' enables continuous inline power which is processed by the planner.
|
||||||
* the powerup/down delay since lasers require negligible time.
|
* Power is stored in move blocks and applied when blocks are processed by the Stepper ISR.
|
||||||
|
*
|
||||||
|
* 'M4 I' sets dynamic mode which uses the current feedrate to calculate a laser power OCR value.
|
||||||
|
*
|
||||||
|
* Any move in dynamic mode will use the current feedrate to calculate the laser power.
|
||||||
|
* Feed rates are set by the F parameter of a move command e.g. G1 X0 Y10 F6000
|
||||||
|
* Laser power would be calculated by bit shifting off 8 LSB's. In binary this is div 256.
|
||||||
|
* The calculation gives us ocr values from 0 to 255, values over F65535 will be set as 255 .
|
||||||
|
* More refined power control such as compesation for accell/decell will be addressed in future releases.
|
||||||
|
*
|
||||||
|
* M5 I clears inline mode and set power to 0, M5 sets the power output to 0 but leaves inline mode on.
|
||||||
*/
|
*/
|
||||||
//#define LASER_POWER_INLINE
|
|
||||||
|
|
||||||
#if ENABLED(LASER_POWER_INLINE)
|
/**
|
||||||
|
* Enable M3 commands for laser mode inline power planner syncing.
|
||||||
|
* This feature enables any M3 S-value to be injected into the block buffers while in
|
||||||
|
* CUTTER_MODE_CONTINUOUS. The option allows M3 laser power to be commited without waiting
|
||||||
|
* for a planner syncronization
|
||||||
|
*/
|
||||||
|
//#define LASER_POWER_SYNC
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scale the laser's power in proportion to the movement rate.
|
* Scale the laser's power in proportion to the movement rate.
|
||||||
*
|
*
|
||||||
@@ -3576,62 +3599,7 @@
|
|||||||
* - Ramps the power up every N steps to approximate the speed trapezoid.
|
* - Ramps the power up every N steps to approximate the speed trapezoid.
|
||||||
* - Due to the limited power resolution this is only approximate.
|
* - Due to the limited power resolution this is only approximate.
|
||||||
*/
|
*/
|
||||||
#define LASER_POWER_INLINE_TRAPEZOID
|
//#define LASER_POWER_TRAP
|
||||||
|
|
||||||
/**
|
|
||||||
* Continuously calculate the current power (nominal_power * current_rate / nominal_rate).
|
|
||||||
* Required for accurate power with non-trapezoidal acceleration (e.g., S_CURVE_ACCELERATION).
|
|
||||||
* This is a costly calculation so this option is discouraged on 8-bit AVR boards.
|
|
||||||
*
|
|
||||||
* LASER_POWER_INLINE_TRAPEZOID_CONT_PER defines how many step cycles there are between power updates. If your
|
|
||||||
* board isn't able to generate steps fast enough (and you are using LASER_POWER_INLINE_TRAPEZOID_CONT), increase this.
|
|
||||||
* Note that when this is zero it means it occurs every cycle; 1 means a delay wait one cycle then run, etc.
|
|
||||||
*/
|
|
||||||
//#define LASER_POWER_INLINE_TRAPEZOID_CONT
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stepper iterations between power updates. Increase this value if the board
|
|
||||||
* can't keep up with the processing demands of LASER_POWER_INLINE_TRAPEZOID_CONT.
|
|
||||||
* Disable (or set to 0) to recalculate power on every stepper iteration.
|
|
||||||
*/
|
|
||||||
//#define LASER_POWER_INLINE_TRAPEZOID_CONT_PER 10
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Include laser power in G0/G1/G2/G3/G5 commands with the 'S' parameter
|
|
||||||
*/
|
|
||||||
//#define LASER_MOVE_POWER
|
|
||||||
|
|
||||||
#if ENABLED(LASER_MOVE_POWER)
|
|
||||||
// Turn off the laser on G0 moves with no power parameter.
|
|
||||||
// If a power parameter is provided, use that instead.
|
|
||||||
//#define LASER_MOVE_G0_OFF
|
|
||||||
|
|
||||||
// Turn off the laser on G28 homing.
|
|
||||||
//#define LASER_MOVE_G28_OFF
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inline flag inverted
|
|
||||||
*
|
|
||||||
* WARNING: M5 will NOT turn off the laser unless another move
|
|
||||||
* is done (so G-code files must end with 'M5 I').
|
|
||||||
*/
|
|
||||||
//#define LASER_POWER_INLINE_INVERT
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Continuously apply inline power. ('M3 S3' == 'G1 S3' == 'M3 S3 I')
|
|
||||||
*
|
|
||||||
* The laser might do some weird things, so only enable this
|
|
||||||
* feature if you understand the implications.
|
|
||||||
*/
|
|
||||||
//#define LASER_POWER_INLINE_CONTINUOUS
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#define SPINDLE_LASER_POWERUP_DELAY 50 // (ms) Delay to allow the spindle/laser to come up to speed/power
|
|
||||||
#define SPINDLE_LASER_POWERDOWN_DELAY 50 // (ms) Delay to allow the spindle to stop
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Laser I2C Ammeter (High precision INA226 low/high side module)
|
// Laser I2C Ammeter (High precision INA226 low/high side module)
|
||||||
|
123
Marlin/Makefile
123
Marlin/Makefile
@@ -109,7 +109,7 @@ LIQUID_TWI2 ?= 0
|
|||||||
# This defines if Wire is needed
|
# This defines if Wire is needed
|
||||||
WIRE ?= 0
|
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.
|
# Disabling this (and SPEAKER) saves approximately 350 bytes of memory.
|
||||||
TONE ?= 1
|
TONE ?= 1
|
||||||
|
|
||||||
@@ -317,123 +317,10 @@ else ifeq ($(HARDWARE_MOTHERBOARD),1159)
|
|||||||
else ifeq ($(HARDWARE_MOTHERBOARD),1160)
|
else ifeq ($(HARDWARE_MOTHERBOARD),1160)
|
||||||
# Longer LKx PRO / Alfawise Uxx Pro (PRO version)
|
# Longer LKx PRO / Alfawise Uxx Pro (PRO version)
|
||||||
else ifeq ($(HARDWARE_MOTHERBOARD),1161)
|
else ifeq ($(HARDWARE_MOTHERBOARD),1161)
|
||||||
|
# Zonestar zrib V5.3 (Chinese RAMPS replica)
|
||||||
|
else ifeq ($(HARDWARE_MOTHERBOARD),1162)
|
||||||
# 3Drag Controller
|
# Pxmalion Core I3
|
||||||
else ifeq ($(HARDWARE_MOTHERBOARD),1100)
|
else ifeq ($(HARDWARE_MOTHERBOARD),1163)
|
||||||
# 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
|
# RAMBo and derivatives
|
||||||
|
@@ -28,7 +28,7 @@
|
|||||||
/**
|
/**
|
||||||
* Marlin release version identifier
|
* Marlin release version identifier
|
||||||
*/
|
*/
|
||||||
//#define SHORT_BUILD_VERSION "2.0.9.4"
|
//#define SHORT_BUILD_VERSION "bugfix-2.0.x"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verbose version identifier which should contain a reference to the location
|
* 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
|
* here we define this default string as the date where the latest release
|
||||||
* version was tagged.
|
* version was tagged.
|
||||||
*/
|
*/
|
||||||
//#define STRING_DISTRIBUTION_DATE "2022-06-04"
|
//#define STRING_DISTRIBUTION_DATE "2023-04-16"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a generic printer name to be output to the LCD after booting Marlin.
|
* Defines a generic printer name to be output to the LCD after booting Marlin.
|
||||||
|
211
Marlin/config.ini
Normal file
211
Marlin/config.ini
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
#
|
||||||
|
# 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
|
@@ -19,6 +19,10 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HAL for Arduino AVR
|
||||||
|
*/
|
||||||
|
|
||||||
#include "../shared/Marduino.h"
|
#include "../shared/Marduino.h"
|
||||||
#include "../shared/HAL_SPI.h"
|
#include "../shared/HAL_SPI.h"
|
||||||
#include "fastio.h"
|
#include "fastio.h"
|
||||||
|
@@ -66,27 +66,26 @@ static volatile int8_t Channel[_Nbr_16timers]; // counter for the s
|
|||||||
|
|
||||||
/************ static functions common to all instances ***********************/
|
/************ static functions common to all instances ***********************/
|
||||||
|
|
||||||
static inline void handle_interrupts(timer16_Sequence_t timer, volatile uint16_t* TCNTn, volatile uint16_t* OCRnA) {
|
static inline void handle_interrupts(const timer16_Sequence_t timer, volatile uint16_t* TCNTn, volatile uint16_t* OCRnA) {
|
||||||
if (Channel[timer] < 0)
|
int8_t cho = Channel[timer]; // Handle the prior Channel[timer] first
|
||||||
*TCNTn = 0; // channel set to -1 indicated that refresh interval completed so reset the timer
|
if (cho < 0) // Channel -1 indicates the refresh interval completed...
|
||||||
else {
|
*TCNTn = 0; // ...so reset the timer
|
||||||
if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && SERVO(timer, Channel[timer]).Pin.isActive)
|
else if (SERVO_INDEX(timer, cho) < ServoCount) // prior channel handled?
|
||||||
extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, LOW); // pulse this channel low if activated
|
extDigitalWrite(SERVO(timer, cho).Pin.nbr, LOW); // pulse the prior channel LOW
|
||||||
}
|
|
||||||
|
|
||||||
Channel[timer]++; // increment to the next channel
|
Channel[timer] = ++cho; // Handle the next channel (or 0)
|
||||||
if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) {
|
if (cho < SERVOS_PER_TIMER && SERVO_INDEX(timer, cho) < ServoCount) {
|
||||||
*OCRnA = *TCNTn + SERVO(timer, Channel[timer]).ticks;
|
*OCRnA = *TCNTn + SERVO(timer, cho).ticks; // set compare to current ticks plus duration
|
||||||
if (SERVO(timer, Channel[timer]).Pin.isActive) // check if activated
|
if (SERVO(timer, cho).Pin.isActive) // activated?
|
||||||
extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, HIGH); // it's an active channel so pulse it high
|
extDigitalWrite(SERVO(timer, cho).Pin.nbr, HIGH); // yes: pulse HIGH
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// finished all channels so wait for the refresh period to expire before starting over
|
// finished all channels so wait for the refresh period to expire before starting over
|
||||||
if (((unsigned)*TCNTn) + 4 < usToTicks(REFRESH_INTERVAL)) // allow a few ticks to ensure the next OCR1A not missed
|
const unsigned int cval = ((unsigned)*TCNTn) + 32 / (SERVO_TIMER_PRESCALER), // allow 32 cycles to ensure the next OCR1A not missed
|
||||||
*OCRnA = (unsigned int)usToTicks(REFRESH_INTERVAL);
|
ival = (unsigned int)usToTicks(REFRESH_INTERVAL); // at least REFRESH_INTERVAL has elapsed
|
||||||
else
|
*OCRnA = max(cval, ival);
|
||||||
*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
|
Channel[timer] = -1; // reset the timer counter to 0 on the next call
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,9 +122,12 @@ static inline void handle_interrupts(timer16_Sequence_t timer, volatile uint16_t
|
|||||||
|
|
||||||
/****************** end of static functions ******************************/
|
/****************** end of static functions ******************************/
|
||||||
|
|
||||||
void initISR(timer16_Sequence_t timer) {
|
void initISR(const timer16_Sequence_t timer_index) {
|
||||||
|
switch (timer_index) {
|
||||||
|
default: break;
|
||||||
|
|
||||||
#ifdef _useTimer1
|
#ifdef _useTimer1
|
||||||
if (timer == _timer1) {
|
case _timer1:
|
||||||
TCCR1A = 0; // normal counting mode
|
TCCR1A = 0; // normal counting mode
|
||||||
TCCR1B = _BV(CS11); // set prescaler of 8
|
TCCR1B = _BV(CS11); // set prescaler of 8
|
||||||
TCNT1 = 0; // clear the timer count
|
TCNT1 = 0; // clear the timer count
|
||||||
@@ -140,11 +142,11 @@ void initISR(timer16_Sequence_t timer) {
|
|||||||
#ifdef WIRING
|
#ifdef WIRING
|
||||||
timerAttach(TIMER1OUTCOMPAREA_INT, Timer1Service);
|
timerAttach(TIMER1OUTCOMPAREA_INT, Timer1Service);
|
||||||
#endif
|
#endif
|
||||||
}
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _useTimer3
|
#ifdef _useTimer3
|
||||||
if (timer == _timer3) {
|
case _timer3:
|
||||||
TCCR3A = 0; // normal counting mode
|
TCCR3A = 0; // normal counting mode
|
||||||
TCCR3B = _BV(CS31); // set prescaler of 8
|
TCCR3B = _BV(CS31); // set prescaler of 8
|
||||||
TCNT3 = 0; // clear the timer count
|
TCNT3 = 0; // clear the timer count
|
||||||
@@ -158,56 +160,64 @@ void initISR(timer16_Sequence_t timer) {
|
|||||||
#ifdef WIRING
|
#ifdef WIRING
|
||||||
timerAttach(TIMER3OUTCOMPAREA_INT, Timer3Service); // for Wiring platform only
|
timerAttach(TIMER3OUTCOMPAREA_INT, Timer3Service); // for Wiring platform only
|
||||||
#endif
|
#endif
|
||||||
}
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _useTimer4
|
#ifdef _useTimer4
|
||||||
if (timer == _timer4) {
|
case _timer4:
|
||||||
TCCR4A = 0; // normal counting mode
|
TCCR4A = 0; // normal counting mode
|
||||||
TCCR4B = _BV(CS41); // set prescaler of 8
|
TCCR4B = _BV(CS41); // set prescaler of 8
|
||||||
TCNT4 = 0; // clear the timer count
|
TCNT4 = 0; // clear the timer count
|
||||||
TIFR4 = _BV(OCF4A); // clear any pending interrupts;
|
TIFR4 = _BV(OCF4A); // clear any pending interrupts;
|
||||||
TIMSK4 = _BV(OCIE4A); // enable the output compare interrupt
|
TIMSK4 = _BV(OCIE4A); // enable the output compare interrupt
|
||||||
}
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _useTimer5
|
#ifdef _useTimer5
|
||||||
if (timer == _timer5) {
|
case _timer5:
|
||||||
TCCR5A = 0; // normal counting mode
|
TCCR5A = 0; // normal counting mode
|
||||||
TCCR5B = _BV(CS51); // set prescaler of 8
|
TCCR5B = _BV(CS51); // set prescaler of 8
|
||||||
TCNT5 = 0; // clear the timer count
|
TCNT5 = 0; // clear the timer count
|
||||||
TIFR5 = _BV(OCF5A); // clear any pending interrupts;
|
TIFR5 = _BV(OCF5A); // clear any pending interrupts;
|
||||||
TIMSK5 = _BV(OCIE5A); // enable the output compare interrupt
|
TIMSK5 = _BV(OCIE5A); // enable the output compare interrupt
|
||||||
}
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void finISR(timer16_Sequence_t timer) {
|
void finISR(const timer16_Sequence_t timer_index) {
|
||||||
// Disable use of the given timer
|
// Disable use of the given timer
|
||||||
#ifdef WIRING
|
#ifdef WIRING
|
||||||
if (timer == _timer1) {
|
switch (timer_index) {
|
||||||
|
default: break;
|
||||||
|
|
||||||
|
case _timer1:
|
||||||
CBI(
|
CBI(
|
||||||
#if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
|
#if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
|
||||||
TIMSK1
|
TIMSK1
|
||||||
#else
|
#else
|
||||||
TIMSK
|
TIMSK
|
||||||
#endif
|
#endif
|
||||||
, OCIE1A); // disable timer 1 output compare interrupt
|
, OCIE1A // disable timer 1 output compare interrupt
|
||||||
|
);
|
||||||
timerDetach(TIMER1OUTCOMPAREA_INT);
|
timerDetach(TIMER1OUTCOMPAREA_INT);
|
||||||
}
|
break;
|
||||||
else if (timer == _timer3) {
|
|
||||||
|
case _timer3:
|
||||||
CBI(
|
CBI(
|
||||||
#if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
|
#if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
|
||||||
TIMSK3
|
TIMSK3
|
||||||
#else
|
#else
|
||||||
ETIMSK
|
ETIMSK
|
||||||
#endif
|
#endif
|
||||||
, OCIE3A); // disable the timer3 output compare A interrupt
|
, OCIE3A // disable the timer3 output compare A interrupt
|
||||||
|
);
|
||||||
timerDetach(TIMER3OUTCOMPAREA_INT);
|
timerDetach(TIMER3OUTCOMPAREA_INT);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
#else // !WIRING
|
#else // !WIRING
|
||||||
// For arduino - in future: call here to a currently undefined function to reset the timer
|
// For arduino - in future: call here to a currently undefined function to reset the timer
|
||||||
UNUSED(timer);
|
UNUSED(timer_index);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -47,12 +47,12 @@
|
|||||||
#include "../shared/servo.h"
|
#include "../shared/servo.h"
|
||||||
#include "../shared/servo_private.h"
|
#include "../shared/servo_private.h"
|
||||||
|
|
||||||
static volatile int8_t Channel[_Nbr_16timers]; // counter for the servo being pulsed for each timer (or -1 if refresh interval)
|
static Flags<_Nbr_16timers> DisablePending; // ISR should disable the timer at the next timer reset
|
||||||
|
|
||||||
// ------------------------
|
// ------------------------
|
||||||
/// Interrupt handler for the TC0 channel 1.
|
/// Interrupt handler for the TC0 channel 1.
|
||||||
// ------------------------
|
// ------------------------
|
||||||
void Servo_Handler(timer16_Sequence_t timer, Tc *pTc, uint8_t channel);
|
void Servo_Handler(const timer16_Sequence_t, Tc*, const uint8_t);
|
||||||
|
|
||||||
#ifdef _useTimer1
|
#ifdef _useTimer1
|
||||||
void HANDLER_FOR_TIMER1() { Servo_Handler(_timer1, TC_FOR_TIMER1, CHANNEL_FOR_TIMER1); }
|
void HANDLER_FOR_TIMER1() { Servo_Handler(_timer1, TC_FOR_TIMER1, CHANNEL_FOR_TIMER1); }
|
||||||
@@ -70,88 +70,92 @@ void Servo_Handler(timer16_Sequence_t timer, Tc *pTc, uint8_t channel);
|
|||||||
void HANDLER_FOR_TIMER5() { Servo_Handler(_timer5, TC_FOR_TIMER5, CHANNEL_FOR_TIMER5); }
|
void HANDLER_FOR_TIMER5() { Servo_Handler(_timer5, TC_FOR_TIMER5, CHANNEL_FOR_TIMER5); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Servo_Handler(timer16_Sequence_t timer, Tc *tc, uint8_t channel) {
|
void Servo_Handler(const timer16_Sequence_t timer, Tc *tc, const uint8_t channel) {
|
||||||
// clear interrupt
|
static int8_t Channel[_Nbr_16timers]; // Servo counters to pulse (or -1 for refresh interval)
|
||||||
tc->TC_CHANNEL[channel].TC_SR;
|
int8_t cho = Channel[timer]; // Handle the prior Channel[timer] first
|
||||||
if (Channel[timer] < 0)
|
if (cho < 0) { // Channel -1 indicates the refresh interval completed...
|
||||||
tc->TC_CHANNEL[channel].TC_CCR |= TC_CCR_SWTRG; // channel set to -1 indicated that refresh interval completed so reset the timer
|
tc->TC_CHANNEL[channel].TC_CCR |= TC_CCR_SWTRG; // ...so reset the timer
|
||||||
else if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && SERVO(timer, Channel[timer]).Pin.isActive)
|
if (DisablePending[timer]) {
|
||||||
extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, LOW); // pulse this channel low if activated
|
// 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
|
||||||
|
|
||||||
Channel[timer]++; // increment to the next channel
|
Channel[timer] = ++cho; // go to the next channel (or 0)
|
||||||
if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) {
|
if (cho < SERVOS_PER_TIMER && SERVO_INDEX(timer, cho) < ServoCount) {
|
||||||
tc->TC_CHANNEL[channel].TC_RA = tc->TC_CHANNEL[channel].TC_CV + SERVO(timer,Channel[timer]).ticks;
|
tc->TC_CHANNEL[channel].TC_RA = tc->TC_CHANNEL[channel].TC_CV + SERVO(timer, cho).ticks;
|
||||||
if (SERVO(timer,Channel[timer]).Pin.isActive) // check if activated
|
if (SERVO(timer, cho).Pin.isActive) // activated?
|
||||||
extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, HIGH); // its an active channel so pulse it high
|
extDigitalWrite(SERVO(timer, cho).Pin.nbr, HIGH); // yes: pulse HIGH
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// finished all channels so wait for the refresh period to expire before starting over
|
// finished all channels so wait for the refresh period to expire before starting over
|
||||||
tc->TC_CHANNEL[channel].TC_RA =
|
const unsigned int cval = tc->TC_CHANNEL[channel].TC_CV + 128 / (SERVO_TIMER_PRESCALER), // allow 128 cycles to ensure the next CV not missed
|
||||||
tc->TC_CHANNEL[channel].TC_CV < usToTicks(REFRESH_INTERVAL) - 4
|
ival = (unsigned int)usToTicks(REFRESH_INTERVAL); // at least REFRESH_INTERVAL has elapsed
|
||||||
? (unsigned int)usToTicks(REFRESH_INTERVAL) // allow a few ticks to ensure the next OCR1A not missed
|
tc->TC_CHANNEL[channel].TC_RA = max(cval, ival);
|
||||||
: 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
|
Channel[timer] = -1; // reset the timer CCR on the next call
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tc->TC_CHANNEL[channel].TC_SR; // clear interrupt
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _initISR(Tc *tc, uint32_t channel, uint32_t id, IRQn_Type irqn) {
|
static void _initISR(Tc *tc, uint32_t channel, uint32_t id, IRQn_Type irqn) {
|
||||||
pmc_enable_periph_clk(id);
|
pmc_enable_periph_clk(id);
|
||||||
TC_Configure(tc, channel,
|
TC_Configure(tc, channel,
|
||||||
TC_CMR_TCCLKS_TIMER_CLOCK3 | // MCK/32
|
TC_CMR_WAVE // Waveform mode
|
||||||
TC_CMR_WAVE | // Waveform mode
|
| TC_CMR_WAVSEL_UP_RC // Counter running up and reset when equal to RC
|
||||||
TC_CMR_WAVSEL_UP_RC ); // Counter running up and reset when equals 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
|
||||||
|
);
|
||||||
|
|
||||||
/* 84MHz, MCK/32, for 1.5ms: 3937 */
|
// Wait 1ms before the first ISR
|
||||||
TC_SetRA(tc, channel, 2625); // 1ms
|
TC_SetRA(tc, channel, (F_CPU) / (SERVO_TIMER_PRESCALER) / 1000UL); // 1ms
|
||||||
|
|
||||||
/* Configure and enable interrupt */
|
// Configure and enable interrupt
|
||||||
NVIC_EnableIRQ(irqn);
|
NVIC_EnableIRQ(irqn);
|
||||||
// TC_IER_CPAS: RA Compare
|
tc->TC_CHANNEL[channel].TC_IER = TC_IER_CPAS; // 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
|
// Enables the timer clock and performs a software reset to start the counting
|
||||||
TC_Start(tc, channel);
|
TC_Start(tc, channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void initISR(timer16_Sequence_t timer) {
|
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
|
#ifdef _useTimer1
|
||||||
if (timer == _timer1)
|
case _timer1: return _initISR(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1, ID_TC_FOR_TIMER1, IRQn_FOR_TIMER1);
|
||||||
_initISR(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1, ID_TC_FOR_TIMER1, IRQn_FOR_TIMER1);
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef _useTimer2
|
#ifdef _useTimer2
|
||||||
if (timer == _timer2)
|
case _timer2: return _initISR(TC_FOR_TIMER2, CHANNEL_FOR_TIMER2, ID_TC_FOR_TIMER2, IRQn_FOR_TIMER2);
|
||||||
_initISR(TC_FOR_TIMER2, CHANNEL_FOR_TIMER2, ID_TC_FOR_TIMER2, IRQn_FOR_TIMER2);
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef _useTimer3
|
#ifdef _useTimer3
|
||||||
if (timer == _timer3)
|
case _timer3: return _initISR(TC_FOR_TIMER3, CHANNEL_FOR_TIMER3, ID_TC_FOR_TIMER3, IRQn_FOR_TIMER3);
|
||||||
_initISR(TC_FOR_TIMER3, CHANNEL_FOR_TIMER3, ID_TC_FOR_TIMER3, IRQn_FOR_TIMER3);
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef _useTimer4
|
#ifdef _useTimer4
|
||||||
if (timer == _timer4)
|
case _timer4: return _initISR(TC_FOR_TIMER4, CHANNEL_FOR_TIMER4, ID_TC_FOR_TIMER4, IRQn_FOR_TIMER4);
|
||||||
_initISR(TC_FOR_TIMER4, CHANNEL_FOR_TIMER4, ID_TC_FOR_TIMER4, IRQn_FOR_TIMER4);
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef _useTimer5
|
#ifdef _useTimer5
|
||||||
if (timer == _timer5)
|
case _timer5: return _initISR(TC_FOR_TIMER5, CHANNEL_FOR_TIMER5, ID_TC_FOR_TIMER5, IRQn_FOR_TIMER5);
|
||||||
_initISR(TC_FOR_TIMER5, CHANNEL_FOR_TIMER5, ID_TC_FOR_TIMER5, IRQn_FOR_TIMER5);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void finISR(timer16_Sequence_t) {
|
void finISR(const timer16_Sequence_t timer_index) {
|
||||||
#ifdef _useTimer1
|
// Timer is disabled from the ISR, to ensure proper final pulse length.
|
||||||
TC_Stop(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1);
|
DisablePending.set(timer_index);
|
||||||
#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
|
#endif // HAS_SERVOS
|
||||||
|
@@ -37,7 +37,7 @@
|
|||||||
#define _useTimer5
|
#define _useTimer5
|
||||||
|
|
||||||
#define TRIM_DURATION 2 // compensation ticks to trim adjust for digitalWrite delays
|
#define TRIM_DURATION 2 // compensation ticks to trim adjust for digitalWrite delays
|
||||||
#define SERVO_TIMER_PRESCALER 32 // timer prescaler
|
#define SERVO_TIMER_PRESCALER 2 // timer prescaler
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TC0, chan 0 => TC0_Handler
|
TC0, chan 0 => TC0_Handler
|
||||||
|
@@ -89,10 +89,17 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
|
|||||||
NVIC_SetPriority(irq, timer_config[timer_num].priority);
|
NVIC_SetPriority(irq, timer_config[timer_num].priority);
|
||||||
|
|
||||||
// wave mode, reset counter on match with RC,
|
// wave mode, reset counter on match with RC,
|
||||||
TC_Configure(tc, channel, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK1);
|
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)
|
||||||
|
);
|
||||||
|
|
||||||
// Set compare value
|
// Set compare value
|
||||||
TC_SetRC(tc, channel, VARIANT_MCK / 2 / frequency);
|
TC_SetRC(tc, channel, VARIANT_MCK / (HAL_TIMER_PRESCALER) / frequency);
|
||||||
|
|
||||||
// And start timer
|
// And start timer
|
||||||
TC_Start(tc, channel);
|
TC_Start(tc, channel);
|
||||||
|
@@ -35,7 +35,8 @@
|
|||||||
typedef uint32_t hal_timer_t;
|
typedef uint32_t hal_timer_t;
|
||||||
#define HAL_TIMER_TYPE_MAX 0xFFFFFFFF
|
#define HAL_TIMER_TYPE_MAX 0xFFFFFFFF
|
||||||
|
|
||||||
#define HAL_TIMER_RATE ((F_CPU) / 2) // frequency of timers peripherals
|
#define HAL_TIMER_PRESCALER 2
|
||||||
|
#define HAL_TIMER_RATE ((F_CPU) / (HAL_TIMER_PRESCALER)) // frequency of timers peripherals
|
||||||
|
|
||||||
#ifndef MF_TIMER_STEP
|
#ifndef MF_TIMER_STEP
|
||||||
#define MF_TIMER_STEP 2 // Timer Index for Stepper
|
#define MF_TIMER_STEP 2 // Timer Index for Stepper
|
||||||
|
@@ -1059,7 +1059,7 @@ static inline void convert_64_bit_to_byte_array(uint64_t value, uint8_t *data)
|
|||||||
while (val_index < 8)
|
while (val_index < 8)
|
||||||
{
|
{
|
||||||
data[val_index++] = value & 0xFF;
|
data[val_index++] = value & 0xFF;
|
||||||
value = value >> 8;
|
value >>= 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -65,6 +65,7 @@ portMUX_TYPE MarlinHAL::spinlock = portMUX_INITIALIZER_UNLOCKED;
|
|||||||
// ------------------------
|
// ------------------------
|
||||||
|
|
||||||
uint16_t MarlinHAL::adc_result;
|
uint16_t MarlinHAL::adc_result;
|
||||||
|
pwm_pin_t MarlinHAL::pwm_pin_data[MAX_EXPANDER_BITS];
|
||||||
|
|
||||||
// ------------------------
|
// ------------------------
|
||||||
// Private Variables
|
// Private Variables
|
||||||
@@ -330,14 +331,38 @@ 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*/) {
|
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);
|
const int8_t cid = get_pwm_channel(pin, PWM_FREQUENCY, PWM_RESOLUTION);
|
||||||
if (cid >= 0) {
|
if (cid >= 0) {
|
||||||
uint32_t duty = map(invert ? v_size - v : v, 0, v_size, 0, _BV(PWM_RESOLUTION)-1);
|
const uint32_t duty = map(invert ? v_size - v : v, 0, v_size, 0, _BV(PWM_RESOLUTION)-1);
|
||||||
ledcWrite(cid, duty);
|
ledcWrite(cid, duty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int8_t MarlinHAL::set_pwm_frequency(const pin_t pin, const uint32_t f_desired) {
|
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);
|
const int8_t cid = channel_for_pin(pin);
|
||||||
if (cid >= 0) {
|
if (cid >= 0) {
|
||||||
if (f_desired == ledcReadFreq(cid)) return cid; // no freq change
|
if (f_desired == ledcReadFreq(cid)) return cid; // no freq change
|
||||||
@@ -346,6 +371,7 @@ int8_t MarlinHAL::set_pwm_frequency(const pin_t pin, const uint32_t f_desired) {
|
|||||||
}
|
}
|
||||||
return get_pwm_channel(pin, f_desired, PWM_RESOLUTION); // try for new one
|
return get_pwm_channel(pin, f_desired, PWM_RESOLUTION); // try for new one
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// use hardware PWM if avail, if not then ISR
|
// use hardware PWM if avail, if not then ISR
|
||||||
void analogWrite(const pin_t pin, const uint16_t value, const uint32_t freq/*=PWM_FREQUENCY*/, const uint16_t res/*=8*/) { // always 8 bit resolution!
|
void analogWrite(const pin_t pin, const uint16_t value, const uint32_t freq/*=PWM_FREQUENCY*/, const uint16_t res/*=8*/) { // always 8 bit resolution!
|
||||||
|
@@ -60,14 +60,17 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define CRITICAL_SECTION_START() portENTER_CRITICAL(&spinlock)
|
#define CRITICAL_SECTION_START() portENTER_CRITICAL(&hal.spinlock)
|
||||||
#define CRITICAL_SECTION_END() portEXIT_CRITICAL(&spinlock)
|
#define CRITICAL_SECTION_END() portEXIT_CRITICAL(&hal.spinlock)
|
||||||
|
|
||||||
#define HAL_CAN_SET_PWM_FREQ // This HAL supports PWM Frequency adjustment
|
#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_FREQUENCY 1000u // Default PWM frequency when set_pwm_duty() is called without set_pwm_frequency()
|
||||||
#define PWM_RESOLUTION 10u // Default PWM bit resolution
|
#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 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
|
#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
|
// Types
|
||||||
@@ -76,6 +79,12 @@
|
|||||||
typedef double isr_float_t; // FPU ops are used for single-precision, so use double for ISRs.
|
typedef double isr_float_t; // FPU ops are used for single-precision, so use double for ISRs.
|
||||||
typedef int16_t pin_t;
|
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;
|
class Servo;
|
||||||
typedef Servo hal_servo_t;
|
typedef Servo hal_servo_t;
|
||||||
|
|
||||||
@@ -197,6 +206,8 @@ public:
|
|||||||
// Free SRAM
|
// Free SRAM
|
||||||
static int freeMemory();
|
static int freeMemory();
|
||||||
|
|
||||||
|
static pwm_pin_t pwm_pin_data[MAX_EXPANDER_BITS];
|
||||||
|
|
||||||
//
|
//
|
||||||
// ADC Methods
|
// ADC Methods
|
||||||
//
|
//
|
||||||
|
@@ -337,6 +337,26 @@ uint8_t i2s_state(uint8_t pin) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void i2s_push_sample() {
|
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;
|
dma.current[dma.rw_pos++] = i2s_port_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -20,3 +20,10 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#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
|
||||||
|
@@ -48,3 +48,7 @@
|
|||||||
#if USING_PULLDOWNS
|
#if USING_PULLDOWNS
|
||||||
#error "PULLDOWN pin mode is not available on ESP32 boards."
|
#error "PULLDOWN pin mode is not available on ESP32 boards."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if BOTH(I2S_STEPPER_STREAM, LIN_ADVANCE)
|
||||||
|
#error "I2S stream is currently incompatible with LIN_ADVANCE."
|
||||||
|
#endif
|
||||||
|
@@ -74,7 +74,7 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
|
|||||||
}
|
}
|
||||||
|
|
||||||
crc16(crc, value, size);
|
crc16(crc, value, size);
|
||||||
pos = pos + size;
|
pos += size;
|
||||||
return (bytes_written != size); // return true for any error
|
return (bytes_written != size); // return true for any error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,7 +96,7 @@ bool PersistentStore::read_data(int &pos, uint8_t *value, const size_t size, uin
|
|||||||
crc16(crc, temp, size);
|
crc16(crc, temp, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
pos = pos + size;
|
pos += size;
|
||||||
return bytes_read != size; // return true for any error
|
return bytes_read != size; // return true for any error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -26,8 +26,8 @@
|
|||||||
struct LowpassFilter {
|
struct LowpassFilter {
|
||||||
uint64_t data_delay = 0;
|
uint64_t data_delay = 0;
|
||||||
uint16_t update(uint16_t value) {
|
uint16_t update(uint16_t value) {
|
||||||
data_delay = data_delay - (data_delay >> 6) + value;
|
data_delay += value - (data_delay >> 6);
|
||||||
return (uint16_t)(data_delay >> 6);
|
return uint16_t(data_delay >> 6);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -12,7 +12,7 @@ if pioutil.is_pio_build():
|
|||||||
target_filename = "FIRMWARE.CUR"
|
target_filename = "FIRMWARE.CUR"
|
||||||
target_drive = "REARM"
|
target_drive = "REARM"
|
||||||
|
|
||||||
import os,getpass,platform
|
import platform
|
||||||
|
|
||||||
current_OS = platform.system()
|
current_OS = platform.system()
|
||||||
Import("env")
|
Import("env")
|
||||||
@@ -26,6 +26,7 @@ if pioutil.is_pio_build():
|
|||||||
|
|
||||||
def before_upload(source, target, env):
|
def before_upload(source, target, env):
|
||||||
try:
|
try:
|
||||||
|
from pathlib import Path
|
||||||
#
|
#
|
||||||
# Find a disk for upload
|
# Find a disk for upload
|
||||||
#
|
#
|
||||||
@@ -38,6 +39,7 @@ if pioutil.is_pio_build():
|
|||||||
# Windows - doesn't care about the disk's name, only cares about the drive letter
|
# Windows - doesn't care about the disk's name, only cares about the drive letter
|
||||||
import subprocess,string
|
import subprocess,string
|
||||||
from ctypes import windll
|
from ctypes import windll
|
||||||
|
from pathlib import PureWindowsPath
|
||||||
|
|
||||||
# getting list of drives
|
# getting list of drives
|
||||||
# https://stackoverflow.com/questions/827371/is-there-a-way-to-list-all-the-available-drive-letters-in-python
|
# https://stackoverflow.com/questions/827371/is-there-a-way-to-list-all-the-available-drive-letters-in-python
|
||||||
@@ -49,7 +51,7 @@ if pioutil.is_pio_build():
|
|||||||
bitmask >>= 1
|
bitmask >>= 1
|
||||||
|
|
||||||
for drive in drives:
|
for drive in drives:
|
||||||
final_drive_name = drive + ':\\'
|
final_drive_name = drive + ':'
|
||||||
# print ('disc check: {}'.format(final_drive_name))
|
# print ('disc check: {}'.format(final_drive_name))
|
||||||
try:
|
try:
|
||||||
volume_info = str(subprocess.check_output('cmd /C dir ' + final_drive_name, stderr=subprocess.STDOUT))
|
volume_info = str(subprocess.check_output('cmd /C dir ' + final_drive_name, stderr=subprocess.STDOUT))
|
||||||
@@ -59,29 +61,33 @@ if pioutil.is_pio_build():
|
|||||||
else:
|
else:
|
||||||
if target_drive in volume_info and not target_file_found: # set upload if not found target file yet
|
if target_drive in volume_info and not target_file_found: # set upload if not found target file yet
|
||||||
target_drive_found = True
|
target_drive_found = True
|
||||||
upload_disk = final_drive_name
|
upload_disk = PureWindowsPath(final_drive_name)
|
||||||
if target_filename in volume_info:
|
if target_filename in volume_info:
|
||||||
if not target_file_found:
|
if not target_file_found:
|
||||||
upload_disk = final_drive_name
|
upload_disk = PureWindowsPath(final_drive_name)
|
||||||
target_file_found = True
|
target_file_found = True
|
||||||
|
|
||||||
elif current_OS == 'Linux':
|
elif current_OS == 'Linux':
|
||||||
#
|
#
|
||||||
# platformio.ini will accept this for a Linux upload port designation: 'upload_port = /media/media_name/drive'
|
# 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()))
|
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.
|
if target_drive in drives: # If target drive is found, use it.
|
||||||
target_drive_found = True
|
target_drive_found = True
|
||||||
upload_disk = os.path.join(os.sep, 'media', getpass.getuser(), target_drive) + os.sep
|
upload_disk = mpath / target_drive
|
||||||
else:
|
else:
|
||||||
for drive in drives:
|
for drive in drives:
|
||||||
try:
|
try:
|
||||||
files = os.listdir(os.path.join(os.sep, 'media', getpass.getuser(), drive))
|
fpath = mpath / drive
|
||||||
|
filenames = [ x.name for x in fpath.iterdir() if x.is_file() ]
|
||||||
except:
|
except:
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
if target_filename in files:
|
if target_filename in filenames:
|
||||||
upload_disk = os.path.join(os.sep, 'media', getpass.getuser(), drive) + os.sep
|
upload_disk = mpath / drive
|
||||||
target_file_found = True
|
target_file_found = True
|
||||||
break
|
break
|
||||||
#
|
#
|
||||||
@@ -97,26 +103,28 @@ if pioutil.is_pio_build():
|
|||||||
#
|
#
|
||||||
# platformio.ini will accept this for a OSX upload port designation: 'upload_port = /media/media_name/drive'
|
# platformio.ini will accept this for a OSX upload port designation: 'upload_port = /media/media_name/drive'
|
||||||
#
|
#
|
||||||
drives = os.listdir('/Volumes') # human readable names
|
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
|
if target_drive in drives and not target_file_found: # set upload if not found target file yet
|
||||||
target_drive_found = True
|
target_drive_found = True
|
||||||
upload_disk = '/Volumes/' + target_drive + '/'
|
upload_disk = dpath / target_drive
|
||||||
for drive in drives:
|
for drive in drives:
|
||||||
try:
|
try:
|
||||||
filenames = os.listdir('/Volumes/' + drive + '/') # will get an error if the drive is protected
|
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:
|
except:
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
if target_filename in filenames:
|
if target_filename in filenames:
|
||||||
if not target_file_found:
|
upload_disk = dpath / drive
|
||||||
upload_disk = '/Volumes/' + drive + '/'
|
|
||||||
target_file_found = True
|
target_file_found = True
|
||||||
|
break
|
||||||
|
|
||||||
#
|
#
|
||||||
# Set upload_port to drive if found
|
# Set upload_port to drive if found
|
||||||
#
|
#
|
||||||
if target_file_found or target_drive_found:
|
if target_file_found or target_drive_found:
|
||||||
env.Replace(UPLOAD_PORT=upload_disk)
|
env.Replace(UPLOAD_PORT=str(upload_disk))
|
||||||
print('\nUpload disk: ', upload_disk, '\n')
|
print('\nUpload disk: ', upload_disk, '\n')
|
||||||
else:
|
else:
|
||||||
print_error('Autodetect Error')
|
print_error('Autodetect Error')
|
||||||
|
@@ -598,7 +598,7 @@ void MarlinHAL::dma_init() {
|
|||||||
void MarlinHAL::init() {
|
void MarlinHAL::init() {
|
||||||
TERN_(DMA_IS_REQUIRED, dma_init());
|
TERN_(DMA_IS_REQUIRED, dma_init());
|
||||||
#if ENABLED(SDSUPPORT)
|
#if ENABLED(SDSUPPORT)
|
||||||
#if SD_CONNECTION_IS(ONBOARD) && PIN_EXISTS(SD_DETECT)
|
#if HAS_SD_DETECT && SD_CONNECTION_IS(ONBOARD)
|
||||||
SET_INPUT_PULLUP(SD_DETECT_PIN);
|
SET_INPUT_PULLUP(SD_DETECT_PIN);
|
||||||
#endif
|
#endif
|
||||||
OUT_WRITE(SDSS, HIGH); // Try to set SDSS inactive before any other SPI users start up
|
OUT_WRITE(SDSS, HIGH); // Try to set SDSS inactive before any other SPI users start up
|
||||||
|
@@ -77,7 +77,8 @@ HAL_SERVO_TIMER_ISR() {
|
|||||||
;
|
;
|
||||||
const uint8_t tcChannel = TIMER_TCCHANNEL(timer);
|
const uint8_t tcChannel = TIMER_TCCHANNEL(timer);
|
||||||
|
|
||||||
if (currentServoIndex[timer] < 0) {
|
int8_t cho = currentServoIndex[timer]; // Handle the prior servo first
|
||||||
|
if (cho < 0) { // Servo -1 indicates the refresh interval completed...
|
||||||
#if defined(_useTimer1) && defined(_useTimer2)
|
#if defined(_useTimer1) && defined(_useTimer2)
|
||||||
if (currentServoIndex[timer ^ 1] >= 0) {
|
if (currentServoIndex[timer ^ 1] >= 0) {
|
||||||
// Wait for both channels
|
// Wait for both channels
|
||||||
@@ -86,45 +87,37 @@ HAL_SERVO_TIMER_ISR() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
tc->COUNT16.COUNT.reg = TC_COUNTER_START_VAL;
|
tc->COUNT16.COUNT.reg = TC_COUNTER_START_VAL; // ...so reset the timer
|
||||||
SYNC(tc->COUNT16.SYNCBUSY.bit.COUNT);
|
SYNC(tc->COUNT16.SYNCBUSY.bit.COUNT);
|
||||||
}
|
}
|
||||||
else if (SERVO_INDEX(timer, currentServoIndex[timer]) < ServoCount && SERVO(timer, currentServoIndex[timer]).Pin.isActive)
|
else if (SERVO_INDEX(timer, cho) < ServoCount) // prior channel handled?
|
||||||
digitalWrite(SERVO(timer, currentServoIndex[timer]).Pin.nbr, LOW); // pulse this channel low if activated
|
digitalWrite(SERVO(timer, cho).Pin.nbr, LOW); // pulse the prior channel LOW
|
||||||
|
|
||||||
// Select the next servo controlled by this timer
|
currentServoIndex[timer] = ++cho; // go to the next channel (or 0)
|
||||||
currentServoIndex[timer]++;
|
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
|
||||||
|
|
||||||
if (SERVO_INDEX(timer, currentServoIndex[timer]) < ServoCount && currentServoIndex[timer] < SERVOS_PER_TIMER) {
|
tc->COUNT16.CC[tcChannel].reg = getTimerCount() - (uint16_t)SERVO(timer, cho).ticks;
|
||||||
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 {
|
else {
|
||||||
// finished all channels so wait for the refresh period to expire before starting over
|
// finished all channels so wait for the refresh period to expire before starting over
|
||||||
currentServoIndex[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel
|
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
|
||||||
const uint16_t tcCounterValue = getTimerCount();
|
ival = (TC_COUNTER_START_VAL) - (uint16_t)usToTicks(REFRESH_INTERVAL); // at least REFRESH_INTERVAL has elapsed
|
||||||
|
tc->COUNT16.CC[tcChannel].reg = min(cval, ival);
|
||||||
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) {
|
if (tcChannel == 0) {
|
||||||
SYNC(tc->COUNT16.SYNCBUSY.bit.CC0);
|
SYNC(tc->COUNT16.SYNCBUSY.bit.CC0);
|
||||||
// Clear the interrupt
|
tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC0; // Clear the interrupt
|
||||||
tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC0;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
SYNC(tc->COUNT16.SYNCBUSY.bit.CC1);
|
SYNC(tc->COUNT16.SYNCBUSY.bit.CC1);
|
||||||
// Clear the interrupt
|
tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC1; // Clear the interrupt
|
||||||
tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void initISR(timer16_Sequence_t timer) {
|
void initISR(const timer16_Sequence_t timer) {
|
||||||
Tc * const tc = timer_config[SERVO_TC].pTc;
|
Tc * const tc = timer_config[SERVO_TC].pTc;
|
||||||
const uint8_t tcChannel = TIMER_TCCHANNEL(timer);
|
const uint8_t tcChannel = TIMER_TCCHANNEL(timer);
|
||||||
|
|
||||||
@@ -201,9 +194,9 @@ void initISR(timer16_Sequence_t timer) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void finISR(timer16_Sequence_t timer) {
|
void finISR(const timer16_Sequence_t timer_index) {
|
||||||
Tc * const tc = timer_config[SERVO_TC].pTc;
|
Tc * const tc = timer_config[SERVO_TC].pTc;
|
||||||
const uint8_t tcChannel = TIMER_TCCHANNEL(timer);
|
const uint8_t tcChannel = TIMER_TCCHANNEL(timer_index);
|
||||||
|
|
||||||
// Disable the match channel interrupt request
|
// Disable the match channel interrupt request
|
||||||
tc->COUNT16.INTENCLR.reg = (tcChannel == 0) ? TC_INTENCLR_MC0 : TC_INTENCLR_MC1;
|
tc->COUNT16.INTENCLR.reg = (tcChannel == 0) ? TC_INTENCLR_MC0 : TC_INTENCLR_MC1;
|
||||||
|
@@ -33,155 +33,41 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
// use local drivers
|
|
||||||
#if defined(STM32F103xE) || defined(STM32F103xG)
|
#if defined(STM32F103xE) || defined(STM32F103xG)
|
||||||
#include <stm32f1xx.h>
|
#include <stm32f1xx_hal_rcc_ex.h>
|
||||||
|
#include <stm32f1xx_hal_sd.h>
|
||||||
#elif defined(STM32F4xx)
|
#elif defined(STM32F4xx)
|
||||||
#include <stm32f4xx.h>
|
#include <stm32f4xx_hal_rcc.h>
|
||||||
|
#include <stm32f4xx_hal_dma.h>
|
||||||
|
#include <stm32f4xx_hal_gpio.h>
|
||||||
|
#include <stm32f4xx_hal_sd.h>
|
||||||
#elif defined(STM32F7xx)
|
#elif defined(STM32F7xx)
|
||||||
#include <stm32f7xx.h>
|
#include <stm32f7xx_hal_rcc.h>
|
||||||
|
#include <stm32f7xx_hal_dma.h>
|
||||||
|
#include <stm32f7xx_hal_gpio.h>
|
||||||
|
#include <stm32f7xx_hal_sd.h>
|
||||||
#elif defined(STM32H7xx)
|
#elif defined(STM32H7xx)
|
||||||
#include <stm32h7xx.h>
|
#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
|
#else
|
||||||
#error "SDIO only supported with STM32F103xE, STM32F103xG, STM32F4xx, STM32F7xx, or STM32H7xx."
|
#error "SDIO is only supported with STM32F103xE, STM32F103xG, STM32F4xx, STM32F7xx, and STM32H7xx."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// SDIO Max Clock (naming from STM Manual, don't change)
|
||||||
|
#define SDIOCLK 48000000
|
||||||
|
|
||||||
// Target Clock, configurable. Default is 18MHz, from STM32F1
|
// Target Clock, configurable. Default is 18MHz, from STM32F1
|
||||||
#ifndef SDIO_CLOCK
|
#ifndef SDIO_CLOCK
|
||||||
#define SDIO_CLOCK 18000000 // 18 MHz
|
#define SDIO_CLOCK 18000000 // 18 MHz
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define SD_TIMEOUT 1000 // ms
|
SD_HandleTypeDef hsd; // SDIO structure
|
||||||
|
|
||||||
// SDIO Max Clock (naming from STM Manual, don't change)
|
|
||||||
#define SDIOCLK 48000000
|
|
||||||
|
|
||||||
#if defined(STM32F1xx)
|
|
||||||
DMA_HandleTypeDef hdma_sdio;
|
|
||||||
extern "C" void DMA2_Channel4_5_IRQHandler(void) {
|
|
||||||
HAL_DMA_IRQHandler(&hdma_sdio);
|
|
||||||
}
|
|
||||||
#elif defined(STM32F4xx)
|
|
||||||
DMA_HandleTypeDef hdma_sdio_rx;
|
|
||||||
DMA_HandleTypeDef hdma_sdio_tx;
|
|
||||||
extern "C" void DMA2_Stream3_IRQHandler(void) {
|
|
||||||
HAL_DMA_IRQHandler(&hdma_sdio_rx);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void DMA2_Stream6_IRQHandler(void) {
|
|
||||||
HAL_DMA_IRQHandler(&hdma_sdio_tx);
|
|
||||||
}
|
|
||||||
#elif defined(STM32H7xx)
|
|
||||||
#define __HAL_RCC_SDIO_FORCE_RESET __HAL_RCC_SDMMC1_FORCE_RESET
|
|
||||||
#define __HAL_RCC_SDIO_RELEASE_RESET __HAL_RCC_SDMMC1_RELEASE_RESET
|
|
||||||
#define __HAL_RCC_SDIO_CLK_ENABLE __HAL_RCC_SDMMC1_CLK_ENABLE
|
|
||||||
#define SDIO SDMMC1
|
|
||||||
#define SDIO_IRQn SDMMC1_IRQn
|
|
||||||
#define SDIO_IRQHandler SDMMC1_IRQHandler
|
|
||||||
#define SDIO_CLOCK_EDGE_RISING SDMMC_CLOCK_EDGE_RISING
|
|
||||||
#define SDIO_CLOCK_POWER_SAVE_DISABLE SDMMC_CLOCK_POWER_SAVE_DISABLE
|
|
||||||
#define SDIO_BUS_WIDE_1B SDMMC_BUS_WIDE_1B
|
|
||||||
#define SDIO_BUS_WIDE_4B SDMMC_BUS_WIDE_4B
|
|
||||||
#define SDIO_HARDWARE_FLOW_CONTROL_DISABLE SDMMC_HARDWARE_FLOW_CONTROL_DISABLE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint8_t waitingRxCplt = 0;
|
|
||||||
uint8_t waitingTxCplt = 0;
|
|
||||||
SD_HandleTypeDef hsd;
|
|
||||||
|
|
||||||
extern "C" void SDIO_IRQHandler(void) {
|
|
||||||
HAL_SD_IRQHandler(&hsd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsdio) {
|
|
||||||
waitingTxCplt = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsdio) {
|
|
||||||
waitingRxCplt = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HAL_SD_MspInit(SD_HandleTypeDef *hsd) {
|
|
||||||
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 if have a four bit wide SDIO bus
|
|
||||||
// D1-D3
|
|
||||||
pinmap_pinout(PC_9, PinMap_SD);
|
|
||||||
pinmap_pinout(PC_10, PinMap_SD);
|
|
||||||
pinmap_pinout(PC_11, PinMap_SD);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
__HAL_RCC_SDIO_CLK_ENABLE();
|
|
||||||
HAL_NVIC_EnableIRQ(SDIO_IRQn);
|
|
||||||
|
|
||||||
// DMA Config
|
|
||||||
#if defined(STM32F1xx)
|
|
||||||
__HAL_RCC_DMA2_CLK_ENABLE();
|
|
||||||
HAL_NVIC_EnableIRQ(DMA2_Channel4_5_IRQn);
|
|
||||||
hdma_sdio.Instance = DMA2_Channel4;
|
|
||||||
hdma_sdio.Init.Direction = DMA_PERIPH_TO_MEMORY;
|
|
||||||
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.Mode = DMA_NORMAL;
|
|
||||||
hdma_sdio.Init.Priority = DMA_PRIORITY_LOW;
|
|
||||||
HAL_DMA_Init(&hdma_sdio);
|
|
||||||
|
|
||||||
__HAL_LINKDMA(hsd, hdmarx ,hdma_sdio);
|
|
||||||
__HAL_LINKDMA(hsd, hdmatx, hdma_sdio);
|
|
||||||
#elif defined(STM32F4xx)
|
|
||||||
__HAL_RCC_DMA2_CLK_ENABLE();
|
|
||||||
HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
|
|
||||||
HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn);
|
|
||||||
hdma_sdio_rx.Instance = DMA2_Stream3;
|
|
||||||
hdma_sdio_rx.Init.Channel = DMA_CHANNEL_4;
|
|
||||||
hdma_sdio_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
|
|
||||||
hdma_sdio_rx.Init.PeriphInc = DMA_PINC_DISABLE;
|
|
||||||
hdma_sdio_rx.Init.MemInc = DMA_MINC_ENABLE;
|
|
||||||
hdma_sdio_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
|
|
||||||
hdma_sdio_rx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
|
|
||||||
hdma_sdio_rx.Init.Mode = DMA_PFCTRL;
|
|
||||||
hdma_sdio_rx.Init.Priority = DMA_PRIORITY_LOW;
|
|
||||||
hdma_sdio_rx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
|
|
||||||
hdma_sdio_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
|
|
||||||
hdma_sdio_rx.Init.MemBurst = DMA_MBURST_INC4;
|
|
||||||
hdma_sdio_rx.Init.PeriphBurst = DMA_PBURST_INC4;
|
|
||||||
HAL_DMA_Init(&hdma_sdio_rx);
|
|
||||||
|
|
||||||
__HAL_LINKDMA(hsd,hdmarx,hdma_sdio_rx);
|
|
||||||
|
|
||||||
hdma_sdio_tx.Instance = DMA2_Stream6;
|
|
||||||
hdma_sdio_tx.Init.Channel = DMA_CHANNEL_4;
|
|
||||||
hdma_sdio_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
|
|
||||||
hdma_sdio_tx.Init.PeriphInc = DMA_PINC_DISABLE;
|
|
||||||
hdma_sdio_tx.Init.MemInc = DMA_MINC_ENABLE;
|
|
||||||
hdma_sdio_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
|
|
||||||
hdma_sdio_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
|
|
||||||
hdma_sdio_tx.Init.Mode = DMA_PFCTRL;
|
|
||||||
hdma_sdio_tx.Init.Priority = DMA_PRIORITY_LOW;
|
|
||||||
hdma_sdio_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
|
|
||||||
hdma_sdio_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
|
|
||||||
hdma_sdio_tx.Init.MemBurst = DMA_MBURST_INC4;
|
|
||||||
hdma_sdio_tx.Init.PeriphBurst = DMA_PBURST_INC4;
|
|
||||||
HAL_DMA_Init(&hdma_sdio_tx);
|
|
||||||
|
|
||||||
__HAL_LINKDMA(hsd,hdmatx,hdma_sdio_tx);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void HAL_SD_MspDeInit(SD_HandleTypeDef *hsd) {
|
|
||||||
#if !defined(STM32F1xx)
|
|
||||||
__HAL_RCC_SDIO_FORCE_RESET();
|
|
||||||
delay(10);
|
|
||||||
__HAL_RCC_SDIO_RELEASE_RESET();
|
|
||||||
delay(10);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t clock_to_divider(uint32_t clk) {
|
static uint32_t clock_to_divider(uint32_t clk) {
|
||||||
#if defined(STM32H7xx)
|
#ifdef SDIO_FOR_STM32H7
|
||||||
// SDMMC_CK frequency = sdmmc_ker_ck / [2 * CLKDIV].
|
// SDMMC_CK frequency = sdmmc_ker_ck / [2 * CLKDIV].
|
||||||
uint32_t sdmmc_clk = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SDMMC);
|
uint32_t sdmmc_clk = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SDMMC);
|
||||||
return sdmmc_clk / (2U * SDIO_CLOCK) + (sdmmc_clk % (2U * SDIO_CLOCK) != 0);
|
return sdmmc_clk / (2U * SDIO_CLOCK) + (sdmmc_clk % (2U * SDIO_CLOCK) != 0);
|
||||||
@@ -198,35 +84,305 @@ static uint32_t clock_to_divider(uint32_t clk) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SDIO_FOR_STM32H7
|
||||||
|
|
||||||
|
#define SD_TIMEOUT 1000 // ms
|
||||||
|
|
||||||
|
extern "C" void SDMMC1_IRQHandler(void) { HAL_SD_IRQHandler(&hsd); }
|
||||||
|
|
||||||
|
uint8_t waitingRxCplt = 0, waitingTxCplt = 0;
|
||||||
|
void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsdio) { waitingTxCplt = 0; }
|
||||||
|
void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsdio) { waitingRxCplt = 0; }
|
||||||
|
|
||||||
|
void HAL_SD_MspDeInit(SD_HandleTypeDef *hsd) {
|
||||||
|
__HAL_RCC_SDMMC1_FORCE_RESET(); delay(10);
|
||||||
|
__HAL_RCC_SDMMC1_RELEASE_RESET(); delay(10);
|
||||||
|
}
|
||||||
|
|
||||||
bool SDIO_Init() {
|
bool SDIO_Init() {
|
||||||
HAL_StatusTypeDef sd_state = HAL_OK;
|
HAL_StatusTypeDef sd_state = HAL_OK;
|
||||||
if (hsd.Instance == SDIO)
|
if (hsd.Instance == SDMMC1) HAL_SD_DeInit(&hsd);
|
||||||
HAL_SD_DeInit(&hsd);
|
|
||||||
|
|
||||||
/* HAL SD initialization */
|
// HAL SD initialization
|
||||||
hsd.Instance = SDIO;
|
hsd.Instance = SDMMC1;
|
||||||
hsd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
|
hsd.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
|
||||||
hsd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
|
hsd.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
|
||||||
hsd.Init.BusWide = SDIO_BUS_WIDE_1B;
|
hsd.Init.BusWide = SDMMC_BUS_WIDE_1B;
|
||||||
hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
|
hsd.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
|
||||||
hsd.Init.ClockDiv = clock_to_divider(SDIO_CLOCK);
|
hsd.Init.ClockDiv = clock_to_divider(SDIO_CLOCK);
|
||||||
sd_state = HAL_SD_Init(&hsd);
|
sd_state = HAL_SD_Init(&hsd);
|
||||||
|
|
||||||
#if PINS_EXIST(SDIO_D1, SDIO_D2, SDIO_D3)
|
#if PINS_EXIST(SDIO_D1, SDIO_D2, SDIO_D3)
|
||||||
if (sd_state == HAL_OK) {
|
if (sd_state == HAL_OK)
|
||||||
sd_state = HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B);
|
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
|
||||||
|
#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;
|
||||||
|
|
||||||
|
#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
|
||||||
|
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
#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);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
go_to_transfer_speed();
|
||||||
|
|
||||||
|
#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();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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
|
#endif
|
||||||
|
|
||||||
return (sd_state == HAL_OK) ? true : false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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;
|
||||||
|
|
||||||
|
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) {
|
||||||
|
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
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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) {
|
bool SDIO_ReadBlock(uint32_t block, uint8_t *dst) {
|
||||||
|
#ifdef SDIO_FOR_STM32H7
|
||||||
|
|
||||||
uint32_t timeout = HAL_GetTick() + SD_TIMEOUT;
|
uint32_t timeout = HAL_GetTick() + SD_TIMEOUT;
|
||||||
|
|
||||||
while (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER) {
|
while (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER)
|
||||||
if (HAL_GetTick() >= timeout) return false;
|
if (HAL_GetTick() >= timeout) return false;
|
||||||
}
|
|
||||||
|
|
||||||
waitingRxCplt = 1;
|
waitingRxCplt = 1;
|
||||||
if (HAL_SD_ReadBlocks_DMA(&hsd, (uint8_t*)dst, block, 1) != HAL_OK)
|
if (HAL_SD_ReadBlocks_DMA(&hsd, (uint8_t*)dst, block, 1) != HAL_OK)
|
||||||
@@ -237,9 +393,28 @@ bool SDIO_ReadBlock(uint32_t block, uint8_t *dst) {
|
|||||||
if (HAL_GetTick() >= timeout) return false;
|
if (HAL_GetTick() >= timeout) return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
uint8_t retries = SDIO_READ_RETRIES;
|
||||||
|
while (retries--) if (SDIO_ReadWriteBlock_DMA(block, nullptr, dst)) return true;
|
||||||
|
return false;
|
||||||
|
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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) {
|
bool SDIO_WriteBlock(uint32_t block, const uint8_t *src) {
|
||||||
|
#ifdef SDIO_FOR_STM32H7
|
||||||
|
|
||||||
uint32_t timeout = HAL_GetTick() + SD_TIMEOUT;
|
uint32_t timeout = HAL_GetTick() + SD_TIMEOUT;
|
||||||
|
|
||||||
while (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER)
|
while (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER)
|
||||||
@@ -254,6 +429,14 @@ bool SDIO_WriteBlock(uint32_t block, const uint8_t *src) {
|
|||||||
if (HAL_GetTick() >= timeout) return false;
|
if (HAL_GetTick() >= timeout) return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
uint8_t retries = SDIO_READ_RETRIES;
|
||||||
|
while (retries--) if (SDIO_ReadWriteBlock_DMA(block, src, nullptr)) return true;
|
||||||
|
return false;
|
||||||
|
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SDIO_IsReady() {
|
bool SDIO_IsReady() {
|
||||||
|
@@ -159,24 +159,28 @@ void GT911::read_reg(uint16_t reg, uint8_t reg_len, uint8_t* r_data, uint8_t r_l
|
|||||||
void GT911::Init() {
|
void GT911::Init() {
|
||||||
OUT_WRITE(GT911_RST_PIN, LOW);
|
OUT_WRITE(GT911_RST_PIN, LOW);
|
||||||
OUT_WRITE(GT911_INT_PIN, LOW);
|
OUT_WRITE(GT911_INT_PIN, LOW);
|
||||||
delay(20);
|
delay(11);
|
||||||
|
WRITE(GT911_INT_PIN, HIGH);
|
||||||
|
delayMicroseconds(110);
|
||||||
WRITE(GT911_RST_PIN, HIGH);
|
WRITE(GT911_RST_PIN, HIGH);
|
||||||
|
delay(6);
|
||||||
|
WRITE(GT911_INT_PIN, LOW);
|
||||||
|
delay(55);
|
||||||
SET_INPUT(GT911_INT_PIN);
|
SET_INPUT(GT911_INT_PIN);
|
||||||
|
|
||||||
sw_iic.init();
|
sw_iic.init();
|
||||||
|
|
||||||
uint8_t clear_reg = 0x0000;
|
uint8_t clear_reg = 0x00;
|
||||||
write_reg(0x814E, 2, &clear_reg, 2); // Reset to 0 for start
|
write_reg(0x814E, 2, &clear_reg, 1); // Reset to 0 for start
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GT911::getFirstTouchPoint(int16_t *x, int16_t *y) {
|
bool GT911::getFirstTouchPoint(int16_t *x, int16_t *y) {
|
||||||
read_reg(0x814E, 2, ®.REG.status, 1);
|
read_reg(0x814E, 2, ®.REG.status, 1);
|
||||||
|
|
||||||
if (reg.REG.status & 0x80) {
|
if (reg.REG.status >= 0x80 && reg.REG.status <= 0x85) {
|
||||||
|
read_reg(0x8150, 2, reg.map + 2, 38);
|
||||||
uint8_t clear_reg = 0x00;
|
uint8_t clear_reg = 0x00;
|
||||||
write_reg(0x814E, 2, &clear_reg, 1); // Reset to 0 for start
|
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
|
// First touch point
|
||||||
*x = ((reg.REG.point[0].xh & 0x0F) << 8) | reg.REG.point[0].xl;
|
*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;
|
*y = ((reg.REG.point[0].yh & 0x0F) << 8) | reg.REG.point[0].yl;
|
||||||
|
@@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
#include "../../../inc/MarlinConfig.h"
|
#include "../../../inc/MarlinConfig.h"
|
||||||
|
|
||||||
#define GT911_SLAVE_ADDRESS 0xBA
|
#define GT911_SLAVE_ADDRESS 0x28
|
||||||
|
|
||||||
#if !PIN_EXISTS(GT911_RST)
|
#if !PIN_EXISTS(GT911_RST)
|
||||||
#error "GT911_RST_PIN is not defined."
|
#error "GT911_RST_PIN is not defined."
|
||||||
|
@@ -372,9 +372,9 @@ void TFT_LTDC::TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Cou
|
|||||||
if (MemoryIncrease == DMA_PINC_ENABLE) {
|
if (MemoryIncrease == DMA_PINC_ENABLE) {
|
||||||
DrawImage(x_min, y_cur, x_min + width, y_cur + height, Data);
|
DrawImage(x_min, y_cur, x_min + width, y_cur + height, Data);
|
||||||
Data += width * height;
|
Data += width * height;
|
||||||
} else {
|
|
||||||
DrawRect(x_min, y_cur, x_min + width, y_cur + height, *Data);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
DrawRect(x_min, y_cur, x_min + width, y_cur + height, *Data);
|
||||||
y_cur += height;
|
y_cur += height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -147,17 +147,17 @@ void libServo::move(const int32_t value) {
|
|||||||
uint16_t SR = timer_get_status(tdev);
|
uint16_t SR = timer_get_status(tdev);
|
||||||
if (SR & TIMER_SR_CC1IF) { // channel 1 off
|
if (SR & TIMER_SR_CC1IF) { // channel 1 off
|
||||||
#ifdef SERVO0_PWM_OD
|
#ifdef SERVO0_PWM_OD
|
||||||
OUT_WRITE_OD(SERVO0_PIN, 1); // off
|
OUT_WRITE_OD(SERVO0_PIN, HIGH); // off
|
||||||
#else
|
#else
|
||||||
OUT_WRITE(SERVO0_PIN, 0);
|
OUT_WRITE(SERVO0_PIN, LOW);
|
||||||
#endif
|
#endif
|
||||||
timer_reset_status_bit(tdev, TIMER_SR_CC1IF_BIT);
|
timer_reset_status_bit(tdev, TIMER_SR_CC1IF_BIT);
|
||||||
}
|
}
|
||||||
if (SR & TIMER_SR_CC2IF) { // channel 2 resume
|
if (SR & TIMER_SR_CC2IF) { // channel 2 resume
|
||||||
#ifdef SERVO0_PWM_OD
|
#ifdef SERVO0_PWM_OD
|
||||||
OUT_WRITE_OD(SERVO0_PIN, 0); // on
|
OUT_WRITE_OD(SERVO0_PIN, LOW); // on
|
||||||
#else
|
#else
|
||||||
OUT_WRITE(SERVO0_PIN, 1);
|
OUT_WRITE(SERVO0_PIN, HIGH);
|
||||||
#endif
|
#endif
|
||||||
timer_reset_status_bit(tdev, TIMER_SR_CC2IF_BIT);
|
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);
|
timer_dev *tdev = HAL_get_timer_dev(MF_TIMER_SERVO0);
|
||||||
if (!tdev) return false;
|
if (!tdev) return false;
|
||||||
#ifdef SERVO0_PWM_OD
|
#ifdef SERVO0_PWM_OD
|
||||||
OUT_WRITE_OD(inPin, 1);
|
OUT_WRITE_OD(inPin, HIGH);
|
||||||
#else
|
#else
|
||||||
OUT_WRITE(inPin, 0);
|
OUT_WRITE(inPin, LOW);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
timer_pause(tdev);
|
timer_pause(tdev);
|
||||||
@@ -200,9 +200,9 @@ void libServo::move(const int32_t value) {
|
|||||||
timer_disable_irq(tdev, 1);
|
timer_disable_irq(tdev, 1);
|
||||||
timer_disable_irq(tdev, 2);
|
timer_disable_irq(tdev, 2);
|
||||||
#ifdef SERVO0_PWM_OD
|
#ifdef SERVO0_PWM_OD
|
||||||
OUT_WRITE_OD(pin, 1); // off
|
OUT_WRITE_OD(pin, HIGH); // off
|
||||||
#else
|
#else
|
||||||
OUT_WRITE(pin, 0);
|
OUT_WRITE(pin, LOW);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -135,11 +135,11 @@ static UnwResult UnwTabExecuteInstructions(const UnwindCallbacks *cb, UnwTabStat
|
|||||||
while ((instruction = UnwTabGetNextInstruction(cb, ucb)) != -1) {
|
while ((instruction = UnwTabGetNextInstruction(cb, ucb)) != -1) {
|
||||||
|
|
||||||
if ((instruction & 0xC0) == 0x00) { // ARM_EXIDX_CMD_DATA_POP
|
if ((instruction & 0xC0) == 0x00) { // ARM_EXIDX_CMD_DATA_POP
|
||||||
/* vsp = vsp + (xxxxxx << 2) + 4 */
|
/* vsp += (xxxxxx << 2) + 4 */
|
||||||
ucb->vrs[13] += ((instruction & 0x3F) << 2) + 4;
|
ucb->vrs[13] += ((instruction & 0x3F) << 2) + 4;
|
||||||
}
|
}
|
||||||
else if ((instruction & 0xC0) == 0x40) { // ARM_EXIDX_CMD_DATA_PUSH
|
else if ((instruction & 0xC0) == 0x40) { // ARM_EXIDX_CMD_DATA_PUSH
|
||||||
/* vsp = vsp - (xxxxxx << 2) - 4 */
|
/* vsp -= (xxxxxx << 2) - 4 */
|
||||||
ucb->vrs[13] -= ((instruction & 0x3F) << 2) - 4;
|
ucb->vrs[13] -= ((instruction & 0x3F) << 2) - 4;
|
||||||
}
|
}
|
||||||
else if ((instruction & 0xF0) == 0x80) {
|
else if ((instruction & 0xF0) == 0x80) {
|
||||||
|
@@ -65,7 +65,7 @@ uint8_t ServoCount = 0; // the total number of attached
|
|||||||
|
|
||||||
/************ static functions common to all instances ***********************/
|
/************ static functions common to all instances ***********************/
|
||||||
|
|
||||||
static boolean isTimerActive(timer16_Sequence_t timer) {
|
static bool anyTimerChannelActive(const timer16_Sequence_t timer) {
|
||||||
// returns true if any servo is active on this timer
|
// returns true if any servo is active on this timer
|
||||||
LOOP_L_N(channel, SERVOS_PER_TIMER) {
|
LOOP_L_N(channel, SERVOS_PER_TIMER) {
|
||||||
if (SERVO(timer, channel).Pin.isActive)
|
if (SERVO(timer, channel).Pin.isActive)
|
||||||
@@ -101,17 +101,18 @@ int8_t Servo::attach(const int inPin, const int inMin, const int inMax) {
|
|||||||
max = (MAX_PULSE_WIDTH - inMax) / 4;
|
max = (MAX_PULSE_WIDTH - inMax) / 4;
|
||||||
|
|
||||||
// initialize the timer if it has not already been initialized
|
// initialize the timer if it has not already been initialized
|
||||||
timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex);
|
const timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex);
|
||||||
if (!isTimerActive(timer)) initISR(timer);
|
if (!anyTimerChannelActive(timer)) initISR(timer);
|
||||||
servo_info[servoIndex].Pin.isActive = true; // this must be set after the check for isTimerActive
|
servo_info[servoIndex].Pin.isActive = true; // this must be set after the check for anyTimerChannelActive
|
||||||
|
|
||||||
return servoIndex;
|
return servoIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Servo::detach() {
|
void Servo::detach() {
|
||||||
servo_info[servoIndex].Pin.isActive = false;
|
servo_info[servoIndex].Pin.isActive = false;
|
||||||
timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex);
|
const timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex);
|
||||||
if (!isTimerActive(timer)) finISR(timer);
|
if (!anyTimerChannelActive(timer)) finISR(timer);
|
||||||
|
//pinMode(servo_info[servoIndex].Pin.nbr, INPUT); // set servo pin to input
|
||||||
}
|
}
|
||||||
|
|
||||||
void Servo::write(int value) {
|
void Servo::write(int value) {
|
||||||
|
@@ -70,10 +70,10 @@
|
|||||||
#define ticksToUs(_ticks) (unsigned(_ticks) * (SERVO_TIMER_PRESCALER) / clockCyclesPerMicrosecond())
|
#define ticksToUs(_ticks) (unsigned(_ticks) * (SERVO_TIMER_PRESCALER) / clockCyclesPerMicrosecond())
|
||||||
|
|
||||||
// convenience macros
|
// convenience macros
|
||||||
#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_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)) // returns the index of the servo on this timer
|
#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) // macro to access servo index by timer and channel
|
#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)]) // macro to access servo class by timer and channel
|
#define SERVO(_timer,_channel) servo_info[SERVO_INDEX(_timer,_channel)] // servo class by timer and channel
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
|
|
||||||
@@ -94,5 +94,5 @@ extern ServoInfo_t servo_info[MAX_SERVOS];
|
|||||||
|
|
||||||
// Public functions
|
// Public functions
|
||||||
|
|
||||||
extern void initISR(timer16_Sequence_t timer);
|
void initISR(const timer16_Sequence_t timer_index);
|
||||||
extern void finISR(timer16_Sequence_t timer);
|
void finISR(const timer16_Sequence_t timer_index);
|
||||||
|
@@ -782,7 +782,7 @@ void idle(bool no_stepper_sleep/*=false*/) {
|
|||||||
manage_inactivity(no_stepper_sleep);
|
manage_inactivity(no_stepper_sleep);
|
||||||
|
|
||||||
// Manage Heaters (and Watchdog)
|
// Manage Heaters (and Watchdog)
|
||||||
thermalManager.manage_heater();
|
thermalManager.task();
|
||||||
|
|
||||||
// Max7219 heartbeat, animation, etc
|
// Max7219 heartbeat, animation, etc
|
||||||
TERN_(MAX7219_DEBUG, max7219.idle_tasks());
|
TERN_(MAX7219_DEBUG, max7219.idle_tasks());
|
||||||
|
@@ -238,6 +238,7 @@
|
|||||||
#define BOARD_BTT_SKR_V1_1 2012 // BigTreeTech SKR v1.1
|
#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_3 2013 // BigTreeTech SKR v1.3
|
||||||
#define BOARD_BTT_SKR_V1_4 2014 // BigTreeTech SKR v1.4
|
#define BOARD_BTT_SKR_V1_4 2014 // BigTreeTech SKR v1.4
|
||||||
|
#define BOARD_EMOTRONIC 2015 // eMotion-Tech eMotronic
|
||||||
|
|
||||||
//
|
//
|
||||||
// LPC1769 ARM Cortex M3
|
// LPC1769 ARM Cortex M3
|
||||||
@@ -332,40 +333,41 @@
|
|||||||
#define BOARD_BTT_SKR_E3_DIP 4029 // BigTreeTech SKR E3 DIP V1.0 (STM32F103RC / STM32F103RE)
|
#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_BTT_SKR_CR6 4030 // BigTreeTech SKR CR6 v1.0 (STM32F103RE)
|
||||||
#define BOARD_JGAURORA_A5S_A1 4031 // JGAurora A5S A1 (STM32F103ZE)
|
#define BOARD_JGAURORA_A5S_A1 4031 // JGAurora A5S A1 (STM32F103ZE)
|
||||||
#define BOARD_FYSETC_AIO_II 4032 // FYSETC AIO_II
|
#define BOARD_FYSETC_AIO_II 4032 // FYSETC AIO_II (STM32F103RC)
|
||||||
#define BOARD_FYSETC_CHEETAH 4033 // FYSETC Cheetah
|
#define BOARD_FYSETC_CHEETAH 4033 // FYSETC Cheetah (STM32F103RC)
|
||||||
#define BOARD_FYSETC_CHEETAH_V12 4034 // FYSETC Cheetah V1.2
|
#define BOARD_FYSETC_CHEETAH_V12 4034 // FYSETC Cheetah V1.2 (STM32F103RC)
|
||||||
#define BOARD_LONGER3D_LK 4035 // Alfawise U20/U20+/U30 (Longer3D LK1/2) / STM32F103VE
|
#define BOARD_LONGER3D_LK 4035 // Longer3D LK1/2 - Alfawise U20/U20+/U30 (STM32F103VE)
|
||||||
#define BOARD_CCROBOT_MEEB_3DP 4036 // ccrobot-online.com MEEB_3DP (STM32F103RC)
|
#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_V5 4037 // Chitu3D TronXY X5SA V5 Board (STM32F103ZE)
|
||||||
#define BOARD_CHITU3D_V6 4038 // Chitu3D TronXY X5SA V6 Board
|
#define BOARD_CHITU3D_V6 4038 // Chitu3D TronXY X5SA V6 Board (STM32F103ZE)
|
||||||
#define BOARD_CHITU3D_V9 4039 // Chitu3D TronXY X5SA V9 Board
|
#define BOARD_CHITU3D_V9 4039 // Chitu3D TronXY X5SA V9 Board (STM32F103ZE)
|
||||||
#define BOARD_CREALITY_V4 4040 // Creality v4.x (STM32F103RC / STM32F103RE)
|
#define BOARD_CREALITY_V4 4040 // Creality v4.x (STM32F103RC / STM32F103RE)
|
||||||
#define BOARD_CREALITY_V422 4041 // Creality v4.2.2 (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_V423 4042 // Creality v4.2.3 (STM32F103RC / STM32F103RE)
|
||||||
#define BOARD_CREALITY_V427 4043 // Creality v4.2.7 (STM32F103RC / STM32F103RE)
|
#define BOARD_CREALITY_V425 4043 // Creality v4.2.5 (STM32F103RC / STM32F103RE)
|
||||||
#define BOARD_CREALITY_V4210 4044 // Creality v4.2.10 (STM32F103RC / STM32F103RE) as found in the CR-30
|
#define BOARD_CREALITY_V427 4044 // Creality v4.2.7 (STM32F103RC / STM32F103RE)
|
||||||
#define BOARD_CREALITY_V431 4045 // Creality v4.3.1 (STM32F103RC / STM32F103RE)
|
#define BOARD_CREALITY_V4210 4045 // Creality v4.2.10 (STM32F103RC / STM32F103RE) as found in the CR-30
|
||||||
#define BOARD_CREALITY_V431_A 4046 // Creality v4.3.1a (STM32F103RC / STM32F103RE)
|
#define BOARD_CREALITY_V431 4046 // Creality v4.3.1 (STM32F103RC / STM32F103RE)
|
||||||
#define BOARD_CREALITY_V431_B 4047 // Creality v4.3.1b (STM32F103RC / STM32F103RE)
|
#define BOARD_CREALITY_V431_A 4047 // Creality v4.3.1a (STM32F103RC / STM32F103RE)
|
||||||
#define BOARD_CREALITY_V431_C 4048 // Creality v4.3.1c (STM32F103RC / STM32F103RE)
|
#define BOARD_CREALITY_V431_B 4048 // Creality v4.3.1b (STM32F103RC / STM32F103RE)
|
||||||
#define BOARD_CREALITY_V431_D 4049 // Creality v4.3.1d (STM32F103RC / STM32F103RE)
|
#define BOARD_CREALITY_V431_C 4049 // Creality v4.3.1c (STM32F103RC / STM32F103RE)
|
||||||
#define BOARD_CREALITY_V452 4050 // Creality v4.5.2 (STM32F103RC / STM32F103RE)
|
#define BOARD_CREALITY_V431_D 4050 // Creality v4.3.1d (STM32F103RC / STM32F103RE)
|
||||||
#define BOARD_CREALITY_V453 4051 // Creality v4.5.3 (STM32F103RC / STM32F103RE)
|
#define BOARD_CREALITY_V452 4051 // Creality v4.5.2 (STM32F103RC / STM32F103RE)
|
||||||
#define BOARD_CREALITY_V24S1 4052 // Creality v2.4.S1 (STM32F103RC / STM32F103RE) v101 as found in the Ender-7
|
#define BOARD_CREALITY_V453 4052 // Creality v4.5.3 (STM32F103RC / STM32F103RE)
|
||||||
#define BOARD_CREALITY_V24S1_301 4053 // Creality v2.4.S1_301 (STM32F103RC / STM32F103RE) v301 as found in the Ender-3 S1
|
#define BOARD_CREALITY_V24S1 4053 // Creality v2.4.S1 (STM32F103RC / STM32F103RE) v101 as found in the Ender-7
|
||||||
#define BOARD_CREALITY_V25S1 4054 // Creality v2.5.S1 (STM32F103RE) as found in the CR-10 Smart Pro
|
#define BOARD_CREALITY_V24S1_301 4054 // Creality v2.4.S1_301 (STM32F103RC / STM32F103RE) v301 as found in the Ender-3 S1
|
||||||
#define BOARD_TRIGORILLA_PRO 4055 // Trigorilla Pro (STM32F103ZE)
|
#define BOARD_CREALITY_V25S1 4055 // Creality v2.5.S1 (STM32F103RE) as found in the CR-10 Smart Pro
|
||||||
#define BOARD_FLY_MINI 4056 // FLYmaker FLY MINI (STM32F103RC)
|
#define BOARD_TRIGORILLA_PRO 4056 // Trigorilla Pro (STM32F103ZE)
|
||||||
#define BOARD_FLSUN_HISPEED 4057 // FLSUN HiSpeedV1 (STM32F103VE)
|
#define BOARD_FLY_MINI 4057 // FLYmaker FLY MINI (STM32F103RC)
|
||||||
#define BOARD_BEAST 4058 // STM32F103RE Libmaple-based controller
|
#define BOARD_FLSUN_HISPEED 4058 // FLSUN HiSpeedV1 (STM32F103VE)
|
||||||
#define BOARD_MINGDA_MPX_ARM_MINI 4059 // STM32F103ZE Mingda MD-16
|
#define BOARD_BEAST 4059 // STM32F103RE Libmaple-based controller
|
||||||
#define BOARD_GTM32_PRO_VD 4060 // STM32F103VE controller
|
#define BOARD_MINGDA_MPX_ARM_MINI 4060 // STM32F103ZE Mingda MD-16
|
||||||
#define BOARD_ZONESTAR_ZM3E2 4061 // Zonestar ZM3E2 (STM32F103RC)
|
#define BOARD_GTM32_PRO_VD 4061 // STM32F103VE controller
|
||||||
#define BOARD_ZONESTAR_ZM3E4 4062 // Zonestar ZM3E4 V1 (STM32F103VC)
|
#define BOARD_ZONESTAR_ZM3E2 4062 // Zonestar ZM3E2 (STM32F103RC)
|
||||||
#define BOARD_ZONESTAR_ZM3E4V2 4063 // Zonestar ZM3E4 V2 (STM32F103VC)
|
#define BOARD_ZONESTAR_ZM3E4 4063 // Zonestar ZM3E4 V1 (STM32F103VC)
|
||||||
#define BOARD_ERYONE_ERY32_MINI 4064 // Eryone Ery32 mini (STM32F103VE)
|
#define BOARD_ZONESTAR_ZM3E4V2 4064 // Zonestar ZM3E4 V2 (STM32F103VC)
|
||||||
#define BOARD_PANDA_PI_V29 4065 // Panda Pi V2.9 - Standalone (STM32F103RC)
|
#define BOARD_ERYONE_ERY32_MINI 4065 // Eryone Ery32 mini (STM32F103VE)
|
||||||
|
#define BOARD_PANDA_PI_V29 4066 // Panda Pi V2.9 - Standalone (STM32F103RC)
|
||||||
|
|
||||||
//
|
//
|
||||||
// ARM Cortex-M4F
|
// ARM Cortex-M4F
|
||||||
@@ -408,17 +410,18 @@
|
|||||||
#define BOARD_MKS_ROBIN_PRO_V2 4227 // MKS Robin Pro V2 (STM32F407VE)
|
#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 4228 // MKS Robin Nano V3 (STM32F407VG)
|
||||||
#define BOARD_MKS_ROBIN_NANO_V3_1 4229 // MKS Robin Nano V3.1 (STM32F407VE)
|
#define BOARD_MKS_ROBIN_NANO_V3_1 4229 // MKS Robin Nano V3.1 (STM32F407VE)
|
||||||
#define BOARD_MKS_MONSTER8 4230 // MKS Monster8 (STM32F407VG)
|
#define BOARD_MKS_MONSTER8_V1 4230 // MKS Monster8 V1 (STM32F407VE)
|
||||||
#define BOARD_ANET_ET4 4231 // ANET ET4 V1.x (STM32F407VG)
|
#define BOARD_MKS_MONSTER8_V2 4231 // MKS Monster8 V2 (STM32F407VE)
|
||||||
#define BOARD_ANET_ET4P 4232 // ANET ET4P V1.x (STM32F407VG)
|
#define BOARD_ANET_ET4 4232 // ANET ET4 V1.x (STM32F407VG)
|
||||||
#define BOARD_FYSETC_CHEETAH_V20 4233 // FYSETC Cheetah V2.0
|
#define BOARD_ANET_ET4P 4233 // ANET ET4P V1.x (STM32F407VG)
|
||||||
#define BOARD_TH3D_EZBOARD_V2 4234 // TH3D EZBoard v2.0
|
#define BOARD_FYSETC_CHEETAH_V20 4234 // FYSETC Cheetah V2.0 (STM32F401RC)
|
||||||
#define BOARD_INDEX_REV03 4235 // Index PnP Controller REV03 (STM32F407VE/VG)
|
#define BOARD_TH3D_EZBOARD_V2 4235 // TH3D EZBoard v2.0 (STM32F405RG)
|
||||||
#define BOARD_MKS_ROBIN_NANO_V1_3_F4 4236 // MKS Robin Nano V1.3 and MKS Robin Nano-S V1.3 (STM32F407VE)
|
#define BOARD_OPULO_LUMEN_REV3 4236 // Opulo Lumen PnP Controller REV3 (STM32F407VE / STM32F407VG)
|
||||||
#define BOARD_MKS_EAGLE 4237 // MKS Eagle (STM32F407VE)
|
#define BOARD_MKS_ROBIN_NANO_V1_3_F4 4237 // MKS Robin Nano V1.3 and MKS Robin Nano-S V1.3 (STM32F407VE)
|
||||||
#define BOARD_ARTILLERY_RUBY 4238 // Artillery Ruby (STM32F401RC)
|
#define BOARD_MKS_EAGLE 4238 // MKS Eagle (STM32F407VE)
|
||||||
#define BOARD_FYSETC_SPIDER_V2_2 4239 // FYSETC Spider V2.2 (STM32F446VE)
|
#define BOARD_ARTILLERY_RUBY 4239 // Artillery Ruby (STM32F401RC)
|
||||||
#define BOARD_CREALITY_V24S1_301F4 4240 // Creality v2.4.S1_301F4 (STM32F401RC) as found in the Ender-3 S1 F4
|
#define BOARD_FYSETC_SPIDER_V2_2 4240 // FYSETC Spider V2.2 (STM32F446VE)
|
||||||
|
#define BOARD_CREALITY_V24S1_301F4 4241 // Creality v2.4.S1_301F4 (STM32F401RC) as found in the Ender-3 S1 F4
|
||||||
|
|
||||||
//
|
//
|
||||||
// ARM Cortex M7
|
// ARM Cortex M7
|
||||||
@@ -428,9 +431,10 @@
|
|||||||
#define BOARD_TEENSY41 5001 // Teensy 4.1
|
#define BOARD_TEENSY41 5001 // Teensy 4.1
|
||||||
#define BOARD_T41U5XBB 5002 // T41U5XBB Teensy 4.1 breakout board
|
#define BOARD_T41U5XBB 5002 // T41U5XBB Teensy 4.1 breakout board
|
||||||
#define BOARD_NUCLEO_F767ZI 5003 // ST NUCLEO-F767ZI Dev Board
|
#define BOARD_NUCLEO_F767ZI 5003 // ST NUCLEO-F767ZI Dev Board
|
||||||
#define BOARD_BTT_SKR_SE_BX 5004 // BigTreeTech SKR SE BX (STM32H743II)
|
#define BOARD_BTT_SKR_SE_BX_V2 5004 // BigTreeTech SKR SE BX V2.0 (STM32H743II)
|
||||||
#define BOARD_BTT_SKR_V3_0 5005 // BigTreeTech SKR V3.0 (STM32H743VG)
|
#define BOARD_BTT_SKR_SE_BX_V3 5005 // BigTreeTech SKR SE BX V3.0 (STM32H743II)
|
||||||
#define BOARD_BTT_SKR_V3_0_EZ 5006 // BigTreeTech SKR V3.0 EZ (STM32H743VG)
|
#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)
|
||||||
|
|
||||||
//
|
//
|
||||||
// Espressif ESP32 WiFi
|
// Espressif ESP32 WiFi
|
||||||
|
@@ -227,10 +227,6 @@
|
|||||||
#define STR_PID_DEBUG " PID_DEBUG "
|
#define STR_PID_DEBUG " PID_DEBUG "
|
||||||
#define STR_PID_DEBUG_INPUT ": Input "
|
#define STR_PID_DEBUG_INPUT ": Input "
|
||||||
#define STR_PID_DEBUG_OUTPUT " Output "
|
#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_INVALID_EXTRUDER_NUM " - Invalid extruder number !"
|
||||||
#define STR_MPC_AUTOTUNE "MPC Autotune"
|
#define STR_MPC_AUTOTUNE "MPC Autotune"
|
||||||
#define STR_MPC_AUTOTUNE_START " start for " STR_E
|
#define STR_MPC_AUTOTUNE_START " start for " STR_E
|
||||||
|
@@ -350,7 +350,7 @@
|
|||||||
|
|
||||||
#define _LIST_N(N,V...) LIST_##N(V)
|
#define _LIST_N(N,V...) LIST_##N(V)
|
||||||
#define LIST_N(N,V...) _LIST_N(N,V)
|
#define LIST_N(N,V...) _LIST_N(N,V)
|
||||||
#define LIST_N_1(N,K) _LIST_N(N,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K)
|
#define LIST_N_1(N,K) _LIST_N(N,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K)
|
||||||
#define ARRAY_N(N,V...) { _LIST_N(N,V) }
|
#define ARRAY_N(N,V...) { _LIST_N(N,V) }
|
||||||
#define ARRAY_N_1(N,K) { LIST_N_1(N,K) }
|
#define ARRAY_N_1(N,K) { LIST_N_1(N,K) }
|
||||||
|
|
||||||
@@ -633,7 +633,7 @@
|
|||||||
#define PROBE() ~, 1 // Second item will be 1 if this is passed
|
#define PROBE() ~, 1 // Second item will be 1 if this is passed
|
||||||
#define _NOT_0 PROBE()
|
#define _NOT_0 PROBE()
|
||||||
#define NOT(x) IS_PROBE(_CAT(_NOT_, x)) // NOT('0') gets '1'. Anything else gets '0'.
|
#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 _BOOL(x) NOT(NOT(x)) // _BOOL('0') gets '0'. Anything else gets '1'.
|
||||||
|
|
||||||
#define IF_ELSE(TF) _IF_ELSE(_BOOL(TF))
|
#define IF_ELSE(TF) _IF_ELSE(_BOOL(TF))
|
||||||
#define _IF_ELSE(TF) _CAT(_IF_, TF)
|
#define _IF_ELSE(TF) _CAT(_IF_, TF)
|
||||||
@@ -647,7 +647,6 @@
|
|||||||
#define HAS_ARGS(V...) _BOOL(FIRST(_END_OF_ARGUMENTS_ V)())
|
#define HAS_ARGS(V...) _BOOL(FIRST(_END_OF_ARGUMENTS_ V)())
|
||||||
#define _END_OF_ARGUMENTS_() 0
|
#define _END_OF_ARGUMENTS_() 0
|
||||||
|
|
||||||
|
|
||||||
// Simple Inline IF Macros, friendly to use in other macro definitions
|
// Simple Inline IF Macros, friendly to use in other macro definitions
|
||||||
#define IF(O, A, B) ((O) ? (A) : (B))
|
#define IF(O, A, B) ((O) ? (A) : (B))
|
||||||
#define IF_0(O, A) IF(O, A, 0)
|
#define IF_0(O, A) IF(O, A, 0)
|
||||||
@@ -700,13 +699,22 @@
|
|||||||
#define RREPEAT2_S(S,N,OP,V...) EVAL1024(_RREPEAT2(S,SUB##S(N),OP,V))
|
#define RREPEAT2_S(S,N,OP,V...) EVAL1024(_RREPEAT2(S,SUB##S(N),OP,V))
|
||||||
#define RREPEAT2(N,OP,V...) RREPEAT2_S(0,N,OP,V)
|
#define RREPEAT2(N,OP,V...) RREPEAT2_S(0,N,OP,V)
|
||||||
|
|
||||||
// See https://github.com/swansontec/map-macro
|
// Call OP(A) with each item as an argument
|
||||||
#define MAP_OUT
|
#define _MAP(_MAP_OP,A,V...) \
|
||||||
#define MAP_END(...)
|
_MAP_OP(A) \
|
||||||
#define MAP_GET_END() 0, MAP_END
|
IF_ELSE(HAS_ARGS(V)) \
|
||||||
#define MAP_NEXT0(test, next, ...) next MAP_OUT
|
( DEFER2(__MAP)()(_MAP_OP,V) ) \
|
||||||
#define MAP_NEXT1(test, next) MAP_NEXT0 (test, next, 0)
|
( /* Do nothing */ )
|
||||||
#define MAP_NEXT(test, next) MAP_NEXT1 (MAP_GET_END test, next)
|
#define __MAP() _MAP
|
||||||
#define MAP0(f, x, peek, ...) f(x) MAP_NEXT (peek, MAP1) (f, peek, __VA_ARGS__)
|
|
||||||
#define MAP1(f, x, peek, ...) f(x) MAP_NEXT (peek, MAP0) (f, peek, __VA_ARGS__)
|
#define MAP(OP,V...) EVAL(_MAP(OP,V))
|
||||||
#define MAP(f, ...) EVAL512 (MAP1 (f, __VA_ARGS__, (), 0))
|
|
||||||
|
// Emit a list of OP(A) with the given items
|
||||||
|
#define _MAPLIST(_MAP_OP,A,V...) \
|
||||||
|
_MAP_OP(A) \
|
||||||
|
IF_ELSE(HAS_ARGS(V)) \
|
||||||
|
( , DEFER2(__MAPLIST)()(_MAP_OP,V) ) \
|
||||||
|
( /* Do nothing */ )
|
||||||
|
#define __MAPLIST() _MAPLIST
|
||||||
|
|
||||||
|
#define MAPLIST(OP,V...) EVAL(_MAPLIST(OP,V))
|
||||||
|
@@ -30,16 +30,15 @@
|
|||||||
uint8_t marlin_debug_flags = MARLIN_DEBUG_NONE;
|
uint8_t marlin_debug_flags = MARLIN_DEBUG_NONE;
|
||||||
|
|
||||||
// Commonly-used strings in serial output
|
// Commonly-used strings in serial output
|
||||||
PGMSTR(NUL_STR, ""); PGMSTR(SP_P_STR, " P"); PGMSTR(SP_T_STR, " T");
|
|
||||||
PGMSTR(X_STR, "X"); PGMSTR(Y_STR, "Y"); PGMSTR(Z_STR, "Z"); PGMSTR(E_STR, "E");
|
|
||||||
PGMSTR(X_LBL, "X:"); PGMSTR(Y_LBL, "Y:"); PGMSTR(Z_LBL, "Z:"); PGMSTR(E_LBL, "E:");
|
|
||||||
PGMSTR(SP_A_STR, " A"); PGMSTR(SP_B_STR, " B"); PGMSTR(SP_C_STR, " C");
|
PGMSTR(SP_A_STR, " A"); PGMSTR(SP_B_STR, " B"); PGMSTR(SP_C_STR, " C");
|
||||||
PGMSTR(SP_X_STR, " X"); PGMSTR(SP_Y_STR, " Y"); PGMSTR(SP_Z_STR, " Z"); PGMSTR(SP_E_STR, " E");
|
PGMSTR(SP_P_STR, " P"); PGMSTR(SP_T_STR, " T"); PGMSTR(NUL_STR, "");
|
||||||
PGMSTR(SP_X_LBL, " X:"); PGMSTR(SP_Y_LBL, " Y:"); PGMSTR(SP_Z_LBL, " Z:"); PGMSTR(SP_E_LBL, " E:");
|
|
||||||
PGMSTR(I_STR, STR_I); PGMSTR(J_STR, STR_J); PGMSTR(K_STR, STR_K);
|
#define _N_STR(N) PGMSTR(N##_STR, STR_##N);
|
||||||
PGMSTR(I_LBL, STR_I ":"); PGMSTR(J_LBL, STR_J ":"); PGMSTR(K_LBL, STR_K ":");
|
#define _N_LBL(N) PGMSTR(N##_LBL, STR_##N ":");
|
||||||
PGMSTR(SP_I_STR, " " STR_I); PGMSTR(SP_J_STR, " " STR_J); PGMSTR(SP_K_STR, " " STR_K);
|
#define _SP_N_STR(N) PGMSTR(SP_##N##_STR, " " STR_##N);
|
||||||
PGMSTR(SP_I_LBL, " " STR_I ":"); PGMSTR(SP_J_LBL, " " STR_J ":"); PGMSTR(SP_K_LBL, " " STR_K ":");
|
#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);
|
||||||
|
|
||||||
// Hook Meatpack if it's enabled on the first leaf
|
// Hook Meatpack if it's enabled on the first leaf
|
||||||
#if ENABLED(MEATPACK_ON_SERIAL_PORT_1)
|
#if ENABLED(MEATPACK_ON_SERIAL_PORT_1)
|
||||||
@@ -73,8 +72,8 @@ void serial_print_P(PGM_P str) {
|
|||||||
while (const char c = pgm_read_byte(str++)) SERIAL_CHAR(c);
|
while (const char c = pgm_read_byte(str++)) SERIAL_CHAR(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void serial_echo_start() { static PGMSTR(echomagic, "echo:"); serial_print_P(echomagic); }
|
void serial_echo_start() { serial_print(F("echo:")); }
|
||||||
void serial_error_start() { static PGMSTR(errormagic, "Error:"); serial_print_P(errormagic); }
|
void serial_error_start() { serial_print(F("Error:")); }
|
||||||
|
|
||||||
void serial_spaces(uint8_t count) { count *= (PROPORTIONAL_FONT_RATIO); while (count--) SERIAL_CHAR(' '); }
|
void serial_spaces(uint8_t count) { count *= (PROPORTIONAL_FONT_RATIO); while (count--) SERIAL_CHAR(' '); }
|
||||||
|
|
||||||
@@ -102,10 +101,10 @@ void print_bin(uint16_t val) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_pos(LINEAR_AXIS_ARGS(const_float_t), FSTR_P const prefix/*=nullptr*/, FSTR_P const suffix/*=nullptr*/) {
|
void print_pos(NUM_AXIS_ARGS(const_float_t), FSTR_P const prefix/*=nullptr*/, FSTR_P const suffix/*=nullptr*/) {
|
||||||
if (prefix) serial_print(prefix);
|
if (prefix) serial_print(prefix);
|
||||||
SERIAL_ECHOPGM_P(
|
SERIAL_ECHOPGM_P(
|
||||||
LIST_N(DOUBLE(LINEAR_AXES), SP_X_STR, x, SP_Y_STR, y, SP_Z_STR, z, SP_I_STR, i, SP_J_STR, j, SP_K_STR, k)
|
LIST_N(DOUBLE(NUM_AXES), SP_X_STR, x, SP_Y_STR, y, SP_Z_STR, z, SP_I_STR, i, SP_J_STR, j, SP_K_STR, k)
|
||||||
);
|
);
|
||||||
if (suffix) serial_print(suffix); else SERIAL_EOL();
|
if (suffix) serial_print(suffix); else SERIAL_EOL();
|
||||||
}
|
}
|
||||||
|
@@ -28,19 +28,6 @@
|
|||||||
#include "../feature/meatpack.h"
|
#include "../feature/meatpack.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Commonly-used strings in serial output
|
|
||||||
extern const char NUL_STR[],
|
|
||||||
SP_X_STR[], SP_Y_STR[], SP_Z_STR[],
|
|
||||||
SP_A_STR[], SP_B_STR[], SP_C_STR[], SP_E_STR[],
|
|
||||||
SP_X_LBL[], SP_Y_LBL[], SP_Z_LBL[], SP_E_LBL[],
|
|
||||||
SP_I_STR[], SP_J_STR[], SP_K_STR[],
|
|
||||||
SP_I_LBL[], SP_J_LBL[], SP_K_LBL[],
|
|
||||||
SP_P_STR[], SP_T_STR[],
|
|
||||||
X_STR[], Y_STR[], Z_STR[], E_STR[],
|
|
||||||
I_STR[], J_STR[], K_STR[],
|
|
||||||
X_LBL[], Y_LBL[], Z_LBL[], E_LBL[],
|
|
||||||
I_LBL[], J_LBL[], K_LBL[];
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Debugging flags for use by M111
|
// Debugging flags for use by M111
|
||||||
//
|
//
|
||||||
@@ -348,11 +335,40 @@ void serial_spaces(uint8_t count);
|
|||||||
void serial_offset(const_float_t v, const uint8_t sp=0); // For v==0 draw space (sp==1) or plus (sp==2)
|
void serial_offset(const_float_t v, const uint8_t sp=0); // For v==0 draw space (sp==1) or plus (sp==2)
|
||||||
|
|
||||||
void print_bin(const uint16_t val);
|
void print_bin(const uint16_t val);
|
||||||
void print_pos(LINEAR_AXIS_ARGS(const_float_t), FSTR_P const prefix=nullptr, FSTR_P const suffix=nullptr);
|
void print_pos(NUM_AXIS_ARGS(const_float_t), FSTR_P const prefix=nullptr, FSTR_P const suffix=nullptr);
|
||||||
|
|
||||||
inline void print_pos(const xyz_pos_t &xyz, FSTR_P const prefix=nullptr, FSTR_P const suffix=nullptr) {
|
inline void print_pos(const xyz_pos_t &xyz, FSTR_P const prefix=nullptr, FSTR_P const suffix=nullptr) {
|
||||||
print_pos(LINEAR_AXIS_ELEM(xyz), prefix, suffix);
|
print_pos(NUM_AXIS_ELEM(xyz), prefix, suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SERIAL_POS(SUFFIX,VAR) do { print_pos(VAR, F(" " STRINGIFY(VAR) "="), F(" : " SUFFIX "\n")); }while(0)
|
#define SERIAL_POS(SUFFIX,VAR) do { print_pos(VAR, F(" " STRINGIFY(VAR) "="), F(" : " SUFFIX "\n")); }while(0)
|
||||||
#define SERIAL_XYZ(PREFIX,V...) do { print_pos(V, F(PREFIX)); }while(0)
|
#define SERIAL_XYZ(PREFIX,V...) do { print_pos(V, F(PREFIX)); }while(0)
|
||||||
|
|
||||||
|
//
|
||||||
|
// Commonly-used strings in serial output
|
||||||
|
//
|
||||||
|
|
||||||
|
#define _N_STR(N) N##_STR
|
||||||
|
#define _N_LBL(N) N##_LBL
|
||||||
|
#define _N_STR_A(N) _N_STR(N)[]
|
||||||
|
#define _N_LBL_A(N) _N_LBL(N)[]
|
||||||
|
#define _SP_N_STR(N) SP_##N##_STR
|
||||||
|
#define _SP_N_LBL(N) SP_##N##_LBL
|
||||||
|
#define _SP_N_STR_A(N) _SP_N_STR(N)[]
|
||||||
|
#define _SP_N_LBL_A(N) _SP_N_LBL(N)[]
|
||||||
|
|
||||||
|
extern const char SP_A_STR[], SP_B_STR[], SP_C_STR[], SP_P_STR[], SP_T_STR[], NUL_STR[],
|
||||||
|
MAPLIST(_N_STR_A, LOGICAL_AXIS_NAMES), MAPLIST(_SP_N_STR_A, LOGICAL_AXIS_NAMES),
|
||||||
|
MAPLIST(_N_LBL_A, LOGICAL_AXIS_NAMES), MAPLIST(_SP_N_LBL_A, LOGICAL_AXIS_NAMES);
|
||||||
|
|
||||||
|
PGM_P const SP_AXIS_LBL[] PROGMEM = { MAPLIST(_SP_N_LBL, LOGICAL_AXIS_NAMES) };
|
||||||
|
PGM_P const SP_AXIS_STR[] PROGMEM = { MAPLIST(_SP_N_STR, LOGICAL_AXIS_NAMES) };
|
||||||
|
|
||||||
|
#undef _N_STR
|
||||||
|
#undef _N_LBL
|
||||||
|
#undef _N_STR_A
|
||||||
|
#undef _N_LBL_A
|
||||||
|
#undef _SP_N_STR
|
||||||
|
#undef _SP_N_LBL
|
||||||
|
#undef _SP_N_STR_A
|
||||||
|
#undef _SP_N_LBL_A
|
||||||
|
@@ -43,7 +43,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
constexpr SerialMask(const uint8_t mask) : mask(mask) {}
|
constexpr SerialMask(const uint8_t mask) : mask(mask) {}
|
||||||
constexpr SerialMask(const SerialMask & other) : mask(other.mask) {} // Can't use = default here since not all framework support this
|
constexpr SerialMask(const SerialMask &rs) : mask(rs.mask) {} // Can't use = default here since not all frameworks support this
|
||||||
|
|
||||||
|
SerialMask& operator=(const SerialMask &rs) { mask = rs.mask; return *this; }
|
||||||
|
|
||||||
static constexpr uint8_t All = 0xFF;
|
static constexpr uint8_t All = 0xFF;
|
||||||
};
|
};
|
||||||
|
@@ -36,23 +36,40 @@ struct IF { typedef R type; };
|
|||||||
template <class L, class R>
|
template <class L, class R>
|
||||||
struct IF<true, L, R> { typedef L type; };
|
struct IF<true, L, R> { typedef L type; };
|
||||||
|
|
||||||
#define LINEAR_AXIS_GANG(V...) GANG_N(LINEAR_AXES, V)
|
#define NUM_AXIS_GANG(V...) GANG_N(NUM_AXES, V)
|
||||||
#define LINEAR_AXIS_CODE(V...) CODE_N(LINEAR_AXES, V)
|
#define NUM_AXIS_CODE(V...) CODE_N(NUM_AXES, V)
|
||||||
#define LINEAR_AXIS_LIST(V...) LIST_N(LINEAR_AXES, V)
|
#define NUM_AXIS_LIST(V...) LIST_N(NUM_AXES, V)
|
||||||
#define LINEAR_AXIS_ARRAY(V...) { LINEAR_AXIS_LIST(V) }
|
#define NUM_AXIS_LIST_1(V) LIST_N_1(NUM_AXES, V)
|
||||||
#define LINEAR_AXIS_ARGS(T...) LINEAR_AXIS_LIST(T x, T y, T z, T i, T j, T k)
|
#define NUM_AXIS_ARRAY(V...) { NUM_AXIS_LIST(V) }
|
||||||
#define LINEAR_AXIS_ELEM(O) LINEAR_AXIS_LIST(O.x, O.y, O.z, O.i, O.j, O.k)
|
#define NUM_AXIS_ARRAY_1(V) { NUM_AXIS_LIST_1(V) }
|
||||||
#define LINEAR_AXIS_DEFS(T,V) LINEAR_AXIS_LIST(T x=V, T y=V, T z=V, T i=V, T j=V, T k=V)
|
#define NUM_AXIS_ARGS(T...) NUM_AXIS_LIST(T x, T y, T z, T i, T j, T k)
|
||||||
|
#define NUM_AXIS_ELEM(O) NUM_AXIS_LIST(O.x, O.y, O.z, O.i, O.j, O.k)
|
||||||
|
#define NUM_AXIS_DEFS(T,V) NUM_AXIS_LIST(T x=V, T y=V, T z=V, T i=V, T j=V, T k=V)
|
||||||
|
|
||||||
#define LOGICAL_AXIS_GANG(E,V...) LINEAR_AXIS_GANG(V) GANG_ITEM_E(E)
|
#define MAIN_AXIS_NAMES NUM_AXIS_LIST(X, Y, Z, I, J, K)
|
||||||
#define LOGICAL_AXIS_CODE(E,V...) LINEAR_AXIS_CODE(V) CODE_ITEM_E(E)
|
#define MAIN_AXIS_MAP(F) MAP(F, MAIN_AXIS_NAMES)
|
||||||
#define LOGICAL_AXIS_LIST(E,V...) LINEAR_AXIS_LIST(V) LIST_ITEM_E(E)
|
#define STR_AXES_MAIN NUM_AXIS_GANG("X", "Y", "Z", STR_I, STR_J, STR_K)
|
||||||
|
|
||||||
|
#define LOGICAL_AXIS_GANG(E,V...) NUM_AXIS_GANG(V) GANG_ITEM_E(E)
|
||||||
|
#define LOGICAL_AXIS_CODE(E,V...) NUM_AXIS_CODE(V) CODE_ITEM_E(E)
|
||||||
|
#define LOGICAL_AXIS_LIST(E,V...) NUM_AXIS_LIST(V) LIST_ITEM_E(E)
|
||||||
|
#define LOGICAL_AXIS_LIST_1(V) NUM_AXIS_LIST_1(V) LIST_ITEM_E(V)
|
||||||
#define LOGICAL_AXIS_ARRAY(E,V...) { LOGICAL_AXIS_LIST(E,V) }
|
#define LOGICAL_AXIS_ARRAY(E,V...) { LOGICAL_AXIS_LIST(E,V) }
|
||||||
|
#define LOGICAL_AXIS_ARRAY_1(V) { LOGICAL_AXIS_LIST_1(V) }
|
||||||
#define LOGICAL_AXIS_ARGS(T...) LOGICAL_AXIS_LIST(T e, T x, T y, T z, T i, T j, T k)
|
#define LOGICAL_AXIS_ARGS(T...) LOGICAL_AXIS_LIST(T e, T x, T y, T z, T i, T j, T k)
|
||||||
#define LOGICAL_AXIS_ELEM(O) LOGICAL_AXIS_LIST(O.e, O.x, O.y, O.z, O.i, O.j, O.k)
|
#define LOGICAL_AXIS_ELEM(O) LOGICAL_AXIS_LIST(O.e, O.x, O.y, O.z, O.i, O.j, O.k)
|
||||||
#define LOGICAL_AXIS_DECL(T,V) LOGICAL_AXIS_LIST(T e=V, T x=V, T y=V, T z=V, T i=V, T j=V, T k=V)
|
#define LOGICAL_AXIS_DECL(T,V) LOGICAL_AXIS_LIST(T e=V, T x=V, T y=V, T z=V, T i=V, T j=V, T k=V)
|
||||||
|
|
||||||
#define LOGICAL_AXES_STRING LOGICAL_AXIS_GANG("E", "X", "Y", "Z", STR_I, STR_J, STR_K)
|
#define LOGICAL_AXIS_NAMES LOGICAL_AXIS_LIST(E, X, Y, Z, I, J, K)
|
||||||
|
#define LOGICAL_AXIS_MAP(F) MAP(F, LOGICAL_AXIS_NAMES)
|
||||||
|
|
||||||
|
#define STR_AXES_LOGICAL LOGICAL_AXIS_GANG("E", "X", "Y", "Z", STR_I, STR_J, STR_K)
|
||||||
|
|
||||||
|
#define XYZ_GANG(V...) GANG_N(PRIMARY_LINEAR_AXES, V)
|
||||||
|
#define XYZ_CODE(V...) CODE_N(PRIMARY_LINEAR_AXES, V)
|
||||||
|
|
||||||
|
#define SECONDARY_AXIS_GANG(V...) GANG_N(SECONDARY_AXES, V)
|
||||||
|
#define SECONDARY_AXIS_CODE(V...) CODE_N(SECONDARY_AXES, V)
|
||||||
|
|
||||||
#if HAS_EXTRUDERS
|
#if HAS_EXTRUDERS
|
||||||
#define LIST_ITEM_E(N) , N
|
#define LIST_ITEM_E(N) , N
|
||||||
@@ -81,9 +98,9 @@ struct Flags {
|
|||||||
void set(const int n) { b |= (bits_t)_BV(n); }
|
void set(const int n) { b |= (bits_t)_BV(n); }
|
||||||
void clear(const int n) { b &= ~(bits_t)_BV(n); }
|
void clear(const int n) { b &= ~(bits_t)_BV(n); }
|
||||||
bool test(const int n) const { return TEST(b, n); }
|
bool test(const int n) const { return TEST(b, n); }
|
||||||
bool operator[](const int n) { return test(n); }
|
const bool operator[](const int n) { return test(n); }
|
||||||
const bool operator[](const int n) const { return test(n); }
|
const bool operator[](const int n) const { return test(n); }
|
||||||
const int size() const { return sizeof(b); }
|
int size() const { return sizeof(b); }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Specialization for a single bool flag
|
// Specialization for a single bool flag
|
||||||
@@ -95,9 +112,9 @@ struct Flags<1> {
|
|||||||
void set(const int) { b = true; }
|
void set(const int) { b = true; }
|
||||||
void clear(const int) { b = false; }
|
void clear(const int) { b = false; }
|
||||||
bool test(const int) const { return b; }
|
bool test(const int) const { return b; }
|
||||||
bool operator[](const int) { return b; }
|
bool& operator[](const int) { return b; }
|
||||||
const bool operator[](const int) const { return b; }
|
bool operator[](const int) const { return b; }
|
||||||
const int size() const { return sizeof(b); }
|
int size() const { return sizeof(b); }
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef Flags<8> flags_8_t;
|
typedef Flags<8> flags_8_t;
|
||||||
@@ -115,8 +132,8 @@ typedef struct AxisFlags {
|
|||||||
void clear(const int n) { flags.clear(n); }
|
void clear(const int n) { flags.clear(n); }
|
||||||
bool test(const int n) const { return flags.test(n); }
|
bool test(const int n) const { return flags.test(n); }
|
||||||
bool operator[](const int n) { return flags[n]; }
|
bool operator[](const int n) { return flags[n]; }
|
||||||
const bool operator[](const int n) const { return flags[n]; }
|
bool operator[](const int n) const { return flags[n]; }
|
||||||
const int size() const { return sizeof(flags); }
|
int size() const { return sizeof(flags); }
|
||||||
} axis_flags_t;
|
} axis_flags_t;
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -129,7 +146,7 @@ typedef struct AxisFlags {
|
|||||||
enum AxisEnum : uint8_t {
|
enum AxisEnum : uint8_t {
|
||||||
|
|
||||||
// Linear axes may be controlled directly or indirectly
|
// Linear axes may be controlled directly or indirectly
|
||||||
LINEAR_AXIS_LIST(X_AXIS, Y_AXIS, Z_AXIS, I_AXIS, J_AXIS, K_AXIS)
|
NUM_AXIS_LIST(X_AXIS, Y_AXIS, Z_AXIS, I_AXIS, J_AXIS, K_AXIS)
|
||||||
|
|
||||||
// Extruder axes may be considered distinctly
|
// Extruder axes may be considered distinctly
|
||||||
#define _EN_ITEM(N) , E##N##_AXIS
|
#define _EN_ITEM(N) , E##N##_AXIS
|
||||||
@@ -168,7 +185,7 @@ typedef IF<(NUM_AXIS_ENUMS > 8), uint16_t, uint8_t>::type axis_bits_t;
|
|||||||
// Loop over axes
|
// Loop over axes
|
||||||
//
|
//
|
||||||
#define LOOP_ABC(VAR) LOOP_S_LE_N(VAR, A_AXIS, C_AXIS)
|
#define LOOP_ABC(VAR) LOOP_S_LE_N(VAR, A_AXIS, C_AXIS)
|
||||||
#define LOOP_LINEAR_AXES(VAR) LOOP_S_L_N(VAR, X_AXIS, LINEAR_AXES)
|
#define LOOP_NUM_AXES(VAR) LOOP_S_L_N(VAR, X_AXIS, NUM_AXES)
|
||||||
#define LOOP_LOGICAL_AXES(VAR) LOOP_S_L_N(VAR, X_AXIS, LOGICAL_AXES)
|
#define LOOP_LOGICAL_AXES(VAR) LOOP_S_L_N(VAR, X_AXIS, LOGICAL_AXES)
|
||||||
#define LOOP_DISTINCT_AXES(VAR) LOOP_S_L_N(VAR, X_AXIS, DISTINCT_AXES)
|
#define LOOP_DISTINCT_AXES(VAR) LOOP_S_L_N(VAR, X_AXIS, DISTINCT_AXES)
|
||||||
#define LOOP_DISTINCT_E(VAR) LOOP_L_N(VAR, DISTINCT_E)
|
#define LOOP_DISTINCT_E(VAR) LOOP_L_N(VAR, DISTINCT_E)
|
||||||
@@ -313,10 +330,10 @@ struct XYval {
|
|||||||
FI void set(const T px, const T py) { x = px; y = py; }
|
FI void set(const T px, const T py) { x = px; y = py; }
|
||||||
FI void set(const T (&arr)[XY]) { x = arr[0]; y = arr[1]; }
|
FI void set(const T (&arr)[XY]) { x = arr[0]; y = arr[1]; }
|
||||||
#endif
|
#endif
|
||||||
#if LINEAR_AXES > XY
|
#if NUM_AXES > XY
|
||||||
FI void set(const T (&arr)[LINEAR_AXES]) { x = arr[0]; y = arr[1]; }
|
FI void set(const T (&arr)[NUM_AXES]) { x = arr[0]; y = arr[1]; }
|
||||||
#endif
|
#endif
|
||||||
#if LOGICAL_AXES > LINEAR_AXES
|
#if LOGICAL_AXES > NUM_AXES
|
||||||
FI void set(const T (&arr)[LOGICAL_AXES]) { x = arr[0]; y = arr[1]; }
|
FI void set(const T (&arr)[LOGICAL_AXES]) { x = arr[0]; y = arr[1]; }
|
||||||
#if DISTINCT_AXES > LOGICAL_AXES
|
#if DISTINCT_AXES > LOGICAL_AXES
|
||||||
FI void set(const T (&arr)[DISTINCT_AXES]) { x = arr[0]; y = arr[1]; }
|
FI void set(const T (&arr)[DISTINCT_AXES]) { x = arr[0]; y = arr[1]; }
|
||||||
@@ -438,29 +455,29 @@ struct XYval {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
struct XYZval {
|
struct XYZval {
|
||||||
union {
|
union {
|
||||||
struct { T LINEAR_AXIS_ARGS(); };
|
struct { T NUM_AXIS_ARGS(); };
|
||||||
struct { T LINEAR_AXIS_LIST(a, b, c, u, v, w); };
|
struct { T NUM_AXIS_LIST(a, b, c, _i, _j, _k); };
|
||||||
T pos[LINEAR_AXES];
|
T pos[NUM_AXES];
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set all to 0
|
// Set all to 0
|
||||||
FI void reset() { LINEAR_AXIS_GANG(x =, y =, z =, i =, j =, k =) 0; }
|
FI void reset() { NUM_AXIS_GANG(x =, y =, z =, i =, j =, k =) 0; }
|
||||||
|
|
||||||
// Setters taking struct types and arrays
|
// Setters taking struct types and arrays
|
||||||
FI void set(const T px) { x = px; }
|
FI void set(const T px) { x = px; }
|
||||||
FI void set(const T px, const T py) { x = px; y = py; }
|
FI void set(const T px, const T py) { x = px; y = py; }
|
||||||
FI void set(const XYval<T> pxy) { x = pxy.x; y = pxy.y; }
|
FI void set(const XYval<T> pxy) { x = pxy.x; y = pxy.y; }
|
||||||
FI void set(const XYval<T> pxy, const T pz) { LINEAR_AXIS_CODE(x = pxy.x, y = pxy.y, z = pz, NOOP, NOOP, NOOP); }
|
FI void set(const XYval<T> pxy, const T pz) { NUM_AXIS_CODE(x = pxy.x, y = pxy.y, z = pz, NOOP, NOOP, NOOP); }
|
||||||
FI void set(const T (&arr)[XY]) { x = arr[0]; y = arr[1]; }
|
FI void set(const T (&arr)[XY]) { x = arr[0]; y = arr[1]; }
|
||||||
#if HAS_Z_AXIS
|
#if HAS_Z_AXIS
|
||||||
FI void set(const T (&arr)[LINEAR_AXES]) { LINEAR_AXIS_CODE(x = arr[0], y = arr[1], z = arr[2], i = arr[3], j = arr[4], k = arr[5]); }
|
FI void set(const T (&arr)[NUM_AXES]) { NUM_AXIS_CODE(x = arr[0], y = arr[1], z = arr[2], i = arr[3], j = arr[4], k = arr[5]); }
|
||||||
FI void set(LINEAR_AXIS_ARGS(const T)) { LINEAR_AXIS_CODE(a = x, b = y, c = z, u = i, v = j, w = k ); }
|
FI void set(NUM_AXIS_ARGS(const T)) { NUM_AXIS_CODE(a = x, b = y, c = z, _i = i, _j = j, _k = k); }
|
||||||
#endif
|
#endif
|
||||||
#if LOGICAL_AXES > LINEAR_AXES
|
#if LOGICAL_AXES > NUM_AXES
|
||||||
FI void set(const T (&arr)[LOGICAL_AXES]) { LINEAR_AXIS_CODE(x = arr[0], y = arr[1], z = arr[2], i = arr[3], j = arr[4], k = arr[5]); }
|
FI void set(const T (&arr)[LOGICAL_AXES]) { NUM_AXIS_CODE(x = arr[0], y = arr[1], z = arr[2], i = arr[3], j = arr[4], k = arr[5]); }
|
||||||
FI void set(LOGICAL_AXIS_ARGS(const T)) { LINEAR_AXIS_CODE(a = x, b = y, c = z, u = i, v = j, w = k ); }
|
FI void set(LOGICAL_AXIS_ARGS(const T)) { NUM_AXIS_CODE(a = x, b = y, c = z, _i = i, _j = j, _k = k); }
|
||||||
#if DISTINCT_AXES > LOGICAL_AXES
|
#if DISTINCT_AXES > LOGICAL_AXES
|
||||||
FI void set(const T (&arr)[DISTINCT_AXES]) { LINEAR_AXIS_CODE(x = arr[0], y = arr[1], z = arr[2], i = arr[3], j = arr[4], k = arr[5]); }
|
FI void set(const T (&arr)[DISTINCT_AXES]) { NUM_AXIS_CODE(x = arr[0], y = arr[1], z = arr[2], i = arr[3], j = arr[4], k = arr[5]); }
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#if HAS_I_AXIS
|
#if HAS_I_AXIS
|
||||||
@@ -474,24 +491,24 @@ struct XYZval {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Length reduced to one dimension
|
// Length reduced to one dimension
|
||||||
FI T magnitude() const { return (T)sqrtf(LINEAR_AXIS_GANG(x*x, + y*y, + z*z, + i*i, + j*j, + k*k)); }
|
FI T magnitude() const { return (T)sqrtf(NUM_AXIS_GANG(x*x, + y*y, + z*z, + i*i, + j*j, + k*k)); }
|
||||||
// Pointer to the data as a simple array
|
// 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
|
// If any element is true then it's true
|
||||||
FI operator bool() { return LINEAR_AXIS_GANG(x, || y, || z, || i, || j, || k); }
|
FI operator bool() { return NUM_AXIS_GANG(x, || y, || z, || i, || j, || k); }
|
||||||
|
|
||||||
// Explicit copy and copies with conversion
|
// Explicit copy and copies with conversion
|
||||||
FI XYZval<T> copy() const { XYZval<T> o = *this; return o; }
|
FI XYZval<T> copy() const { XYZval<T> o = *this; return o; }
|
||||||
FI XYZval<T> ABS() const { return LINEAR_AXIS_ARRAY(T(_ABS(x)), T(_ABS(y)), T(_ABS(z)), T(_ABS(i)), T(_ABS(j)), T(_ABS(k))); }
|
FI XYZval<T> ABS() const { return NUM_AXIS_ARRAY(T(_ABS(x)), T(_ABS(y)), T(_ABS(z)), T(_ABS(i)), T(_ABS(j)), T(_ABS(k))); }
|
||||||
FI XYZval<int16_t> asInt() { return LINEAR_AXIS_ARRAY(int16_t(x), int16_t(y), int16_t(z), int16_t(i), int16_t(j), int16_t(k)); }
|
FI XYZval<int16_t> asInt() { return NUM_AXIS_ARRAY(int16_t(x), int16_t(y), int16_t(z), int16_t(i), int16_t(j), int16_t(k)); }
|
||||||
FI XYZval<int16_t> asInt() const { return LINEAR_AXIS_ARRAY(int16_t(x), int16_t(y), int16_t(z), int16_t(i), int16_t(j), int16_t(k)); }
|
FI XYZval<int16_t> asInt() const { return NUM_AXIS_ARRAY(int16_t(x), int16_t(y), int16_t(z), int16_t(i), int16_t(j), int16_t(k)); }
|
||||||
FI XYZval<int32_t> asLong() { return LINEAR_AXIS_ARRAY(int32_t(x), int32_t(y), int32_t(z), int32_t(i), int32_t(j), int32_t(k)); }
|
FI XYZval<int32_t> asLong() { return NUM_AXIS_ARRAY(int32_t(x), int32_t(y), int32_t(z), int32_t(i), int32_t(j), int32_t(k)); }
|
||||||
FI XYZval<int32_t> asLong() const { return LINEAR_AXIS_ARRAY(int32_t(x), int32_t(y), int32_t(z), int32_t(i), int32_t(j), int32_t(k)); }
|
FI XYZval<int32_t> asLong() const { return NUM_AXIS_ARRAY(int32_t(x), int32_t(y), int32_t(z), int32_t(i), int32_t(j), int32_t(k)); }
|
||||||
FI XYZval<int32_t> ROUNDL() { return LINEAR_AXIS_ARRAY(int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(i)), int32_t(LROUND(j)), int32_t(LROUND(k))); }
|
FI XYZval<int32_t> ROUNDL() { return NUM_AXIS_ARRAY(int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(i)), int32_t(LROUND(j)), int32_t(LROUND(k))); }
|
||||||
FI XYZval<int32_t> ROUNDL() const { return LINEAR_AXIS_ARRAY(int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(i)), int32_t(LROUND(j)), int32_t(LROUND(k))); }
|
FI XYZval<int32_t> ROUNDL() const { return NUM_AXIS_ARRAY(int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(i)), int32_t(LROUND(j)), int32_t(LROUND(k))); }
|
||||||
FI XYZval<float> asFloat() { return LINEAR_AXIS_ARRAY(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(i), static_cast<float>(j), static_cast<float>(k)); }
|
FI XYZval<float> asFloat() { return NUM_AXIS_ARRAY(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(i), static_cast<float>(j), static_cast<float>(k)); }
|
||||||
FI XYZval<float> asFloat() const { return LINEAR_AXIS_ARRAY(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(i), static_cast<float>(j), static_cast<float>(k)); }
|
FI XYZval<float> asFloat() const { return NUM_AXIS_ARRAY(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(i), static_cast<float>(j), static_cast<float>(k)); }
|
||||||
FI XYZval<float> reciprocal() const { return LINEAR_AXIS_ARRAY(_RECIP(x), _RECIP(y), _RECIP(z), _RECIP(i), _RECIP(j), _RECIP(k)); }
|
FI XYZval<float> reciprocal() const { return NUM_AXIS_ARRAY(_RECIP(x), _RECIP(y), _RECIP(z), _RECIP(i), _RECIP(j), _RECIP(k)); }
|
||||||
|
|
||||||
// Marlin workspace shifting is done with G92 and M206
|
// Marlin workspace shifting is done with G92 and M206
|
||||||
FI XYZval<float> asLogical() const { XYZval<float> o = asFloat(); toLogical(o); return o; }
|
FI XYZval<float> asLogical() const { XYZval<float> o = asFloat(); toLogical(o); return o; }
|
||||||
@@ -502,78 +519,78 @@ struct XYZval {
|
|||||||
FI operator const XYval<T>&() const { return *(const XYval<T>*)this; }
|
FI operator const XYval<T>&() const { return *(const XYval<T>*)this; }
|
||||||
|
|
||||||
// Cast to a type with more fields by making a new object
|
// Cast to a type with more fields by making a new object
|
||||||
FI operator XYZEval<T>() const { return LINEAR_AXIS_ARRAY(x, y, z, i, j, k); }
|
FI operator XYZEval<T>() const { return NUM_AXIS_ARRAY(x, y, z, i, j, k); }
|
||||||
|
|
||||||
// Accessor via an AxisEnum (or any integer) [index]
|
// Accessor via an AxisEnum (or any integer) [index]
|
||||||
FI T& operator[](const int n) { return pos[n]; }
|
FI T& operator[](const int n) { return pos[n]; }
|
||||||
FI const T& operator[](const int n) const { return pos[n]; }
|
FI const T& operator[](const int n) const { return pos[n]; }
|
||||||
|
|
||||||
// Assignment operator overrides do the expected thing
|
// Assignment operator overrides do the expected thing
|
||||||
FI XYZval<T>& operator= (const T v) { set(ARRAY_N_1(LINEAR_AXES, v)); return *this; }
|
FI XYZval<T>& operator= (const T v) { set(ARRAY_N_1(NUM_AXES, v)); return *this; }
|
||||||
FI XYZval<T>& operator= (const XYval<T> &rs) { set(rs.x, rs.y ); return *this; }
|
FI XYZval<T>& operator= (const XYval<T> &rs) { set(rs.x, rs.y ); return *this; }
|
||||||
FI XYZval<T>& operator= (const XYZEval<T> &rs) { set(LINEAR_AXIS_ELEM(rs)); return *this; }
|
FI XYZval<T>& operator= (const XYZEval<T> &rs) { set(NUM_AXIS_ELEM(rs)); return *this; }
|
||||||
|
|
||||||
// Override other operators to get intuitive behaviors
|
// Override other operators to get intuitive behaviors
|
||||||
FI XYZval<T> operator+ (const XYval<T> &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; }
|
FI XYZval<T> operator+ (const XYval<T> &rs) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; }
|
||||||
FI XYZval<T> operator+ (const XYval<T> &rs) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; }
|
FI XYZval<T> operator+ (const XYval<T> &rs) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; }
|
||||||
FI XYZval<T> operator- (const XYval<T> &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; }
|
FI XYZval<T> operator- (const XYval<T> &rs) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; }
|
||||||
FI XYZval<T> operator- (const XYval<T> &rs) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; }
|
FI XYZval<T> operator- (const XYval<T> &rs) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; }
|
||||||
FI XYZval<T> operator* (const XYval<T> &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; }
|
FI XYZval<T> operator* (const XYval<T> &rs) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; }
|
||||||
FI XYZval<T> operator* (const XYval<T> &rs) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; }
|
FI XYZval<T> operator* (const XYval<T> &rs) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; }
|
||||||
FI XYZval<T> operator/ (const XYval<T> &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; }
|
FI XYZval<T> operator/ (const XYval<T> &rs) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; }
|
||||||
FI XYZval<T> operator/ (const XYval<T> &rs) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; }
|
FI XYZval<T> operator/ (const XYval<T> &rs) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; }
|
||||||
FI XYZval<T> operator+ (const XYZval<T> &rs) const { XYZval<T> ls = *this; LINEAR_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); return ls; }
|
FI XYZval<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); return ls; }
|
||||||
FI XYZval<T> operator+ (const XYZval<T> &rs) { XYZval<T> ls = *this; LINEAR_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); return ls; }
|
FI XYZval<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); return ls; }
|
||||||
FI XYZval<T> operator- (const XYZval<T> &rs) const { XYZval<T> ls = *this; LINEAR_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); return ls; }
|
FI XYZval<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); return ls; }
|
||||||
FI XYZval<T> operator- (const XYZval<T> &rs) { XYZval<T> ls = *this; LINEAR_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); return ls; }
|
FI XYZval<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); return ls; }
|
||||||
FI XYZval<T> operator* (const XYZval<T> &rs) const { XYZval<T> ls = *this; LINEAR_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); return ls; }
|
FI XYZval<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); return ls; }
|
||||||
FI XYZval<T> operator* (const XYZval<T> &rs) { XYZval<T> ls = *this; LINEAR_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); return ls; }
|
FI XYZval<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); return ls; }
|
||||||
FI XYZval<T> operator/ (const XYZval<T> &rs) const { XYZval<T> ls = *this; LINEAR_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); return ls; }
|
FI XYZval<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); return ls; }
|
||||||
FI XYZval<T> operator/ (const XYZval<T> &rs) { XYZval<T> ls = *this; LINEAR_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); return ls; }
|
FI XYZval<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); return ls; }
|
||||||
FI XYZval<T> operator+ (const XYZEval<T> &rs) const { XYZval<T> ls = *this; LINEAR_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); 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); return ls; }
|
||||||
FI XYZval<T> operator+ (const XYZEval<T> &rs) { XYZval<T> ls = *this; LINEAR_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); 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); return ls; }
|
||||||
FI XYZval<T> operator- (const XYZEval<T> &rs) const { XYZval<T> ls = *this; LINEAR_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); 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); return ls; }
|
||||||
FI XYZval<T> operator- (const XYZEval<T> &rs) { XYZval<T> ls = *this; LINEAR_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); 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); return ls; }
|
||||||
FI XYZval<T> operator* (const XYZEval<T> &rs) const { XYZval<T> ls = *this; LINEAR_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); 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); return ls; }
|
||||||
FI XYZval<T> operator* (const XYZEval<T> &rs) { XYZval<T> ls = *this; LINEAR_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); 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); return ls; }
|
||||||
FI XYZval<T> operator/ (const XYZEval<T> &rs) const { XYZval<T> ls = *this; LINEAR_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); 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); return ls; }
|
||||||
FI XYZval<T> operator/ (const XYZEval<T> &rs) { XYZval<T> ls = *this; LINEAR_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); 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); return ls; }
|
||||||
FI XYZval<T> operator* (const float &v) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= 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 ); return ls; }
|
||||||
FI XYZval<T> operator* (const float &v) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= 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 ); return ls; }
|
||||||
FI XYZval<T> operator* (const int &v) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= 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 ); return ls; }
|
||||||
FI XYZval<T> operator* (const int &v) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= 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 ); return ls; }
|
||||||
FI XYZval<T> operator/ (const float &v) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= 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 ); return ls; }
|
||||||
FI XYZval<T> operator/ (const float &v) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= 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 ); return ls; }
|
||||||
FI XYZval<T> operator/ (const int &v) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= 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 ); return ls; }
|
||||||
FI XYZval<T> operator/ (const int &v) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= 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 ); return ls; }
|
||||||
FI XYZval<T> operator>>(const int &v) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(_RS(ls.x), _RS(ls.y), _RS(ls.z), _RS(ls.i), _RS(ls.j), _RS(ls.k) ); 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) ); return ls; }
|
||||||
FI XYZval<T> operator>>(const int &v) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(_RS(ls.x), _RS(ls.y), _RS(ls.z), _RS(ls.i), _RS(ls.j), _RS(ls.k) ); 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) ); return ls; }
|
||||||
FI XYZval<T> operator<<(const int &v) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(_LS(ls.x), _LS(ls.y), _LS(ls.z), _LS(ls.i), _LS(ls.j), _LS(ls.k) ); 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) ); return ls; }
|
||||||
FI XYZval<T> operator<<(const int &v) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(_LS(ls.x), _LS(ls.y), _LS(ls.z), _LS(ls.i), _LS(ls.j), _LS(ls.k) ); 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) ); return ls; }
|
||||||
FI const XYZval<T> operator-() const { XYZval<T> o = *this; LINEAR_AXIS_CODE(o.x = -x, o.y = -y, o.z = -z, o.i = -i, o.j = -j, o.k = -k); return o; }
|
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); return o; }
|
||||||
FI XYZval<T> operator-() { XYZval<T> o = *this; LINEAR_AXIS_CODE(o.x = -x, o.y = -y, o.z = -z, o.i = -i, o.j = -j, o.k = -k); 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); return o; }
|
||||||
|
|
||||||
// Modifier operators
|
// Modifier operators
|
||||||
FI XYZval<T>& operator+=(const XYval<T> &rs) { LINEAR_AXIS_CODE(x += rs.x, y += rs.y, NOOP, NOOP, NOOP, NOOP ); return *this; }
|
FI XYZval<T>& operator+=(const XYval<T> &rs) { NUM_AXIS_CODE(x += rs.x, y += rs.y, NOOP, NOOP, NOOP, NOOP ); return *this; }
|
||||||
FI XYZval<T>& operator-=(const XYval<T> &rs) { LINEAR_AXIS_CODE(x -= rs.x, y -= rs.y, NOOP, NOOP, NOOP, NOOP ); return *this; }
|
FI XYZval<T>& operator-=(const XYval<T> &rs) { NUM_AXIS_CODE(x -= rs.x, y -= rs.y, NOOP, NOOP, NOOP, NOOP ); return *this; }
|
||||||
FI XYZval<T>& operator*=(const XYval<T> &rs) { LINEAR_AXIS_CODE(x *= rs.x, y *= rs.y, NOOP, NOOP, NOOP, NOOP ); return *this; }
|
FI XYZval<T>& operator*=(const XYval<T> &rs) { NUM_AXIS_CODE(x *= rs.x, y *= rs.y, NOOP, NOOP, NOOP, NOOP ); return *this; }
|
||||||
FI XYZval<T>& operator/=(const XYval<T> &rs) { LINEAR_AXIS_CODE(x /= rs.x, y /= rs.y, NOOP, NOOP, NOOP, NOOP ); return *this; }
|
FI XYZval<T>& operator/=(const XYval<T> &rs) { NUM_AXIS_CODE(x /= rs.x, y /= rs.y, NOOP, NOOP, NOOP, NOOP ); return *this; }
|
||||||
FI XYZval<T>& operator+=(const XYZval<T> &rs) { LINEAR_AXIS_CODE(x += rs.x, y += rs.y, z += rs.z, i += rs.i, j += rs.j, k += rs.k); return *this; }
|
FI XYZval<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); return *this; }
|
||||||
FI XYZval<T>& operator-=(const XYZval<T> &rs) { LINEAR_AXIS_CODE(x -= rs.x, y -= rs.y, z -= rs.z, i -= rs.i, j -= rs.j, k -= rs.k); return *this; }
|
FI XYZval<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); return *this; }
|
||||||
FI XYZval<T>& operator*=(const XYZval<T> &rs) { LINEAR_AXIS_CODE(x *= rs.x, y *= rs.y, z *= rs.z, i *= rs.i, j *= rs.j, k *= rs.k); return *this; }
|
FI XYZval<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); return *this; }
|
||||||
FI XYZval<T>& operator/=(const XYZval<T> &rs) { LINEAR_AXIS_CODE(x /= rs.x, y /= rs.y, z /= rs.z, i /= rs.i, j /= rs.j, k /= rs.k); return *this; }
|
FI XYZval<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); return *this; }
|
||||||
FI XYZval<T>& operator+=(const XYZEval<T> &rs) { LINEAR_AXIS_CODE(x += rs.x, y += rs.y, z += rs.z, i += rs.i, j += rs.j, k += rs.k); 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); return *this; }
|
||||||
FI XYZval<T>& operator-=(const XYZEval<T> &rs) { LINEAR_AXIS_CODE(x -= rs.x, y -= rs.y, z -= rs.z, i -= rs.i, j -= rs.j, k -= rs.k); 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); return *this; }
|
||||||
FI XYZval<T>& operator*=(const XYZEval<T> &rs) { LINEAR_AXIS_CODE(x *= rs.x, y *= rs.y, z *= rs.z, i *= rs.i, j *= rs.j, k *= rs.k); 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); return *this; }
|
||||||
FI XYZval<T>& operator/=(const XYZEval<T> &rs) { LINEAR_AXIS_CODE(x /= rs.x, y /= rs.y, z /= rs.z, i /= rs.i, j /= rs.j, k /= rs.k); 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); return *this; }
|
||||||
FI XYZval<T>& operator*=(const float &v) { LINEAR_AXIS_CODE(x *= v, y *= v, z *= v, i *= v, j *= v, k *= v); return *this; }
|
FI XYZval<T>& operator*=(const float &v) { NUM_AXIS_CODE(x *= v, y *= v, z *= v, i *= v, j *= v, k *= v); return *this; }
|
||||||
FI XYZval<T>& operator*=(const int &v) { LINEAR_AXIS_CODE(x *= v, y *= v, z *= v, i *= v, j *= v, k *= 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); return *this; }
|
||||||
FI XYZval<T>& operator>>=(const int &v) { LINEAR_AXIS_CODE(_RS(x), _RS(y), _RS(z), _RS(i), _RS(j), _RS(k)); return *this; }
|
FI XYZval<T>& operator>>=(const int &v) { NUM_AXIS_CODE(_RS(x), _RS(y), _RS(z), _RS(i), _RS(j), _RS(k)); return *this; }
|
||||||
FI XYZval<T>& operator<<=(const int &v) { LINEAR_AXIS_CODE(_LS(x), _LS(y), _LS(z), _LS(i), _LS(j), _LS(k)); return *this; }
|
FI XYZval<T>& operator<<=(const int &v) { NUM_AXIS_CODE(_LS(x), _LS(y), _LS(z), _LS(i), _LS(j), _LS(k)); return *this; }
|
||||||
|
|
||||||
// Exact comparisons. For floats a "NEAR" operation may be better.
|
// Exact comparisons. For floats a "NEAR" operation may be better.
|
||||||
FI bool operator==(const XYZEval<T> &rs) { return true LINEAR_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k); }
|
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); }
|
||||||
FI bool operator==(const XYZEval<T> &rs) const { return true LINEAR_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k); }
|
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); }
|
||||||
FI bool operator!=(const XYZEval<T> &rs) { return !operator==(rs); }
|
FI bool operator!=(const XYZEval<T> &rs) { return !operator==(rs); }
|
||||||
FI bool operator!=(const XYZEval<T> &rs) const { return !operator==(rs); }
|
FI bool operator!=(const XYZEval<T> &rs) const { return !operator==(rs); }
|
||||||
};
|
};
|
||||||
@@ -585,7 +602,7 @@ template<typename T>
|
|||||||
struct XYZEval {
|
struct XYZEval {
|
||||||
union {
|
union {
|
||||||
struct { T LOGICAL_AXIS_ARGS(); };
|
struct { T LOGICAL_AXIS_ARGS(); };
|
||||||
struct { T LOGICAL_AXIS_LIST(_e, a, b, c, u, v, w); };
|
struct { T LOGICAL_AXIS_LIST(_e, a, b, c, _i, _j, _k); };
|
||||||
T pos[LOGICAL_AXES];
|
T pos[LOGICAL_AXES];
|
||||||
};
|
};
|
||||||
// Reset all to 0
|
// Reset all to 0
|
||||||
@@ -605,15 +622,15 @@ struct XYZEval {
|
|||||||
#endif
|
#endif
|
||||||
// Setters taking struct types and arrays
|
// Setters taking struct types and arrays
|
||||||
FI void set(const XYval<T> pxy) { x = pxy.x; y = pxy.y; }
|
FI void set(const XYval<T> pxy) { x = pxy.x; y = pxy.y; }
|
||||||
FI void set(const XYZval<T> pxyz) { set(LINEAR_AXIS_ELEM(pxyz)); }
|
FI void set(const XYZval<T> pxyz) { set(NUM_AXIS_ELEM(pxyz)); }
|
||||||
#if HAS_Z_AXIS
|
#if HAS_Z_AXIS
|
||||||
FI void set(LINEAR_AXIS_ARGS(const T)) { LINEAR_AXIS_CODE(a = x, b = y, c = z, u = i, v = j, w = k); }
|
FI void set(NUM_AXIS_ARGS(const T)) { NUM_AXIS_CODE(a = x, b = y, c = z, _i = i, _j = j, _k = k); }
|
||||||
#endif
|
#endif
|
||||||
FI void set(const XYval<T> pxy, const T pz) { set(pxy); TERN_(HAS_Z_AXIS, z = pz); }
|
FI void set(const XYval<T> pxy, const T pz) { set(pxy); TERN_(HAS_Z_AXIS, z = pz); }
|
||||||
#if LOGICAL_AXES > LINEAR_AXES
|
#if LOGICAL_AXES > NUM_AXES
|
||||||
FI void set(const XYval<T> pxy, const T pz, const T pe) { set(pxy, pz); e = pe; }
|
FI void set(const XYval<T> pxy, const T pz, const T pe) { set(pxy, pz); e = pe; }
|
||||||
FI void set(const XYZval<T> pxyz, const T pe) { set(pxyz); e = pe; }
|
FI void set(const XYZval<T> pxyz, const T pe) { set(pxyz); e = pe; }
|
||||||
FI void set(LOGICAL_AXIS_ARGS(const T)) { LOGICAL_AXIS_CODE(_e = e, a = x, b = y, c = z, u = i, v = j, w = k); }
|
FI void set(LOGICAL_AXIS_ARGS(const T)) { LOGICAL_AXIS_CODE(_e = e, a = x, b = y, c = z, _i = i, _j = j, _k = k); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Length reduced to one dimension
|
// Length reduced to one dimension
|
||||||
@@ -651,9 +668,9 @@ struct XYZEval {
|
|||||||
FI const T& operator[](const int n) const { return pos[n]; }
|
FI const T& operator[](const int n) const { return pos[n]; }
|
||||||
|
|
||||||
// Assignment operator overrides do the expected thing
|
// Assignment operator overrides do the expected thing
|
||||||
FI XYZEval<T>& operator= (const T v) { set(LIST_N_1(LINEAR_AXES, v)); return *this; }
|
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 XYval<T> &rs) { set(rs.x, rs.y); return *this; }
|
||||||
FI XYZEval<T>& operator= (const XYZval<T> &rs) { set(LINEAR_AXIS_ELEM(rs)); return *this; }
|
FI XYZEval<T>& operator= (const XYZval<T> &rs) { set(NUM_AXIS_ELEM(rs)); return *this; }
|
||||||
|
|
||||||
// Override other operators to get intuitive behaviors
|
// 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) const { XYZEval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; return ls; }
|
||||||
@@ -664,14 +681,14 @@ struct XYZEval {
|
|||||||
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) { 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) 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) { 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; LINEAR_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); 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); return ls; }
|
||||||
FI XYZEval<T> operator+ (const XYZval<T> &rs) { XYZval<T> ls = *this; LINEAR_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); 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); return ls; }
|
||||||
FI XYZEval<T> operator- (const XYZval<T> &rs) const { XYZval<T> ls = *this; LINEAR_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); 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); return ls; }
|
||||||
FI XYZEval<T> operator- (const XYZval<T> &rs) { XYZval<T> ls = *this; LINEAR_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); 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); return ls; }
|
||||||
FI XYZEval<T> operator* (const XYZval<T> &rs) const { XYZval<T> ls = *this; LINEAR_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); 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); return ls; }
|
||||||
FI XYZEval<T> operator* (const XYZval<T> &rs) { XYZval<T> ls = *this; LINEAR_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); 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); return ls; }
|
||||||
FI XYZEval<T> operator/ (const XYZval<T> &rs) const { XYZval<T> ls = *this; LINEAR_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); 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); return ls; }
|
||||||
FI XYZEval<T> operator/ (const XYZval<T> &rs) { XYZval<T> ls = *this; LINEAR_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); 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); 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); 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); 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); 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); 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); 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); return ls; }
|
||||||
@@ -700,10 +717,10 @@ struct XYZEval {
|
|||||||
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 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) { LINEAR_AXIS_CODE(x += rs.x, y += rs.y, z += rs.z, i += rs.i, j += rs.j, k += rs.k); 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); return *this; }
|
||||||
FI XYZEval<T>& operator-=(const XYZval<T> &rs) { LINEAR_AXIS_CODE(x -= rs.x, y -= rs.y, z -= rs.z, i -= rs.i, j -= rs.j, k -= rs.k); 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); return *this; }
|
||||||
FI XYZEval<T>& operator*=(const XYZval<T> &rs) { LINEAR_AXIS_CODE(x *= rs.x, y *= rs.y, z *= rs.z, i *= rs.i, j *= rs.j, k *= rs.k); 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); return *this; }
|
||||||
FI XYZEval<T>& operator/=(const XYZval<T> &rs) { LINEAR_AXIS_CODE(x /= rs.x, y /= rs.y, z /= rs.z, i /= rs.i, j /= rs.j, k /= rs.k); 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); 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); 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); 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); 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); 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); 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); return *this; }
|
||||||
@@ -713,8 +730,8 @@ struct XYZEval {
|
|||||||
FI XYZEval<T>& operator<<=(const int &v) { LOGICAL_AXIS_CODE(_LS(e), _LS(x), _LS(y), _LS(z), _LS(i), _LS(j), _LS(k)); 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)); return *this; }
|
||||||
|
|
||||||
// Exact comparisons. For floats a "NEAR" operation may be better.
|
// Exact comparisons. For floats a "NEAR" operation may be better.
|
||||||
FI bool operator==(const XYZval<T> &rs) { return true LINEAR_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k); }
|
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); }
|
||||||
FI bool operator==(const XYZval<T> &rs) const { return true LINEAR_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k); }
|
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); }
|
||||||
FI bool operator!=(const XYZval<T> &rs) { return !operator==(rs); }
|
FI bool operator!=(const XYZval<T> &rs) { return !operator==(rs); }
|
||||||
FI bool operator!=(const XYZval<T> &rs) const { return !operator==(rs); }
|
FI bool operator!=(const XYZval<T> &rs) const { return !operator==(rs); }
|
||||||
};
|
};
|
||||||
|
@@ -29,10 +29,10 @@ void safe_delay(millis_t ms) {
|
|||||||
while (ms > 50) {
|
while (ms > 50) {
|
||||||
ms -= 50;
|
ms -= 50;
|
||||||
delay(50);
|
delay(50);
|
||||||
thermalManager.manage_heater();
|
thermalManager.task();
|
||||||
}
|
}
|
||||||
delay(ms);
|
delay(ms);
|
||||||
thermalManager.manage_heater(); // This keeps us safe if too many small safe_delay() calls are made
|
thermalManager.task(); // This keeps us safe if too many small safe_delay() calls are made
|
||||||
}
|
}
|
||||||
|
|
||||||
// A delay to provide brittle hosts time to receive bytes
|
// 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/probe.h"
|
||||||
#include "../module/motion.h"
|
#include "../module/motion.h"
|
||||||
#include "../module/stepper.h"
|
#include "../module/planner.h"
|
||||||
#include "../libs/numtostr.h"
|
#include "../libs/numtostr.h"
|
||||||
#include "../feature/bedlevel/bedlevel.h"
|
#include "../feature/bedlevel/bedlevel.h"
|
||||||
|
|
||||||
@@ -125,18 +125,17 @@ void safe_delay(millis_t ms) {
|
|||||||
#endif
|
#endif
|
||||||
#if ABL_PLANAR
|
#if ABL_PLANAR
|
||||||
SERIAL_ECHOPGM("ABL Adjustment");
|
SERIAL_ECHOPGM("ABL Adjustment");
|
||||||
LOOP_LINEAR_AXES(a) {
|
LOOP_NUM_AXES(a) {
|
||||||
SERIAL_CHAR(' ', AXIS_CHAR(a));
|
SERIAL_ECHOPGM_P((PGM_P)pgm_read_ptr(&SP_AXIS_STR[a]));
|
||||||
serial_offset(planner.get_axis_position_mm(AxisEnum(a)) - current_position[a]);
|
serial_offset(planner.get_axis_position_mm(AxisEnum(a)) - current_position[a]);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#if ENABLED(AUTO_BED_LEVELING_UBL)
|
#if ENABLED(AUTO_BED_LEVELING_UBL)
|
||||||
SERIAL_ECHOPGM("UBL Adjustment Z");
|
SERIAL_ECHOPGM("UBL Adjustment Z");
|
||||||
const float rz = bedlevel.get_z_correction(current_position);
|
|
||||||
#elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
|
#elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
|
||||||
SERIAL_ECHOPGM("ABL Adjustment Z");
|
SERIAL_ECHOPGM("ABL Adjustment Z");
|
||||||
const float rz = bedlevel.get_z_correction(current_position);
|
|
||||||
#endif
|
#endif
|
||||||
|
const float rz = bedlevel.get_z_correction(current_position);
|
||||||
SERIAL_ECHO(ftostr43sign(rz, '+'));
|
SERIAL_ECHO(ftostr43sign(rz, '+'));
|
||||||
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
|
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
|
||||||
if (planner.z_fade_height) {
|
if (planner.z_fade_height) {
|
||||||
@@ -156,11 +155,13 @@ void safe_delay(millis_t ms) {
|
|||||||
SERIAL_ECHOPGM("Mesh Bed Leveling");
|
SERIAL_ECHOPGM("Mesh Bed Leveling");
|
||||||
if (planner.leveling_active) {
|
if (planner.leveling_active) {
|
||||||
SERIAL_ECHOLNPGM(" (enabled)");
|
SERIAL_ECHOLNPGM(" (enabled)");
|
||||||
SERIAL_ECHOPGM("MBL Adjustment Z", ftostr43sign(bedlevel.get_z(current_position), '+'));
|
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, '+'));
|
||||||
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
|
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
|
||||||
if (planner.z_fade_height) {
|
if (planner.z_fade_height) {
|
||||||
SERIAL_ECHOPGM(" (", ftostr43sign(
|
SERIAL_ECHOPGM(" (", ftostr43sign(
|
||||||
bedlevel.get_z(current_position, planner.fade_scaling_factor_for_z(current_position.z)), '+'
|
z_offset + z_correction * planner.fade_scaling_factor_for_z(current_position.z), '+'
|
||||||
));
|
));
|
||||||
SERIAL_CHAR(')');
|
SERIAL_CHAR(')');
|
||||||
}
|
}
|
||||||
|
@@ -59,6 +59,11 @@ void safe_delay(millis_t ms); // Delay ensuring that temperatures are
|
|||||||
#define log_machine_info() NOOP
|
#define log_machine_info() NOOP
|
||||||
#endif
|
#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>
|
template<typename T>
|
||||||
class restorer {
|
class restorer {
|
||||||
T& ref_;
|
T& ref_;
|
||||||
@@ -77,10 +82,13 @@ public:
|
|||||||
// in the range 0-100 while avoiding rounding artifacts
|
// in the range 0-100 while avoiding rounding artifacts
|
||||||
constexpr uint8_t ui8_to_percent(const uint8_t i) { return (int(i) * 100 + 127) / 255; }
|
constexpr uint8_t ui8_to_percent(const uint8_t i) { return (int(i) * 100 + 127) / 255; }
|
||||||
|
|
||||||
|
// Axis names for G-code parsing, reports, etc.
|
||||||
const xyze_char_t axis_codes LOGICAL_AXIS_ARRAY('E', 'X', 'Y', 'Z', AXIS4_NAME, AXIS5_NAME, AXIS6_NAME);
|
const xyze_char_t axis_codes LOGICAL_AXIS_ARRAY('E', 'X', 'Y', 'Z', AXIS4_NAME, AXIS5_NAME, AXIS6_NAME);
|
||||||
|
#if NUM_AXES <= XYZ && !HAS_EXTRUDERS
|
||||||
#if LINEAR_AXES <= XYZ
|
|
||||||
#define AXIS_CHAR(A) ((char)('X' + A))
|
#define AXIS_CHAR(A) ((char)('X' + A))
|
||||||
|
#define IAXIS_CHAR AXIS_CHAR
|
||||||
#else
|
#else
|
||||||
|
const xyze_char_t iaxis_codes LOGICAL_AXIS_ARRAY('E', 'X', 'Y', 'Z', 'I', 'J', 'K');
|
||||||
#define AXIS_CHAR(A) axis_codes[A]
|
#define AXIS_CHAR(A) axis_codes[A]
|
||||||
|
#define IAXIS_CHAR(A) iaxis_codes[A]
|
||||||
#endif
|
#endif
|
||||||
|
@@ -97,7 +97,7 @@ void Backlash::add_correction_steps(const int32_t &da, const int32_t &db, const
|
|||||||
|
|
||||||
const float f_corr = float(correction) / all_on;
|
const float f_corr = float(correction) / all_on;
|
||||||
|
|
||||||
LOOP_LINEAR_AXES(axis) {
|
LOOP_NUM_AXES(axis) {
|
||||||
if (distance_mm[axis]) {
|
if (distance_mm[axis]) {
|
||||||
const bool reverse = TEST(dm, axis);
|
const bool reverse = TEST(dm, axis);
|
||||||
|
|
||||||
@@ -145,7 +145,7 @@ void Backlash::add_correction_steps(const int32_t &da, const int32_t &db, const
|
|||||||
}
|
}
|
||||||
|
|
||||||
int32_t Backlash::get_applied_steps(const AxisEnum axis) {
|
int32_t Backlash::get_applied_steps(const AxisEnum axis) {
|
||||||
if (axis >= LINEAR_AXES) return 0;
|
if (axis >= NUM_AXES) return 0;
|
||||||
|
|
||||||
const bool reverse = TEST(last_direction_bits, axis);
|
const bool reverse = TEST(last_direction_bits, axis);
|
||||||
|
|
||||||
@@ -162,17 +162,20 @@ int32_t Backlash::get_applied_steps(const AxisEnum axis) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Backlash::StepAdjuster {
|
class Backlash::StepAdjuster {
|
||||||
|
private:
|
||||||
xyz_long_t applied_steps;
|
xyz_long_t applied_steps;
|
||||||
public:
|
public:
|
||||||
StepAdjuster() {
|
StepAdjuster() {
|
||||||
LOOP_LINEAR_AXES(axis) applied_steps[axis] = backlash.get_applied_steps((AxisEnum)axis);
|
LOOP_NUM_AXES(axis) applied_steps[axis] = backlash.get_applied_steps((AxisEnum)axis);
|
||||||
}
|
}
|
||||||
~StepAdjuster() {
|
~StepAdjuster() {
|
||||||
// after backlash compensation parameter changes, ensure applied step count does not change
|
// after backlash compensation parameter changes, ensure applied step count does not change
|
||||||
LOOP_LINEAR_AXES(axis) residual_error[axis] += backlash.get_applied_steps((AxisEnum)axis) - applied_steps[axis];
|
LOOP_NUM_AXES(axis) residual_error[axis] += backlash.get_applied_steps((AxisEnum)axis) - applied_steps[axis];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if ENABLED(BACKLASH_GCODE)
|
||||||
|
|
||||||
void Backlash::set_correction_uint8(const uint8_t v) {
|
void Backlash::set_correction_uint8(const uint8_t v) {
|
||||||
StepAdjuster adjuster;
|
StepAdjuster adjuster;
|
||||||
correction = v;
|
correction = v;
|
||||||
@@ -190,6 +193,8 @@ void Backlash::set_distance_mm(const AxisEnum axis, const float v) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#if ENABLED(MEASURE_BACKLASH_WHEN_PROBING)
|
#if ENABLED(MEASURE_BACKLASH_WHEN_PROBING)
|
||||||
|
|
||||||
#include "../module/probe.h"
|
#include "../module/probe.h"
|
||||||
|
@@ -154,7 +154,7 @@ void reset_bed_level() {
|
|||||||
#endif
|
#endif
|
||||||
LOOP_L_N(x, sx) {
|
LOOP_L_N(x, sx) {
|
||||||
SERIAL_CHAR(' ');
|
SERIAL_CHAR(' ');
|
||||||
const float offset = values[x * sx + y];
|
const float offset = values[x * sy + y];
|
||||||
if (!isnan(offset)) {
|
if (!isnan(offset)) {
|
||||||
if (offset >= 0) SERIAL_CHAR('+');
|
if (offset >= 0) SERIAL_CHAR('+');
|
||||||
SERIAL_ECHO_F(offset, int(precision));
|
SERIAL_ECHO_F(offset, int(precision));
|
||||||
|
@@ -31,7 +31,6 @@
|
|||||||
#include "../../../libs/hex_print.h"
|
#include "../../../libs/hex_print.h"
|
||||||
#include "../../../module/settings.h"
|
#include "../../../module/settings.h"
|
||||||
#include "../../../lcd/marlinui.h"
|
#include "../../../lcd/marlinui.h"
|
||||||
#include "../../../module/stepper.h"
|
|
||||||
#include "../../../module/planner.h"
|
#include "../../../module/planner.h"
|
||||||
#include "../../../module/motion.h"
|
#include "../../../module/motion.h"
|
||||||
#include "../../../module/probe.h"
|
#include "../../../module/probe.h"
|
||||||
|
@@ -26,7 +26,6 @@
|
|||||||
|
|
||||||
#include "../bedlevel.h"
|
#include "../bedlevel.h"
|
||||||
#include "../../../module/planner.h"
|
#include "../../../module/planner.h"
|
||||||
#include "../../../module/stepper.h"
|
|
||||||
#include "../../../module/motion.h"
|
#include "../../../module/motion.h"
|
||||||
|
|
||||||
#if ENABLED(DELTA)
|
#if ENABLED(DELTA)
|
||||||
@@ -36,8 +35,18 @@
|
|||||||
#include "../../../MarlinCore.h"
|
#include "../../../MarlinCore.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
//#define DEBUG_UBL_MOTION
|
||||||
|
#define DEBUG_OUT ENABLED(DEBUG_UBL_MOTION)
|
||||||
|
#include "../../../core/debug_out.h"
|
||||||
|
|
||||||
#if !UBL_SEGMENTED
|
#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) {
|
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
|
* Much of the nozzle movement will be within the same cell. So we will do as little computation
|
||||||
@@ -176,7 +185,9 @@
|
|||||||
dest.z += z0;
|
dest.z += z0;
|
||||||
planner.buffer_segment(dest, scaled_fr_mm_s, extruder);
|
planner.buffer_segment(dest, scaled_fr_mm_s, extruder);
|
||||||
|
|
||||||
} //else printf("FIRST MOVE PRUNED ");
|
}
|
||||||
|
else
|
||||||
|
DEBUG_ECHOLNPGM("[ubl] skip Y segment");
|
||||||
}
|
}
|
||||||
|
|
||||||
// At the final destination? Usually not, but when on a Y Mesh Line it's completed.
|
// At the final destination? Usually not, but when on a Y Mesh Line it's completed.
|
||||||
@@ -225,7 +236,9 @@
|
|||||||
dest.z += z0;
|
dest.z += z0;
|
||||||
if (!planner.buffer_segment(dest, scaled_fr_mm_s, extruder)) break;
|
if (!planner.buffer_segment(dest, scaled_fr_mm_s, extruder)) break;
|
||||||
|
|
||||||
} //else printf("FIRST MOVE PRUNED ");
|
}
|
||||||
|
else
|
||||||
|
DEBUG_ECHOLNPGM("[ubl] skip Y segment");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xy_pos_t(current_position) != xy_pos_t(end))
|
if (xy_pos_t(current_position) != xy_pos_t(end))
|
||||||
@@ -360,11 +373,12 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
NOLESS(segments, 1U); // Must have at least one segment
|
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)
|
#if ENABLED(SCARA_FEEDRATE_SCALING)
|
||||||
const float inv_duration = scaled_fr_mm_s / segment_xyz_mm;
|
hints.inv_duration = scaled_fr_mm_s / hints.millimeters;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
xyze_float_t diff = total * inv_segments;
|
xyze_float_t diff = total * inv_segments;
|
||||||
@@ -378,13 +392,9 @@
|
|||||||
if (!planner.leveling_active || !planner.leveling_active_at_z(destination.z)) {
|
if (!planner.leveling_active || !planner.leveling_active_at_z(destination.z)) {
|
||||||
while (--segments) {
|
while (--segments) {
|
||||||
raw += diff;
|
raw += diff;
|
||||||
planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, segment_xyz_mm
|
planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, hints);
|
||||||
OPTARG(SCARA_FEEDRATE_SCALING, inv_duration)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
planner.buffer_line(destination, scaled_fr_mm_s, active_extruder, segment_xyz_mm
|
planner.buffer_line(destination, scaled_fr_mm_s, active_extruder, hints);
|
||||||
OPTARG(SCARA_FEEDRATE_SCALING, inv_duration)
|
|
||||||
);
|
|
||||||
return false; // Did not set current from destination
|
return false; // Did not set current from destination
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -453,7 +463,7 @@
|
|||||||
TERN_(ENABLE_LEVELING_FADE_HEIGHT, * fade_scaling_factor); // apply fade factor to interpolated height
|
TERN_(ENABLE_LEVELING_FADE_HEIGHT, * fade_scaling_factor); // apply fade factor to interpolated height
|
||||||
|
|
||||||
const float oldz = raw.z; raw.z += z_cxcy;
|
const float oldz = raw.z; raw.z += z_cxcy;
|
||||||
planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, segment_xyz_mm OPTARG(SCARA_FEEDRATE_SCALING, inv_duration) );
|
planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, hints);
|
||||||
raw.z = oldz;
|
raw.z = oldz;
|
||||||
|
|
||||||
if (segments == 0) // done with last segment
|
if (segments == 0) // done with last segment
|
||||||
|
@@ -45,7 +45,7 @@ void stop();
|
|||||||
|
|
||||||
bool BLTouch::command(const BLTCommand cmd, const millis_t &ms) {
|
bool BLTouch::command(const BLTCommand cmd, const millis_t &ms) {
|
||||||
if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("BLTouch Command :", cmd);
|
if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("BLTouch Command :", cmd);
|
||||||
MOVE_SERVO(Z_PROBE_SERVO_NR, cmd);
|
servo[Z_PROBE_SERVO_NR].move(cmd);
|
||||||
safe_delay(_MAX(ms, (uint32_t)BLTOUCH_DELAY)); // BLTOUCH_DELAY is also the *minimum* delay
|
safe_delay(_MAX(ms, (uint32_t)BLTOUCH_DELAY)); // BLTOUCH_DELAY is also the *minimum* delay
|
||||||
return triggered();
|
return triggered();
|
||||||
}
|
}
|
||||||
|
@@ -11,7 +11,6 @@
|
|||||||
#include "dac_dac084s085.h"
|
#include "dac_dac084s085.h"
|
||||||
|
|
||||||
#include "../../MarlinCore.h"
|
#include "../../MarlinCore.h"
|
||||||
#include "../../module/stepper.h"
|
|
||||||
#include "../../HAL/shared/Delay.h"
|
#include "../../HAL/shared/Delay.h"
|
||||||
|
|
||||||
dac084s085::dac084s085() { }
|
dac084s085::dac084s085() { }
|
||||||
|
@@ -59,7 +59,7 @@ int StepperDAC::init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void StepperDAC::set_current_value(const uint8_t channel, uint16_t val) {
|
void StepperDAC::set_current_value(const uint8_t channel, uint16_t val) {
|
||||||
if (!dac_present) return;
|
if (!(dac_present && channel < LOGICAL_AXES)) return;
|
||||||
|
|
||||||
NOMORE(val, uint16_t(DAC_STEPPER_MAX));
|
NOMORE(val, uint16_t(DAC_STEPPER_MAX));
|
||||||
|
|
||||||
@@ -84,13 +84,11 @@ void StepperDAC::print_values() {
|
|||||||
if (!dac_present) return;
|
if (!dac_present) return;
|
||||||
SERIAL_ECHO_MSG("Stepper current values in % (Amps):");
|
SERIAL_ECHO_MSG("Stepper current values in % (Amps):");
|
||||||
SERIAL_ECHO_START();
|
SERIAL_ECHO_START();
|
||||||
SERIAL_ECHOPGM_P(SP_X_LBL, dac_perc(X_AXIS), PSTR(" ("), dac_amps(X_AXIS), PSTR(")"));
|
LOOP_LOGICAL_AXES(a) {
|
||||||
#if HAS_Y_AXIS
|
SERIAL_CHAR(' ', IAXIS_CHAR(a), ':');
|
||||||
SERIAL_ECHOPGM_P(SP_Y_LBL, dac_perc(Y_AXIS), PSTR(" ("), dac_amps(Y_AXIS), PSTR(")"));
|
SERIAL_ECHO(dac_perc(a));
|
||||||
#endif
|
SERIAL_ECHOPGM_P(PSTR(" ("), dac_amps(AxisEnum(a)), PSTR(")"));
|
||||||
#if HAS_Z_AXIS
|
}
|
||||||
SERIAL_ECHOPGM_P(SP_Z_LBL, dac_perc(Z_AXIS), PSTR(" ("), dac_amps(Z_AXIS), PSTR(")"));
|
|
||||||
#endif
|
|
||||||
#if HAS_EXTRUDERS
|
#if HAS_EXTRUDERS
|
||||||
SERIAL_ECHOLNPGM_P(SP_E_LBL, dac_perc(E_AXIS), PSTR(" ("), dac_amps(E_AXIS), PSTR(")"));
|
SERIAL_ECHOLNPGM_P(SP_E_LBL, dac_perc(E_AXIS), PSTR(" ("), dac_amps(E_AXIS), PSTR(")"));
|
||||||
#endif
|
#endif
|
||||||
|
@@ -143,14 +143,16 @@ namespace DirectStepping {
|
|||||||
// special case for 8-bit, check if rolled back to 0
|
// special case for 8-bit, check if rolled back to 0
|
||||||
if (Cfg::DIRECTIONAL || !write_page_size) { // full 256 bytes
|
if (Cfg::DIRECTIONAL || !write_page_size) { // full 256 bytes
|
||||||
if (write_byte_idx) return true;
|
if (write_byte_idx) return true;
|
||||||
} else {
|
|
||||||
if (write_byte_idx < write_page_size) return true;
|
|
||||||
}
|
}
|
||||||
} else if (Cfg::DIRECTIONAL) {
|
else if (write_byte_idx < write_page_size)
|
||||||
if (write_byte_idx != Cfg::PAGE_SIZE) return true;
|
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;
|
state = State::CHECKSUM;
|
||||||
return true;
|
return true;
|
||||||
@@ -161,11 +163,10 @@ namespace DirectStepping {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case State::UNFAIL:
|
case State::UNFAIL:
|
||||||
if (c == 0) {
|
if (c == 0)
|
||||||
set_page_state(write_page_idx, PageState::FREE);
|
set_page_state(write_page_idx, PageState::FREE);
|
||||||
} else {
|
else
|
||||||
fatal_error = true;
|
fatal_error = true;
|
||||||
}
|
|
||||||
state = State::MONITOR;
|
state = State::MONITOR;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -49,7 +49,7 @@ void I2CPositionEncoder::init(const uint8_t address, const AxisEnum axis) {
|
|||||||
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
|
|
||||||
SERIAL_ECHOLNPGM("Setting up encoder on ", AS_CHAR(axis_codes[encoderAxis]), " axis, addr = ", address);
|
SERIAL_ECHOLNPGM("Setting up encoder on ", AS_CHAR(AXIS_CHAR(encoderAxis)), " axis, addr = ", address);
|
||||||
|
|
||||||
position = get_position();
|
position = get_position();
|
||||||
}
|
}
|
||||||
@@ -67,7 +67,7 @@ void I2CPositionEncoder::update() {
|
|||||||
/*
|
/*
|
||||||
if (trusted) { //commented out as part of the note below
|
if (trusted) { //commented out as part of the note below
|
||||||
trusted = false;
|
trusted = false;
|
||||||
SERIAL_ECHOLNPGM("Fault detected on ", AS_CHAR(axis_codes[encoderAxis]), " axis encoder. Disengaging error correction until module is trusted again.");
|
SERIAL_ECHOLNPGM("Fault detected on ", AS_CHAR(AXIS_CHAR(encoderAxis)), " axis encoder. Disengaging error correction until module is trusted again.");
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
return;
|
return;
|
||||||
@@ -92,7 +92,7 @@ void I2CPositionEncoder::update() {
|
|||||||
if (millis() - lastErrorTime > I2CPE_TIME_TRUSTED) {
|
if (millis() - lastErrorTime > I2CPE_TIME_TRUSTED) {
|
||||||
trusted = true;
|
trusted = true;
|
||||||
|
|
||||||
SERIAL_ECHOLNPGM("Untrusted encoder module on ", AS_CHAR(axis_codes[encoderAxis]), " axis has been fault-free for set duration, reinstating error correction.");
|
SERIAL_ECHOLNPGM("Untrusted encoder module on ", AS_CHAR(AXIS_CHAR(encoderAxis)), " axis has been fault-free for set duration, reinstating error correction.");
|
||||||
|
|
||||||
//the encoder likely lost its place when the error occurred, so we'll reset and use the printer's
|
//the encoder likely lost its place when the error occurred, so we'll reset and use the printer's
|
||||||
//idea of where it the axis is to re-initialize
|
//idea of where it the axis is to re-initialize
|
||||||
@@ -172,7 +172,7 @@ void I2CPositionEncoder::update() {
|
|||||||
float sumP = 0;
|
float sumP = 0;
|
||||||
LOOP_L_N(i, I2CPE_ERR_PRST_ARRAY_SIZE) sumP += errPrst[i];
|
LOOP_L_N(i, I2CPE_ERR_PRST_ARRAY_SIZE) sumP += errPrst[i];
|
||||||
const int32_t errorP = int32_t(sumP * RECIPROCAL(I2CPE_ERR_PRST_ARRAY_SIZE));
|
const int32_t errorP = int32_t(sumP * RECIPROCAL(I2CPE_ERR_PRST_ARRAY_SIZE));
|
||||||
SERIAL_CHAR(axis_codes[encoderAxis]);
|
SERIAL_CHAR(AXIS_CHAR(encoderAxis));
|
||||||
SERIAL_ECHOLNPGM(" : CORRECT ERR ", errorP * planner.mm_per_step[encoderAxis], "mm");
|
SERIAL_ECHOLNPGM(" : CORRECT ERR ", errorP * planner.mm_per_step[encoderAxis], "mm");
|
||||||
babystep.add_steps(encoderAxis, -LROUND(errorP));
|
babystep.add_steps(encoderAxis, -LROUND(errorP));
|
||||||
errPrstIdx = 0;
|
errPrstIdx = 0;
|
||||||
@@ -192,7 +192,7 @@ void I2CPositionEncoder::update() {
|
|||||||
if (ABS(error) > I2CPE_ERR_CNT_THRESH * planner.settings.axis_steps_per_mm[encoderAxis]) {
|
if (ABS(error) > I2CPE_ERR_CNT_THRESH * planner.settings.axis_steps_per_mm[encoderAxis]) {
|
||||||
const millis_t ms = millis();
|
const millis_t ms = millis();
|
||||||
if (ELAPSED(ms, nextErrorCountTime)) {
|
if (ELAPSED(ms, nextErrorCountTime)) {
|
||||||
SERIAL_CHAR(axis_codes[encoderAxis]);
|
SERIAL_CHAR(AXIS_CHAR(encoderAxis));
|
||||||
SERIAL_ECHOLNPGM(" : LARGE ERR ", error, "; diffSum=", diffSum);
|
SERIAL_ECHOLNPGM(" : LARGE ERR ", error, "; diffSum=", diffSum);
|
||||||
errorCount++;
|
errorCount++;
|
||||||
nextErrorCountTime = ms + I2CPE_ERR_CNT_DEBOUNCE_MS;
|
nextErrorCountTime = ms + I2CPE_ERR_CNT_DEBOUNCE_MS;
|
||||||
@@ -212,7 +212,7 @@ void I2CPositionEncoder::set_homed() {
|
|||||||
homed = trusted = true;
|
homed = trusted = true;
|
||||||
|
|
||||||
#ifdef I2CPE_DEBUG
|
#ifdef I2CPE_DEBUG
|
||||||
SERIAL_CHAR(axis_codes[encoderAxis]);
|
SERIAL_CHAR(AXIS_CHAR(encoderAxis));
|
||||||
SERIAL_ECHOLNPGM(" axis encoder homed, offset of ", zeroOffset, " ticks.");
|
SERIAL_ECHOLNPGM(" axis encoder homed, offset of ", zeroOffset, " ticks.");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -223,7 +223,7 @@ void I2CPositionEncoder::set_unhomed() {
|
|||||||
homed = trusted = false;
|
homed = trusted = false;
|
||||||
|
|
||||||
#ifdef I2CPE_DEBUG
|
#ifdef I2CPE_DEBUG
|
||||||
SERIAL_CHAR(axis_codes[encoderAxis]);
|
SERIAL_CHAR(AXIS_CHAR(encoderAxis));
|
||||||
SERIAL_ECHOLNPGM(" axis encoder unhomed.");
|
SERIAL_ECHOLNPGM(" axis encoder unhomed.");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -231,7 +231,7 @@ void I2CPositionEncoder::set_unhomed() {
|
|||||||
bool I2CPositionEncoder::passes_test(const bool report) {
|
bool I2CPositionEncoder::passes_test(const bool report) {
|
||||||
if (report) {
|
if (report) {
|
||||||
if (H != I2CPE_MAG_SIG_GOOD) SERIAL_ECHOPGM("Warning. ");
|
if (H != I2CPE_MAG_SIG_GOOD) SERIAL_ECHOPGM("Warning. ");
|
||||||
SERIAL_CHAR(axis_codes[encoderAxis]);
|
SERIAL_CHAR(AXIS_CHAR(encoderAxis));
|
||||||
serial_ternary(H == I2CPE_MAG_SIG_BAD, F(" axis "), F("magnetic strip "), F("encoder "));
|
serial_ternary(H == I2CPE_MAG_SIG_BAD, F(" axis "), F("magnetic strip "), F("encoder "));
|
||||||
switch (H) {
|
switch (H) {
|
||||||
case I2CPE_MAG_SIG_GOOD:
|
case I2CPE_MAG_SIG_GOOD:
|
||||||
@@ -252,7 +252,7 @@ float I2CPositionEncoder::get_axis_error_mm(const bool report) {
|
|||||||
error = ABS(diff) > 10000 ? 0 : diff; // Huge error is a bad reading
|
error = ABS(diff) > 10000 ? 0 : diff; // Huge error is a bad reading
|
||||||
|
|
||||||
if (report) {
|
if (report) {
|
||||||
SERIAL_CHAR(axis_codes[encoderAxis]);
|
SERIAL_CHAR(AXIS_CHAR(encoderAxis));
|
||||||
SERIAL_ECHOLNPGM(" axis target=", target, "mm; actual=", actual, "mm; err=", error, "mm");
|
SERIAL_ECHOLNPGM(" axis target=", target, "mm; actual=", actual, "mm; err=", error, "mm");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,7 +262,7 @@ float I2CPositionEncoder::get_axis_error_mm(const bool report) {
|
|||||||
int32_t I2CPositionEncoder::get_axis_error_steps(const bool report) {
|
int32_t I2CPositionEncoder::get_axis_error_steps(const bool report) {
|
||||||
if (!active) {
|
if (!active) {
|
||||||
if (report) {
|
if (report) {
|
||||||
SERIAL_CHAR(axis_codes[encoderAxis]);
|
SERIAL_CHAR(AXIS_CHAR(encoderAxis));
|
||||||
SERIAL_ECHOLNPGM(" axis encoder not active!");
|
SERIAL_ECHOLNPGM(" axis encoder not active!");
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -287,7 +287,7 @@ int32_t I2CPositionEncoder::get_axis_error_steps(const bool report) {
|
|||||||
errorPrev = error;
|
errorPrev = error;
|
||||||
|
|
||||||
if (report) {
|
if (report) {
|
||||||
SERIAL_CHAR(axis_codes[encoderAxis]);
|
SERIAL_CHAR(AXIS_CHAR(encoderAxis));
|
||||||
SERIAL_ECHOLNPGM(" axis target=", target, "; actual=", encoderCountInStepperTicksScaled, "; err=", error);
|
SERIAL_ECHOLNPGM(" axis target=", target, "; actual=", encoderCountInStepperTicksScaled, "; err=", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,7 +337,7 @@ bool I2CPositionEncoder::test_axis() {
|
|||||||
ec = false;
|
ec = false;
|
||||||
|
|
||||||
xyze_pos_t startCoord, endCoord;
|
xyze_pos_t startCoord, endCoord;
|
||||||
LOOP_LINEAR_AXES(a) {
|
LOOP_NUM_AXES(a) {
|
||||||
startCoord[a] = planner.get_axis_position_mm((AxisEnum)a);
|
startCoord[a] = planner.get_axis_position_mm((AxisEnum)a);
|
||||||
endCoord[a] = planner.get_axis_position_mm((AxisEnum)a);
|
endCoord[a] = planner.get_axis_position_mm((AxisEnum)a);
|
||||||
}
|
}
|
||||||
@@ -395,7 +395,7 @@ void I2CPositionEncoder::calibrate_steps_mm(const uint8_t iter) {
|
|||||||
travelDistance = endDistance - startDistance;
|
travelDistance = endDistance - startDistance;
|
||||||
|
|
||||||
xyze_pos_t startCoord, endCoord;
|
xyze_pos_t startCoord, endCoord;
|
||||||
LOOP_LINEAR_AXES(a) {
|
LOOP_NUM_AXES(a) {
|
||||||
startCoord[a] = planner.get_axis_position_mm((AxisEnum)a);
|
startCoord[a] = planner.get_axis_position_mm((AxisEnum)a);
|
||||||
endCoord[a] = planner.get_axis_position_mm((AxisEnum)a);
|
endCoord[a] = planner.get_axis_position_mm((AxisEnum)a);
|
||||||
}
|
}
|
||||||
@@ -657,7 +657,7 @@ void I2CPositionEncodersMgr::report_position(const int8_t idx, const bool units,
|
|||||||
else {
|
else {
|
||||||
if (noOffset) {
|
if (noOffset) {
|
||||||
const int32_t raw_count = encoders[idx].get_raw_count();
|
const int32_t raw_count = encoders[idx].get_raw_count();
|
||||||
SERIAL_CHAR(axis_codes[encoders[idx].get_axis()], ' ');
|
SERIAL_CHAR(AXIS_CHAR(encoders[idx).get_axis()], ' ');
|
||||||
|
|
||||||
for (uint8_t j = 31; j > 0; j--)
|
for (uint8_t j = 31; j > 0; j--)
|
||||||
SERIAL_ECHO((bool)(0x00000001 & (raw_count >> j)));
|
SERIAL_ECHO((bool)(0x00000001 & (raw_count >> j)));
|
||||||
@@ -712,7 +712,7 @@ void I2CPositionEncodersMgr::change_module_address(const uint8_t oldaddr, const
|
|||||||
// and enable it (it will likely have failed initialization on power-up, before the address change).
|
// and enable it (it will likely have failed initialization on power-up, before the address change).
|
||||||
const int8_t idx = idx_from_addr(newaddr);
|
const int8_t idx = idx_from_addr(newaddr);
|
||||||
if (idx >= 0 && !encoders[idx].get_active()) {
|
if (idx >= 0 && !encoders[idx].get_active()) {
|
||||||
SERIAL_CHAR(axis_codes[encoders[idx].get_axis()]);
|
SERIAL_CHAR(AXIS_CHAR(encoders[idx).get_axis()]);
|
||||||
SERIAL_ECHOLNPGM(" axis encoder was not detected on printer startup. Trying again.");
|
SERIAL_ECHOLNPGM(" axis encoder was not detected on printer startup. Trying again.");
|
||||||
encoders[idx].set_active(encoders[idx].passes_test(true));
|
encoders[idx].set_active(encoders[idx].passes_test(true));
|
||||||
}
|
}
|
||||||
@@ -814,7 +814,7 @@ void I2CPositionEncodersMgr::M860() {
|
|||||||
|
|
||||||
if (I2CPE_idx == 0xFF) {
|
if (I2CPE_idx == 0xFF) {
|
||||||
LOOP_LOGICAL_AXES(i) {
|
LOOP_LOGICAL_AXES(i) {
|
||||||
if (!I2CPE_anyaxis || parser.seen_test(axis_codes[i])) {
|
if (!I2CPE_anyaxis || parser.seen_test(AXIS_CHAR(i))) {
|
||||||
const uint8_t idx = idx_from_axis(AxisEnum(i));
|
const uint8_t idx = idx_from_axis(AxisEnum(i));
|
||||||
if ((int8_t)idx >= 0) report_position(idx, hasU, hasO);
|
if ((int8_t)idx >= 0) report_position(idx, hasU, hasO);
|
||||||
}
|
}
|
||||||
@@ -841,7 +841,7 @@ void I2CPositionEncodersMgr::M861() {
|
|||||||
|
|
||||||
if (I2CPE_idx == 0xFF) {
|
if (I2CPE_idx == 0xFF) {
|
||||||
LOOP_LOGICAL_AXES(i) {
|
LOOP_LOGICAL_AXES(i) {
|
||||||
if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) {
|
if (!I2CPE_anyaxis || parser.seen(AXIS_CHAR(i))) {
|
||||||
const uint8_t idx = idx_from_axis(AxisEnum(i));
|
const uint8_t idx = idx_from_axis(AxisEnum(i));
|
||||||
if ((int8_t)idx >= 0) report_status(idx);
|
if ((int8_t)idx >= 0) report_status(idx);
|
||||||
}
|
}
|
||||||
@@ -869,7 +869,7 @@ void I2CPositionEncodersMgr::M862() {
|
|||||||
|
|
||||||
if (I2CPE_idx == 0xFF) {
|
if (I2CPE_idx == 0xFF) {
|
||||||
LOOP_LOGICAL_AXES(i) {
|
LOOP_LOGICAL_AXES(i) {
|
||||||
if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) {
|
if (!I2CPE_anyaxis || parser.seen(AXIS_CHAR(i))) {
|
||||||
const uint8_t idx = idx_from_axis(AxisEnum(i));
|
const uint8_t idx = idx_from_axis(AxisEnum(i));
|
||||||
if ((int8_t)idx >= 0) test_axis(idx);
|
if ((int8_t)idx >= 0) test_axis(idx);
|
||||||
}
|
}
|
||||||
@@ -900,7 +900,7 @@ void I2CPositionEncodersMgr::M863() {
|
|||||||
|
|
||||||
if (I2CPE_idx == 0xFF) {
|
if (I2CPE_idx == 0xFF) {
|
||||||
LOOP_LOGICAL_AXES(i) {
|
LOOP_LOGICAL_AXES(i) {
|
||||||
if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) {
|
if (!I2CPE_anyaxis || parser.seen(AXIS_CHAR(i))) {
|
||||||
const uint8_t idx = idx_from_axis(AxisEnum(i));
|
const uint8_t idx = idx_from_axis(AxisEnum(i));
|
||||||
if ((int8_t)idx >= 0) calibrate_steps_mm(idx, iterations);
|
if ((int8_t)idx >= 0) calibrate_steps_mm(idx, iterations);
|
||||||
}
|
}
|
||||||
@@ -976,7 +976,7 @@ void I2CPositionEncodersMgr::M865() {
|
|||||||
|
|
||||||
if (!I2CPE_addr) {
|
if (!I2CPE_addr) {
|
||||||
LOOP_LOGICAL_AXES(i) {
|
LOOP_LOGICAL_AXES(i) {
|
||||||
if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) {
|
if (!I2CPE_anyaxis || parser.seen(AXIS_CHAR(i))) {
|
||||||
const uint8_t idx = idx_from_axis(AxisEnum(i));
|
const uint8_t idx = idx_from_axis(AxisEnum(i));
|
||||||
if ((int8_t)idx >= 0) report_module_firmware(encoders[idx].get_address());
|
if ((int8_t)idx >= 0) report_module_firmware(encoders[idx].get_address());
|
||||||
}
|
}
|
||||||
@@ -1007,7 +1007,7 @@ void I2CPositionEncodersMgr::M866() {
|
|||||||
|
|
||||||
if (I2CPE_idx == 0xFF) {
|
if (I2CPE_idx == 0xFF) {
|
||||||
LOOP_LOGICAL_AXES(i) {
|
LOOP_LOGICAL_AXES(i) {
|
||||||
if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) {
|
if (!I2CPE_anyaxis || parser.seen(AXIS_CHAR(i))) {
|
||||||
const uint8_t idx = idx_from_axis(AxisEnum(i));
|
const uint8_t idx = idx_from_axis(AxisEnum(i));
|
||||||
if ((int8_t)idx >= 0) {
|
if ((int8_t)idx >= 0) {
|
||||||
if (hasR)
|
if (hasR)
|
||||||
@@ -1045,7 +1045,7 @@ void I2CPositionEncodersMgr::M867() {
|
|||||||
|
|
||||||
if (I2CPE_idx == 0xFF) {
|
if (I2CPE_idx == 0xFF) {
|
||||||
LOOP_LOGICAL_AXES(i) {
|
LOOP_LOGICAL_AXES(i) {
|
||||||
if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) {
|
if (!I2CPE_anyaxis || parser.seen(AXIS_CHAR(i))) {
|
||||||
const uint8_t idx = idx_from_axis(AxisEnum(i));
|
const uint8_t idx = idx_from_axis(AxisEnum(i));
|
||||||
if ((int8_t)idx >= 0) {
|
if ((int8_t)idx >= 0) {
|
||||||
const bool ena = onoff == -1 ? !encoders[I2CPE_idx].get_ec_enabled() : !!onoff;
|
const bool ena = onoff == -1 ? !encoders[I2CPE_idx].get_ec_enabled() : !!onoff;
|
||||||
@@ -1081,7 +1081,7 @@ void I2CPositionEncodersMgr::M868() {
|
|||||||
|
|
||||||
if (I2CPE_idx == 0xFF) {
|
if (I2CPE_idx == 0xFF) {
|
||||||
LOOP_LOGICAL_AXES(i) {
|
LOOP_LOGICAL_AXES(i) {
|
||||||
if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) {
|
if (!I2CPE_anyaxis || parser.seen(AXIS_CHAR(i))) {
|
||||||
const uint8_t idx = idx_from_axis(AxisEnum(i));
|
const uint8_t idx = idx_from_axis(AxisEnum(i));
|
||||||
if ((int8_t)idx >= 0) {
|
if ((int8_t)idx >= 0) {
|
||||||
if (newThreshold != -9999)
|
if (newThreshold != -9999)
|
||||||
@@ -1115,7 +1115,7 @@ void I2CPositionEncodersMgr::M869() {
|
|||||||
|
|
||||||
if (I2CPE_idx == 0xFF) {
|
if (I2CPE_idx == 0xFF) {
|
||||||
LOOP_LOGICAL_AXES(i) {
|
LOOP_LOGICAL_AXES(i) {
|
||||||
if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) {
|
if (!I2CPE_anyaxis || parser.seen(AXIS_CHAR(i))) {
|
||||||
const uint8_t idx = idx_from_axis(AxisEnum(i));
|
const uint8_t idx = idx_from_axis(AxisEnum(i));
|
||||||
if ((int8_t)idx >= 0) report_error(idx);
|
if ((int8_t)idx >= 0) report_error(idx);
|
||||||
}
|
}
|
||||||
|
@@ -261,32 +261,32 @@ class I2CPositionEncodersMgr {
|
|||||||
|
|
||||||
static void report_error_count(const int8_t idx, const AxisEnum axis) {
|
static void report_error_count(const int8_t idx, const AxisEnum axis) {
|
||||||
CHECK_IDX();
|
CHECK_IDX();
|
||||||
SERIAL_ECHOLNPGM("Error count on ", AS_CHAR(axis_codes[axis]), " axis is ", encoders[idx].get_error_count());
|
SERIAL_ECHOLNPGM("Error count on ", AS_CHAR(AXIS_CHAR(axis)), " axis is ", encoders[idx].get_error_count());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void reset_error_count(const int8_t idx, const AxisEnum axis) {
|
static void reset_error_count(const int8_t idx, const AxisEnum axis) {
|
||||||
CHECK_IDX();
|
CHECK_IDX();
|
||||||
encoders[idx].set_error_count(0);
|
encoders[idx].set_error_count(0);
|
||||||
SERIAL_ECHOLNPGM("Error count on ", AS_CHAR(axis_codes[axis]), " axis has been reset.");
|
SERIAL_ECHOLNPGM("Error count on ", AS_CHAR(AXIS_CHAR(axis)), " axis has been reset.");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void enable_ec(const int8_t idx, const bool enabled, const AxisEnum axis) {
|
static void enable_ec(const int8_t idx, const bool enabled, const AxisEnum axis) {
|
||||||
CHECK_IDX();
|
CHECK_IDX();
|
||||||
encoders[idx].set_ec_enabled(enabled);
|
encoders[idx].set_ec_enabled(enabled);
|
||||||
SERIAL_ECHOPGM("Error correction on ", AS_CHAR(axis_codes[axis]));
|
SERIAL_ECHOPGM("Error correction on ", AS_CHAR(AXIS_CHAR(axis)));
|
||||||
SERIAL_ECHO_TERNARY(encoders[idx].get_ec_enabled(), " axis is ", "en", "dis", "abled.\n");
|
SERIAL_ECHO_TERNARY(encoders[idx].get_ec_enabled(), " axis is ", "en", "dis", "abled.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_ec_threshold(const int8_t idx, const float newThreshold, const AxisEnum axis) {
|
static void set_ec_threshold(const int8_t idx, const float newThreshold, const AxisEnum axis) {
|
||||||
CHECK_IDX();
|
CHECK_IDX();
|
||||||
encoders[idx].set_ec_threshold(newThreshold);
|
encoders[idx].set_ec_threshold(newThreshold);
|
||||||
SERIAL_ECHOLNPGM("Error correct threshold for ", AS_CHAR(axis_codes[axis]), " axis set to ", newThreshold, "mm.");
|
SERIAL_ECHOLNPGM("Error correct threshold for ", AS_CHAR(AXIS_CHAR(axis)), " axis set to ", newThreshold, "mm.");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void get_ec_threshold(const int8_t idx, const AxisEnum axis) {
|
static void get_ec_threshold(const int8_t idx, const AxisEnum axis) {
|
||||||
CHECK_IDX();
|
CHECK_IDX();
|
||||||
const float threshold = encoders[idx].get_ec_threshold();
|
const float threshold = encoders[idx].get_ec_threshold();
|
||||||
SERIAL_ECHOLNPGM("Error correct threshold for ", AS_CHAR(axis_codes[axis]), " axis is ", threshold, "mm.");
|
SERIAL_ECHOLNPGM("Error correct threshold for ", AS_CHAR(AXIS_CHAR(axis)), " axis is ", threshold, "mm.");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int8_t idx_from_axis(const AxisEnum axis) {
|
static int8_t idx_from_axis(const AxisEnum axis) {
|
||||||
|
@@ -34,7 +34,6 @@ FWRetract fwretract; // Single instance - this calls the constructor
|
|||||||
|
|
||||||
#include "../module/motion.h"
|
#include "../module/motion.h"
|
||||||
#include "../module/planner.h"
|
#include "../module/planner.h"
|
||||||
#include "../module/stepper.h"
|
|
||||||
|
|
||||||
#include "../gcode/gcode.h"
|
#include "../gcode/gcode.h"
|
||||||
|
|
||||||
|
@@ -163,7 +163,7 @@ Joystick joystick;
|
|||||||
// norm_jog values of [-1 .. 1] maps linearly to [-feedrate .. feedrate]
|
// norm_jog values of [-1 .. 1] maps linearly to [-feedrate .. feedrate]
|
||||||
xyz_float_t move_dist{0};
|
xyz_float_t move_dist{0};
|
||||||
float hypot2 = 0;
|
float hypot2 = 0;
|
||||||
LOOP_LINEAR_AXES(i) if (norm_jog[i]) {
|
LOOP_NUM_AXES(i) if (norm_jog[i]) {
|
||||||
move_dist[i] = seg_time * norm_jog[i] * TERN(EXTENSIBLE_UI, manual_feedrate_mm_s, planner.settings.max_feedrate_mm_s)[i];
|
move_dist[i] = seg_time * norm_jog[i] * TERN(EXTENSIBLE_UI, manual_feedrate_mm_s, planner.settings.max_feedrate_mm_s)[i];
|
||||||
hypot2 += sq(move_dist[i]);
|
hypot2 += sq(move_dist[i]);
|
||||||
}
|
}
|
||||||
@@ -172,8 +172,9 @@ Joystick joystick;
|
|||||||
current_position += move_dist;
|
current_position += move_dist;
|
||||||
apply_motion_limits(current_position);
|
apply_motion_limits(current_position);
|
||||||
const float length = sqrt(hypot2);
|
const float length = sqrt(hypot2);
|
||||||
|
PlannerHints hints(length);
|
||||||
injecting_now = true;
|
injecting_now = true;
|
||||||
planner.buffer_line(current_position, length / seg_time, active_extruder, length);
|
planner.buffer_line(current_position, length / seg_time, active_extruder, hints);
|
||||||
injecting_now = false;
|
injecting_now = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -44,7 +44,6 @@
|
|||||||
#include "max7219.h"
|
#include "max7219.h"
|
||||||
|
|
||||||
#include "../module/planner.h"
|
#include "../module/planner.h"
|
||||||
#include "../module/stepper.h"
|
|
||||||
#include "../MarlinCore.h"
|
#include "../MarlinCore.h"
|
||||||
#include "../HAL/shared/Delay.h"
|
#include "../HAL/shared/Delay.h"
|
||||||
|
|
||||||
|
@@ -35,10 +35,13 @@
|
|||||||
#include "../gcode/gcode.h"
|
#include "../gcode/gcode.h"
|
||||||
#include "../module/motion.h"
|
#include "../module/motion.h"
|
||||||
#include "../module/planner.h"
|
#include "../module/planner.h"
|
||||||
#include "../module/stepper.h"
|
|
||||||
#include "../module/printcounter.h"
|
#include "../module/printcounter.h"
|
||||||
#include "../module/temperature.h"
|
#include "../module/temperature.h"
|
||||||
|
|
||||||
|
#if HAS_EXTRUDERS
|
||||||
|
#include "../module/stepper.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if ENABLED(AUTO_BED_LEVELING_UBL)
|
#if ENABLED(AUTO_BED_LEVELING_UBL)
|
||||||
#include "bedlevel/bedlevel.h"
|
#include "bedlevel/bedlevel.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -63,7 +66,7 @@
|
|||||||
|
|
||||||
#include "../lcd/marlinui.h"
|
#include "../lcd/marlinui.h"
|
||||||
|
|
||||||
#if HAS_BUZZER
|
#if HAS_SOUND
|
||||||
#include "../libs/buzzer.h"
|
#include "../libs/buzzer.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -98,7 +101,7 @@ fil_change_settings_t fc_settings[EXTRUDERS];
|
|||||||
#define _PMSG(L) L##_LCD
|
#define _PMSG(L) L##_LCD
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if HAS_BUZZER
|
#if HAS_SOUND
|
||||||
static void impatient_beep(const int8_t max_beep_count, const bool restart=false) {
|
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;
|
if (TERN0(HAS_MARLINUI_MENU, pause_mode == PAUSE_MODE_PAUSE_PRINT)) return;
|
||||||
@@ -711,9 +714,13 @@ void resume_print(const_float_t slow_load_length/*=0*/, const_float_t fast_load_
|
|||||||
|
|
||||||
TERN_(HAS_FILAMENT_SENSOR, runout.reset());
|
TERN_(HAS_FILAMENT_SENSOR, runout.reset());
|
||||||
|
|
||||||
TERN(DWIN_LCD_PROUI, DWIN_Print_Resume(), ui.reset_status());
|
#if ENABLED(DWIN_LCD_PROUI)
|
||||||
TERN_(HAS_MARLINUI_MENU, ui.return_to_status());
|
DWIN_Print_Resume();
|
||||||
TERN_(DWIN_LCD_PROUI, HMI_ReturnScreen());
|
HMI_ReturnScreen();
|
||||||
|
#else
|
||||||
|
ui.reset_status();
|
||||||
|
ui.return_to_status();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // ADVANCED_PAUSE_FEATURE
|
#endif // ADVANCED_PAUSE_FEATURE
|
||||||
|
@@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
#include "power.h"
|
#include "power.h"
|
||||||
#include "../module/planner.h"
|
#include "../module/planner.h"
|
||||||
#include "../module/stepper.h"
|
#include "../module/stepper/indirection.h" // for restore_stepper_drivers
|
||||||
#include "../module/temperature.h"
|
#include "../module/temperature.h"
|
||||||
#include "../MarlinCore.h"
|
#include "../MarlinCore.h"
|
||||||
|
|
||||||
@@ -46,6 +46,7 @@ Power powerManager;
|
|||||||
bool Power::psu_on;
|
bool Power::psu_on;
|
||||||
|
|
||||||
#if ENABLED(AUTO_POWER_CONTROL)
|
#if ENABLED(AUTO_POWER_CONTROL)
|
||||||
|
#include "../module/stepper.h"
|
||||||
#include "../module/temperature.h"
|
#include "../module/temperature.h"
|
||||||
|
|
||||||
#if BOTH(USE_CONTROLLER_FAN, AUTO_POWER_CONTROLLERFAN)
|
#if BOTH(USE_CONTROLLER_FAN, AUTO_POWER_CONTROLLERFAN)
|
||||||
|
@@ -53,7 +53,7 @@ PowerMonitor power_monitor; // Single instance - this calls the constructor
|
|||||||
void PowerMonitor::draw_current() {
|
void PowerMonitor::draw_current() {
|
||||||
const float amps = getAmps();
|
const float amps = getAmps();
|
||||||
lcd_put_u8str(amps < 100 ? ftostr31ns(amps) : ui16tostr4rj((uint16_t)amps));
|
lcd_put_u8str(amps < 100 ? ftostr31ns(amps) : ui16tostr4rj((uint16_t)amps));
|
||||||
lcd_put_wchar('A');
|
lcd_put_lchar('A');
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ PowerMonitor power_monitor; // Single instance - this calls the constructor
|
|||||||
void PowerMonitor::draw_voltage() {
|
void PowerMonitor::draw_voltage() {
|
||||||
const float volts = getVolts();
|
const float volts = getVolts();
|
||||||
lcd_put_u8str(volts < 100 ? ftostr31ns(volts) : ui16tostr4rj((uint16_t)volts));
|
lcd_put_u8str(volts < 100 ? ftostr31ns(volts) : ui16tostr4rj((uint16_t)volts));
|
||||||
lcd_put_wchar('V');
|
lcd_put_lchar('V');
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ PowerMonitor power_monitor; // Single instance - this calls the constructor
|
|||||||
void PowerMonitor::draw_power() {
|
void PowerMonitor::draw_power() {
|
||||||
const float power = getPower();
|
const float power = getPower();
|
||||||
lcd_put_u8str(power < 100 ? ftostr31ns(power) : ui16tostr4rj((uint16_t)power));
|
lcd_put_u8str(power < 100 ? ftostr31ns(power) : ui16tostr4rj((uint16_t)power));
|
||||||
lcd_put_wchar('W');
|
lcd_put_lchar('W');
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -32,7 +32,7 @@ struct pm_lpf_t {
|
|||||||
uint32_t filter_buf;
|
uint32_t filter_buf;
|
||||||
float value;
|
float value;
|
||||||
void add_sample(const uint16_t sample) {
|
void add_sample(const uint16_t sample) {
|
||||||
filter_buf = filter_buf - (filter_buf >> K_VALUE) + (uint32_t(sample) << K_SCALE);
|
filter_buf += (uint32_t(sample) << K_SCALE) - (filter_buf >> K_VALUE);
|
||||||
}
|
}
|
||||||
void capture() {
|
void capture() {
|
||||||
value = filter_buf * (SCALE * (1.0f / (1UL << (PM_K_VALUE + PM_K_SCALE))));
|
value = filter_buf * (SCALE * (1.0f / (1UL << (PM_K_VALUE + PM_K_SCALE))));
|
||||||
|
@@ -567,7 +567,7 @@ void PrintJobRecovery::resume() {
|
|||||||
TERN_(HAS_HOME_OFFSET, home_offset = info.home_offset);
|
TERN_(HAS_HOME_OFFSET, home_offset = info.home_offset);
|
||||||
TERN_(HAS_POSITION_SHIFT, position_shift = info.position_shift);
|
TERN_(HAS_POSITION_SHIFT, position_shift = info.position_shift);
|
||||||
#if HAS_HOME_OFFSET || HAS_POSITION_SHIFT
|
#if HAS_HOME_OFFSET || HAS_POSITION_SHIFT
|
||||||
LOOP_LINEAR_AXES(i) update_workspace_offset((AxisEnum)i);
|
LOOP_NUM_AXES(i) update_workspace_offset((AxisEnum)i);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Relative axis modes
|
// Relative axis modes
|
||||||
@@ -617,7 +617,7 @@ void PrintJobRecovery::resume() {
|
|||||||
|
|
||||||
#if HAS_HOME_OFFSET
|
#if HAS_HOME_OFFSET
|
||||||
DEBUG_ECHOPGM("home_offset: ");
|
DEBUG_ECHOPGM("home_offset: ");
|
||||||
LOOP_LINEAR_AXES(i) {
|
LOOP_NUM_AXES(i) {
|
||||||
if (i) DEBUG_CHAR(',');
|
if (i) DEBUG_CHAR(',');
|
||||||
DEBUG_DECIMAL(info.home_offset[i]);
|
DEBUG_DECIMAL(info.home_offset[i]);
|
||||||
}
|
}
|
||||||
@@ -626,7 +626,7 @@ void PrintJobRecovery::resume() {
|
|||||||
|
|
||||||
#if HAS_POSITION_SHIFT
|
#if HAS_POSITION_SHIFT
|
||||||
DEBUG_ECHOPGM("position_shift: ");
|
DEBUG_ECHOPGM("position_shift: ");
|
||||||
LOOP_LINEAR_AXES(i) {
|
LOOP_NUM_AXES(i) {
|
||||||
if (i) DEBUG_CHAR(',');
|
if (i) DEBUG_CHAR(',');
|
||||||
DEBUG_DECIMAL(info.position_shift[i]);
|
DEBUG_DECIMAL(info.position_shift[i]);
|
||||||
}
|
}
|
||||||
|
@@ -39,18 +39,26 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
SpindleLaser cutter;
|
SpindleLaser cutter;
|
||||||
uint8_t SpindleLaser::power,
|
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
|
SpindleLaser::last_power_applied; // = 0 // Basic power state tracking
|
||||||
#if ENABLED(LASER_FEATURE)
|
|
||||||
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
|
|
||||||
|
|
||||||
#if ENABLED(MARLIN_DEV_MODE)
|
#if ENABLED(LASER_FEATURE)
|
||||||
cutter_frequency_t SpindleLaser::frequency; // PWM frequency setting; range: 2K - 50K
|
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
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
#define SPINDLE_LASER_PWM_OFF TERN(SPINDLE_LASER_PWM_INVERT, 255, 0)
|
#define SPINDLE_LASER_PWM_OFF TERN(SPINDLE_LASER_PWM_INVERT, 255, 0)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -58,21 +66,21 @@ cutter_power_t SpindleLaser::menuPower, // Power s
|
|||||||
*/
|
*/
|
||||||
void SpindleLaser::init() {
|
void SpindleLaser::init() {
|
||||||
#if ENABLED(SPINDLE_SERVO)
|
#if ENABLED(SPINDLE_SERVO)
|
||||||
MOVE_SERVO(SPINDLE_SERVO_NR, SPINDLE_SERVO_MIN);
|
servo[SPINDLE_SERVO_NR].move(SPINDLE_SERVO_MIN);
|
||||||
#else
|
#else
|
||||||
OUT_WRITE(SPINDLE_LASER_ENA_PIN, !SPINDLE_LASER_ACTIVE_STATE); // Init spindle to off
|
OUT_WRITE(SPINDLE_LASER_ENA_PIN, !SPINDLE_LASER_ACTIVE_STATE); // Init spindle to off
|
||||||
#endif
|
#endif
|
||||||
#if ENABLED(SPINDLE_CHANGE_DIR)
|
#if ENABLED(SPINDLE_CHANGE_DIR)
|
||||||
OUT_WRITE(SPINDLE_DIR_PIN, SPINDLE_INVERT_DIR); // Init rotation to clockwise (M3)
|
OUT_WRITE(SPINDLE_DIR_PIN, SPINDLE_INVERT_DIR); // Init rotation to clockwise (M3)
|
||||||
#endif
|
#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)
|
#if ENABLED(SPINDLE_LASER_USE_PWM)
|
||||||
SET_PWM(SPINDLE_LASER_PWM_PIN);
|
SET_PWM(SPINDLE_LASER_PWM_PIN);
|
||||||
hal.set_pwm_duty(pin_t(SPINDLE_LASER_PWM_PIN), SPINDLE_LASER_PWM_OFF); // Set to lowest speed
|
hal.set_pwm_duty(pin_t(SPINDLE_LASER_PWM_PIN), SPINDLE_LASER_PWM_OFF); // Set to lowest speed
|
||||||
#endif
|
#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)
|
#if ENABLED(AIR_EVACUATION)
|
||||||
OUT_WRITE(AIR_EVACUATION_PIN, !AIR_EVACUATION_ACTIVE); // Init Vacuum/Blower OFF
|
OUT_WRITE(AIR_EVACUATION_PIN, !AIR_EVACUATION_ACTIVE); // Init Vacuum/Blower OFF
|
||||||
#endif
|
#endif
|
||||||
@@ -90,7 +98,7 @@ void SpindleLaser::init() {
|
|||||||
*/
|
*/
|
||||||
void SpindleLaser::_set_ocr(const uint8_t ocr) {
|
void SpindleLaser::_set_ocr(const uint8_t ocr) {
|
||||||
#if ENABLED(HAL_CAN_SET_PWM_FREQ) && SPINDLE_LASER_FREQUENCY
|
#if ENABLED(HAL_CAN_SET_PWM_FREQ) && SPINDLE_LASER_FREQUENCY
|
||||||
hal.set_pwm_frequency(pin_t(SPINDLE_LASER_PWM_PIN), TERN(MARLIN_DEV_MODE, frequency, SPINDLE_LASER_FREQUENCY));
|
hal.set_pwm_frequency(pin_t(SPINDLE_LASER_PWM_PIN), frequency);
|
||||||
#endif
|
#endif
|
||||||
hal.set_pwm_duty(pin_t(SPINDLE_LASER_PWM_PIN), ocr ^ SPINDLE_LASER_PWM_OFF);
|
hal.set_pwm_duty(pin_t(SPINDLE_LASER_PWM_PIN), ocr ^ SPINDLE_LASER_PWM_OFF);
|
||||||
}
|
}
|
||||||
@@ -107,36 +115,42 @@ void SpindleLaser::init() {
|
|||||||
#endif // SPINDLE_LASER_USE_PWM
|
#endif // SPINDLE_LASER_USE_PWM
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply power for laser/spindle
|
* Apply power for Laser or Spindle
|
||||||
*
|
*
|
||||||
* Apply cutter power value for PWM, Servo, and on/off pin.
|
* Apply cutter power value for PWM, Servo, and on/off pin.
|
||||||
*
|
*
|
||||||
* @param opwr Power value. Range 0 to MAX. When 0 disable spindle/laser.
|
* @param opwr Power value. Range 0 to MAX.
|
||||||
*/
|
*/
|
||||||
void SpindleLaser::apply_power(const uint8_t opwr) {
|
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;
|
if (opwr == last_power_applied) return;
|
||||||
last_power_applied = opwr;
|
last_power_applied = opwr;
|
||||||
power = opwr;
|
// Handle PWM driven or just simple on/off
|
||||||
#if ENABLED(SPINDLE_LASER_USE_PWM)
|
#if ENABLED(SPINDLE_LASER_USE_PWM)
|
||||||
if (cutter.unitPower == 0 && CUTTER_UNIT_IS(RPM)) {
|
if (CUTTER_UNIT_IS(RPM) && unitPower == 0)
|
||||||
ocr_off();
|
ocr_off();
|
||||||
isReady = false;
|
else if (ENABLED(CUTTER_POWER_RELATIVE) || enabled() || opwr == 0) {
|
||||||
|
set_ocr(opwr);
|
||||||
|
isReadyForUI = true;
|
||||||
}
|
}
|
||||||
else if (ENABLED(CUTTER_POWER_RELATIVE) || enabled()) {
|
else
|
||||||
set_ocr(power);
|
|
||||||
isReady = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ocr_off();
|
ocr_off();
|
||||||
isReady = false;
|
|
||||||
}
|
|
||||||
#elif ENABLED(SPINDLE_SERVO)
|
#elif ENABLED(SPINDLE_SERVO)
|
||||||
MOVE_SERVO(SPINDLE_SERVO_NR, power);
|
MOVE_SERVO(SPINDLE_SERVO_NR, power);
|
||||||
#else
|
#else
|
||||||
WRITE(SPINDLE_LASER_ENA_PIN, enabled() ? SPINDLE_LASER_ACTIVE_STATE : !SPINDLE_LASER_ACTIVE_STATE);
|
WRITE(SPINDLE_LASER_ENA_PIN, enabled() ? SPINDLE_LASER_ACTIVE_STATE : !SPINDLE_LASER_ACTIVE_STATE);
|
||||||
isReady = true;
|
isReadyForUI = true;
|
||||||
#endif
|
#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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if ENABLED(SPINDLE_CHANGE_DIR)
|
#if ENABLED(SPINDLE_CHANGE_DIR)
|
||||||
/**
|
/**
|
||||||
|
@@ -34,87 +34,97 @@
|
|||||||
#include "../libs/buzzer.h"
|
#include "../libs/buzzer.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ENABLED(LASER_POWER_INLINE)
|
// Inline laser power
|
||||||
#include "../module/planner.h"
|
#include "../module/planner.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#define PCT_TO_PWM(X) ((X) * 255 / 100)
|
#define PCT_TO_PWM(X) ((X) * 255 / 100)
|
||||||
#define PCT_TO_SERVO(X) ((X) * 180 / 100)
|
#define PCT_TO_SERVO(X) ((X) * 180 / 100)
|
||||||
|
|
||||||
// #define _MAP(N,S1,S2,D1,D2) ((N)*_MAX((D2)-(D1),0)/_MAX((S2)-(S1),1)+(D1))
|
// 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 {
|
class SpindleLaser {
|
||||||
public:
|
public:
|
||||||
static const inline uint8_t pct_to_ocr(const_float_t pct) { return uint8_t(PCT_TO_PWM(pct)); }
|
static CutterMode cutter_mode;
|
||||||
|
|
||||||
|
static constexpr uint8_t pct_to_ocr(const_float_t pct) { return uint8_t(PCT_TO_PWM(pct)); }
|
||||||
|
|
||||||
// cpower = configured values (e.g., SPEED_POWER_MAX)
|
// cpower = configured values (e.g., SPEED_POWER_MAX)
|
||||||
|
|
||||||
// Convert configured power range to a percentage
|
// Convert configured power range to a percentage
|
||||||
static const inline uint8_t cpwr_to_pct(const cutter_cpower_t cpwr) {
|
static constexpr cutter_cpower_t power_floor = TERN(CUTTER_POWER_RELATIVE, SPEED_POWER_MIN, 0);
|
||||||
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) {
|
||||||
power_range = SPEED_POWER_MAX - power_floor;
|
return cpwr ? round(100.0f * (cpwr - power_floor) / (SPEED_POWER_MAX - power_floor)) : 0;
|
||||||
return cpwr ? round(100.0f * (cpwr - power_floor) / power_range) : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert a cpower (e.g., SPEED_POWER_STARTUP) to unit power (upwr, upower),
|
// Convert config defines from RPM to %, angle or PWM when in Spindle mode
|
||||||
// which can be PWM, Percent, Servo angle, or RPM (rel/abs).
|
// and convert from PERCENT to PWM when in Laser mode
|
||||||
static const inline cutter_power_t cpwr_to_upwr(const cutter_cpower_t cpwr) { // STARTUP power to Unit power
|
static constexpr cutter_power_t cpwr_to_upwr(const cutter_cpower_t cpwr) { // STARTUP power to Unit power
|
||||||
const cutter_power_t upwr = (
|
return (
|
||||||
#if ENABLED(SPINDLE_FEATURE)
|
#if ENABLED(SPINDLE_FEATURE)
|
||||||
// Spindle configured values are in RPM
|
// Spindle configured define values are in RPM
|
||||||
#if CUTTER_UNIT_IS(RPM)
|
#if CUTTER_UNIT_IS(RPM)
|
||||||
cpwr // to RPM
|
cpwr // to same
|
||||||
#elif CUTTER_UNIT_IS(PERCENT) // to PCT
|
#elif CUTTER_UNIT_IS(PERCENT)
|
||||||
cpwr_to_pct(cpwr)
|
cpwr_to_pct(cpwr) // to Percent
|
||||||
#elif CUTTER_UNIT_IS(SERVO) // to SERVO angle
|
#elif CUTTER_UNIT_IS(SERVO)
|
||||||
PCT_TO_SERVO(cpwr_to_pct(cpwr))
|
PCT_TO_SERVO(cpwr_to_pct(cpwr)) // to SERVO angle
|
||||||
#else // to PWM
|
#else
|
||||||
PCT_TO_PWM(cpwr_to_pct(cpwr))
|
PCT_TO_PWM(cpwr_to_pct(cpwr)) // to PWM
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
// Laser configured values are in PCT
|
// Laser configured define values are in Percent
|
||||||
#if CUTTER_UNIT_IS(PWM255)
|
#if CUTTER_UNIT_IS(PWM255)
|
||||||
PCT_TO_PWM(cpwr)
|
PCT_TO_PWM(cpwr) // to PWM
|
||||||
#else
|
#else
|
||||||
cpwr // to RPM/PCT
|
cpwr // to same
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
return upwr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const cutter_power_t mpower_min() { return cpwr_to_upwr(SPEED_POWER_MIN); }
|
static constexpr 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); }
|
static constexpr cutter_power_t mpower_max() { return cpwr_to_upwr(SPEED_POWER_MAX); }
|
||||||
|
|
||||||
#if ENABLED(LASER_FEATURE)
|
#if ENABLED(LASER_FEATURE)
|
||||||
static cutter_test_pulse_t testPulse; // Test fire Pulse ms value
|
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;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static bool isReady; // Ready to apply power setting from the UI to OCR
|
static bool isReadyForUI; // Ready to apply power setting from the UI to OCR
|
||||||
|
static bool enable_state;
|
||||||
static uint8_t power,
|
static uint8_t power,
|
||||||
last_power_applied; // Basic power state tracking
|
last_power_applied; // Basic power state tracking
|
||||||
|
|
||||||
#if ENABLED(MARLIN_DEV_MODE)
|
|
||||||
static cutter_frequency_t frequency; // Set PWM frequency; range: 2K-50K
|
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
|
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
|
unitPower; // Power as displayed status in PWM, Percentage or RPM
|
||||||
|
|
||||||
static void init();
|
static void init();
|
||||||
|
|
||||||
#if ENABLED(MARLIN_DEV_MODE)
|
#if ENABLED(HAL_CAN_SET_PWM_FREQ) && SPINDLE_LASER_FREQUENCY
|
||||||
static void refresh_frequency() { hal.set_pwm_frequency(pin_t(SPINDLE_LASER_PWM_PIN), frequency); }
|
static void refresh_frequency() { hal.set_pwm_frequency(pin_t(SPINDLE_LASER_PWM_PIN), frequency); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Modifying this function should update everywhere
|
// Modifying this function should update everywhere
|
||||||
static bool enabled(const cutter_power_t opwr) { return opwr > 0; }
|
static bool enabled(const cutter_power_t opwr) { return opwr > 0; }
|
||||||
static bool enabled() { return enabled(power); }
|
static bool enabled() { return enable_state; }
|
||||||
|
|
||||||
static void apply_power(const uint8_t inpow);
|
static void apply_power(const uint8_t inpow);
|
||||||
|
|
||||||
FORCE_INLINE static void refresh() { apply_power(power); }
|
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)
|
#if ENABLED(SPINDLE_LASER_USE_PWM)
|
||||||
|
|
||||||
@@ -125,7 +135,6 @@ public:
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
static void set_ocr(const uint8_t ocr);
|
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();
|
static void ocr_off();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -143,78 +152,76 @@ public:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // SPINDLE_LASER_USE_PWM
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Correct power to configured range
|
* Correct power to configured range
|
||||||
*/
|
*/
|
||||||
static cutter_power_t power_to_range(const cutter_power_t pwr) {
|
static cutter_power_t power_to_range(const cutter_power_t pwr, const uint8_t pwrUnit=_CUTTER_POWER(CUTTER_POWER_UNIT)) {
|
||||||
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
|
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)),
|
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);
|
max_pct = TERN(SPINDLE_FEATURE, 100, SPEED_POWER_MAX);
|
||||||
if (pwr <= 0) return 0;
|
if (pwr <= 0) return 0;
|
||||||
cutter_power_t upwr;
|
cutter_power_t upwr;
|
||||||
switch (pwrUnit) {
|
switch (pwrUnit) {
|
||||||
case _CUTTER_POWER_PWM255:
|
case _CUTTER_POWER_PWM255: { // PWM
|
||||||
upwr = cutter_power_t(
|
const uint8_t pmin = pct_to_ocr(min_pct), pmax = pct_to_ocr(max_pct);
|
||||||
(pwr < pct_to_ocr(min_pct)) ? pct_to_ocr(min_pct) // Use minimum if set below
|
upwr = cutter_power_t(constrain(pwr, pmin, pmax));
|
||||||
: (pwr > pct_to_ocr(max_pct)) ? pct_to_ocr(max_pct) // Use maximum if set above
|
} break;
|
||||||
: pwr
|
case _CUTTER_POWER_PERCENT: // Percent
|
||||||
);
|
upwr = cutter_power_t(constrain(pwr, min_pct, max_pct));
|
||||||
break;
|
break;
|
||||||
case _CUTTER_POWER_PERCENT:
|
case _CUTTER_POWER_RPM: // Calculate OCR value
|
||||||
upwr = cutter_power_t(
|
upwr = cutter_power_t(constrain(pwr, SPEED_POWER_MIN, SPEED_POWER_MAX));
|
||||||
(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;
|
break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
return upwr;
|
return upwr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // SPINDLE_LASER_USE_PWM
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable/Disable spindle/laser
|
* Enable Laser or Spindle output.
|
||||||
* @param enable true = enable; false = disable
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
*/
|
*/
|
||||||
static void set_enabled(const bool enable) {
|
static void set_enabled(const bool enable) {
|
||||||
uint8_t value = 0;
|
switch (cutter_mode) {
|
||||||
if (enable) {
|
case CUTTER_MODE_STANDARD:
|
||||||
#if ENABLED(SPINDLE_LASER_USE_PWM)
|
apply_power(enable ? TERN(SPINDLE_LASER_USE_PWM, (power ?: (unitPower ? upower_to_ocr(cpwr_to_upwr(SPEED_POWER_STARTUP)) : 0)), 255) : 0);
|
||||||
if (power)
|
break;
|
||||||
value = power;
|
case CUTTER_MODE_CONTINUOUS:
|
||||||
else if (unitPower)
|
TERN_(LASER_FEATURE, set_inline_enabled(enable));
|
||||||
value = upower_to_ocr(cpwr_to_upwr(SPEED_POWER_STARTUP));
|
break;
|
||||||
#else
|
case CUTTER_MODE_DYNAMIC:
|
||||||
value = 255;
|
TERN_(LASER_FEATURE, set_inline_enabled(enable));
|
||||||
|
break;
|
||||||
|
case CUTTER_MODE_ERROR: // Error mode, no enable and kill power.
|
||||||
|
enable_state = false;
|
||||||
|
apply_power(0);
|
||||||
|
}
|
||||||
|
#if SPINDLE_LASER_ENA_PIN
|
||||||
|
WRITE(SPINDLE_LASER_ENA_PIN, enable ? SPINDLE_LASER_ACTIVE_STATE : !SPINDLE_LASER_ACTIVE_STATE);
|
||||||
#endif
|
#endif
|
||||||
}
|
enable_state = enable;
|
||||||
set_power(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void disable() { isReady = false; set_enabled(false); }
|
static void disable() { isReadyForUI = false; set_enabled(false); }
|
||||||
|
|
||||||
/**
|
// Wait for spindle/laser to startup or shutdown
|
||||||
* Wait for spindle to spin up or spin down
|
|
||||||
*
|
|
||||||
* @param on true = state to on; false = state to off.
|
|
||||||
*/
|
|
||||||
static void power_delay(const bool on) {
|
static void power_delay(const bool on) {
|
||||||
#if DISABLED(LASER_POWER_INLINE)
|
|
||||||
safe_delay(on ? SPINDLE_LASER_POWERUP_DELAY : SPINDLE_LASER_POWERDOWN_DELAY);
|
safe_delay(on ? SPINDLE_LASER_POWERUP_DELAY : SPINDLE_LASER_POWERDOWN_DELAY);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLED(SPINDLE_CHANGE_DIR)
|
#if ENABLED(SPINDLE_CHANGE_DIR)
|
||||||
@@ -244,8 +251,10 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if HAS_MARLINUI_MENU
|
#if HAS_MARLINUI_MENU
|
||||||
|
|
||||||
|
#if ENABLED(SPINDLE_FEATURE)
|
||||||
static void enable_with_dir(const bool reverse) {
|
static void enable_with_dir(const bool reverse) {
|
||||||
isReady = true;
|
isReadyForUI = true;
|
||||||
const uint8_t ocr = TERN(SPINDLE_LASER_USE_PWM, upower_to_ocr(menuPower), 255);
|
const uint8_t ocr = TERN(SPINDLE_LASER_USE_PWM, upower_to_ocr(menuPower), 255);
|
||||||
if (menuPower)
|
if (menuPower)
|
||||||
power = ocr;
|
power = ocr;
|
||||||
@@ -258,90 +267,63 @@ public:
|
|||||||
FORCE_INLINE static void enable_forward() { enable_with_dir(false); }
|
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_reverse() { enable_with_dir(true); }
|
||||||
FORCE_INLINE static void enable_same_dir() { enable_with_dir(is_reverse()); }
|
FORCE_INLINE static void enable_same_dir() { enable_with_dir(is_reverse()); }
|
||||||
|
#endif // SPINDLE_FEATURE
|
||||||
|
|
||||||
#if ENABLED(SPINDLE_LASER_USE_PWM)
|
#if ENABLED(SPINDLE_LASER_USE_PWM)
|
||||||
static void update_from_mpower() {
|
static void update_from_mpower() {
|
||||||
if (isReady) power = upower_to_ocr(menuPower);
|
if (isReadyForUI) power = upower_to_ocr(menuPower);
|
||||||
unitPower = menuPower;
|
unitPower = menuPower;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ENABLED(LASER_FEATURE)
|
#if ENABLED(LASER_FEATURE)
|
||||||
|
// Toggle the laser on/off with menuPower. Apply SPEED_POWER_STARTUP if it was 0 on entry.
|
||||||
|
static void laser_menu_toggle(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test fire the laser using the testPulse ms duration
|
* Test fire the laser using the testPulse ms duration
|
||||||
* Also fires with any PWM power that was previous set
|
* Also fires with any PWM power that was previous set
|
||||||
* If not set defaults to 80% power
|
* If not set defaults to 80% power
|
||||||
*/
|
*/
|
||||||
static void test_fire_pulse() {
|
static void test_fire_pulse() {
|
||||||
TERN_(HAS_BEEPER, buzzer.tone(30, 3000));
|
BUZZ(30, 3000);
|
||||||
enable_forward(); // Turn Laser on (Spindle speak but same funct)
|
cutter_mode = CUTTER_MODE_STANDARD;// Menu needs standard mode.
|
||||||
|
laser_menu_toggle(true); // Laser On
|
||||||
delay(testPulse); // Delay for time set by user in pulse ms menu screen.
|
delay(testPulse); // Delay for time set by user in pulse ms menu screen.
|
||||||
disable(); // Turn laser off
|
laser_menu_toggle(false); // Laser Off
|
||||||
}
|
}
|
||||||
#endif
|
#endif // LASER_FEATURE
|
||||||
|
|
||||||
#endif // HAS_MARLINUI_MENU
|
#endif // HAS_MARLINUI_MENU
|
||||||
|
|
||||||
#if ENABLED(LASER_POWER_INLINE)
|
#if ENABLED(LASER_FEATURE)
|
||||||
/**
|
|
||||||
* Inline power adds extra fields to the planner block
|
|
||||||
* to handle laser power and scale to movement speed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Force disengage planner power control
|
// Dynamic mode rate calculation
|
||||||
static void inline_disable() {
|
static uint8_t calc_dynamic_power() {
|
||||||
isReady = false;
|
if (feedrate_mm_m > 65535) return 255; // Too fast, go always on
|
||||||
unitPower = 0;
|
uint16_t rate = uint16_t(feedrate_mm_m); // 16 bits from the G-code parser float input
|
||||||
planner.laser_inline.status.isPlanned = false;
|
rate >>= 8; // Take the G-code input e.g. F40000 and shift off the lower bits to get an OCR value from 1-255
|
||||||
planner.laser_inline.status.isEnabled = false;
|
return uint8_t(rate);
|
||||||
planner.laser_inline.power = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inline modes of all other functions; all enable planner inline power control
|
// Inline modes of all other functions; all enable planner inline power control
|
||||||
static void set_inline_enabled(const bool enable) {
|
static void set_inline_enabled(const bool enable) { planner.laser_inline.status.isEnabled = 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the power for subsequent movement blocks
|
// Set the power for subsequent movement blocks
|
||||||
static void inline_power(const cutter_power_t upwr) {
|
static void inline_power(const cutter_power_t cpwr) {
|
||||||
unitPower = menuPower = upwr;
|
TERN(SPINDLE_LASER_USE_PWM, power = planner.laser_inline.power = cpwr, planner.laser_inline.power = cpwr > 0 ? 255 : 0);
|
||||||
#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 inline_direction(const bool) { /* never */ }
|
#endif // LASER_FEATURE
|
||||||
|
|
||||||
#if ENABLED(SPINDLE_LASER_USE_PWM)
|
static void kill() { disable(); }
|
||||||
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;
|
extern SpindleLaser cutter;
|
||||||
|
@@ -74,12 +74,10 @@ typedef IF<(SPEED_POWER_MAX > 255), uint16_t, uint8_t>::type cutter_cpower_t;
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef uint16_t cutter_frequency_t;
|
||||||
|
|
||||||
#if ENABLED(LASER_FEATURE)
|
#if ENABLED(LASER_FEATURE)
|
||||||
typedef uint16_t cutter_test_pulse_t;
|
typedef uint16_t cutter_test_pulse_t;
|
||||||
#define CUTTER_MENU_PULSE_TYPE uint16_3
|
#define CUTTER_MENU_PULSE_TYPE uint16_3
|
||||||
#endif
|
|
||||||
|
|
||||||
#if ENABLED(MARLIN_DEV_MODE)
|
|
||||||
typedef uint16_t cutter_frequency_t;
|
|
||||||
#define CUTTER_MENU_FREQUENCY_TYPE uint16_5
|
#define CUTTER_MENU_FREQUENCY_TYPE uint16_5
|
||||||
#endif
|
#endif
|
||||||
|
@@ -33,17 +33,12 @@
|
|||||||
#include "../gcode/gcode.h"
|
#include "../gcode/gcode.h"
|
||||||
|
|
||||||
#if ENABLED(TMC_DEBUG)
|
#if ENABLED(TMC_DEBUG)
|
||||||
#include "../module/planner.h"
|
|
||||||
#include "../libs/hex_print.h"
|
#include "../libs/hex_print.h"
|
||||||
#if ENABLED(MONITOR_DRIVER_STATUS)
|
#if ENABLED(MONITOR_DRIVER_STATUS)
|
||||||
static uint16_t report_tmc_status_interval; // = 0
|
static uint16_t report_tmc_status_interval; // = 0
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if HAS_MARLINUI_MENU
|
|
||||||
#include "../module/stepper.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check for over temperature or short to ground error flags.
|
* Check for over temperature or short to ground error flags.
|
||||||
* Report and log warning of overtemperature condition.
|
* Report and log warning of overtemperature condition.
|
||||||
|
@@ -348,7 +348,7 @@ void test_tmc_connection(LOGICAL_AXIS_DECL(const bool, true));
|
|||||||
#if USE_SENSORLESS
|
#if USE_SENSORLESS
|
||||||
|
|
||||||
// Track enabled status of stealthChop and only re-enable where applicable
|
// Track enabled status of stealthChop and only re-enable where applicable
|
||||||
struct sensorless_t { bool LINEAR_AXIS_ARGS(), x2, y2, z2, z3, z4; };
|
struct sensorless_t { bool NUM_AXIS_ARGS(), x2, y2, z2, z3, z4; };
|
||||||
|
|
||||||
#if ENABLED(IMPROVE_HOMING_RELIABILITY)
|
#if ENABLED(IMPROVE_HOMING_RELIABILITY)
|
||||||
extern millis_t sg_guard_period;
|
extern millis_t sg_guard_period;
|
||||||
|
@@ -107,7 +107,6 @@
|
|||||||
|
|
||||||
#include "../../MarlinCore.h"
|
#include "../../MarlinCore.h"
|
||||||
#include "../../module/planner.h"
|
#include "../../module/planner.h"
|
||||||
#include "../../module/stepper.h"
|
|
||||||
#include "../../module/motion.h"
|
#include "../../module/motion.h"
|
||||||
#include "../../module/tool_change.h"
|
#include "../../module/tool_change.h"
|
||||||
#include "../../module/temperature.h"
|
#include "../../module/temperature.h"
|
||||||
@@ -306,7 +305,7 @@ typedef struct {
|
|||||||
LIMIT(e.x, X_MIN_POS + 1, X_MAX_POS - 1);
|
LIMIT(e.x, X_MIN_POS + 1, X_MAX_POS - 1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (position_is_reachable(s.x, s.y) && position_is_reachable(e.x, e.y))
|
if (position_is_reachable(s) && position_is_reachable(e))
|
||||||
print_line_from_here_to_there(s, e);
|
print_line_from_here_to_there(s, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -32,7 +32,6 @@
|
|||||||
#include "../../../feature/bedlevel/bedlevel.h"
|
#include "../../../feature/bedlevel/bedlevel.h"
|
||||||
#include "../../../module/motion.h"
|
#include "../../../module/motion.h"
|
||||||
#include "../../../module/planner.h"
|
#include "../../../module/planner.h"
|
||||||
#include "../../../module/stepper.h"
|
|
||||||
#include "../../../module/probe.h"
|
#include "../../../module/probe.h"
|
||||||
#include "../../queue.h"
|
#include "../../queue.h"
|
||||||
|
|
||||||
|
@@ -36,7 +36,7 @@
|
|||||||
#include "../../../libs/buzzer.h"
|
#include "../../../libs/buzzer.h"
|
||||||
#include "../../../lcd/marlinui.h"
|
#include "../../../lcd/marlinui.h"
|
||||||
#include "../../../module/motion.h"
|
#include "../../../module/motion.h"
|
||||||
#include "../../../module/stepper.h"
|
#include "../../../module/planner.h"
|
||||||
|
|
||||||
#if ENABLED(EXTENSIBLE_UI)
|
#if ENABLED(EXTENSIBLE_UI)
|
||||||
#include "../../../lcd/extui/ui_api.h"
|
#include "../../../lcd/extui/ui_api.h"
|
||||||
|
@@ -24,8 +24,9 @@
|
|||||||
|
|
||||||
#include "../gcode.h"
|
#include "../gcode.h"
|
||||||
|
|
||||||
#include "../../module/stepper.h"
|
|
||||||
#include "../../module/endstops.h"
|
#include "../../module/endstops.h"
|
||||||
|
#include "../../module/planner.h"
|
||||||
|
#include "../../module/stepper.h" // for various
|
||||||
|
|
||||||
#if HAS_MULTI_HOTEND
|
#if HAS_MULTI_HOTEND
|
||||||
#include "../../module/tool_change.h"
|
#include "../../module/tool_change.h"
|
||||||
@@ -59,7 +60,7 @@
|
|||||||
#include "../../libs/L64XX/L64XX_Marlin.h"
|
#include "../../libs/L64XX/L64XX_Marlin.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ENABLED(LASER_MOVE_G28_OFF)
|
#if ENABLED(LASER_FEATURE)
|
||||||
#include "../../feature/spindle_laser.h"
|
#include "../../feature/spindle_laser.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -82,7 +83,7 @@
|
|||||||
|
|
||||||
#if ENABLED(SENSORLESS_HOMING)
|
#if ENABLED(SENSORLESS_HOMING)
|
||||||
sensorless_t stealth_states {
|
sensorless_t stealth_states {
|
||||||
LINEAR_AXIS_LIST(
|
NUM_AXIS_LIST(
|
||||||
TERN0(X_SENSORLESS, tmc_enable_stallguard(stepperX)),
|
TERN0(X_SENSORLESS, tmc_enable_stallguard(stepperX)),
|
||||||
TERN0(Y_SENSORLESS, tmc_enable_stallguard(stepperY)),
|
TERN0(Y_SENSORLESS, tmc_enable_stallguard(stepperY)),
|
||||||
false, false, false, false
|
false, false, false, false
|
||||||
@@ -169,7 +170,7 @@
|
|||||||
motion_state.jerk_state = planner.max_jerk;
|
motion_state.jerk_state = planner.max_jerk;
|
||||||
planner.max_jerk.set(0, 0 OPTARG(DELTA, 0));
|
planner.max_jerk.set(0, 0 OPTARG(DELTA, 0));
|
||||||
#endif
|
#endif
|
||||||
planner.reset_acceleration_rates();
|
planner.refresh_acceleration_rates();
|
||||||
return motion_state;
|
return motion_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,7 +179,7 @@
|
|||||||
planner.settings.max_acceleration_mm_per_s2[Y_AXIS] = motion_state.acceleration.y;
|
planner.settings.max_acceleration_mm_per_s2[Y_AXIS] = motion_state.acceleration.y;
|
||||||
TERN_(DELTA, planner.settings.max_acceleration_mm_per_s2[Z_AXIS] = motion_state.acceleration.z);
|
TERN_(DELTA, planner.settings.max_acceleration_mm_per_s2[Z_AXIS] = motion_state.acceleration.z);
|
||||||
TERN_(HAS_CLASSIC_JERK, planner.max_jerk = motion_state.jerk_state);
|
TERN_(HAS_CLASSIC_JERK, planner.max_jerk = motion_state.jerk_state);
|
||||||
planner.reset_acceleration_rates();
|
planner.refresh_acceleration_rates();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // IMPROVE_HOMING_RELIABILITY
|
#endif // IMPROVE_HOMING_RELIABILITY
|
||||||
@@ -205,7 +206,12 @@ void GcodeSuite::G28() {
|
|||||||
DEBUG_SECTION(log_G28, "G28", DEBUGGING(LEVELING));
|
DEBUG_SECTION(log_G28, "G28", DEBUGGING(LEVELING));
|
||||||
if (DEBUGGING(LEVELING)) log_machine_info();
|
if (DEBUGGING(LEVELING)) log_machine_info();
|
||||||
|
|
||||||
TERN_(LASER_MOVE_G28_OFF, cutter.set_inline_enabled(false)); // turn off laser
|
/*
|
||||||
|
* Set the laser power to false to stop the planner from processing the current power setting.
|
||||||
|
*/
|
||||||
|
#if ENABLED(LASER_FEATURE)
|
||||||
|
planner.laser_inline.status.isPowered = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if ENABLED(DUAL_X_CARRIAGE)
|
#if ENABLED(DUAL_X_CARRIAGE)
|
||||||
bool IDEX_saved_duplication_state = extruder_duplication_enabled;
|
bool IDEX_saved_duplication_state = extruder_duplication_enabled;
|
||||||
@@ -214,7 +220,7 @@ void GcodeSuite::G28() {
|
|||||||
|
|
||||||
#if ENABLED(MARLIN_DEV_MODE)
|
#if ENABLED(MARLIN_DEV_MODE)
|
||||||
if (parser.seen_test('S')) {
|
if (parser.seen_test('S')) {
|
||||||
LOOP_LINEAR_AXES(a) set_axis_is_at_home((AxisEnum)a);
|
LOOP_NUM_AXES(a) set_axis_is_at_home((AxisEnum)a);
|
||||||
sync_plan_position();
|
sync_plan_position();
|
||||||
SERIAL_ECHOLNPGM("Simulated Homing");
|
SERIAL_ECHOLNPGM("Simulated Homing");
|
||||||
report_current_position();
|
report_current_position();
|
||||||
@@ -367,21 +373,21 @@ void GcodeSuite::G28() {
|
|||||||
#define _UNSAFE(A) (homeZ && TERN0(Z_SAFE_HOMING, axes_should_home(_BV(A##_AXIS))))
|
#define _UNSAFE(A) (homeZ && TERN0(Z_SAFE_HOMING, axes_should_home(_BV(A##_AXIS))))
|
||||||
|
|
||||||
const bool homeZ = TERN0(HAS_Z_AXIS, parser.seen_test('Z')),
|
const bool homeZ = TERN0(HAS_Z_AXIS, parser.seen_test('Z')),
|
||||||
LINEAR_AXIS_LIST( // Other axes should be homed before Z safe-homing
|
NUM_AXIS_LIST( // Other axes should be homed before Z safe-homing
|
||||||
needX = _UNSAFE(X), needY = _UNSAFE(Y), needZ = false, // UNUSED
|
needX = _UNSAFE(X), needY = _UNSAFE(Y), needZ = false, // UNUSED
|
||||||
needI = _UNSAFE(I), needJ = _UNSAFE(J), needK = _UNSAFE(K)
|
needI = _UNSAFE(I), needJ = _UNSAFE(J), needK = _UNSAFE(K)
|
||||||
),
|
),
|
||||||
LINEAR_AXIS_LIST( // Home each axis if needed or flagged
|
NUM_AXIS_LIST( // Home each axis if needed or flagged
|
||||||
homeX = needX || parser.seen_test('X'),
|
homeX = needX || parser.seen_test('X'),
|
||||||
homeY = needY || parser.seen_test('Y'),
|
homeY = needY || parser.seen_test('Y'),
|
||||||
homeZZ = homeZ,
|
homeZZ = homeZ,
|
||||||
homeI = needI || parser.seen_test(AXIS4_NAME), homeJ = needJ || parser.seen_test(AXIS5_NAME), homeK = needK || parser.seen_test(AXIS6_NAME)
|
homeI = needI || parser.seen_test(AXIS4_NAME), homeJ = needJ || parser.seen_test(AXIS5_NAME), homeK = needK || parser.seen_test(AXIS6_NAME)
|
||||||
),
|
),
|
||||||
home_all = LINEAR_AXIS_GANG( // Home-all if all or none are flagged
|
home_all = NUM_AXIS_GANG( // Home-all if all or none are flagged
|
||||||
homeX == homeX, && homeY == homeX, && homeZ == homeX,
|
homeX == homeX, && homeY == homeX, && homeZ == homeX,
|
||||||
&& homeI == homeX, && homeJ == homeX, && homeK == homeX
|
&& homeI == homeX, && homeJ == homeX, && homeK == homeX
|
||||||
),
|
),
|
||||||
LINEAR_AXIS_LIST(
|
NUM_AXIS_LIST(
|
||||||
doX = home_all || homeX, doY = home_all || homeY, doZ = home_all || homeZ,
|
doX = home_all || homeX, doY = home_all || homeY, doZ = home_all || homeZ,
|
||||||
doI = home_all || homeI, doJ = home_all || homeJ, doK = home_all || homeK
|
doI = home_all || homeI, doJ = home_all || homeJ, doK = home_all || homeK
|
||||||
);
|
);
|
||||||
@@ -397,7 +403,7 @@ void GcodeSuite::G28() {
|
|||||||
const bool seenR = parser.seenval('R');
|
const bool seenR = parser.seenval('R');
|
||||||
const float z_homing_height = seenR ? parser.value_linear_units() : Z_HOMING_HEIGHT;
|
const float z_homing_height = seenR ? parser.value_linear_units() : Z_HOMING_HEIGHT;
|
||||||
|
|
||||||
if (z_homing_height && (seenR || LINEAR_AXIS_GANG(doX, || doY, || TERN0(Z_SAFE_HOMING, doZ), || doI, || doJ, || doK))) {
|
if (z_homing_height && (seenR || NUM_AXIS_GANG(doX, || doY, || TERN0(Z_SAFE_HOMING, doZ), || doI, || doJ, || doK))) {
|
||||||
// Raise Z before homing any other axes and z is not already high enough (never lower z)
|
// Raise Z before homing any other axes and z is not already high enough (never lower z)
|
||||||
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Raise Z (before homing) by ", z_homing_height);
|
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Raise Z (before homing) by ", z_homing_height);
|
||||||
do_z_clearance(z_homing_height);
|
do_z_clearance(z_homing_height);
|
||||||
@@ -460,9 +466,11 @@ void GcodeSuite::G28() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TERN_(HAS_I_AXIS, if (doI) homeaxis(I_AXIS));
|
SECONDARY_AXIS_CODE(
|
||||||
TERN_(HAS_J_AXIS, if (doJ) homeaxis(J_AXIS));
|
if (doI) homeaxis(I_AXIS),
|
||||||
TERN_(HAS_K_AXIS, if (doK) homeaxis(K_AXIS));
|
if (doJ) homeaxis(J_AXIS),
|
||||||
|
if (doK) homeaxis(K_AXIS)
|
||||||
|
);
|
||||||
|
|
||||||
sync_plan_position();
|
sync_plan_position();
|
||||||
|
|
||||||
@@ -568,7 +576,7 @@ void GcodeSuite::G28() {
|
|||||||
// If not, this will need a PROGMEM directive and an accessor.
|
// If not, this will need a PROGMEM directive and an accessor.
|
||||||
#define _EN_ITEM(N) , E_AXIS
|
#define _EN_ITEM(N) , E_AXIS
|
||||||
static constexpr AxisEnum L64XX_axis_xref[MAX_L64XX] = {
|
static constexpr AxisEnum L64XX_axis_xref[MAX_L64XX] = {
|
||||||
LINEAR_AXIS_LIST(X_AXIS, Y_AXIS, Z_AXIS, I_AXIS, J_AXIS, K_AXIS),
|
NUM_AXIS_LIST(X_AXIS, Y_AXIS, Z_AXIS, I_AXIS, J_AXIS, K_AXIS),
|
||||||
X_AXIS, Y_AXIS, Z_AXIS, Z_AXIS, Z_AXIS
|
X_AXIS, Y_AXIS, Z_AXIS, Z_AXIS, Z_AXIS
|
||||||
REPEAT(E_STEPPERS, _EN_ITEM)
|
REPEAT(E_STEPPERS, _EN_ITEM)
|
||||||
};
|
};
|
||||||
|
@@ -27,7 +27,7 @@
|
|||||||
#include "../gcode.h"
|
#include "../gcode.h"
|
||||||
#include "../../module/delta.h"
|
#include "../../module/delta.h"
|
||||||
#include "../../module/motion.h"
|
#include "../../module/motion.h"
|
||||||
#include "../../module/stepper.h"
|
#include "../../module/planner.h"
|
||||||
#include "../../module/endstops.h"
|
#include "../../module/endstops.h"
|
||||||
#include "../../lcd/marlinui.h"
|
#include "../../lcd/marlinui.h"
|
||||||
|
|
||||||
@@ -343,7 +343,7 @@ static float auto_tune_a(const float dcr) {
|
|||||||
abc_float_t delta_e = { 0.0f }, delta_t = { 0.0f };
|
abc_float_t delta_e = { 0.0f }, delta_t = { 0.0f };
|
||||||
|
|
||||||
delta_t.reset();
|
delta_t.reset();
|
||||||
LOOP_LINEAR_AXES(axis) {
|
LOOP_NUM_AXES(axis) {
|
||||||
delta_t[axis] = diff;
|
delta_t[axis] = diff;
|
||||||
calc_kinematics_diff_probe_points(z_pt, dcr, delta_e, delta_r, delta_t);
|
calc_kinematics_diff_probe_points(z_pt, dcr, delta_e, delta_r, delta_t);
|
||||||
delta_t[axis] = 0;
|
delta_t[axis] = 0;
|
||||||
@@ -437,7 +437,7 @@ void GcodeSuite::G33() {
|
|||||||
const bool stow_after_each = parser.seen_test('E');
|
const bool stow_after_each = parser.seen_test('E');
|
||||||
|
|
||||||
#if HAS_DELTA_SENSORLESS_PROBING
|
#if HAS_DELTA_SENSORLESS_PROBING
|
||||||
probe.test_sensitivity.set(!parser.seen_test('X'), !parser.seen_test('Y'), !parser.seen_test('Z'));
|
probe.test_sensitivity = { !parser.seen_test('X'), !parser.seen_test('Y'), !parser.seen_test('Z') };
|
||||||
const bool do_save_offset_adj = parser.seen_test('S');
|
const bool do_save_offset_adj = parser.seen_test('S');
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -557,7 +557,7 @@ void GcodeSuite::G33() {
|
|||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
test_precision = 0.0f; // forced end
|
test_precision = 0.0f; // forced end
|
||||||
LOOP_LINEAR_AXES(axis) e_delta[axis] = +Z4(CEN);
|
LOOP_NUM_AXES(axis) e_delta[axis] = +Z4(CEN);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
@@ -605,14 +605,14 @@ void GcodeSuite::G33() {
|
|||||||
// Normalize angles to least-squares
|
// Normalize angles to least-squares
|
||||||
if (_angle_results) {
|
if (_angle_results) {
|
||||||
float a_sum = 0.0f;
|
float a_sum = 0.0f;
|
||||||
LOOP_LINEAR_AXES(axis) a_sum += delta_tower_angle_trim[axis];
|
LOOP_NUM_AXES(axis) a_sum += delta_tower_angle_trim[axis];
|
||||||
LOOP_LINEAR_AXES(axis) delta_tower_angle_trim[axis] -= a_sum / 3.0f;
|
LOOP_NUM_AXES(axis) delta_tower_angle_trim[axis] -= a_sum / 3.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
// adjust delta_height and endstops by the max amount
|
// adjust delta_height and endstops by the max amount
|
||||||
const float z_temp = _MAX(delta_endstop_adj.a, delta_endstop_adj.b, delta_endstop_adj.c);
|
const float z_temp = _MAX(delta_endstop_adj.a, delta_endstop_adj.b, delta_endstop_adj.c);
|
||||||
delta_height -= z_temp;
|
delta_height -= z_temp;
|
||||||
LOOP_LINEAR_AXES(axis) delta_endstop_adj[axis] -= z_temp;
|
LOOP_NUM_AXES(axis) delta_endstop_adj[axis] -= z_temp;
|
||||||
}
|
}
|
||||||
recalc_delta_settings();
|
recalc_delta_settings();
|
||||||
NOMORE(zero_std_dev_min, zero_std_dev);
|
NOMORE(zero_std_dev_min, zero_std_dev);
|
||||||
|
@@ -26,9 +26,12 @@
|
|||||||
|
|
||||||
#include "../gcode.h"
|
#include "../gcode.h"
|
||||||
#include "../../module/motion.h"
|
#include "../../module/motion.h"
|
||||||
#include "../../module/stepper.h"
|
|
||||||
#include "../../module/endstops.h"
|
#include "../../module/endstops.h"
|
||||||
|
|
||||||
|
#if ANY(HAS_MOTOR_CURRENT_SPI, HAS_MOTOR_CURRENT_PWM, HAS_TRINAMIC_CONFIG)
|
||||||
|
#include "../../module/stepper.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if HAS_LEVELING
|
#if HAS_LEVELING
|
||||||
#include "../../feature/bedlevel/bedlevel.h"
|
#include "../../feature/bedlevel/bedlevel.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -79,7 +82,7 @@ void GcodeSuite::G34() {
|
|||||||
stepper.set_digipot_current(Z_AXIS, target_current);
|
stepper.set_digipot_current(Z_AXIS, target_current);
|
||||||
#elif HAS_MOTOR_CURRENT_PWM
|
#elif HAS_MOTOR_CURRENT_PWM
|
||||||
const uint16_t target_current = parser.intval('S', GANTRY_CALIBRATION_CURRENT);
|
const uint16_t target_current = parser.intval('S', GANTRY_CALIBRATION_CURRENT);
|
||||||
const uint32_t previous_current = stepper.motor_current_setting[Z_AXIS];
|
const uint32_t previous_current = stepper.motor_current_setting[1]; // Z
|
||||||
stepper.set_digipot_current(1, target_current);
|
stepper.set_digipot_current(1, target_current);
|
||||||
#elif HAS_MOTOR_CURRENT_DAC
|
#elif HAS_MOTOR_CURRENT_DAC
|
||||||
const float target_current = parser.floatval('S', GANTRY_CALIBRATION_CURRENT);
|
const float target_current = parser.floatval('S', GANTRY_CALIBRATION_CURRENT);
|
||||||
|
@@ -224,13 +224,15 @@ void GcodeSuite::G34() {
|
|||||||
// Safe clearance even on an incline
|
// Safe clearance even on an incline
|
||||||
if ((iteration == 0 || i > 0) && z_probe > current_position.z) do_blocking_move_to_z(z_probe);
|
if ((iteration == 0 || i > 0) && z_probe > current_position.z) do_blocking_move_to_z(z_probe);
|
||||||
|
|
||||||
|
xy_pos_t &ppos = z_stepper_align.xy[iprobe];
|
||||||
|
|
||||||
if (DEBUGGING(LEVELING))
|
if (DEBUGGING(LEVELING))
|
||||||
DEBUG_ECHOLNPGM_P(PSTR("Probing X"), z_stepper_align.xy[iprobe].x, SP_Y_STR, z_stepper_align.xy[iprobe].y);
|
DEBUG_ECHOLNPGM_P(PSTR("Probing X"), ppos.x, SP_Y_STR, ppos.y);
|
||||||
|
|
||||||
// Probe a Z height for each stepper.
|
// Probe a Z height for each stepper.
|
||||||
// Probing sanity check is disabled, as it would trigger even in normal cases because
|
// Probing sanity check is disabled, as it would trigger even in normal cases because
|
||||||
// current_position.z has been manually altered in the "dirty trick" above.
|
// current_position.z has been manually altered in the "dirty trick" above.
|
||||||
const float z_probed_height = probe.probe_at_point(z_stepper_align.xy[iprobe], raise_after, 0, true, false);
|
const float z_probed_height = probe.probe_at_point(DIFF_TERN(HAS_HOME_OFFSET, ppos, xy_pos_t(home_offset)), raise_after, 0, true, false);
|
||||||
if (isnan(z_probed_height)) {
|
if (isnan(z_probed_height)) {
|
||||||
SERIAL_ECHOLNPGM("Probing failed");
|
SERIAL_ECHOLNPGM("Probing failed");
|
||||||
LCD_MESSAGE(MSG_LCD_PROBING_FAILED);
|
LCD_MESSAGE(MSG_LCD_PROBING_FAILED);
|
||||||
|
@@ -88,7 +88,7 @@
|
|||||||
|
|
||||||
enum side_t : uint8_t {
|
enum side_t : uint8_t {
|
||||||
TOP, RIGHT, FRONT, LEFT, BACK, NUM_SIDES,
|
TOP, RIGHT, FRONT, LEFT, BACK, NUM_SIDES,
|
||||||
LIST_N(DOUBLE(SUB3(LINEAR_AXES)), IMINIMUM, IMAXIMUM, JMINIMUM, JMAXIMUM, KMINIMUM, KMAXIMUM)
|
LIST_N(DOUBLE(SECONDARY_AXES), IMINIMUM, IMAXIMUM, JMINIMUM, JMAXIMUM, KMINIMUM, KMAXIMUM)
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr xyz_pos_t true_center CALIBRATION_OBJECT_CENTER;
|
static constexpr xyz_pos_t true_center CALIBRATION_OBJECT_CENTER;
|
||||||
@@ -352,7 +352,7 @@ inline void probe_sides(measurements_t &m, const float uncertainty) {
|
|||||||
|
|
||||||
// The difference between the known and the measured location
|
// The difference between the known and the measured location
|
||||||
// of the calibration object is the positional error
|
// of the calibration object is the positional error
|
||||||
LINEAR_AXIS_CODE(
|
NUM_AXIS_CODE(
|
||||||
m.pos_error.x = TERN0(HAS_X_CENTER, true_center.x - m.obj_center.x),
|
m.pos_error.x = TERN0(HAS_X_CENTER, true_center.x - m.obj_center.x),
|
||||||
m.pos_error.y = TERN0(HAS_Y_CENTER, true_center.y - m.obj_center.y),
|
m.pos_error.y = TERN0(HAS_Y_CENTER, true_center.y - m.obj_center.y),
|
||||||
m.pos_error.z = true_center.z - m.obj_center.z,
|
m.pos_error.z = true_center.z - m.obj_center.z,
|
||||||
@@ -597,7 +597,7 @@ inline void calibrate_backlash(measurements_t &m, const float uncertainty) {
|
|||||||
// New scope for TEMPORARY_BACKLASH_CORRECTION
|
// New scope for TEMPORARY_BACKLASH_CORRECTION
|
||||||
TEMPORARY_BACKLASH_CORRECTION(backlash.all_on);
|
TEMPORARY_BACKLASH_CORRECTION(backlash.all_on);
|
||||||
TEMPORARY_BACKLASH_SMOOTHING(0.0f);
|
TEMPORARY_BACKLASH_SMOOTHING(0.0f);
|
||||||
const xyz_float_t move = LINEAR_AXIS_ARRAY(
|
const xyz_float_t move = NUM_AXIS_ARRAY(
|
||||||
AXIS_CAN_CALIBRATE(X) * 3, AXIS_CAN_CALIBRATE(Y) * 3, AXIS_CAN_CALIBRATE(Z) * 3,
|
AXIS_CAN_CALIBRATE(X) * 3, AXIS_CAN_CALIBRATE(Y) * 3, AXIS_CAN_CALIBRATE(Z) * 3,
|
||||||
AXIS_CAN_CALIBRATE(I) * 3, AXIS_CAN_CALIBRATE(J) * 3, AXIS_CAN_CALIBRATE(K) * 3
|
AXIS_CAN_CALIBRATE(I) * 3, AXIS_CAN_CALIBRATE(J) * 3, AXIS_CAN_CALIBRATE(K) * 3
|
||||||
);
|
);
|
||||||
|
@@ -47,23 +47,17 @@ void GcodeSuite::M425() {
|
|||||||
bool noArgs = true;
|
bool noArgs = true;
|
||||||
|
|
||||||
auto axis_can_calibrate = [](const uint8_t a) {
|
auto axis_can_calibrate = [](const uint8_t a) {
|
||||||
|
#define _CAN_CASE(N) case N##_AXIS: return AXIS_CAN_CALIBRATE(N);
|
||||||
switch (a) {
|
switch (a) {
|
||||||
default: return false;
|
default: return false;
|
||||||
LINEAR_AXIS_CODE(
|
MAIN_AXIS_MAP(_CAN_CASE)
|
||||||
case X_AXIS: return AXIS_CAN_CALIBRATE(X),
|
|
||||||
case Y_AXIS: return AXIS_CAN_CALIBRATE(Y),
|
|
||||||
case Z_AXIS: return AXIS_CAN_CALIBRATE(Z),
|
|
||||||
case I_AXIS: return AXIS_CAN_CALIBRATE(I),
|
|
||||||
case J_AXIS: return AXIS_CAN_CALIBRATE(J),
|
|
||||||
case K_AXIS: return AXIS_CAN_CALIBRATE(K)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
LOOP_LINEAR_AXES(a) {
|
LOOP_NUM_AXES(a) {
|
||||||
if (axis_can_calibrate(a) && parser.seen(AXIS_CHAR(a))) {
|
if (axis_can_calibrate(a) && parser.seen(AXIS_CHAR(a))) {
|
||||||
planner.synchronize();
|
planner.synchronize();
|
||||||
backlash.set_distance_mm(AxisEnum(a), parser.has_value() ? parser.value_linear_units() : backlash.get_measurement(AxisEnum(a)));
|
backlash.set_distance_mm((AxisEnum)a, parser.has_value() ? parser.value_axis_units((AxisEnum)a) : backlash.get_measurement((AxisEnum)a));
|
||||||
noArgs = false;
|
noArgs = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -88,10 +82,8 @@ void GcodeSuite::M425() {
|
|||||||
SERIAL_ECHOLNPGM("active:");
|
SERIAL_ECHOLNPGM("active:");
|
||||||
SERIAL_ECHOLNPGM(" Correction Amount/Fade-out: F", backlash.get_correction(), " (F1.0 = full, F0.0 = none)");
|
SERIAL_ECHOLNPGM(" Correction Amount/Fade-out: F", backlash.get_correction(), " (F1.0 = full, F0.0 = none)");
|
||||||
SERIAL_ECHOPGM(" Backlash Distance (mm): ");
|
SERIAL_ECHOPGM(" Backlash Distance (mm): ");
|
||||||
LOOP_LINEAR_AXES(a) if (axis_can_calibrate(a)) {
|
LOOP_NUM_AXES(a) if (axis_can_calibrate(a)) {
|
||||||
SERIAL_CHAR(' ', AXIS_CHAR(a));
|
SERIAL_ECHOLNPGM_P((PGM_P)pgm_read_ptr(&SP_AXIS_STR[a]), backlash.get_distance_mm((AxisEnum)a));
|
||||||
SERIAL_ECHO(backlash.get_distance_mm(AxisEnum(a)));
|
|
||||||
SERIAL_EOL();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef BACKLASH_SMOOTHING_MM
|
#ifdef BACKLASH_SMOOTHING_MM
|
||||||
@@ -101,9 +93,8 @@ void GcodeSuite::M425() {
|
|||||||
#if ENABLED(MEASURE_BACKLASH_WHEN_PROBING)
|
#if ENABLED(MEASURE_BACKLASH_WHEN_PROBING)
|
||||||
SERIAL_ECHOPGM(" Average measured backlash (mm):");
|
SERIAL_ECHOPGM(" Average measured backlash (mm):");
|
||||||
if (backlash.has_any_measurement()) {
|
if (backlash.has_any_measurement()) {
|
||||||
LOOP_LINEAR_AXES(a) if (axis_can_calibrate(a) && backlash.has_measurement(AxisEnum(a))) {
|
LOOP_NUM_AXES(a) if (axis_can_calibrate(a) && backlash.has_measurement(AxisEnum(a))) {
|
||||||
SERIAL_CHAR(' ', AXIS_CHAR(a));
|
SERIAL_ECHOPGM_P((PGM_P)pgm_read_ptr(&SP_AXIS_STR[a]), backlash.get_measurement((AxisEnum)a));
|
||||||
SERIAL_ECHO(backlash.get_measurement(AxisEnum(a)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -120,7 +111,7 @@ void GcodeSuite::M425_report(const bool forReplay/*=true*/) {
|
|||||||
#ifdef BACKLASH_SMOOTHING_MM
|
#ifdef BACKLASH_SMOOTHING_MM
|
||||||
, PSTR(" S"), LINEAR_UNIT(backlash.get_smoothing_mm())
|
, PSTR(" S"), LINEAR_UNIT(backlash.get_smoothing_mm())
|
||||||
#endif
|
#endif
|
||||||
, LIST_N(DOUBLE(LINEAR_AXES),
|
, LIST_N(DOUBLE(NUM_AXES),
|
||||||
SP_X_STR, LINEAR_UNIT(backlash.get_distance_mm(X_AXIS)),
|
SP_X_STR, LINEAR_UNIT(backlash.get_distance_mm(X_AXIS)),
|
||||||
SP_Y_STR, LINEAR_UNIT(backlash.get_distance_mm(Y_AXIS)),
|
SP_Y_STR, LINEAR_UNIT(backlash.get_distance_mm(Y_AXIS)),
|
||||||
SP_Z_STR, LINEAR_UNIT(backlash.get_distance_mm(Z_AXIS)),
|
SP_Z_STR, LINEAR_UNIT(backlash.get_distance_mm(Z_AXIS)),
|
||||||
|
@@ -86,7 +86,7 @@
|
|||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
*
|
*
|
||||||
* S[segments-per-second] - Segments-per-second
|
* S[segments] - Segments-per-second
|
||||||
*
|
*
|
||||||
* Without NO_WORKSPACE_OFFSETS:
|
* Without NO_WORKSPACE_OFFSETS:
|
||||||
*
|
*
|
||||||
@@ -152,18 +152,35 @@
|
|||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
*
|
*
|
||||||
* S[segments-per-second] - Segments-per-second
|
* S[segments] - Segments-per-second
|
||||||
|
* L[left] - Work area minimum X
|
||||||
|
* R[right] - Work area maximum X
|
||||||
|
* T[top] - Work area maximum Y
|
||||||
|
* B[bottom] - Work area minimum Y
|
||||||
|
* H[length] - Maximum belt length
|
||||||
*/
|
*/
|
||||||
void GcodeSuite::M665() {
|
void GcodeSuite::M665() {
|
||||||
if (parser.seenval('S'))
|
if (!parser.seen_any()) return M665_report();
|
||||||
segments_per_second = parser.value_float();
|
if (parser.seenval('S')) segments_per_second = parser.value_float();
|
||||||
else
|
if (parser.seenval('L')) draw_area_min.x = parser.value_linear_units();
|
||||||
M665_report();
|
if (parser.seenval('R')) draw_area_max.x = parser.value_linear_units();
|
||||||
|
if (parser.seenval('T')) draw_area_max.y = parser.value_linear_units();
|
||||||
|
if (parser.seenval('B')) draw_area_min.y = parser.value_linear_units();
|
||||||
|
if (parser.seenval('H')) polargraph_max_belt_len = parser.value_linear_units();
|
||||||
|
draw_area_size.x = draw_area_max.x - draw_area_min.x;
|
||||||
|
draw_area_size.y = draw_area_max.y - draw_area_min.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GcodeSuite::M665_report(const bool forReplay/*=true*/) {
|
void GcodeSuite::M665_report(const bool forReplay/*=true*/) {
|
||||||
report_heading_etc(forReplay, F(STR_POLARGRAPH_SETTINGS " (" STR_S_SEG_PER_SEC ")"));
|
report_heading_etc(forReplay, F(STR_POLARGRAPH_SETTINGS));
|
||||||
SERIAL_ECHOLNPGM(" M665 S", segments_per_second);
|
SERIAL_ECHOLNPGM_P(
|
||||||
|
PSTR(" M665 S"), LINEAR_UNIT(segments_per_second),
|
||||||
|
PSTR(" L"), LINEAR_UNIT(draw_area_min.x),
|
||||||
|
PSTR(" R"), LINEAR_UNIT(draw_area_max.x),
|
||||||
|
SP_T_STR, LINEAR_UNIT(draw_area_max.y),
|
||||||
|
SP_B_STR, LINEAR_UNIT(draw_area_min.y),
|
||||||
|
PSTR(" H"), LINEAR_UNIT(polargraph_max_belt_len)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -44,8 +44,8 @@
|
|||||||
void GcodeSuite::M666() {
|
void GcodeSuite::M666() {
|
||||||
DEBUG_SECTION(log_M666, "M666", DEBUGGING(LEVELING));
|
DEBUG_SECTION(log_M666, "M666", DEBUGGING(LEVELING));
|
||||||
bool is_err = false, is_set = false;
|
bool is_err = false, is_set = false;
|
||||||
LOOP_LINEAR_AXES(i) {
|
LOOP_NUM_AXES(i) {
|
||||||
if (parser.seen(AXIS_CHAR(i))) {
|
if (parser.seenval(AXIS_CHAR(i))) {
|
||||||
is_set = true;
|
is_set = true;
|
||||||
const float v = parser.value_linear_units();
|
const float v = parser.value_linear_units();
|
||||||
if (v > 0)
|
if (v > 0)
|
||||||
|
@@ -122,7 +122,7 @@
|
|||||||
* S<percent> : Speed factor percentage.
|
* S<percent> : Speed factor percentage.
|
||||||
*/
|
*/
|
||||||
void GcodeSuite::M201() {
|
void GcodeSuite::M201() {
|
||||||
if (!parser.seen("T" LOGICAL_AXES_STRING TERN_(XY_FREQUENCY_LIMIT, "FS")))
|
if (!parser.seen("T" STR_AXES_LOGICAL TERN_(XY_FREQUENCY_LIMIT, "FS")))
|
||||||
return M201_report();
|
return M201_report();
|
||||||
|
|
||||||
const int8_t target_extruder = get_target_extruder_from_command();
|
const int8_t target_extruder = get_target_extruder_from_command();
|
||||||
@@ -134,9 +134,9 @@ void GcodeSuite::M201() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
LOOP_LOGICAL_AXES(i) {
|
LOOP_LOGICAL_AXES(i) {
|
||||||
if (parser.seenval(axis_codes[i])) {
|
if (parser.seenval(AXIS_CHAR(i))) {
|
||||||
const uint8_t a = TERN(HAS_EXTRUDERS, (i == E_AXIS ? uint8_t(E_AXIS_N(target_extruder)) : i), i);
|
const AxisEnum a = TERN(HAS_EXTRUDERS, (i == E_AXIS ? E_AXIS_N(target_extruder) : (AxisEnum)i), (AxisEnum)i);
|
||||||
planner.set_max_acceleration(a, parser.value_axis_units((AxisEnum)a));
|
planner.set_max_acceleration(a, parser.value_axis_units(a));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -144,7 +144,7 @@ void GcodeSuite::M201() {
|
|||||||
void GcodeSuite::M201_report(const bool forReplay/*=true*/) {
|
void GcodeSuite::M201_report(const bool forReplay/*=true*/) {
|
||||||
report_heading_etc(forReplay, F(STR_MAX_ACCELERATION));
|
report_heading_etc(forReplay, F(STR_MAX_ACCELERATION));
|
||||||
SERIAL_ECHOLNPGM_P(
|
SERIAL_ECHOLNPGM_P(
|
||||||
LIST_N(DOUBLE(LINEAR_AXES),
|
LIST_N(DOUBLE(NUM_AXES),
|
||||||
PSTR(" M201 X"), LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[X_AXIS]),
|
PSTR(" M201 X"), LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[X_AXIS]),
|
||||||
SP_Y_STR, LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[Y_AXIS]),
|
SP_Y_STR, LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[Y_AXIS]),
|
||||||
SP_Z_STR, LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[Z_AXIS]),
|
SP_Z_STR, LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[Z_AXIS]),
|
||||||
@@ -173,23 +173,23 @@ void GcodeSuite::M201_report(const bool forReplay/*=true*/) {
|
|||||||
* With multiple extruders use T to specify which one.
|
* With multiple extruders use T to specify which one.
|
||||||
*/
|
*/
|
||||||
void GcodeSuite::M203() {
|
void GcodeSuite::M203() {
|
||||||
if (!parser.seen("T" LOGICAL_AXES_STRING))
|
if (!parser.seen("T" STR_AXES_LOGICAL))
|
||||||
return M203_report();
|
return M203_report();
|
||||||
|
|
||||||
const int8_t target_extruder = get_target_extruder_from_command();
|
const int8_t target_extruder = get_target_extruder_from_command();
|
||||||
if (target_extruder < 0) return;
|
if (target_extruder < 0) return;
|
||||||
|
|
||||||
LOOP_LOGICAL_AXES(i)
|
LOOP_LOGICAL_AXES(i)
|
||||||
if (parser.seenval(axis_codes[i])) {
|
if (parser.seenval(AXIS_CHAR(i))) {
|
||||||
const uint8_t a = TERN(HAS_EXTRUDERS, (i == E_AXIS ? uint8_t(E_AXIS_N(target_extruder)) : i), i);
|
const AxisEnum a = TERN(HAS_EXTRUDERS, (i == E_AXIS ? E_AXIS_N(target_extruder) : (AxisEnum)i), (AxisEnum)i);
|
||||||
planner.set_max_feedrate(a, parser.value_axis_units((AxisEnum)a));
|
planner.set_max_feedrate(a, parser.value_axis_units(a));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GcodeSuite::M203_report(const bool forReplay/*=true*/) {
|
void GcodeSuite::M203_report(const bool forReplay/*=true*/) {
|
||||||
report_heading_etc(forReplay, F(STR_MAX_FEEDRATES));
|
report_heading_etc(forReplay, F(STR_MAX_FEEDRATES));
|
||||||
SERIAL_ECHOLNPGM_P(
|
SERIAL_ECHOLNPGM_P(
|
||||||
LIST_N(DOUBLE(LINEAR_AXES),
|
LIST_N(DOUBLE(NUM_AXES),
|
||||||
PSTR(" M203 X"), LINEAR_UNIT(planner.settings.max_feedrate_mm_s[X_AXIS]),
|
PSTR(" M203 X"), LINEAR_UNIT(planner.settings.max_feedrate_mm_s[X_AXIS]),
|
||||||
SP_Y_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[Y_AXIS]),
|
SP_Y_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[Y_AXIS]),
|
||||||
SP_Z_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[Z_AXIS]),
|
SP_Z_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[Z_AXIS]),
|
||||||
@@ -298,7 +298,7 @@ void GcodeSuite::M205_report(const bool forReplay/*=true*/) {
|
|||||||
"Advanced (B<min_segment_time_us> S<min_feedrate> T<min_travel_feedrate>"
|
"Advanced (B<min_segment_time_us> S<min_feedrate> T<min_travel_feedrate>"
|
||||||
TERN_(HAS_JUNCTION_DEVIATION, " J<junc_dev>")
|
TERN_(HAS_JUNCTION_DEVIATION, " J<junc_dev>")
|
||||||
#if HAS_CLASSIC_JERK
|
#if HAS_CLASSIC_JERK
|
||||||
LINEAR_AXIS_GANG(
|
NUM_AXIS_GANG(
|
||||||
" X<max_jerk>", " Y<max_jerk>", " Z<max_jerk>",
|
" X<max_jerk>", " Y<max_jerk>", " Z<max_jerk>",
|
||||||
" " STR_I "<max_jerk>", " " STR_J "<max_jerk>", " " STR_K "<max_jerk>"
|
" " STR_I "<max_jerk>", " " STR_J "<max_jerk>", " " STR_K "<max_jerk>"
|
||||||
)
|
)
|
||||||
@@ -314,7 +314,7 @@ void GcodeSuite::M205_report(const bool forReplay/*=true*/) {
|
|||||||
, PSTR(" J"), LINEAR_UNIT(planner.junction_deviation_mm)
|
, PSTR(" J"), LINEAR_UNIT(planner.junction_deviation_mm)
|
||||||
#endif
|
#endif
|
||||||
#if HAS_CLASSIC_JERK
|
#if HAS_CLASSIC_JERK
|
||||||
, LIST_N(DOUBLE(LINEAR_AXES),
|
, LIST_N(DOUBLE(NUM_AXES),
|
||||||
SP_X_STR, LINEAR_UNIT(planner.max_jerk.x),
|
SP_X_STR, LINEAR_UNIT(planner.max_jerk.x),
|
||||||
SP_Y_STR, LINEAR_UNIT(planner.max_jerk.y),
|
SP_Y_STR, LINEAR_UNIT(planner.max_jerk.y),
|
||||||
SP_Z_STR, LINEAR_UNIT(planner.max_jerk.z),
|
SP_Z_STR, LINEAR_UNIT(planner.max_jerk.z),
|
||||||
|
@@ -50,9 +50,9 @@
|
|||||||
* W[linear] 0/1 Enable park & Z Raise
|
* W[linear] 0/1 Enable park & Z Raise
|
||||||
* X[linear] Park X (Requires TOOLCHANGE_PARK)
|
* X[linear] Park X (Requires TOOLCHANGE_PARK)
|
||||||
* Y[linear] Park Y (Requires TOOLCHANGE_PARK)
|
* Y[linear] Park Y (Requires TOOLCHANGE_PARK)
|
||||||
* I[linear] Park I (Requires TOOLCHANGE_PARK and LINEAR_AXES >= 4)
|
* I[linear] Park I (Requires TOOLCHANGE_PARK and NUM_AXES >= 4)
|
||||||
* J[linear] Park J (Requires TOOLCHANGE_PARK and LINEAR_AXES >= 5)
|
* J[linear] Park J (Requires TOOLCHANGE_PARK and NUM_AXES >= 5)
|
||||||
* K[linear] Park K (Requires TOOLCHANGE_PARK and LINEAR_AXES >= 6)
|
* K[linear] Park K (Requires TOOLCHANGE_PARK and NUM_AXES >= 6)
|
||||||
* Z[linear] Z Raise
|
* Z[linear] Z Raise
|
||||||
* F[speed] Fan Speed 0-255
|
* F[speed] Fan Speed 0-255
|
||||||
* D[seconds] Fan time
|
* D[seconds] Fan time
|
||||||
@@ -174,14 +174,12 @@ void GcodeSuite::M217_report(const bool forReplay/*=true*/) {
|
|||||||
#if HAS_Y_AXIS
|
#if HAS_Y_AXIS
|
||||||
, SP_Y_STR, LINEAR_UNIT(toolchange_settings.change_point.y)
|
, SP_Y_STR, LINEAR_UNIT(toolchange_settings.change_point.y)
|
||||||
#endif
|
#endif
|
||||||
#if HAS_I_AXIS
|
#if SECONDARY_AXES >= 1
|
||||||
, SP_I_STR, LINEAR_UNIT(toolchange_settings.change_point.i)
|
, LIST_N(DOUBLE(SECONDARY_AXES),
|
||||||
#endif
|
SP_I_STR, I_AXIS_UNIT(toolchange_settings.change_point.i),
|
||||||
#if HAS_J_AXIS
|
SP_J_STR, J_AXIS_UNIT(toolchange_settings.change_point.j),
|
||||||
, SP_J_STR, LINEAR_UNIT(toolchange_settings.change_point.j)
|
SP_K_STR, K_AXIS_UNIT(toolchange_settings.change_point.k)
|
||||||
#endif
|
)
|
||||||
#if HAS_K_AXIS
|
|
||||||
, SP_K_STR, LINEAR_UNIT(toolchange_settings.change_point.k)
|
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -47,8 +47,8 @@ void GcodeSuite::M281() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (parser.seen('L')) servo_angles[servo_index][0] = parser.value_int();
|
if (parser.seenval('L')) servo_angles[servo_index][0] = parser.value_int();
|
||||||
if (parser.seen('U')) servo_angles[servo_index][1] = parser.value_int();
|
if (parser.seenval('U')) servo_angles[servo_index][1] = parser.value_int();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
SERIAL_ERROR_MSG("Servo ", servo_index, " out of range");
|
SERIAL_ERROR_MSG("Servo ", servo_index, " out of range");
|
||||||
|
@@ -36,9 +36,9 @@
|
|||||||
*/
|
*/
|
||||||
void GcodeSuite::M304() {
|
void GcodeSuite::M304() {
|
||||||
if (!parser.seen("PID")) return M304_report();
|
if (!parser.seen("PID")) return M304_report();
|
||||||
if (parser.seen('P')) thermalManager.temp_bed.pid.Kp = parser.value_float();
|
if (parser.seenval('P')) thermalManager.temp_bed.pid.Kp = parser.value_float();
|
||||||
if (parser.seen('I')) thermalManager.temp_bed.pid.Ki = scalePID_i(parser.value_float());
|
if (parser.seenval('I')) thermalManager.temp_bed.pid.Ki = scalePID_i(parser.value_float());
|
||||||
if (parser.seen('D')) thermalManager.temp_bed.pid.Kd = scalePID_d(parser.value_float());
|
if (parser.seenval('D')) thermalManager.temp_bed.pid.Kd = scalePID_d(parser.value_float());
|
||||||
}
|
}
|
||||||
|
|
||||||
void GcodeSuite::M304_report(const bool forReplay/*=true*/) {
|
void GcodeSuite::M304_report(const bool forReplay/*=true*/) {
|
||||||
|
@@ -52,19 +52,19 @@ void GcodeSuite::M305() {
|
|||||||
if (t_index >= (USER_THERMISTORS) || (do_set && t_index < 0))
|
if (t_index >= (USER_THERMISTORS) || (do_set && t_index < 0))
|
||||||
SERIAL_ECHO_MSG("!Invalid index. (0 <= P <= ", USER_THERMISTORS - 1, ")");
|
SERIAL_ECHO_MSG("!Invalid index. (0 <= P <= ", USER_THERMISTORS - 1, ")");
|
||||||
else if (do_set) {
|
else if (do_set) {
|
||||||
if (parser.seen('R')) // Pullup resistor value
|
if (parser.seenval('R')) // Pullup resistor value
|
||||||
if (!thermalManager.set_pull_up_res(t_index, parser.value_float()))
|
if (!thermalManager.set_pull_up_res(t_index, parser.value_float()))
|
||||||
SERIAL_ECHO_MSG("!Invalid series resistance. (0 < R < 1000000)");
|
SERIAL_ECHO_MSG("!Invalid series resistance. (0 < R < 1000000)");
|
||||||
|
|
||||||
if (parser.seen('T')) // Resistance at 25C
|
if (parser.seenval('T')) // Resistance at 25C
|
||||||
if (!thermalManager.set_res25(t_index, parser.value_float()))
|
if (!thermalManager.set_res25(t_index, parser.value_float()))
|
||||||
SERIAL_ECHO_MSG("!Invalid 25C resistance. (0 < T < 10000000)");
|
SERIAL_ECHO_MSG("!Invalid 25C resistance. (0 < T < 10000000)");
|
||||||
|
|
||||||
if (parser.seen('B')) // Beta value
|
if (parser.seenval('B')) // Beta value
|
||||||
if (!thermalManager.set_beta(t_index, parser.value_float()))
|
if (!thermalManager.set_beta(t_index, parser.value_float()))
|
||||||
SERIAL_ECHO_MSG("!Invalid beta. (0 < B < 1000000)");
|
SERIAL_ECHO_MSG("!Invalid beta. (0 < B < 1000000)");
|
||||||
|
|
||||||
if (parser.seen('C')) // Steinhart-Hart C coefficient
|
if (parser.seenval('C')) // Steinhart-Hart C coefficient
|
||||||
if (!thermalManager.set_sh_coeff(t_index, parser.value_float()))
|
if (!thermalManager.set_sh_coeff(t_index, parser.value_float()))
|
||||||
SERIAL_ECHO_MSG("!Invalid Steinhart-Hart C coeff. (-0.01 < C < +0.01)");
|
SERIAL_ECHO_MSG("!Invalid Steinhart-Hart C coeff. (-0.01 < C < +0.01)");
|
||||||
} // If not setting then report parameters
|
} // If not setting then report parameters
|
||||||
|
@@ -198,10 +198,10 @@ inline void servo_probe_test() {
|
|||||||
uint8_t i = 0;
|
uint8_t i = 0;
|
||||||
SERIAL_ECHOLNPGM(". Deploy & stow 4 times");
|
SERIAL_ECHOLNPGM(". Deploy & stow 4 times");
|
||||||
do {
|
do {
|
||||||
MOVE_SERVO(probe_index, servo_angles[Z_PROBE_SERVO_NR][0]); // Deploy
|
servo[probe_index].move(servo_angles[Z_PROBE_SERVO_NR][0]); // Deploy
|
||||||
safe_delay(500);
|
safe_delay(500);
|
||||||
deploy_state = READ(PROBE_TEST_PIN);
|
deploy_state = READ(PROBE_TEST_PIN);
|
||||||
MOVE_SERVO(probe_index, servo_angles[Z_PROBE_SERVO_NR][1]); // Stow
|
servo[probe_index].move(servo_angles[Z_PROBE_SERVO_NR][1]); // Stow
|
||||||
safe_delay(500);
|
safe_delay(500);
|
||||||
stow_state = READ(PROBE_TEST_PIN);
|
stow_state = READ(PROBE_TEST_PIN);
|
||||||
} while (++i < 4);
|
} while (++i < 4);
|
||||||
@@ -226,7 +226,7 @@ inline void servo_probe_test() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ask the user for a trigger event and measure the pulse width.
|
// Ask the user for a trigger event and measure the pulse width.
|
||||||
MOVE_SERVO(probe_index, servo_angles[Z_PROBE_SERVO_NR][0]); // Deploy
|
servo[probe_index].move(servo_angles[Z_PROBE_SERVO_NR][0]); // Deploy
|
||||||
safe_delay(500);
|
safe_delay(500);
|
||||||
SERIAL_ECHOLNPGM("** Please trigger probe within 30 sec **");
|
SERIAL_ECHOLNPGM("** Please trigger probe within 30 sec **");
|
||||||
uint16_t probe_counter = 0;
|
uint16_t probe_counter = 0;
|
||||||
@@ -256,7 +256,7 @@ inline void servo_probe_test() {
|
|||||||
}
|
}
|
||||||
else SERIAL_ECHOLNPGM("FAIL: Noise detected - please re-run test");
|
else SERIAL_ECHOLNPGM("FAIL: Noise detected - please re-run test");
|
||||||
|
|
||||||
MOVE_SERVO(probe_index, servo_angles[Z_PROBE_SERVO_NR][1]); // Stow
|
servo[probe_index].move(servo_angles[Z_PROBE_SERVO_NR][1]); // Stow
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -25,7 +25,7 @@
|
|||||||
#if ENABLED(SD_ABORT_ON_ENDSTOP_HIT)
|
#if ENABLED(SD_ABORT_ON_ENDSTOP_HIT)
|
||||||
|
|
||||||
#include "../gcode.h"
|
#include "../gcode.h"
|
||||||
#include "../../module/stepper.h"
|
#include "../../module/planner.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* M540: Set whether SD card print should abort on endstop hit (M540 S<0|1>)
|
* M540: Set whether SD card print should abort on endstop hit (M540 S<0|1>)
|
||||||
|
@@ -43,11 +43,11 @@ void GcodeSuite::M92() {
|
|||||||
if (target_extruder < 0) return;
|
if (target_extruder < 0) return;
|
||||||
|
|
||||||
// No arguments? Show M92 report.
|
// No arguments? Show M92 report.
|
||||||
if (!parser.seen(LOGICAL_AXES_STRING TERN_(MAGIC_NUMBERS_GCODE, "HL")))
|
if (!parser.seen(STR_AXES_LOGICAL TERN_(MAGIC_NUMBERS_GCODE, "HL")))
|
||||||
return M92_report(true, target_extruder);
|
return M92_report(true, target_extruder);
|
||||||
|
|
||||||
LOOP_LOGICAL_AXES(i) {
|
LOOP_LOGICAL_AXES(i) {
|
||||||
if (parser.seenval(axis_codes[i])) {
|
if (parser.seenval(AXIS_CHAR(i))) {
|
||||||
if (TERN1(HAS_EXTRUDERS, i != E_AXIS))
|
if (TERN1(HAS_EXTRUDERS, i != E_AXIS))
|
||||||
planner.settings.axis_steps_per_mm[i] = parser.value_per_axis_units((AxisEnum)i);
|
planner.settings.axis_steps_per_mm[i] = parser.value_per_axis_units((AxisEnum)i);
|
||||||
else {
|
else {
|
||||||
@@ -92,7 +92,7 @@ void GcodeSuite::M92() {
|
|||||||
|
|
||||||
void GcodeSuite::M92_report(const bool forReplay/*=true*/, const int8_t e/*=-1*/) {
|
void GcodeSuite::M92_report(const bool forReplay/*=true*/, const int8_t e/*=-1*/) {
|
||||||
report_heading_etc(forReplay, F(STR_STEPS_PER_UNIT));
|
report_heading_etc(forReplay, F(STR_STEPS_PER_UNIT));
|
||||||
SERIAL_ECHOPGM_P(LIST_N(DOUBLE(LINEAR_AXES),
|
SERIAL_ECHOPGM_P(LIST_N(DOUBLE(NUM_AXES),
|
||||||
PSTR(" M92 X"), LINEAR_UNIT(planner.settings.axis_steps_per_mm[X_AXIS]),
|
PSTR(" M92 X"), LINEAR_UNIT(planner.settings.axis_steps_per_mm[X_AXIS]),
|
||||||
SP_Y_STR, LINEAR_UNIT(planner.settings.axis_steps_per_mm[Y_AXIS]),
|
SP_Y_STR, LINEAR_UNIT(planner.settings.axis_steps_per_mm[Y_AXIS]),
|
||||||
SP_Z_STR, LINEAR_UNIT(planner.settings.axis_steps_per_mm[Z_AXIS]),
|
SP_Z_STR, LINEAR_UNIT(planner.settings.axis_steps_per_mm[Z_AXIS]),
|
||||||
|
@@ -49,7 +49,7 @@ void GcodeSuite::M111() {
|
|||||||
LOOP_L_N(i, COUNT(debug_strings)) {
|
LOOP_L_N(i, COUNT(debug_strings)) {
|
||||||
if (TEST(marlin_debug_flags, i)) {
|
if (TEST(marlin_debug_flags, i)) {
|
||||||
if (comma++) SERIAL_CHAR(',');
|
if (comma++) SERIAL_CHAR(',');
|
||||||
SERIAL_ECHOPGM_P((char*)pgm_read_ptr(&debug_strings[i]));
|
SERIAL_ECHOPGM_P((PGM_P)pgm_read_ptr(&debug_strings[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -23,6 +23,8 @@
|
|||||||
#include "../gcode.h"
|
#include "../gcode.h"
|
||||||
#include "../../MarlinCore.h" // for stepper_inactive_time, disable_e_steppers
|
#include "../../MarlinCore.h" // for stepper_inactive_time, disable_e_steppers
|
||||||
#include "../../lcd/marlinui.h"
|
#include "../../lcd/marlinui.h"
|
||||||
|
#include "../../module/motion.h" // for e_axis_mask
|
||||||
|
#include "../../module/planner.h"
|
||||||
#include "../../module/stepper.h"
|
#include "../../module/stepper.h"
|
||||||
|
|
||||||
#if ENABLED(AUTO_BED_LEVELING_UBL)
|
#if ENABLED(AUTO_BED_LEVELING_UBL)
|
||||||
@@ -43,10 +45,10 @@ inline stepper_flags_t selected_axis_bits() {
|
|||||||
selected.bits = _BV(INDEX_OF_AXIS(E_AXIS, e));
|
selected.bits = _BV(INDEX_OF_AXIS(E_AXIS, e));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
selected.bits = selected.e_bits();
|
selected.bits = e_axis_mask;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
selected.bits |= LINEAR_AXIS_GANG(
|
selected.bits |= NUM_AXIS_GANG(
|
||||||
(parser.seen_test('X') << X_AXIS),
|
(parser.seen_test('X') << X_AXIS),
|
||||||
| (parser.seen_test('Y') << Y_AXIS),
|
| (parser.seen_test('Y') << Y_AXIS),
|
||||||
| (parser.seen_test('Z') << Z_AXIS),
|
| (parser.seen_test('Z') << Z_AXIS),
|
||||||
@@ -69,10 +71,10 @@ void do_enable(const stepper_flags_t to_enable) {
|
|||||||
ena_mask_t also_enabled = 0; // Track steppers enabled due to overlap
|
ena_mask_t also_enabled = 0; // Track steppers enabled due to overlap
|
||||||
|
|
||||||
// Enable all flagged axes
|
// Enable all flagged axes
|
||||||
LOOP_LINEAR_AXES(a) {
|
LOOP_NUM_AXES(a) {
|
||||||
if (TEST(shall_enable, a)) {
|
if (TEST(shall_enable, a)) {
|
||||||
stepper.enable_axis(AxisEnum(a)); // Mark and enable the requested axis
|
stepper.enable_axis(AxisEnum(a)); // Mark and enable the requested axis
|
||||||
DEBUG_ECHOLNPGM("Enabled ", axis_codes[a], " (", a, ") with overlap ", hex_word(enable_overlap[a]), " ... Enabled: ", hex_word(stepper.axis_enabled.bits));
|
DEBUG_ECHOLNPGM("Enabled ", AXIS_CHAR(a), " (", a, ") with overlap ", hex_word(enable_overlap[a]), " ... Enabled: ", hex_word(stepper.axis_enabled.bits));
|
||||||
also_enabled |= enable_overlap[a];
|
also_enabled |= enable_overlap[a];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -89,7 +91,7 @@ void do_enable(const stepper_flags_t to_enable) {
|
|||||||
|
|
||||||
if ((also_enabled &= ~(shall_enable | was_enabled))) {
|
if ((also_enabled &= ~(shall_enable | was_enabled))) {
|
||||||
SERIAL_CHAR('(');
|
SERIAL_CHAR('(');
|
||||||
LOOP_LINEAR_AXES(a) if (TEST(also_enabled, a)) SERIAL_CHAR(axis_codes[a], ' ');
|
LOOP_NUM_AXES(a) if (TEST(also_enabled, a)) SERIAL_CHAR(AXIS_CHAR(a), ' ');
|
||||||
#if HAS_EXTRUDERS
|
#if HAS_EXTRUDERS
|
||||||
#define _EN_ALSO(N) if (TEST(also_enabled, INDEX_OF_AXIS(E_AXIS, N))) SERIAL_CHAR('E', '0' + N, ' ');
|
#define _EN_ALSO(N) if (TEST(also_enabled, INDEX_OF_AXIS(E_AXIS, N))) SERIAL_CHAR('E', '0' + N, ' ');
|
||||||
REPEAT(EXTRUDERS, _EN_ALSO)
|
REPEAT(EXTRUDERS, _EN_ALSO)
|
||||||
@@ -125,14 +127,8 @@ void GcodeSuite::M17() {
|
|||||||
stepper.enable_e_steppers();
|
stepper.enable_e_steppers();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
LINEAR_AXIS_CODE(
|
LOOP_NUM_AXES(a)
|
||||||
if (parser.seen_test('X')) stepper.enable_axis(X_AXIS),
|
if (parser.seen_test(AXIS_CHAR(a))) stepper.enable_axis((AxisEnum)a);
|
||||||
if (parser.seen_test('Y')) stepper.enable_axis(Y_AXIS),
|
|
||||||
if (parser.seen_test('Z')) stepper.enable_axis(Z_AXIS),
|
|
||||||
if (parser.seen_test(AXIS4_NAME)) stepper.enable_axis(I_AXIS),
|
|
||||||
if (parser.seen_test(AXIS5_NAME)) stepper.enable_axis(J_AXIS),
|
|
||||||
if (parser.seen_test(AXIS6_NAME)) stepper.enable_axis(K_AXIS)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -149,9 +145,9 @@ void try_to_disable(const stepper_flags_t to_disable) {
|
|||||||
if (!still_enabled) return;
|
if (!still_enabled) return;
|
||||||
|
|
||||||
// Attempt to disable all flagged axes
|
// Attempt to disable all flagged axes
|
||||||
LOOP_LINEAR_AXES(a)
|
LOOP_NUM_AXES(a)
|
||||||
if (TEST(to_disable.bits, a)) {
|
if (TEST(to_disable.bits, a)) {
|
||||||
DEBUG_ECHOPGM("Try to disable ", axis_codes[a], " (", a, ") with overlap ", hex_word(enable_overlap[a]), " ... ");
|
DEBUG_ECHOPGM("Try to disable ", AXIS_CHAR(a), " (", a, ") with overlap ", hex_word(enable_overlap[a]), " ... ");
|
||||||
if (stepper.disable_axis(AxisEnum(a))) { // Mark the requested axis and request to disable
|
if (stepper.disable_axis(AxisEnum(a))) { // Mark the requested axis and request to disable
|
||||||
DEBUG_ECHOPGM("OK");
|
DEBUG_ECHOPGM("OK");
|
||||||
still_enabled &= ~(_BV(a) | enable_overlap[a]); // If actually disabled, clear one or more tracked bits
|
still_enabled &= ~(_BV(a) | enable_overlap[a]); // If actually disabled, clear one or more tracked bits
|
||||||
@@ -178,7 +174,7 @@ void try_to_disable(const stepper_flags_t to_disable) {
|
|||||||
|
|
||||||
auto overlap_warning = [](const ena_mask_t axis_bits) {
|
auto overlap_warning = [](const ena_mask_t axis_bits) {
|
||||||
SERIAL_ECHOPGM(" not disabled. Shared with");
|
SERIAL_ECHOPGM(" not disabled. Shared with");
|
||||||
LOOP_LINEAR_AXES(a) if (TEST(axis_bits, a)) SERIAL_CHAR(' ', axis_codes[a]);
|
LOOP_NUM_AXES(a) if (TEST(axis_bits, a)) SERIAL_ECHOPGM_P((PGM_P)pgm_read_ptr(&SP_AXIS_STR[a]));
|
||||||
#if HAS_EXTRUDERS
|
#if HAS_EXTRUDERS
|
||||||
#define _EN_STILLON(N) if (TEST(axis_bits, INDEX_OF_AXIS(E_AXIS, N))) SERIAL_CHAR(' ', 'E', '0' + N);
|
#define _EN_STILLON(N) if (TEST(axis_bits, INDEX_OF_AXIS(E_AXIS, N))) SERIAL_CHAR(' ', 'E', '0' + N);
|
||||||
REPEAT(EXTRUDERS, _EN_STILLON)
|
REPEAT(EXTRUDERS, _EN_STILLON)
|
||||||
@@ -187,9 +183,9 @@ void try_to_disable(const stepper_flags_t to_disable) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// If any of the requested axes are still enabled, give a warning
|
// If any of the requested axes are still enabled, give a warning
|
||||||
LOOP_LINEAR_AXES(a) {
|
LOOP_NUM_AXES(a) {
|
||||||
if (TEST(still_enabled, a)) {
|
if (TEST(still_enabled, a)) {
|
||||||
SERIAL_CHAR(axis_codes[a]);
|
SERIAL_CHAR(AXIS_CHAR(a));
|
||||||
overlap_warning(stepper.axis_enabled.bits & enable_overlap[a]);
|
overlap_warning(stepper.axis_enabled.bits & enable_overlap[a]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -238,14 +234,8 @@ void GcodeSuite::M18_M84() {
|
|||||||
stepper.disable_e_steppers();
|
stepper.disable_e_steppers();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
LINEAR_AXIS_CODE(
|
LOOP_NUM_AXES(a)
|
||||||
if (parser.seen_test('X')) stepper.disable_axis(X_AXIS),
|
if (parser.seen_test(AXIS_CHAR(a))) stepper.disable_axis((AxisEnum)a);
|
||||||
if (parser.seen_test('Y')) stepper.disable_axis(Y_AXIS),
|
|
||||||
if (parser.seen_test('Z')) stepper.disable_axis(Z_AXIS),
|
|
||||||
if (parser.seen_test(AXIS4_NAME)) stepper.disable_axis(I_AXIS),
|
|
||||||
if (parser.seen_test(AXIS5_NAME)) stepper.disable_axis(J_AXIS),
|
|
||||||
if (parser.seen_test(AXIS6_NAME)) stepper.disable_axis(K_AXIS)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
#include "../gcode.h"
|
#include "../gcode.h"
|
||||||
#include "../../MarlinCore.h" // for pin_is_protected and idle()
|
#include "../../MarlinCore.h" // for pin_is_protected and idle()
|
||||||
#include "../../module/stepper.h"
|
#include "../../module/planner.h"
|
||||||
|
|
||||||
void protected_pin_err();
|
void protected_pin_err();
|
||||||
|
|
||||||
|
@@ -48,7 +48,7 @@ void GcodeSuite::M280() {
|
|||||||
const int anew = parser.value_int();
|
const int anew = parser.value_int();
|
||||||
if (anew >= 0) {
|
if (anew >= 0) {
|
||||||
#if ENABLED(POLARGRAPH)
|
#if ENABLED(POLARGRAPH)
|
||||||
if (parser.seen('T')) { // (ms) Total duration of servo move
|
if (parser.seenval('T')) { // (ms) Total duration of servo move
|
||||||
const int16_t t = constrain(parser.value_int(), 0, 10000);
|
const int16_t t = constrain(parser.value_int(), 0, 10000);
|
||||||
const int aold = servo[servo_index].read();
|
const int aold = servo[servo_index].read();
|
||||||
millis_t now = millis();
|
millis_t now = millis();
|
||||||
@@ -56,14 +56,14 @@ void GcodeSuite::M280() {
|
|||||||
while (PENDING(now, end)) {
|
while (PENDING(now, end)) {
|
||||||
safe_delay(50);
|
safe_delay(50);
|
||||||
now = _MIN(millis(), end);
|
now = _MIN(millis(), end);
|
||||||
MOVE_SERVO(servo_index, LROUND(aold + (anew - aold) * (float(now - start) / t)));
|
servo[servo_index].move(LROUND(aold + (anew - aold) * (float(now - start) / t)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // POLARGRAPH
|
#endif // POLARGRAPH
|
||||||
MOVE_SERVO(servo_index, anew);
|
servo[servo_index].move(anew);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
DETACH_SERVO(servo_index);
|
servo[servo_index].detach();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
SERIAL_ECHO_MSG(" Servo ", servo_index, ": ", servo[servo_index].read());
|
SERIAL_ECHO_MSG(" Servo ", servo_index, ": ", servo[servo_index].read());
|
||||||
|
@@ -36,7 +36,7 @@ void GcodeSuite::M282() {
|
|||||||
|
|
||||||
const int servo_index = parser.value_int();
|
const int servo_index = parser.value_int();
|
||||||
if (WITHIN(servo_index, 0, NUM_SERVOS - 1))
|
if (WITHIN(servo_index, 0, NUM_SERVOS - 1))
|
||||||
DETACH_SERVO(servo_index);
|
servo[servo_index].detach();
|
||||||
else
|
else
|
||||||
SERIAL_ECHO_MSG("Servo ", servo_index, " out of range");
|
SERIAL_ECHO_MSG("Servo ", servo_index, " out of range");
|
||||||
|
|
||||||
|
@@ -26,22 +26,32 @@
|
|||||||
|
|
||||||
#include "../gcode.h"
|
#include "../gcode.h"
|
||||||
#include "../../feature/spindle_laser.h"
|
#include "../../feature/spindle_laser.h"
|
||||||
#include "../../module/stepper.h"
|
#include "../../module/planner.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Laser:
|
* Laser:
|
||||||
* M3 - Laser ON/Power (Ramped power)
|
* M3 - Laser ON/Power (Ramped power)
|
||||||
* M4 - Laser ON/Power (Continuous power)
|
* M4 - Laser ON/Power (Ramped power)
|
||||||
|
* M5 - Set power output to 0 (leaving inline mode unchanged).
|
||||||
|
*
|
||||||
|
* M3I - Enable continuous inline power to be processed by the planner, with power
|
||||||
|
* calculated and set in the planner blocks, processed inline during stepping.
|
||||||
|
* Within inline mode M3 S-Values will set the power for the next moves e.g. G1 X10 Y10 powers on with the last S-Value.
|
||||||
|
* M3I must be set before using planner-synced M3 inline S-Values (LASER_POWER_SYNC).
|
||||||
|
*
|
||||||
|
* M4I - Set dynamic mode which calculates laser power OCR based on the current feedrate.
|
||||||
|
*
|
||||||
|
* M5I - Clear inline mode and set power to 0.
|
||||||
*
|
*
|
||||||
* Spindle:
|
* Spindle:
|
||||||
* M3 - Spindle ON (Clockwise)
|
* M3 - Spindle ON (Clockwise)
|
||||||
* M4 - Spindle ON (Counter-clockwise)
|
* M4 - Spindle ON (Counter-clockwise)
|
||||||
|
* M5 - Spindle OFF
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* S<power> - Set power. S0 will turn the spindle/laser off, except in relative mode.
|
* S<power> - Set power. S0 will turn the spindle/laser off.
|
||||||
* O<ocr> - Set power and OCR (oscillator count register)
|
|
||||||
*
|
*
|
||||||
* If no PWM pin is defined then M3/M4 just turns it on.
|
* If no PWM pin is defined then M3/M4 just turns it on or off.
|
||||||
*
|
*
|
||||||
* At least 12.8kHz (50Hz * 256) is needed for Spindle PWM.
|
* At least 12.8kHz (50Hz * 256) is needed for Spindle PWM.
|
||||||
* Hardware PWM is required on AVR. ISRs are too slow.
|
* Hardware PWM is required on AVR. ISRs are too slow.
|
||||||
@@ -70,77 +80,77 @@ void GcodeSuite::M3_M4(const bool is_M4) {
|
|||||||
reset_stepper_timeout(); // Reset timeout to allow subsequent G-code to power the laser (imm.)
|
reset_stepper_timeout(); // Reset timeout to allow subsequent G-code to power the laser (imm.)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if EITHER(SPINDLE_LASER_USE_PWM, SPINDLE_SERVO)
|
if (cutter.cutter_mode == CUTTER_MODE_STANDARD)
|
||||||
auto get_s_power = [] {
|
planner.synchronize(); // Wait for previous movement commands (G0/G1/G2/G3) to complete before changing power
|
||||||
if (parser.seenval('S')) {
|
|
||||||
const float spwr = parser.value_float();
|
|
||||||
#if ENABLED(SPINDLE_SERVO)
|
|
||||||
cutter.unitPower = spwr;
|
|
||||||
#else
|
|
||||||
cutter.unitPower = TERN(SPINDLE_LASER_USE_PWM,
|
|
||||||
cutter.power_to_range(cutter_power_t(round(spwr))),
|
|
||||||
spwr > 0 ? 255 : 0);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
cutter.unitPower = cutter.cpwr_to_upwr(SPEED_POWER_STARTUP);
|
|
||||||
return cutter.unitPower;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if ENABLED(LASER_POWER_INLINE)
|
#if ENABLED(LASER_FEATURE)
|
||||||
if (parser.seen('I') == DISABLED(LASER_POWER_INLINE_INVERT)) {
|
if (parser.seen_test('I')) {
|
||||||
// Laser power in inline mode
|
cutter.cutter_mode = is_M4 ? CUTTER_MODE_DYNAMIC : CUTTER_MODE_CONTINUOUS;
|
||||||
cutter.inline_direction(is_M4); // Should always be unused
|
cutter.inline_power(0);
|
||||||
#if ENABLED(SPINDLE_LASER_USE_PWM)
|
|
||||||
if (parser.seen('O')) {
|
|
||||||
cutter.unitPower = cutter.power_to_range(parser.value_byte(), 0);
|
|
||||||
cutter.inline_ocr_power(cutter.unitPower); // The OCR is a value from 0 to 255 (uint8_t)
|
|
||||||
}
|
|
||||||
else
|
|
||||||
cutter.inline_power(cutter.upower_to_ocr(get_s_power()));
|
|
||||||
#else
|
|
||||||
cutter.set_inline_enabled(true);
|
|
||||||
#endif
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Non-inline, standard case
|
|
||||||
cutter.inline_disable(); // Prevent future blocks re-setting the power
|
|
||||||
#endif
|
|
||||||
|
|
||||||
planner.synchronize(); // Wait for previous movement commands (G0/G0/G2/G3) to complete before changing power
|
|
||||||
cutter.set_reverse(is_M4);
|
|
||||||
|
|
||||||
#if ENABLED(SPINDLE_LASER_USE_PWM)
|
|
||||||
if (parser.seenval('O')) {
|
|
||||||
cutter.unitPower = cutter.power_to_range(parser.value_byte(), 0);
|
|
||||||
cutter.ocr_set_power(cutter.unitPower); // The OCR is a value from 0 to 255 (uint8_t)
|
|
||||||
}
|
|
||||||
else
|
|
||||||
cutter.set_power(cutter.upower_to_ocr(get_s_power()));
|
|
||||||
#elif ENABLED(SPINDLE_SERVO)
|
|
||||||
cutter.set_power(get_s_power());
|
|
||||||
#else
|
|
||||||
cutter.set_enabled(true);
|
cutter.set_enabled(true);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
cutter.menuPower = cutter.unitPower;
|
|
||||||
|
auto get_s_power = [] {
|
||||||
|
float u;
|
||||||
|
if (parser.seenval('S')) {
|
||||||
|
const float v = parser.value_float();
|
||||||
|
u = TERN(LASER_POWER_TRAP, v, cutter.power_to_range(v));
|
||||||
|
}
|
||||||
|
else if (cutter.cutter_mode == CUTTER_MODE_STANDARD)
|
||||||
|
u = cutter.cpwr_to_upwr(SPEED_POWER_STARTUP);
|
||||||
|
|
||||||
|
cutter.menuPower = cutter.unitPower = u;
|
||||||
|
|
||||||
|
// PWM not implied, power converted to OCR from unit definition and on/off if not PWM.
|
||||||
|
cutter.power = TERN(SPINDLE_LASER_USE_PWM, cutter.upower_to_ocr(u), u > 0 ? 255 : 0);
|
||||||
|
return u;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (cutter.cutter_mode == CUTTER_MODE_CONTINUOUS || cutter.cutter_mode == CUTTER_MODE_DYNAMIC) { // Laser power in inline mode
|
||||||
|
#if ENABLED(LASER_FEATURE)
|
||||||
|
planner.laser_inline.status.isPowered = true; // M3 or M4 is powered either way
|
||||||
|
get_s_power(); // Update cutter.power if seen
|
||||||
|
#if ENABLED(LASER_POWER_SYNC)
|
||||||
|
// With power sync we only set power so it does not effect queued inline power sets
|
||||||
|
planner.buffer_sync_block(BLOCK_BIT_LASER_PWR); // Send the flag, queueing inline power
|
||||||
|
#else
|
||||||
|
planner.synchronize();
|
||||||
|
cutter.inline_power(cutter.power);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cutter.set_enabled(true);
|
||||||
|
get_s_power();
|
||||||
|
cutter.apply_power(
|
||||||
|
#if ENABLED(SPINDLE_SERVO)
|
||||||
|
cutter.unitPower
|
||||||
|
#elif ENABLED(SPINDLE_LASER_USE_PWM)
|
||||||
|
cutter.upower_to_ocr(cutter.unitPower)
|
||||||
|
#else
|
||||||
|
cutter.unitPower > 0 ? 255 : 0
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
TERN_(SPINDLE_CHANGE_DIR, cutter.set_reverse(is_M4));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* M5 - Cutter OFF (when moves are complete)
|
* M5 - Cutter OFF (when moves are complete)
|
||||||
*/
|
*/
|
||||||
void GcodeSuite::M5() {
|
void GcodeSuite::M5() {
|
||||||
#if ENABLED(LASER_POWER_INLINE)
|
|
||||||
if (parser.seen('I') == DISABLED(LASER_POWER_INLINE_INVERT)) {
|
|
||||||
cutter.set_inline_enabled(false); // Laser power in inline mode
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Non-inline, standard case
|
|
||||||
cutter.inline_disable(); // Prevent future blocks re-setting the power
|
|
||||||
#endif
|
|
||||||
planner.synchronize();
|
planner.synchronize();
|
||||||
cutter.set_enabled(false);
|
cutter.power = 0;
|
||||||
cutter.menuPower = cutter.unitPower;
|
cutter.apply_power(0); // M5 just kills power, leaving inline mode unchanged
|
||||||
|
if (cutter.cutter_mode != CUTTER_MODE_STANDARD) {
|
||||||
|
if (parser.seen_test('I')) {
|
||||||
|
TERN_(LASER_FEATURE, cutter.inline_power(cutter.power));
|
||||||
|
cutter.set_enabled(false); // Needs to happen while we are in inline mode to clear inline power.
|
||||||
|
cutter.cutter_mode = CUTTER_MODE_STANDARD; // Switch from inline to standard mode.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cutter.set_enabled(false); // Disable enable output setting
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // HAS_CUTTER
|
#endif // HAS_CUTTER
|
||||||
|
@@ -27,35 +27,45 @@
|
|||||||
#include "../gcode.h"
|
#include "../gcode.h"
|
||||||
#include "../../module/stepper.h"
|
#include "../../module/stepper.h"
|
||||||
|
|
||||||
|
#if NUM_AXES == XYZ && EXTRUDERS >= 1
|
||||||
|
#define HAS_M350_B_PARAM 1 // "5th axis" (after E0) for an original XYZEB setup.
|
||||||
|
#if AXIS_COLLISION('B')
|
||||||
|
#error "M350 parameter 'B' collision with axis name."
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* M350: Set axis microstepping modes. S sets mode for all drivers.
|
* M350: Set axis microstepping modes. S sets mode for all drivers.
|
||||||
*
|
*
|
||||||
* Warning: Steps-per-unit remains unchanged.
|
* Warning: Steps-per-unit remains unchanged.
|
||||||
*/
|
*/
|
||||||
void GcodeSuite::M350() {
|
void GcodeSuite::M350() {
|
||||||
if (parser.seen('S')) LOOP_LE_N(i, 4) stepper.microstep_mode(i, parser.value_byte());
|
if (parser.seen('S')) LOOP_DISTINCT_AXES(i) stepper.microstep_mode(i, parser.value_byte());
|
||||||
LOOP_LOGICAL_AXES(i) if (parser.seen(axis_codes[i])) stepper.microstep_mode(i, parser.value_byte());
|
LOOP_LOGICAL_AXES(i) if (parser.seenval(AXIS_CHAR(i))) stepper.microstep_mode(i, parser.value_byte());
|
||||||
if (parser.seen('B')) stepper.microstep_mode(4, parser.value_byte());
|
TERN_(HAS_M350_B_PARAM, if (parser.seenval('B')) stepper.microstep_mode(E_AXIS + 1, parser.value_byte()));
|
||||||
stepper.microstep_readings();
|
stepper.microstep_readings();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* M351: Toggle MS1 MS2 pins directly with axis codes X Y Z E B
|
* M351: Toggle MS1 MS2 pins directly with axis codes X Y Z . . . E [B]
|
||||||
* S# determines MS1, MS2 or MS3, X# sets the pin high/low.
|
* S# determines MS1, MS2 or MS3, X# sets the pin high/low.
|
||||||
|
*
|
||||||
|
* Parameter 'B' sets "5th axis" (after E0) only for an original XYZEB setup.
|
||||||
*/
|
*/
|
||||||
void GcodeSuite::M351() {
|
void GcodeSuite::M351() {
|
||||||
|
const int8_t bval = TERN(HAS_M350_B_PARAM, parser.byteval('B', -1), -1); UNUSED(bval);
|
||||||
if (parser.seenval('S')) switch (parser.value_byte()) {
|
if (parser.seenval('S')) switch (parser.value_byte()) {
|
||||||
case 1:
|
case 1:
|
||||||
LOOP_LOGICAL_AXES(i) if (parser.seenval(axis_codes[i])) stepper.microstep_ms(i, parser.value_byte(), -1, -1);
|
LOOP_LOGICAL_AXES(i) if (parser.seenval(AXIS_CHAR(i))) stepper.microstep_ms(i, parser.value_byte(), -1, -1);
|
||||||
if (parser.seenval('B')) stepper.microstep_ms(4, parser.value_byte(), -1, -1);
|
TERN_(HAS_M350_B_PARAM, if (bval >= 0) stepper.microstep_ms(E_AXIS + 1, bval != 0, -1, -1));
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
LOOP_LOGICAL_AXES(i) if (parser.seenval(axis_codes[i])) stepper.microstep_ms(i, -1, parser.value_byte(), -1);
|
LOOP_LOGICAL_AXES(i) if (parser.seenval(AXIS_CHAR(i))) stepper.microstep_ms(i, -1, parser.value_byte(), -1);
|
||||||
if (parser.seenval('B')) stepper.microstep_ms(4, -1, parser.value_byte(), -1);
|
TERN_(HAS_M350_B_PARAM, if (bval >= 0) stepper.microstep_ms(E_AXIS + 1, -1, bval != 0, -1));
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
LOOP_LOGICAL_AXES(i) if (parser.seenval(axis_codes[i])) stepper.microstep_ms(i, -1, -1, parser.value_byte());
|
LOOP_LOGICAL_AXES(i) if (parser.seenval(AXIS_CHAR(i))) stepper.microstep_ms(i, -1, -1, parser.value_byte());
|
||||||
if (parser.seenval('B')) stepper.microstep_ms(4, -1, -1, parser.value_byte());
|
TERN_(HAS_M350_B_PARAM, if (bval >= 0) stepper.microstep_ms(E_AXIS + 1, -1, -1, bval != 0));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
stepper.microstep_readings();
|
stepper.microstep_readings();
|
||||||
|
@@ -21,7 +21,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../gcode.h"
|
#include "../gcode.h"
|
||||||
#include "../../module/stepper.h"
|
#include "../../module/planner.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* M400: Finish all moves
|
* M400: Finish all moves
|
||||||
|
@@ -28,7 +28,6 @@
|
|||||||
|
|
||||||
#include "../gcode.h"
|
#include "../gcode.h"
|
||||||
#include "../../module/motion.h"
|
#include "../../module/motion.h"
|
||||||
#include "../../module/stepper.h"
|
|
||||||
#include "../../module/tool_change.h"
|
#include "../../module/tool_change.h"
|
||||||
#include "../../module/planner.h"
|
#include "../../module/planner.h"
|
||||||
|
|
||||||
@@ -64,7 +63,7 @@
|
|||||||
void GcodeSuite::M605() {
|
void GcodeSuite::M605() {
|
||||||
planner.synchronize();
|
planner.synchronize();
|
||||||
|
|
||||||
if (parser.seen('S')) {
|
if (parser.seenval('S')) {
|
||||||
const DualXMode previous_mode = dual_x_carriage_mode;
|
const DualXMode previous_mode = dual_x_carriage_mode;
|
||||||
|
|
||||||
dual_x_carriage_mode = (DualXMode)parser.value_byte();
|
dual_x_carriage_mode = (DualXMode)parser.value_byte();
|
||||||
@@ -78,8 +77,8 @@
|
|||||||
|
|
||||||
case DXC_DUPLICATION_MODE:
|
case DXC_DUPLICATION_MODE:
|
||||||
// Set the X offset, but no less than the safety gap
|
// Set the X offset, but no less than the safety gap
|
||||||
if (parser.seen('X')) duplicate_extruder_x_offset = _MAX(parser.value_linear_units(), (X2_MIN_POS) - (X1_MIN_POS));
|
if (parser.seenval('X')) duplicate_extruder_x_offset = _MAX(parser.value_linear_units(), (X2_MIN_POS) - (X1_MIN_POS));
|
||||||
if (parser.seen('R')) duplicate_extruder_temp_offset = parser.value_celsius_diff();
|
if (parser.seenval('R')) duplicate_extruder_temp_offset = parser.value_celsius_diff();
|
||||||
// Always switch back to tool 0
|
// Always switch back to tool 0
|
||||||
if (active_extruder != 0) tool_change(0);
|
if (active_extruder != 0) tool_change(0);
|
||||||
break;
|
break;
|
||||||
@@ -146,7 +145,7 @@
|
|||||||
|
|
||||||
HOTEND_LOOP() {
|
HOTEND_LOOP() {
|
||||||
DEBUG_ECHOPGM_P(SP_T_STR, e);
|
DEBUG_ECHOPGM_P(SP_T_STR, e);
|
||||||
LOOP_LINEAR_AXES(a) DEBUG_ECHOPGM(" hotend_offset[", e, "].", AS_CHAR(AXIS_CHAR(a) | 0x20), "=", hotend_offset[e][a]);
|
LOOP_NUM_AXES(a) DEBUG_ECHOPGM(" hotend_offset[", e, "].", AS_CHAR(AXIS_CHAR(a) | 0x20), "=", hotend_offset[e][a]);
|
||||||
DEBUG_EOL();
|
DEBUG_EOL();
|
||||||
}
|
}
|
||||||
DEBUG_EOL();
|
DEBUG_EOL();
|
||||||
|
@@ -25,7 +25,7 @@
|
|||||||
#if HAS_L64XX
|
#if HAS_L64XX
|
||||||
|
|
||||||
#if AXIS_COLLISION('I')
|
#if AXIS_COLLISION('I')
|
||||||
#error "M906 parameter collision with axis name."
|
#error "M906 parameter 'I' collision with axis name."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../../gcode.h"
|
#include "../../gcode.h"
|
||||||
@@ -211,7 +211,7 @@ void L64XX_report_current(L64XX &motor, const L64XX_axis_t axis) {
|
|||||||
* 1 - monitor only X2, Y2, Z2
|
* 1 - monitor only X2, Y2, Z2
|
||||||
* 2 - monitor only Z3
|
* 2 - monitor only Z3
|
||||||
* 3 - monitor only Z4
|
* 3 - monitor only Z4
|
||||||
* Xxxx, Yxxx, Zxxx, Exxx - axis to change (optional)
|
* Xxxx, Yxxx, Zxxx, Axxx, Bxxx, Cxxx, Exxx - axis to change (optional)
|
||||||
* L6474 - current in mA (4A max)
|
* L6474 - current in mA (4A max)
|
||||||
* All others - 0-255
|
* All others - 0-255
|
||||||
*
|
*
|
||||||
@@ -236,7 +236,7 @@ void GcodeSuite::M906() {
|
|||||||
constexpr int8_t index = -1;
|
constexpr int8_t index = -1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
LOOP_LOGICAL_AXES(i) if (uint16_t value = parser.intval(axis_codes[i])) {
|
LOOP_LOGICAL_AXES(i) if (uint16_t value = parser.intval(AXIS_CHAR(i))) {
|
||||||
|
|
||||||
report_current = false;
|
report_current = false;
|
||||||
|
|
||||||
|
@@ -26,7 +26,6 @@
|
|||||||
|
|
||||||
#include "../../gcode.h"
|
#include "../../gcode.h"
|
||||||
#include "../../../module/planner.h"
|
#include "../../../module/planner.h"
|
||||||
#include "../../../module/stepper.h"
|
|
||||||
|
|
||||||
#if ENABLED(EXTRA_LIN_ADVANCE_K)
|
#if ENABLED(EXTRA_LIN_ADVANCE_K)
|
||||||
float other_extruder_advance_K[EXTRUDERS];
|
float other_extruder_advance_K[EXTRUDERS];
|
||||||
|
@@ -44,14 +44,14 @@ void GcodeSuite::M486() {
|
|||||||
cancelable.object_count = parser.intval('T', 1);
|
cancelable.object_count = parser.intval('T', 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parser.seen('S'))
|
if (parser.seenval('S'))
|
||||||
cancelable.set_active_object(parser.value_int());
|
cancelable.set_active_object(parser.value_int());
|
||||||
|
|
||||||
if (parser.seen('C')) cancelable.cancel_active_object();
|
if (parser.seen('C')) cancelable.cancel_active_object();
|
||||||
|
|
||||||
if (parser.seen('P')) cancelable.cancel_object(parser.value_int());
|
if (parser.seenval('P')) cancelable.cancel_object(parser.value_int());
|
||||||
|
|
||||||
if (parser.seen('U')) cancelable.uncancel_object(parser.value_int());
|
if (parser.seenval('U')) cancelable.uncancel_object(parser.value_int());
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // CANCEL_OBJECTS
|
#endif // CANCEL_OBJECTS
|
||||||
|
@@ -45,9 +45,10 @@
|
|||||||
* X, Y, Z : Specify axes to move during cleaning. Default: ALL.
|
* X, Y, Z : Specify axes to move during cleaning. Default: ALL.
|
||||||
*/
|
*/
|
||||||
void GcodeSuite::G12() {
|
void GcodeSuite::G12() {
|
||||||
|
|
||||||
// Don't allow nozzle cleaning without homing first
|
// Don't allow nozzle cleaning without homing first
|
||||||
if (homing_needed_error(linear_bits & ~TERN0(NOZZLE_CLEAN_NO_Z, Z_AXIS) & ~TERN0(NOZZLE_CLEAN_NO_Y, Y_AXIS)))
|
constexpr main_axes_bits_t clean_axis_mask = main_axes_mask & ~TERN0(NOZZLE_CLEAN_NO_Z, Z_AXIS) & ~TERN0(NOZZLE_CLEAN_NO_Y, Y_AXIS);
|
||||||
return;
|
if (homing_needed_error(clean_axis_mask)) return;
|
||||||
|
|
||||||
#ifdef WIPE_SEQUENCE_COMMANDS
|
#ifdef WIPE_SEQUENCE_COMMANDS
|
||||||
if (!parser.seen_any()) {
|
if (!parser.seen_any()) {
|
||||||
|
@@ -39,25 +39,40 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* M907: Set digital trimpot motor current using axis codes X [Y] [Z] [E]
|
* M907: Set digital trimpot motor current using axis codes X [Y] [Z] [I] [J] [K] [E]
|
||||||
* B<current> - Special case for 4th (E) axis
|
* B<current> - Special case for E1 (Requires DIGIPOTSS_PIN or DIGIPOT_MCP4018 or DIGIPOT_MCP4451)
|
||||||
* S<current> - Special case to set first 3 axes
|
* C<current> - Special case for E2 (Requires DIGIPOTSS_PIN or DIGIPOT_MCP4018 or DIGIPOT_MCP4451)
|
||||||
|
* S<current> - Set current in mA for all axes (Requires DIGIPOTSS_PIN or DIGIPOT_MCP4018 or DIGIPOT_MCP4451), or
|
||||||
|
* Set percentage of max current for all axes (Requires HAS_DIGIPOT_DAC)
|
||||||
*/
|
*/
|
||||||
void GcodeSuite::M907() {
|
void GcodeSuite::M907() {
|
||||||
#if HAS_MOTOR_CURRENT_SPI
|
#if HAS_MOTOR_CURRENT_SPI
|
||||||
|
|
||||||
if (!parser.seen("BS" LOGICAL_AXES_STRING))
|
if (!parser.seen("BS" STR_AXES_LOGICAL))
|
||||||
return M907_report();
|
return M907_report();
|
||||||
|
|
||||||
LOOP_LOGICAL_AXES(i) if (parser.seenval(axis_codes[i])) stepper.set_digipot_current(i, parser.value_int());
|
if (parser.seenval('S')) LOOP_L_N(i, MOTOR_CURRENT_COUNT) stepper.set_digipot_current(i, parser.value_int());
|
||||||
if (parser.seenval('B')) stepper.set_digipot_current(4, parser.value_int());
|
LOOP_LOGICAL_AXES(i) if (parser.seenval(IAXIS_CHAR(i))) stepper.set_digipot_current(i, parser.value_int()); // X Y Z (I J K) E (map to drivers according to DIGIPOT_CHANNELS. Default with NUM_AXES 3: map X Y Z E to X Y Z E0)
|
||||||
if (parser.seenval('S')) LOOP_LE_N(i, 4) stepper.set_digipot_current(i, parser.value_int());
|
// Additional extruders use B,C.
|
||||||
|
// TODO: Change these parameters because 'E' is used and D should be reserved for debugging. B<index>?
|
||||||
|
#if E_STEPPERS >= 2
|
||||||
|
if (parser.seenval('B')) stepper.set_digipot_current(E_AXIS + 1, parser.value_int());
|
||||||
|
#if E_STEPPERS >= 3
|
||||||
|
if (parser.seenval('C')) stepper.set_digipot_current(E_AXIS + 2, parser.value_int());
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#elif HAS_MOTOR_CURRENT_PWM
|
#elif HAS_MOTOR_CURRENT_PWM
|
||||||
|
|
||||||
if (!parser.seen(
|
#if ANY_PIN(MOTOR_CURRENT_PWM_X, MOTOR_CURRENT_PWM_Y, MOTOR_CURRENT_PWM_XY, MOTOR_CURRENT_PWM_I, MOTOR_CURRENT_PWM_J, MOTOR_CURRENT_PWM_K)
|
||||||
#if ANY_PIN(MOTOR_CURRENT_PWM_X, MOTOR_CURRENT_PWM_Y, MOTOR_CURRENT_PWM_XY)
|
#define HAS_X_Y_XY_I_J_K 1
|
||||||
"XY"
|
#endif
|
||||||
|
|
||||||
|
#if HAS_X_Y_XY_I_J_K || ANY_PIN(MOTOR_CURRENT_PWM_E, MOTOR_CURRENT_PWM_Z)
|
||||||
|
|
||||||
|
if (!parser.seen("S"
|
||||||
|
#if HAS_X_Y_XY_I_J_K
|
||||||
|
"XY" SECONDARY_AXIS_GANG("I", "J", "K")
|
||||||
#endif
|
#endif
|
||||||
#if PIN_EXISTS(MOTOR_CURRENT_PWM_Z)
|
#if PIN_EXISTS(MOTOR_CURRENT_PWM_Z)
|
||||||
"Z"
|
"Z"
|
||||||
@@ -67,8 +82,13 @@ void GcodeSuite::M907() {
|
|||||||
#endif
|
#endif
|
||||||
)) return M907_report();
|
)) return M907_report();
|
||||||
|
|
||||||
#if ANY_PIN(MOTOR_CURRENT_PWM_X, MOTOR_CURRENT_PWM_Y, MOTOR_CURRENT_PWM_XY)
|
if (parser.seenval('S')) LOOP_L_N(a, MOTOR_CURRENT_COUNT) stepper.set_digipot_current(a, parser.value_int());
|
||||||
if (parser.seenval('X') || parser.seenval('Y')) stepper.set_digipot_current(0, parser.value_int());
|
|
||||||
|
#if HAS_X_Y_XY_I_J_K
|
||||||
|
if (NUM_AXIS_GANG(
|
||||||
|
parser.seenval('X'), || parser.seenval('Y'), || false,
|
||||||
|
|| parser.seenval('I'), || parser.seenval('J'), || parser.seenval('K')
|
||||||
|
)) stepper.set_digipot_current(0, parser.value_int());
|
||||||
#endif
|
#endif
|
||||||
#if PIN_EXISTS(MOTOR_CURRENT_PWM_Z)
|
#if PIN_EXISTS(MOTOR_CURRENT_PWM_Z)
|
||||||
if (parser.seenval('Z')) stepper.set_digipot_current(1, parser.value_int());
|
if (parser.seenval('Z')) stepper.set_digipot_current(1, parser.value_int());
|
||||||
@@ -77,15 +97,18 @@ void GcodeSuite::M907() {
|
|||||||
if (parser.seenval('E')) stepper.set_digipot_current(2, parser.value_int());
|
if (parser.seenval('E')) stepper.set_digipot_current(2, parser.value_int());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // HAS_MOTOR_CURRENT_PWM
|
#endif // HAS_MOTOR_CURRENT_PWM
|
||||||
|
|
||||||
#if HAS_MOTOR_CURRENT_I2C
|
#if HAS_MOTOR_CURRENT_I2C
|
||||||
// this one uses actual amps in floating point
|
// this one uses actual amps in floating point
|
||||||
LOOP_LOGICAL_AXES(i) if (parser.seenval(axis_codes[i])) digipot_i2c.set_current(i, parser.value_float());
|
if (parser.seenval('S')) LOOP_L_N(q, DIGIPOT_I2C_NUM_CHANNELS) digipot_i2c.set_current(q, parser.value_float());
|
||||||
// Additional extruders use B,C,D for channels 4,5,6.
|
LOOP_LOGICAL_AXES(i) if (parser.seenval(IAXIS_CHAR(i))) digipot_i2c.set_current(i, parser.value_float()); // X Y Z (I J K) E (map to drivers according to pots adresses. Default with NUM_AXES 3 X Y Z E: map to X Y Z E0)
|
||||||
// TODO: Change these parameters because 'E' is used. B<index>?
|
// Additional extruders use B,C,D.
|
||||||
#if HAS_EXTRUDERS
|
// TODO: Change these parameters because 'E' is used and because 'D' should be reserved for debugging. B<index>?
|
||||||
for (uint8_t i = E_AXIS + 1; i < DIGIPOT_I2C_NUM_CHANNELS; i++)
|
#if E_STEPPERS >= 2
|
||||||
|
for (uint8_t i = E_AXIS + 1; i <= _MIN(DIGIPOT_I2C_NUM_CHANNELS - 1, E_AXIS + 3); i++) // Up to B=E1 C=E2 D=E3
|
||||||
if (parser.seenval('B' + i - (E_AXIS + 1))) digipot_i2c.set_current(i, parser.value_float());
|
if (parser.seenval('B' + i - (E_AXIS + 1))) digipot_i2c.set_current(i, parser.value_float());
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
@@ -93,9 +116,9 @@ void GcodeSuite::M907() {
|
|||||||
#if HAS_MOTOR_CURRENT_DAC
|
#if HAS_MOTOR_CURRENT_DAC
|
||||||
if (parser.seenval('S')) {
|
if (parser.seenval('S')) {
|
||||||
const float dac_percent = parser.value_float();
|
const float dac_percent = parser.value_float();
|
||||||
LOOP_LE_N(i, 4) stepper_dac.set_current_percent(i, dac_percent);
|
LOOP_LOGICAL_AXES(i) stepper_dac.set_current_percent(i, dac_percent);
|
||||||
}
|
}
|
||||||
LOOP_LOGICAL_AXES(i) if (parser.seenval(axis_codes[i])) stepper_dac.set_current_percent(i, parser.value_float());
|
LOOP_LOGICAL_AXES(i) if (parser.seenval(IAXIS_CHAR(i))) stepper_dac.set_current_percent(i, parser.value_float()); // X Y Z (I J K) E (map to drivers according to DAC_STEPPER_ORDER. Default with NUM_AXES 3: X Y Z E map to X Y Z E0)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,18 +128,24 @@ void GcodeSuite::M907() {
|
|||||||
report_heading_etc(forReplay, F(STR_STEPPER_MOTOR_CURRENTS));
|
report_heading_etc(forReplay, F(STR_STEPPER_MOTOR_CURRENTS));
|
||||||
#if HAS_MOTOR_CURRENT_PWM
|
#if HAS_MOTOR_CURRENT_PWM
|
||||||
SERIAL_ECHOLNPGM_P( // PWM-based has 3 values:
|
SERIAL_ECHOLNPGM_P( // PWM-based has 3 values:
|
||||||
PSTR(" M907 X"), stepper.motor_current_setting[0] // X and Y
|
PSTR(" M907 X"), stepper.motor_current_setting[0] // X, Y, (I, J, K)
|
||||||
, SP_Z_STR, stepper.motor_current_setting[1] // Z
|
, SP_Z_STR, stepper.motor_current_setting[1] // Z
|
||||||
, SP_E_STR, stepper.motor_current_setting[2] // E
|
, SP_E_STR, stepper.motor_current_setting[2] // E
|
||||||
);
|
);
|
||||||
#elif HAS_MOTOR_CURRENT_SPI
|
#elif HAS_MOTOR_CURRENT_SPI
|
||||||
SERIAL_ECHOPGM(" M907"); // SPI-based has 5 values:
|
SERIAL_ECHOPGM(" M907"); // SPI-based has 5 values:
|
||||||
LOOP_LOGICAL_AXES(q) { // X Y Z (I J K) E (map to X Y Z (I J K) E0 by default)
|
LOOP_LOGICAL_AXES(q) { // X Y Z (I J K) E (map to X Y Z (I J K) E0 by default)
|
||||||
SERIAL_CHAR(' ', axis_codes[q]);
|
SERIAL_CHAR(' ', IAXIS_CHAR(q));
|
||||||
SERIAL_ECHO(stepper.motor_current_setting[q]);
|
SERIAL_ECHO(stepper.motor_current_setting[q]);
|
||||||
}
|
}
|
||||||
SERIAL_CHAR(' ', 'B'); // B (maps to E1 by default)
|
#if E_STEPPERS >= 2
|
||||||
SERIAL_ECHOLN(stepper.motor_current_setting[4]);
|
SERIAL_ECHOPGM_P(PSTR(" B"), stepper.motor_current_setting[E_AXIS + 1] // B (maps to E1 with NUM_AXES 3 according to DIGIPOT_CHANNELS)
|
||||||
|
#if E_STEPPERS >= 3
|
||||||
|
, PSTR(" C"), stepper.motor_current_setting[E_AXIS + 2] // C (mapping to E2 must be defined by DIGIPOT_CHANNELS)
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
SERIAL_EOL();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -45,10 +45,10 @@
|
|||||||
*/
|
*/
|
||||||
void GcodeSuite::M260() {
|
void GcodeSuite::M260() {
|
||||||
// Set the target address
|
// Set the target address
|
||||||
if (parser.seen('A')) i2c.address(parser.value_byte());
|
if (parser.seenval('A')) i2c.address(parser.value_byte());
|
||||||
|
|
||||||
// Add a new byte to the buffer
|
// Add a new byte to the buffer
|
||||||
if (parser.seen('B')) i2c.addbyte(parser.value_byte());
|
if (parser.seenval('B')) i2c.addbyte(parser.value_byte());
|
||||||
|
|
||||||
// Flush the buffer to the bus
|
// Flush the buffer to the bus
|
||||||
if (parser.seen('S')) i2c.send();
|
if (parser.seen('S')) i2c.send();
|
||||||
@@ -63,7 +63,7 @@ void GcodeSuite::M260() {
|
|||||||
* Usage: M261 A<slave device address base 10> B<number of bytes> S<style>
|
* Usage: M261 A<slave device address base 10> B<number of bytes> S<style>
|
||||||
*/
|
*/
|
||||||
void GcodeSuite::M261() {
|
void GcodeSuite::M261() {
|
||||||
if (parser.seen('A')) i2c.address(parser.value_byte());
|
if (parser.seenval('A')) i2c.address(parser.value_byte());
|
||||||
|
|
||||||
const uint8_t bytes = parser.byteval('B', 1), // Bytes to request
|
const uint8_t bytes = parser.byteval('B', 1), // Bytes to request
|
||||||
style = parser.byteval('S'); // Serial output style (ASCII, HEX etc)
|
style = parser.byteval('S'); // Serial output style (ASCII, HEX etc)
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user