Compare commits

...

48 Commits

Author SHA1 Message Date
InsanityAutomation 1bbae4676f Speed tweaks 2024-06-03 08:19:46 -04:00
InsanityAutomation 6802260626 Merge branch 'LPC4078_DevUpd' of https://github.com/InsanityAutomation/Marlin into LPC4078_DevUpd 2024-05-29 12:21:31 -04:00
InsanityAutomation ed34dbb4b6 Update Configuration_adv.h 2024-05-29 12:21:14 -04:00
InsanityAutomation 721209a898 uint64_t planner test 2024-05-29 12:21:04 -04:00
InsanityAutomation 7c6dfc4ec2 Update planner.cpp 2024-05-28 14:10:47 -04:00
Mihail Dumitrescu 62008024cd Protect pulse generation timing by disabling interrupts for longer. 2024-05-28 14:10:46 -04:00
Mihail Dumitrescu e09672edac Fully guard multistepping code in Stepper::pulse_phase_isr(). 2024-05-28 14:10:46 -04:00
Mihail Dumitrescu 825e0b800c Add 4th order S_CURVE_ACCELERATION with configurable S_CURVE_FACTOR. 2024-05-28 14:10:46 -04:00
Mihail Dumitrescu 0f489c6584 PR27035
Smoother motion by fixing calculating trapezoids and ISR stepping.

Fix rounding directions in calculate_trapezoid_for_block().
Fix off-by-ones errors in ac/deceleration steps in block_phase_isr.
Half-initialize ac/deceleration_time to smooth the speed change shock that happens between segments, which is critical as jerk/deviation adds to this.

The result is a smoother motion profile that follows the imposed acceleration limits with a well defined 0.5-1.5x error factor (or 2x if axis is starting from ~0). Errors are due to converting a real-valued motion profile into discrete numbers of steps.
Fixes are general and improve S_CURVE_ACCELERATION too (no endorsement implied).

Tested by looking at the generated step/dir impulses with a logic analyzer.

Enjoy the smoother motion or use more aggresive acceleration/jerk/deviation values for faster prints.

Also improves: #12491

Remove nominal_length, remove MINIMAL_STEP_RATE, add min_entry_speed_sqr, initial clean up of reverse_pass_kernel and forward_pass_kernel.

Removing MINIMAL_STEP_RATE allows for correct handling of moves with low acceleration, including fixing judder that's caused when the planner computes an entry speed based on minimum_planner_speed_sqr that's then promptly overriden by MINIMAL_STEP_RATE.

Added min_entry_speed_sqr to avoid a specific potential source of judder due to working with discrete steps rather continuous real-valued physics. The first step of any segment runs at initial_rate. If it is too low compared to acceleration_steps_per_s2 it will result in too much accumulated acceleration_time (see stepper.cpp) which will mean the following step will be at a much higher speed, and the speed change will significantly surpass the set acceleration_steps_per_s2 limit. Making sure we can match this limit is why we have minimum_planner_speed_sqr in the first place.

Optimal number of sqrts and trapezoid calculations.

Remove forward_pass(). Call forward_pass_kernel() from recalculate() instead.
Fix potential for large speed changes if planner falls behind.

group for clarity and review

as described

combined float sq

match modified names

Optimal number of sqrts and trapezoid calculations.

Remove forward_pass(). Call forward_pass_kernel() from recalculate() instead.
Fix potential for large speed changes if planner falls behind.

Save and use block->steps_per_mm to avoid many divisions.
2024-05-28 14:10:46 -04:00
John Robertson 6ae43349f7 PR26881
Fix planner wrong trap generation

If the planner `entry_rate` or `final_rate` are larger thanthe  `block->nominal_rate` then the trapezoid entry ramp continuously accelerates. Only happens if feed rate is less than MAXIMAL_STEP_RATE.

Update planner.cpp

removed

Update planner.h

Moved MINIMAL_STEP_RATE to this file.

Update planner.h

Added calc for MINIMAL_STEP_RATE

Update planner.h

fix minimal_step_rate calc

Update planner.h

Remove MINIMAL_STEP_RATE

Revert "Update planner.cpp"

This reverts commit 5e0158a8ee1340e5b0e6a7313eb5f5f7058bfa15.

Revert "Update planner.h"

This reverts commit 3da5d0c00102620dc7eddf46a30044773770a667.

Update planner.cpp

Update planner.h

Update planner.cpp

ws

Apply to min_step_rate
2024-05-28 14:10:45 -04:00
Mihail Dumitrescu f6b52a80d6 PR26555
Fix menu responsiveness when HAS_MARLINUI_U8GLIB.

Co-Authored-By: Jason Smith <jason.inet@gmail.com>
2024-05-28 14:10:45 -04:00
InsanityAutomation 38711ed5e6 Update lpc176x.ini 2024-05-28 14:10:45 -04:00
InsanityAutomation 5a714c76b8 Update Configuration.h 2024-05-28 14:10:45 -04:00
InsanityAutomation 8c1a547f2a Config Tweak 2024-05-28 14:10:45 -04:00
InsanityAutomation 16be10d2f3 SPI updates from @p3p upstream 2024-05-28 14:10:44 -04:00
InsanityAutomation d4dde255ad Debug 2024-05-28 14:10:44 -04:00
InsanityAutomation b5c7712531 Update Configuration.h 2024-05-28 14:10:44 -04:00
InsanityAutomation 8dc8361f02 tmc5160 and spi 2024-05-28 14:10:44 -04:00
InsanityAutomation 433f3ba3ab Change read function for PS_ON and EDM pins 2024-05-28 14:10:37 -04:00
InsanityAutomation 78e2aa6eac Fix interupts and pin debugging 2024-05-28 14:10:29 -04:00
InsanityAutomation 54da1da13f Tweaks 2024-05-28 14:10:29 -04:00
InsanityAutomation 544765f1a1 Update Configuration.h 2024-05-28 14:10:25 -04:00
InsanityAutomation f261fea59a Redundant Power control with EDM - First Pass 2024-05-28 14:10:24 -04:00
InsanityAutomation 00785eb14e Update Configuration_adv.h
Co-Authored-By: Chris Pepper <24342+p3p@users.noreply.github.com>
2024-05-28 14:10:04 -04:00
InsanityAutomation 6713185aea LPC4078 Initial Commit
Co-Authored-By: Chris Pepper <24342+p3p@users.noreply.github.com>
2024-05-28 14:09:51 -04:00
InsanityAutomation 298c3f2344 Update planner.cpp 2024-05-28 11:15:33 -04:00
Mihail Dumitrescu 82c1171028 Protect pulse generation timing by disabling interrupts for longer. 2024-05-28 10:46:49 -04:00
Mihail Dumitrescu 122b01d253 Fully guard multistepping code in Stepper::pulse_phase_isr(). 2024-05-28 10:46:13 -04:00
Mihail Dumitrescu 42e4321b6f Add 4th order S_CURVE_ACCELERATION with configurable S_CURVE_FACTOR. 2024-05-28 10:45:45 -04:00
Mihail Dumitrescu 87faa73bee PR27035
Smoother motion by fixing calculating trapezoids and ISR stepping.

Fix rounding directions in calculate_trapezoid_for_block().
Fix off-by-ones errors in ac/deceleration steps in block_phase_isr.
Half-initialize ac/deceleration_time to smooth the speed change shock that happens between segments, which is critical as jerk/deviation adds to this.

The result is a smoother motion profile that follows the imposed acceleration limits with a well defined 0.5-1.5x error factor (or 2x if axis is starting from ~0). Errors are due to converting a real-valued motion profile into discrete numbers of steps.
Fixes are general and improve S_CURVE_ACCELERATION too (no endorsement implied).

Tested by looking at the generated step/dir impulses with a logic analyzer.

Enjoy the smoother motion or use more aggresive acceleration/jerk/deviation values for faster prints.

Also improves: #12491

Remove nominal_length, remove MINIMAL_STEP_RATE, add min_entry_speed_sqr, initial clean up of reverse_pass_kernel and forward_pass_kernel.

Removing MINIMAL_STEP_RATE allows for correct handling of moves with low acceleration, including fixing judder that's caused when the planner computes an entry speed based on minimum_planner_speed_sqr that's then promptly overriden by MINIMAL_STEP_RATE.

Added min_entry_speed_sqr to avoid a specific potential source of judder due to working with discrete steps rather continuous real-valued physics. The first step of any segment runs at initial_rate. If it is too low compared to acceleration_steps_per_s2 it will result in too much accumulated acceleration_time (see stepper.cpp) which will mean the following step will be at a much higher speed, and the speed change will significantly surpass the set acceleration_steps_per_s2 limit. Making sure we can match this limit is why we have minimum_planner_speed_sqr in the first place.

Optimal number of sqrts and trapezoid calculations.

Remove forward_pass(). Call forward_pass_kernel() from recalculate() instead.
Fix potential for large speed changes if planner falls behind.

group for clarity and review

as described

combined float sq

match modified names

Optimal number of sqrts and trapezoid calculations.

Remove forward_pass(). Call forward_pass_kernel() from recalculate() instead.
Fix potential for large speed changes if planner falls behind.

Save and use block->steps_per_mm to avoid many divisions.
2024-05-28 10:43:59 -04:00
John Robertson 666e8c0116 PR26881
Fix planner wrong trap generation

If the planner `entry_rate` or `final_rate` are larger thanthe  `block->nominal_rate` then the trapezoid entry ramp continuously accelerates. Only happens if feed rate is less than MAXIMAL_STEP_RATE.

Update planner.cpp

removed

Update planner.h

Moved MINIMAL_STEP_RATE to this file.

Update planner.h

Added calc for MINIMAL_STEP_RATE

Update planner.h

fix minimal_step_rate calc

Update planner.h

Remove MINIMAL_STEP_RATE

Revert "Update planner.cpp"

This reverts commit 5e0158a8ee1340e5b0e6a7313eb5f5f7058bfa15.

Revert "Update planner.h"

This reverts commit 3da5d0c00102620dc7eddf46a30044773770a667.

Update planner.cpp

Update planner.h

Update planner.cpp

ws

Apply to min_step_rate
2024-05-28 10:29:03 -04:00
Mihail Dumitrescu 5a0332ddee PR26555
Fix menu responsiveness when HAS_MARLINUI_U8GLIB.

Co-Authored-By: Jason Smith <jason.inet@gmail.com>
2024-05-28 10:29:02 -04:00
InsanityAutomation f67a0f847f Update lpc176x.ini 2024-05-28 09:39:16 -04:00
InsanityAutomation 0f1a5a7434 Update Configuration.h 2024-05-28 09:32:10 -04:00
InsanityAutomation 01df7e11dc Config Tweak 2024-05-26 15:04:33 -04:00
InsanityAutomation 9200e8c284 SPI updates from @p3p upstream 2024-05-26 14:59:09 -04:00
InsanityAutomation 0dcfc91c9e Debug 2024-05-25 19:53:01 -04:00
InsanityAutomation acf53d6f84 Merge branch 'bugfix-2.1.x' into LPC4078_DevUpd 2024-05-25 18:34:14 -04:00
InsanityAutomation da068d5bb1 Update Configuration.h 2024-03-06 10:53:44 -05:00
InsanityAutomation 7f339f7001 tmc5160 and spi 2024-03-06 10:53:00 -05:00
ellensp 7150d0eb5c 🔨 No strlcpy in Windows (#26748) 2024-02-27 10:35:13 -05:00
InsanityAutomation ca18690349 Change read function for PS_ON and EDM pins 2024-01-30 11:52:57 -05:00
InsanityAutomation 0316242347 Fix interupts and pin debugging 2024-01-18 22:36:36 -05:00
InsanityAutomation 6087ab6347 Tweaks 2024-01-14 15:41:52 -05:00
InsanityAutomation a44871b272 Update Configuration.h 2024-01-14 15:38:54 -05:00
InsanityAutomation bef646d52c Redundant Power control with EDM - First Pass 2024-01-14 15:36:28 -05:00
InsanityAutomation 4d78a91cbd Update Configuration_adv.h
Co-Authored-By: Chris Pepper <24342+p3p@users.noreply.github.com>
2024-01-14 15:36:03 -05:00
InsanityAutomation 95bafca9d9 LPC4078 Initial Commit
Co-Authored-By: Chris Pepper <24342+p3p@users.noreply.github.com>
2024-01-14 15:35:57 -05:00
63 changed files with 5289 additions and 789 deletions
+110 -98
View File
@@ -61,14 +61,14 @@
// @section info
// Author info of this build printed to the host during boot and M115
#define STRING_CONFIG_H_AUTHOR "(none, default config)" // Who made the changes.
#define STRING_CONFIG_H_AUTHOR "InsanityAutomation" // Who made the changes.
//#define CUSTOM_VERSION_FILE Version.h // Path from the root directory (no quotes)
// @section machine
// Choose the name from boards.h that matches your setup
#ifndef MOTHERBOARD
#define MOTHERBOARD BOARD_RAMPS_14_EFB
#define MOTHERBOARD BOARD_EBAB
#endif
/**
@@ -79,7 +79,7 @@
*
* :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
*/
#define SERIAL_PORT 0
#define SERIAL_PORT -1
/**
* Serial Port Baud Rate
@@ -101,7 +101,7 @@
* Currently Ethernet (-2) is only supported on Teensy 4.1 boards.
* :[-2, -1, 0, 1, 2, 3, 4, 5, 6, 7]
*/
//#define SERIAL_PORT_2 -1
//#define SERIAL_PORT_2 1
//#define BAUDRATE_2 250000 // :[2400, 9600, 19200, 38400, 57600, 115200, 250000, 500000, 1000000] Enable to override BAUDRATE
/**
@@ -116,7 +116,7 @@
//#define BLUETOOTH
// Name displayed in the LCD "Ready" message and Info menu
//#define CUSTOM_MACHINE_NAME "3D Printer"
#define CUSTOM_MACHINE_NAME "FatBoy"
// Printer's unique ID, used by some programs to differentiate between machines.
// Choose your own or use a service like https://www.uuidgenerator.net/version4
@@ -135,25 +135,25 @@
* Options: A4988, A5984, DRV8825, LV8729, TB6560, TB6600, TMC2100,
* TMC2130, TMC2130_STANDALONE, TMC2160, TMC2160_STANDALONE,
* TMC2208, TMC2208_STANDALONE, TMC2209, TMC2209_STANDALONE,
* TMC2660, TMC2660_STANDALONE, TMC5130, TMC5130_STANDALONE,
* TMC5160, TMC5160_STANDALONE
* :['A4988', 'A5984', 'DRV8825', 'LV8729', 'TB6560', 'TB6600', 'TMC2100', 'TMC2130', 'TMC2130_STANDALONE', 'TMC2160', 'TMC2160_STANDALONE', 'TMC2208', 'TMC2208_STANDALONE', 'TMC2209', 'TMC2209_STANDALONE', 'TMC2660', 'TMC2660_STANDALONE', 'TMC5130', 'TMC5130_STANDALONE', 'TMC5160', 'TMC5160_STANDALONE']
* TMC26X, TMC26X_STANDALONE, TMC2660, TMC2660_STANDALONE,
* TMC5130, TMC5130_STANDALONE, TMC5160, TMC5160_STANDALONE
* :['A4988', 'A5984', 'DRV8825', 'LV8729', 'TB6560', 'TB6600', 'TMC2100', 'TMC2130', 'TMC2130_STANDALONE', 'TMC2160', 'TMC2160_STANDALONE', 'TMC2208', 'TMC2208_STANDALONE', 'TMC2209', 'TMC2209_STANDALONE', 'TMC26X', 'TMC26X_STANDALONE', 'TMC2660', 'TMC2660_STANDALONE', 'TMC5130', 'TMC5130_STANDALONE', 'TMC5160', 'TMC5160_STANDALONE']
*/
#define X_DRIVER_TYPE A4988
#define Y_DRIVER_TYPE A4988
#define Z_DRIVER_TYPE A4988
#define X_DRIVER_TYPE TMC5160
#define Y_DRIVER_TYPE TMC5160
#define Z_DRIVER_TYPE TMC5160_STANDALONE
//#define X2_DRIVER_TYPE A4988
//#define Y2_DRIVER_TYPE A4988
//#define Z2_DRIVER_TYPE A4988
//#define Z3_DRIVER_TYPE A4988
//#define Z4_DRIVER_TYPE A4988
#define Y2_DRIVER_TYPE TMC5160
#define Z2_DRIVER_TYPE TMC5160_STANDALONE
#define Z3_DRIVER_TYPE TMC5160_STANDALONE
#define Z4_DRIVER_TYPE TMC5160_STANDALONE
//#define I_DRIVER_TYPE A4988
//#define J_DRIVER_TYPE A4988
//#define K_DRIVER_TYPE A4988
//#define U_DRIVER_TYPE A4988
//#define V_DRIVER_TYPE A4988
//#define W_DRIVER_TYPE A4988
#define E0_DRIVER_TYPE A4988
#define E0_DRIVER_TYPE TMC2209
//#define E1_DRIVER_TYPE A4988
//#define E2_DRIVER_TYPE A4988
//#define E3_DRIVER_TYPE A4988
@@ -399,20 +399,29 @@
//#define MKS_PWC // Using the MKS PWC add-on
//#define PS_OFF_CONFIRM // Confirm dialog when power off
//#define PS_OFF_SOUND // Beep 1s when power off
#define PSU_ACTIVE_STATE LOW // Set 'LOW' for ATX, 'HIGH' for X-Box
#define PSU_ACTIVE_STATE HIGH // Set 'LOW' for ATX, 'HIGH' for X-Box
//#define PSU_DEFAULT_OFF // Keep power off until enabled directly with M80
//#define PSU_POWERUP_DELAY 250 // (ms) Delay for the PSU to warm up to full power
//#define LED_POWEROFF_TIMEOUT 10000 // (ms) Turn off LEDs after power-off, with this amount of delay
#define PSU_DEFAULT_OFF // Keep power off until enabled directly with M80
#define PSU_POWERUP_DELAY 750 // (ms) Delay for the PSU to warm up to full power
//#define LED_POWEROFF_TIMEOUT 10000 // (ms) Turn off LEDs after power-off, with this amount of delay
//#define PSU_OFF_REDUNDANT // Second pin for redundant power control
//#define PSU_OFF_REDUNDANT_INVERTED // Redundant pin state is the inverse of PSU_ACTIVE_STATE
#define PSU_OFF_REDUNDANT // Second pin for redundant power control
//#define PSU_OFF_REDUNDANT_OPPOSING // Redundant pin works opposite standard pin
#define PS_ON_PIN P4_28 // Redundant Pin
#define PS_ON1_PIN P1_03 // Redundant Pin
//#define PS_ON1_PIN 6 // Redundant pin required to enable power in combination with PS_ON_PIN
#define PS_ON_EDM_PIN P4_29 // EDM Pins to monitor feedback on external power control relay. Fault on mismatch.
#define PS_ON1_EDM_PIN P1_17
#define PS_EDM_RESPONSE 1000 // Time in MS to allow for relay action
//#define PS_ON_EDM_PIN 8 // External Device Monitoring pins for external power control relay feedback. Fault on mismatch.
//#define PS_ON1_EDM_PIN 9
#define PS_EDM_RESPONSE 250 // (ms) Time to allow for relay action
#define PSU_OFF_REDUNDANT // Second pin for redundant power control
//#define PSU_OFF_REDUNDANT_OPPOSING // Redundant pin works opposite standard pin
#define PS_ON_PIN P4_28 // Redundant Pin
#define PS_ON1_PIN P1_03 // Redundant Pin
#define PS_ON_EDM_PIN P4_29 // EDM Pins to monitor feedback on external power control relay. Fault on mismatch.
#define PS_ON1_EDM_PIN P1_17
#define PS_EDM_RESPONSE 1000 // Time in MS to allow for relay action
//#define POWER_OFF_TIMER // Enable M81 D<seconds> to power off after a delay
//#define POWER_OFF_WAIT_FOR_COOLDOWN // Enable M81 S to power off only after cooldown
@@ -420,7 +429,7 @@
//#define PSU_POWERUP_GCODE "M355 S1" // G-code to run after power-on (e.g., case light on)
//#define PSU_POWEROFF_GCODE "M355 S0" // G-code to run before power-off (e.g., case light off)
//#define AUTO_POWER_CONTROL // Enable automatic control of the PS_ON pin
#define AUTO_POWER_CONTROL // Enable automatic control of the PS_ON pin
#if ENABLED(AUTO_POWER_CONTROL)
#define AUTO_POWER_FANS // Turn on PSU for fans
#define AUTO_POWER_E_FANS // Turn on PSU for E Fans
@@ -561,7 +570,7 @@
#define TEMP_SENSOR_5 0
#define TEMP_SENSOR_6 0
#define TEMP_SENSOR_7 0
#define TEMP_SENSOR_BED 1
#define TEMP_SENSOR_BED 11
#define TEMP_SENSOR_PROBE 0
#define TEMP_SENSOR_CHAMBER 0
#define TEMP_SENSOR_COOLER 0
@@ -637,7 +646,7 @@
// Above this temperature the heater will be switched off.
// This can protect components from overheating, but NOT from shorts and failures.
// (Use MINTEMP for thermistor short/failure protection.)
#define HEATER_0_MAXTEMP 275
#define HEATER_0_MAXTEMP 300
#define HEATER_1_MAXTEMP 275
#define HEATER_2_MAXTEMP 275
#define HEATER_3_MAXTEMP 275
@@ -645,7 +654,7 @@
#define HEATER_5_MAXTEMP 275
#define HEATER_6_MAXTEMP 275
#define HEATER_7_MAXTEMP 275
#define BED_MAXTEMP 150
#define BED_MAXTEMP 120
#define CHAMBER_MAXTEMP 60
/**
@@ -654,7 +663,7 @@
* (especially before PID tuning). Setting the target temperature too close to MAXTEMP guarantees
* a MAXTEMP shutdown! Use these values to forbid temperatures being set too close to MAXTEMP.
*/
#define HOTEND_OVERSHOOT 15 // (°C) Forbid temperatures over MAXTEMP - OVERSHOOT
#define HOTEND_OVERSHOOT 10 // (°C) Forbid temperatures over MAXTEMP - OVERSHOOT
#define BED_OVERSHOOT 10 // (°C) Forbid temperatures over MAXTEMP - OVERSHOOT
#define COOLER_OVERSHOOT 2 // (°C) Forbid temperatures closer than OVERSHOOT
@@ -672,7 +681,7 @@
* MPCTEMP : Predictive Model temperature control. (~1.8K without auto-tune)
*/
#define PIDTEMP // See the PID Tuning Guide at https://reprap.org/wiki/PID_Tuning
//#define MPCTEMP // See https://marlinfw.org/docs/features/model_predictive_control.html
//#define MPCTEMP // ** EXPERIMENTAL ** See https://marlinfw.org/docs/features/model_predictive_control.html
#define PID_MAX 255 // Limit hotend current while PID is active (see PID_FUNCTIONAL_RANGE below); 255=full current
#define PID_K1 0.95 // Smoothing factor within any PID loop
@@ -757,7 +766,7 @@
* When set to any value below 255, enables a form of PWM to the bed that acts like a divider
* so don't use it unless you are OK with PWM on your bed. (See the comment on enabling PIDTEMPBED)
*/
#define MAX_BED_POWER 255 // limits duty cycle to bed; 255=full current
#define MAX_BED_POWER 180 // limits duty cycle to bed; 255=full current
/**
* PID Bed Heating
@@ -771,7 +780,7 @@
*
* With this option disabled, bang-bang will be used. BED_LIMIT_SWITCHING enables hysteresis.
*/
//#define PIDTEMPBED
#define PIDTEMPBED
#if ENABLED(PIDTEMPBED)
//#define MIN_BED_POWER 0
@@ -842,8 +851,8 @@
#define PID_FUNCTIONAL_RANGE 10 // If the temperature difference between the target temperature and the actual temperature
// is more than PID_FUNCTIONAL_RANGE then the PID will be shut off and the heater will be set to min/max.
//#define PID_EDIT_MENU // Add PID editing to the "Advanced Settings" menu. (~700 bytes of flash)
//#define PID_AUTOTUNE_MENU // Add PID auto-tuning to the "Advanced Settings" menu. (~250 bytes of flash)
#define PID_EDIT_MENU // Add PID editing to the "Advanced Settings" menu. (~700 bytes of flash)
#define PID_AUTOTUNE_MENU // Add PID auto-tuning to the "Advanced Settings" menu. (~250 bytes of flash)
#endif
// @section safety
@@ -1015,6 +1024,9 @@
// 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 https://www.morgan3dp.com/morgan-calibration-guide/
#define PSI_HOMING_OFFSET 0 // Calculated from Calibration Guide and M364 / M114. See https://www.morgan3dp.com/morgan-calibration-guide/
#elif ENABLED(MP_SCARA)
#define SCARA_OFFSET_THETA1 12 // degrees
@@ -1033,19 +1045,23 @@
#define DEFAULT_SEGMENTS_PER_SECOND 200
// Length of inner and outer support arms. Measure arm lengths precisely.
#define TPARA_LINKAGE_1 120 // (mm)
#define TPARA_LINKAGE_2 120 // (mm)
#define TPARA_LINKAGE_1 120 // (mm)
#define TPARA_LINKAGE_2 120 // (mm)
// TPARA tower offset (position of Tower relative to bed zero position)
// This needs to be reasonably accurate as it defines the printbed position in the TPARA space.
#define TPARA_OFFSET_X 0 // (mm)
#define TPARA_OFFSET_Y 0 // (mm)
#define TPARA_OFFSET_Z 0 // (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 TPARA_OFFSET_X 0 // (mm)
#define TPARA_OFFSET_Y 0 // (mm)
#define TPARA_OFFSET_Z 0 // (mm)
#define 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 https://www.morgan3dp.com/morgan-calibration-guide/
#define THETA_HOMING_OFFSET 0
#define PSI_HOMING_OFFSET 0
#endif
// @section polar
@@ -1170,9 +1186,9 @@
* Endstop "Hit" State
* Set to the state (HIGH or LOW) that applies to each endstop.
*/
#define X_MIN_ENDSTOP_HIT_STATE HIGH
#define X_MIN_ENDSTOP_HIT_STATE LOW
#define X_MAX_ENDSTOP_HIT_STATE HIGH
#define Y_MIN_ENDSTOP_HIT_STATE HIGH
#define Y_MIN_ENDSTOP_HIT_STATE LOW
#define Y_MAX_ENDSTOP_HIT_STATE HIGH
#define Z_MIN_ENDSTOP_HIT_STATE HIGH
#define Z_MAX_ENDSTOP_HIT_STATE HIGH
@@ -1236,7 +1252,7 @@
* Override with M92 (when enabled below)
* X, Y, Z [, I [, J [, K...]]], E0 [, E1[, E2...]]
*/
#define DEFAULT_AXIS_STEPS_PER_UNIT { 80, 80, 400, 500 }
#define DEFAULT_AXIS_STEPS_PER_UNIT { 40, 40, 200, 425 }
/**
* Enable support for M92. Disable to save at least ~530 bytes of flash.
@@ -1261,7 +1277,7 @@
* Override with M201
* X, Y, Z [, I [, J [, K...]]], E0 [, E1[, E2...]]
*/
#define DEFAULT_MAX_ACCELERATION { 3000, 3000, 100, 10000 }
#define DEFAULT_MAX_ACCELERATION { 12000, 12000, 500, 10000 }
//#define LIMITED_MAX_ACCEL_EDITING // Limit edit via M201 or LCD to DEFAULT_MAX_ACCELERATION * 2
#if ENABLED(LIMITED_MAX_ACCEL_EDITING)
@@ -1276,9 +1292,9 @@
* M204 R Retract Acceleration
* M204 T Travel Acceleration
*/
#define DEFAULT_ACCELERATION 3000 // X, Y, Z and E acceleration for printing moves
#define DEFAULT_ACCELERATION 7000 // X, Y, Z and E acceleration for printing moves
#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 7000 // X, Y, Z acceleration for travel (non printing) moves
/**
* Default Jerk limits (mm/s)
@@ -1293,7 +1309,6 @@
#define DEFAULT_XJERK 10.0
#define DEFAULT_YJERK 10.0
#define DEFAULT_ZJERK 0.3
#define DEFAULT_EJERK 5.0
//#define DEFAULT_IJERK 0.3
//#define DEFAULT_JJERK 0.3
//#define DEFAULT_KJERK 0.3
@@ -1309,6 +1324,8 @@
#endif
#endif
#define DEFAULT_EJERK 5.0 // May be used by Linear Advance
/**
* Junction Deviation Factor
*
@@ -1330,7 +1347,12 @@
*
* See https://github.com/synthetos/TinyG/wiki/Jerk-Controlled-Motion-Explained
*/
//#define S_CURVE_ACCELERATION
#define S_CURVE_ACCELERATION
#if ENABLED(S_CURVE_ACCELERATION)
// Uncomment to use 4th instead of 6th order motion curve
#define S_CURVE_FACTOR 0.35 // Initial and final acceleration factor, ideally 0.1 to 0.4
// Shouldn't generally require tuning
#endif
//===========================================================================
//============================= Z Probe Options =============================
@@ -1346,10 +1368,10 @@
* The probe replaces the Z-MIN endstop and is used for Z homing.
* (Automatically enables USE_PROBE_FOR_Z_HOMING.)
*/
#define Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN
//#define Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN
// Force the use of the probe for Z-axis homing
//#define USE_PROBE_FOR_Z_HOMING
#define USE_PROBE_FOR_Z_HOMING
/**
* Z_MIN_PROBE_PIN
@@ -1406,7 +1428,7 @@
/**
* The BLTouch probe uses a Hall effect sensor and emulates a servo.
*/
//#define BLTOUCH
#define BLTOUCH
/**
* MagLev V4 probe by MDD
@@ -1448,17 +1470,6 @@
//#define BD_SENSOR_PROBE_NO_STOP // Probe bed without stopping at each probe point
#endif
/**
* BIQU MicroProbe
*
* A lightweight, solenoid-driven probe.
* For information about this sensor https://github.com/bigtreetech/MicroProbe
*
* Also requires: PROBE_ENABLE_DISABLE
*/
//#define BIQU_MICROPROBE_V1 // Triggers HIGH
//#define BIQU_MICROPROBE_V2 // Triggers LOW
// A probe that is deployed and stowed with a solenoid pin (SOL1_PIN)
//#define SOLENOID_PROBE
@@ -1647,7 +1658,7 @@
* A total of 2 does fast/slow probes with a weighted average.
* A total of 3 or more adds more slow probes, taking the average.
*/
//#define MULTIPLE_PROBING 2
#define MULTIPLE_PROBING 2
//#define EXTRA_PROBING 1
/**
@@ -1670,7 +1681,7 @@
#define Z_PROBE_ERROR_TOLERANCE 3 // (mm) Tolerance for early trigger (<= -probe.offset.z + ZPET)
//#define Z_AFTER_PROBING 5 // (mm) Z position after probing is done
#define Z_PROBE_LOW_POINT -2 // (mm) Farthest distance below the trigger-point to go before stopping
#define Z_PROBE_LOW_POINT -5 // (mm) Farthest distance below the trigger-point to go before stopping
// For M851 provide ranges for adjusting the X, Y, and Z probe offsets
//#define PROBE_OFFSET_XMIN -50 // (mm)
@@ -1749,9 +1760,9 @@
// @section motion
// Invert the stepper direction. Change (or reverse the motor connector) if an axis goes the wrong way.
#define INVERT_X_DIR false
#define INVERT_Y_DIR true
#define INVERT_Z_DIR false
#define INVERT_X_DIR true
#define INVERT_Y_DIR false
#define INVERT_Z_DIR true
//#define INVERT_I_DIR false
//#define INVERT_J_DIR false
//#define INVERT_K_DIR false
@@ -1821,8 +1832,8 @@
// @section geometry
// The size of the printable area
#define X_BED_SIZE 200
#define Y_BED_SIZE 200
#define X_BED_SIZE 1200
#define Y_BED_SIZE 1200
// Travel limits (linear=mm, rotational=°) after homing, corresponding to endstop positions.
#define X_MIN_POS 0
@@ -1830,7 +1841,7 @@
#define Z_MIN_POS 0
#define X_MAX_POS X_BED_SIZE
#define Y_MAX_POS Y_BED_SIZE
#define Z_MAX_POS 200
#define Z_MAX_POS 1000
//#define I_MIN_POS 0
//#define I_MAX_POS 50
//#define J_MIN_POS 0
@@ -1882,7 +1893,7 @@
#endif
#if ANY(MIN_SOFTWARE_ENDSTOPS, MAX_SOFTWARE_ENDSTOPS)
//#define SOFT_ENDSTOPS_MENU_ITEM // Enable/Disable software endstops from the LCD
#define SOFT_ENDSTOPS_MENU_ITEM // Enable/Disable software endstops from the LCD
#endif
/**
@@ -2041,7 +2052,7 @@
*/
//#define AUTO_BED_LEVELING_3POINT
//#define AUTO_BED_LEVELING_LINEAR
//#define AUTO_BED_LEVELING_BILINEAR
#define AUTO_BED_LEVELING_BILINEAR
//#define AUTO_BED_LEVELING_UBL
//#define MESH_BED_LEVELING
@@ -2049,14 +2060,14 @@
* Commands to execute at the end of G29 probing.
* Useful to retract or move the Z probe out of the way.
*/
//#define EVENT_GCODE_AFTER_G29 "G1 Z10 F12000\nG1 X15 Y330\nG1 Z0.5\nG1 Z10"
//#define Z_PROBE_END_SCRIPT "G1 Z10 F12000\nG1 X15 Y330\nG1 Z0.5\nG1 Z10"
/**
* Normally G28 leaves leveling disabled on completion. Enable one of
* these options to restore the prior leveling state or to always enable
* leveling immediately after G28.
*/
//#define RESTORE_LEVELING_AFTER_G28
#define RESTORE_LEVELING_AFTER_G28
//#define ENABLE_LEVELING_AFTER_G28
/**
@@ -2071,7 +2082,7 @@
/**
* Enable detailed logging of G28, G29, M48, etc.
* Turn on with the command 'M111 S32'.
* NOTE: Requires a lot of flash!
* NOTE: Requires a lot of PROGMEM!
*/
//#define DEBUG_LEVELING_FEATURE
@@ -2088,7 +2099,7 @@
*/
#define ENABLE_LEVELING_FADE_HEIGHT
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
#define DEFAULT_LEVELING_FADE_HEIGHT 10.0 // (mm) Default fade height.
#define DEFAULT_LEVELING_FADE_HEIGHT 0.0 // (mm) Default fade height.
#endif
/**
@@ -2102,7 +2113,7 @@
/**
* Enable the G26 Mesh Validation Pattern tool.
*/
//#define G26_MESH_VALIDATION
#define G26_MESH_VALIDATION
#if ENABLED(G26_MESH_VALIDATION)
#define MESH_TEST_NOZZLE_SIZE 0.4 // (mm) Diameter of primary nozzle.
#define MESH_TEST_LAYER_HEIGHT 0.2 // (mm) Default layer height for G26.
@@ -2118,7 +2129,7 @@
#if ANY(AUTO_BED_LEVELING_LINEAR, AUTO_BED_LEVELING_BILINEAR)
// Set the number of grid points per dimension.
#define GRID_MAX_POINTS_X 3
#define GRID_MAX_POINTS_X 15
#define GRID_MAX_POINTS_Y GRID_MAX_POINTS_X
// Probe along the Y axis, advancing X after each column
@@ -2128,7 +2139,7 @@
// Beyond the probed grid, continue the implied tilt?
// Default is to maintain the height of the nearest edge.
//#define EXTRAPOLATE_BEYOND_GRID
#define EXTRAPOLATE_BEYOND_GRID
//
// Subdivision of the grid by Catmull-Rom method.
@@ -2204,12 +2215,12 @@
* Add a bed leveling sub-menu for ABL or MBL.
* Include a guided procedure if manual probing is enabled.
*/
//#define LCD_BED_LEVELING
#define LCD_BED_LEVELING
#if ENABLED(LCD_BED_LEVELING)
#define MESH_EDIT_Z_STEP 0.025 // (mm) Step size while manually probing Z axis.
#define LCD_PROBE_Z_RANGE 4 // (mm) Z Range centered on Z_MIN_POS for LCD Z adjustment
//#define MESH_EDIT_MENU // Add a menu to edit mesh points
#define LCD_PROBE_Z_RANGE 8 // (mm) Z Range centered on Z_MIN_POS for LCD Z adjustment
#define MESH_EDIT_MENU // Add a menu to edit mesh points
#endif
// Add a menu item to move between bed corners for manual bed adjustment
@@ -2218,7 +2229,7 @@
#if ENABLED(LCD_BED_TRAMMING)
#define BED_TRAMMING_INSET_LFRB { 30, 30, 30, 30 } // (mm) Left, Front, Right, Back insets
#define BED_TRAMMING_HEIGHT 0.0 // (mm) Z height of nozzle at tramming points
#define BED_TRAMMING_Z_HOP 4.0 // (mm) Z raise between tramming points
#define BED_TRAMMING_Z_HOP 4.0 // (mm) Z height of nozzle between tramming points
//#define BED_TRAMMING_INCLUDE_CENTER // Move to the center after the last corner
//#define BED_TRAMMING_USE_PROBE
#if ENABLED(BED_TRAMMING_USE_PROBE)
@@ -2271,7 +2282,7 @@
* - Allows Z homing only when XY positions are known and trusted.
* - If stepper drivers sleep, XY homing may be required again before Z homing.
*/
//#define Z_SAFE_HOMING
#define Z_SAFE_HOMING
#if ENABLED(Z_SAFE_HOMING)
#define Z_SAFE_HOMING_X_POINT X_CENTER // (mm) X point for Z homing
@@ -2358,12 +2369,12 @@
* M501 - Read settings from EEPROM. (i.e., Throw away unsaved changes)
* M502 - Revert settings to "factory" defaults. (Follow with M500 to init the EEPROM.)
*/
//#define EEPROM_SETTINGS // Persistent storage with M500 and M501
#define EEPROM_SETTINGS // Persistent storage with M500 and M501
//#define DISABLE_M503 // Saves ~2700 bytes of flash. Disable for release!
#define EEPROM_CHITCHAT // Give feedback on EEPROM commands. Disable to save flash.
#define EEPROM_CHITCHAT // Give feedback on EEPROM commands. Disable to save PROGMEM.
#define EEPROM_BOOT_SILENT // Keep M503 quiet and only give errors during first load
#if ENABLED(EEPROM_SETTINGS)
//#define EEPROM_AUTO_INIT // Init EEPROM automatically on any errors.
#define EEPROM_AUTO_INIT // Init EEPROM automatically on any errors.
//#define EEPROM_INIT_NOW // Init EEPROM on first boot after a new build.
#endif
@@ -2421,11 +2432,11 @@
* P1 Raise the nozzle always to Z-park height.
* P2 Raise the nozzle by Z-park amount, limited to Z_MAX_POS.
*/
//#define NOZZLE_PARK_FEATURE
#define NOZZLE_PARK_FEATURE
#if ENABLED(NOZZLE_PARK_FEATURE)
// Specify a park position as { X, Y, Z_raise }
#define NOZZLE_PARK_POINT { (X_MIN_POS + 10), (Y_MAX_POS - 10), 20 }
#define NOZZLE_PARK_POINT { (X_MIN_POS + 10), (Y_MIN_POS + 10), 5 }
#define NOZZLE_PARK_MOVE 0 // Park motion: 0 = XY Move, 1 = X Only, 2 = Y Only, 3 = X before Y, 4 = Y before X
#define NOZZLE_PARK_Z_RAISE_MIN 2 // (mm) Always raise Z by at least this distance
#define NOZZLE_PARK_XY_FEEDRATE 100 // (mm/s) X and Y axes feedrate (also used for delta Z axis)
@@ -2636,9 +2647,9 @@
#define DISPLAY_CHARSET_HD44780 JAPANESE
/**
* Info Screen Style (0:Classic, 1:Průša, 2:CNC)
* Info Screen Style (0:Classic, 1:Průša)
*
* :[0:'Classic', 1:'Průša', 2:'CNC']
* :[0:'Classic', 1:'Průša']
*/
#define LCD_INFO_SCREEN_STYLE 0
@@ -2648,7 +2659,7 @@
* SD Card support is disabled by default. If your controller has an SD slot,
* you must uncomment the following option or it won't work.
*/
//#define SDSUPPORT
#define SDSUPPORT
/**
* SD CARD: ENABLE CRC
@@ -2728,7 +2739,7 @@
//
// Add individual axis homing items (Home X, Home Y, and Home Z) to the LCD menu.
//
//#define INDIVIDUAL_AXIS_HOMING_MENU
#define INDIVIDUAL_AXIS_HOMING_MENU
//#define INDIVIDUAL_AXIS_HOMING_SUBMENU
//
@@ -2931,7 +2942,7 @@
// RepRapDiscount FULL GRAPHIC Smart Controller
// https://reprap.org/wiki/RepRapDiscount_Full_Graphic_Smart_Controller
//
//#define REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER
#define REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER
//
// K.3D Full Graphic Smart Controller
@@ -3039,7 +3050,7 @@
//
// Factory display for Creality CR-10 / CR-7 / Ender-3
// https://marlinfw.org/docs/hardware/controllers.html#cr10_stockdisplay
// https://www.aliexpress.com/item/32833148327.html
//
// Connect to EXP1 on RAMPS and compatible boards.
//
@@ -3416,6 +3427,7 @@
#define BUTTON_DELAY_MENU 250 // (ms) Button repeat delay for menus
//#define DISABLE_ENCODER // Disable the click encoder, if any
//#define TOUCH_IDLE_SLEEP_MINS 5 // (minutes) Display Sleep after a period of inactivity. Set with M255 S.
#define TOUCH_SCREEN_CALIBRATION
+112 -116
View File
@@ -307,11 +307,11 @@
#define THERMAL_PROTECTION_PERIOD 40 // (seconds)
#define THERMAL_PROTECTION_HYSTERESIS 4 // (°C)
//#define ADAPTIVE_FAN_SLOWING // Slow down the part-cooling fan if the temperature drops
#define ADAPTIVE_FAN_SLOWING // Slow down the part-cooling fan if the temperature drops
#if ENABLED(ADAPTIVE_FAN_SLOWING)
//#define REPORT_ADAPTIVE_FAN_SLOWING // Report fan slowing activity to the console
#if ANY(MPCTEMP, PIDTEMP)
//#define TEMP_TUNING_MAINTAIN_FAN // Don't slow down the fan speed during M303 or M306 T
#define TEMP_TUNING_MAINTAIN_FAN // Don't slow down the fan speed during M303 or M306 T
#endif
#endif
@@ -335,7 +335,7 @@
* Thermal Protection parameters for the bed are just as above for hotends.
*/
#if ENABLED(THERMAL_PROTECTION_BED)
#define THERMAL_PROTECTION_BED_PERIOD 20 // (seconds)
#define THERMAL_PROTECTION_BED_PERIOD 90 // (seconds)
#define THERMAL_PROTECTION_BED_HYSTERESIS 2 // (°C)
/**
@@ -459,7 +459,7 @@
#define PID_FAN_SCALING_LIN_FACTOR (PID_FAN_SCALING_AT_FULL_SPEED-DEFAULT_Kf)/255.0
#else
#define PID_FAN_SCALING_LIN_FACTOR (0) // Power-loss due to cooling = Kf * (fan_speed)
#define PID_FAN_SCALING_LIN_FACTOR (0) // Power loss due to cooling = Kf * (fan_speed)
#define DEFAULT_Kf 10 // A constant value added to the PID-tuner
#define PID_FAN_SCALING_MIN_SPEED 10 // Minimum fan speed at which to enable PID_FAN_SCALING
#endif
@@ -547,10 +547,10 @@
* Hotend Idle Timeout
* Prevent filament in the nozzle from charring and causing a critical jam.
*/
//#define HOTEND_IDLE_TIMEOUT
#define HOTEND_IDLE_TIMEOUT
#if ENABLED(HOTEND_IDLE_TIMEOUT)
#define HOTEND_IDLE_TIMEOUT_SEC (5*60) // (seconds) Time without extruder movement to trigger protection
#define HOTEND_IDLE_MIN_TRIGGER 180 // (°C) Minimum temperature to enable hotend protection
#define HOTEND_IDLE_TIMEOUT_SEC (30*60) // (seconds) Time without extruder movement to trigger protection
#define HOTEND_IDLE_MIN_TRIGGER 170 // (°C) Minimum temperature to enable hotend protection
#define HOTEND_IDLE_NOZZLE_TARGET 0 // (°C) Safe temperature for the nozzle after timeout
#define HOTEND_IDLE_BED_TARGET 0 // (°C) Safe temperature for the bed after timeout
#endif
@@ -602,8 +602,8 @@
* gets it spinning reliably for a short time before setting the requested speed.
* (Does not work on Sanguinololu with FAN_SOFT_PWM.)
*/
//#define FAN_KICKSTART_TIME 100 // (ms)
//#define FAN_KICKSTART_POWER 180 // 64-255
#define FAN_KICKSTART_TIME 100 // (ms)
#define FAN_KICKSTART_POWER 180 // 64-255
// Some coolers may require a non-zero "off" state.
//#define FAN_OFF_PWM 1
@@ -931,7 +931,7 @@
//#define HOMING_BACKOFF_POST_MM { 2, 2, 2 } // (linear=mm, rotational=°) Backoff from endstops after homing
//#define XY_COUNTERPART_BACKOFF_MM 0 // (mm) Backoff X after homing Y, and vice-versa
//#define QUICK_HOME // If G28 contains XY do a diagonal move first
#define QUICK_HOME // If G28 contains XY do a diagonal move first
//#define HOME_Y_BEFORE_X // If G28 contains XY home Y before X
//#define HOME_Z_FIRST // Home Z first. Requires a real endstop (not a probe).
//#define CODEPENDENT_XY_HOMING // If X/Y can't home without homing Y/X first
@@ -1020,7 +1020,7 @@
* Z Steppers Auto-Alignment
* Add the G34 command to align multiple Z steppers using a bed probe.
*/
//#define Z_STEPPER_AUTO_ALIGN
#define Z_STEPPER_AUTO_ALIGN
#if ENABLED(Z_STEPPER_AUTO_ALIGN)
/**
* Define probe X and Y positions for Z1, Z2 [, Z3 [, Z4]]
@@ -1185,32 +1185,33 @@
* Zero Vibration (ZV) Input Shaping for X and/or Y movements.
*
* This option uses a lot of SRAM for the step buffer. The buffer size is
* calculated automatically from SHAPING_FREQ_[XYZ], DEFAULT_AXIS_STEPS_PER_UNIT,
* calculated automatically from SHAPING_FREQ_[XY], DEFAULT_AXIS_STEPS_PER_UNIT,
* DEFAULT_MAX_FEEDRATE and ADAPTIVE_STEP_SMOOTHING. The default calculation can
* be overridden by setting SHAPING_MIN_FREQ and/or SHAPING_MAX_FEEDRATE.
* The higher the frequency and the lower the feedrate, the smaller the buffer.
* If the buffer is too small at runtime, input shaping will have reduced
* effectiveness during high speed movements.
*
* Tune with M593 D<factor> F<frequency>
* Tune with M593 D<factor> F<frequency>:
*
* D<factor> Set the zeta/damping factor. If axes (X, Y, etc.) are not specified, set for all axes.
* F<frequency> Set the frequency. If axes (X, Y, etc.) are not specified, set for all axes.
* T[map] Input Shaping type, 0:ZV, 1:EI, 2:2H EI (not implemented yet)
* X<1> Set the given parameters only for the X axis.
* Y<1> Set the given parameters only for the Y axis.
*/
//#define INPUT_SHAPING_X
//#define INPUT_SHAPING_Y
//#define INPUT_SHAPING_Z
#if ANY(INPUT_SHAPING_X, INPUT_SHAPING_Y, INPUT_SHAPING_Z)
#if ANY(INPUT_SHAPING_X, INPUT_SHAPING_Y)
#if ENABLED(INPUT_SHAPING_X)
#define SHAPING_FREQ_X 40.0 // (Hz) The default dominant resonant frequency on the X axis.
#define SHAPING_ZETA_X 0.15 // Damping ratio of the X axis (range: 0.0 = no damping to 1.0 = critical damping).
#define SHAPING_FREQ_X 40 // (Hz) The default dominant resonant frequency on the X axis.
#define SHAPING_ZETA_X 0.15f // Damping ratio of the X axis (range: 0.0 = no damping to 1.0 = critical damping).
#endif
#if ENABLED(INPUT_SHAPING_Y)
#define SHAPING_FREQ_Y 40.0 // (Hz) The default dominant resonant frequency on the Y axis.
#define SHAPING_ZETA_Y 0.15 // Damping ratio of the Y axis (range: 0.0 = no damping to 1.0 = critical damping).
#define SHAPING_FREQ_Y 40 // (Hz) The default dominant resonant frequency on the Y axis.
#define SHAPING_ZETA_Y 0.15f // Damping ratio of the Y axis (range: 0.0 = no damping to 1.0 = critical damping).
#endif
#if ENABLED(INPUT_SHAPING_Z)
#define SHAPING_FREQ_Z 40.0 // (Hz) The default dominant resonant frequency on the Z axis.
#define SHAPING_ZETA_Z 0.15 // Damping ratio of the Z axis (range: 0.0 = no damping to 1.0 = critical damping).
#endif
//#define SHAPING_MIN_FREQ 20.0 // (Hz) By default the minimum of the shaping frequencies. Override to affect SRAM usage.
//#define SHAPING_MIN_FREQ 20 // By default the minimum of the shaping frequencies. Override to affect SRAM usage.
//#define SHAPING_MAX_STEPRATE 10000 // By default the maximum total step rate of the shaped axes. Override to affect SRAM usage.
//#define SHAPING_MENU // Add a menu to the LCD to set shaping parameters.
#endif
@@ -1269,18 +1270,18 @@
* XY Frequency limit
* Reduce resonance by limiting the frequency of small zigzag infill moves.
* See https://hydraraptor.blogspot.com/2010/12/frequency-limit.html
* Use M201 F<freq> S<min%> to change limits at runtime.
* Use M201 F<freq> G<min%> to change limits at runtime.
*/
//#define XY_FREQUENCY_LIMIT 10 // (Hz) Maximum frequency of small zigzag infill moves. Set with M201 F<hertz>.
#ifdef XY_FREQUENCY_LIMIT
#define XY_FREQUENCY_MIN_PERCENT 5 // (%) Minimum FR percentage to apply. Set with M201 S<min%>.
#define XY_FREQUENCY_MIN_PERCENT 5 // (%) Minimum FR percentage to apply. Set with M201 G<min%>.
#endif
//
// Backlash Compensation
// Adds extra movement to axes on direction-changes to account for backlash.
//
//#define BACKLASH_COMPENSATION
#define BACKLASH_COMPENSATION
#if ENABLED(BACKLASH_COMPENSATION)
// Define values for backlash distance and correction.
// If BACKLASH_GCODE is enabled these values are the defaults.
@@ -1295,7 +1296,7 @@
//#define BACKLASH_SMOOTHING_MM 3 // (mm)
// Add runtime configuration and tuning of backlash values (M425)
//#define BACKLASH_GCODE
#define BACKLASH_GCODE
#if ENABLED(BACKLASH_GCODE)
// Measure the Z backlash when probing (G29) and set with "M425 Z"
@@ -1341,7 +1342,7 @@
#define CALIBRATION_NOZZLE_TIP_HEIGHT 1.0 // mm
#define CALIBRATION_NOZZLE_OUTER_DIAMETER 2.0 // mm
// Uncomment to enable reporting (required for "G425 V", but consumes flash).
// Uncomment to enable reporting (required for "G425 V", but consumes PROGMEM).
//#define CALIBRATION_REPORTING
// The true location and dimension the cube/bolt/washer on the bed.
@@ -1385,7 +1386,7 @@
* Multi-stepping sends steps in bursts to reduce MCU usage for high step-rates.
* This allows higher feedrates than the MCU could otherwise support.
*/
#define MULTISTEPPING_LIMIT 16 //: [1, 2, 4, 8, 16, 32, 64, 128]
#define MULTISTEPPING_LIMIT 32 //: [1, 2, 4, 8, 16, 32, 64, 128]
/**
* Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies
@@ -1393,7 +1394,7 @@
* vibration and surface artifacts. The algorithm adapts to provide the best possible step smoothing at the
* lowest stepping frequencies.
*/
//#define ADAPTIVE_STEP_SMOOTHING
#define ADAPTIVE_STEP_SMOOTHING
/**
* Custom Microstepping
@@ -1473,7 +1474,6 @@
#if IS_ULTIPANEL
#define MANUAL_E_MOVES_RELATIVE // Display extruder move distance rather than "position"
#define ULTIPANEL_FEEDMULTIPLY // Encoder sets the feedrate multiplier on the Status Screen
//#define ULTIPANEL_FLOWPERCENT // Encoder sets the flow percentage on the Status Screen
#endif
#endif
@@ -1528,7 +1528,7 @@
#endif
// Include a page of printer information in the LCD Main Menu
//#define LCD_INFO_MENU
#define LCD_INFO_MENU
#if ENABLED(LCD_INFO_MENU)
//#define LCD_PRINTER_INFO_IS_BOOTSCREEN // Show bootscreen(s) instead of Printer Info pages
#endif
@@ -1539,7 +1539,6 @@
* Axis moves <= 1/2 the axis length and Extruder moves <= EXTRUDE_MAXLENGTH
* will be shown in the move submenus.
*/
#define MANUAL_MOVE_DISTANCE_MM 10, 1.0, 0.1 // (mm)
//#define MANUAL_MOVE_DISTANCE_MM 100, 50, 10, 1.0, 0.1 // (mm)
//#define MANUAL_MOVE_DISTANCE_MM 500, 100, 50, 10, 1.0, 0.1 // (mm)
@@ -1581,9 +1580,9 @@
#define BOOT_MARLIN_LOGO_SMALL // Show a smaller Marlin logo on the Boot Screen (saving lots of flash)
#endif
#if HAS_MARLINUI_U8GLIB
//#define BOOT_MARLIN_LOGO_ANIMATED // Animated Marlin logo. Costs ~3260 (or ~940) bytes of flash.
#define BOOT_MARLIN_LOGO_ANIMATED // Animated Marlin logo. Costs ~3260 (or ~940) bytes of flash.
#endif
#if ANY(HAS_MARLINUI_U8GLIB, TOUCH_UI_FTDI_EVE, HAS_MARLINUI_HD44780)
#if ANY(HAS_MARLINUI_U8GLIB, TOUCH_UI_FTDI_EVE)
//#define SHOW_CUSTOM_BOOTSCREEN // Show the bitmap in Marlin/_Bootscreen.h on startup.
#endif
#endif
@@ -1600,10 +1599,10 @@
#endif
// The timeout to return to the status screen from sub-menus
//#define LCD_TIMEOUT_TO_STATUS 15000 // (ms)
#define LCD_TIMEOUT_TO_STATUS 15000 // (ms)
// Scroll a longer status message into view
//#define STATUS_MESSAGE_SCROLLING
#define STATUS_MESSAGE_SCROLLING
// Apply a timeout to low-priority status messages
//#define STATUS_MESSAGE_TIMEOUT_SEC 30 // (seconds)
@@ -1655,7 +1654,7 @@
#endif
// Add 'M73' to set print job progress, overrides Marlin's built-in estimate
//#define SET_PROGRESS_MANUALLY
#define SET_PROGRESS_MANUALLY
#if ENABLED(SET_PROGRESS_MANUALLY)
#define SET_PROGRESS_PERCENT // Add 'P' parameter to set percentage done
#define SET_REMAINING_TIME // Add 'R' parameter to set remaining time
@@ -1744,26 +1743,21 @@
*/
//#define POWER_LOSS_RECOVERY
#if ENABLED(POWER_LOSS_RECOVERY)
#define PLR_ENABLED_DEFAULT false // Power-Loss Recovery enabled by default. (Set with 'M413 Sn' & M500)
#define PLR_ENABLED_DEFAULT false // Power Loss Recovery enabled by default. (Set with 'M413 Sn' & M500)
//#define PLR_BED_THRESHOLD BED_MAXTEMP // (°C) Skip user confirmation at or above this bed temperature (0 to disable)
//#define POWER_LOSS_PIN 44 // Pin to detect power-loss. Set to -1 to disable default pin on boards without module, or comment to use board default.
//#define POWER_LOSS_STATE HIGH // State of pin indicating power-loss
//#define BACKUP_POWER_SUPPLY // Backup power / UPS to move the steppers on power loss
//#define POWER_LOSS_ZRAISE 2 // (mm) Z axis raise on resume (on power loss with UPS)
//#define POWER_LOSS_PIN 44 // Pin to detect power loss. Set to -1 to disable default pin on boards without module.
//#define POWER_LOSS_STATE HIGH // State of pin indicating power loss
//#define POWER_LOSS_PULLUP // Set pullup / pulldown as appropriate for your sensor
//#define POWER_LOSS_PULLDOWN
//#define POWER_LOSS_ZRAISE 2 // (mm) Z axis raise on resume (on power-loss with UPS)
//#define POWER_LOSS_PURGE_LEN 20 // (mm) Length of filament to purge on resume
//#define POWER_LOSS_PURGE_LEN 20 // (mm) Length of filament to purge on resume
//#define POWER_LOSS_RETRACT_LEN 10 // (mm) Length of filament to retract on fail. Requires backup power.
// Without a POWER_LOSS_PIN the following option helps reduce wear on the SD card,
// especially with "vase mode" printing. Set too high and vases cannot be continued.
#define POWER_LOSS_MIN_Z_CHANGE 0.05 // (mm) Minimum Z change before saving power-loss data
//#define BACKUP_POWER_SUPPLY // Backup power / UPS to move the steppers on power-loss
#if ENABLED(BACKUP_POWER_SUPPLY)
//#define POWER_LOSS_RETRACT_LEN 10 // (mm) Length of filament to retract on fail
#endif
// Enable if Z homing is needed for proper recovery. 99.9% of the time this should be disabled!
//#define POWER_LOSS_RECOVER_ZHOME
#if ENABLED(POWER_LOSS_RECOVER_ZHOME)
@@ -1812,13 +1806,13 @@
// Allow international symbols in long filenames. To display correctly, the
// LCD's font must contain the characters. Check your selected LCD language.
//#define UTF_FILENAME_SUPPORT
#define UTF_FILENAME_SUPPORT
//#define LONG_FILENAME_HOST_SUPPORT // Get the long filename of a file/folder with 'M33 <dosname>' and list long filenames with 'M20 L'
#define LONG_FILENAME_HOST_SUPPORT // Get the long filename of a file/folder with 'M33 <dosname>' and list long filenames with 'M20 L'
//#define LONG_FILENAME_WRITE_SUPPORT // Create / delete files with long filenames via M28, M30, and Binary Transfer Protocol
//#define M20_TIMESTAMP_SUPPORT // Include timestamps by adding the 'T' flag to M20 commands
//#define SCROLL_LONG_FILENAMES // Scroll long filenames in the SD card menu
#define SCROLL_LONG_FILENAMES // Scroll long filenames in the SD card menu
//#define SD_ABORT_NO_COOLDOWN // Leave the heaters on after Stop Print (not recommended!)
@@ -1919,7 +1913,7 @@
*
* :[ 'LCD', 'ONBOARD', 'CUSTOM_CABLE' ]
*/
//#define SDCARD_CONNECTION LCD
#define SDCARD_CONNECTION ONBOARD
// Enable if SD detect is rendered useless (e.g., by using an SD extender)
//#define NO_SD_DETECT
@@ -1969,6 +1963,17 @@
// Western only. Not available for Cyrillic, Kana, Turkish, Greek, or Chinese.
//#define USE_SMALL_INFOFONT
/**
* Graphical Display Sleep
*
* The U8G library provides sleep / wake functions for SH1106, SSD1306,
* SSD1309, and some other DOGM displays.
* Enable this option to save energy and prevent OLED pixel burn-in.
* Adds the menu item Configuration > LCD Timeout (m) to set a wait period
* from 0 (disabled) to 99 minutes.
*/
//#define DISPLAY_SLEEP_MINUTES 2 // (minutes) Timeout before turning off the screen. Set with M255 S.
/**
* ST7920-based LCDs can emulate a 16 x 4 character display using
* the ST7920 character-generator for very fast screen updates.
@@ -2217,20 +2222,13 @@
//#define TFT_BTOKMENU_COLOR 0x145F // 00010 100010 11111 Cyan
#endif
/**
* Display Sleep
* Enable this option to save energy and prevent OLED pixel burn-in.
*/
//#define DISPLAY_SLEEP_MINUTES 2 // (minutes) Timeout before turning off the screen
/**
* LCD Backlight Timeout
* Requires a display with a controllable backlight
*/
//
// LCD Backlight Timeout
// Requires a display with a controllable backlight
//
//#define LCD_BACKLIGHT_TIMEOUT_MINS 1 // (minutes) Timeout before turning off the backlight
#if defined(DISPLAY_SLEEP_MINUTES) || defined(LCD_BACKLIGHT_TIMEOUT_MINS)
#define EDITABLE_DISPLAY_TIMEOUT // Edit sleep / backlight timeout with M255 S<minutes> and a menu item
#define EDITABLE_DISPLAY_TIMEOUT // Edit timeout with M255 S<minutes> and a menu item
#endif
//
@@ -2265,18 +2263,18 @@
*
* Warning: Does not respect endstops!
*/
//#define BABYSTEPPING
#define BABYSTEPPING
#if ENABLED(BABYSTEPPING)
//#define EP_BABYSTEPPING // M293/M294 babystepping with EMERGENCY_PARSER support
//#define BABYSTEP_WITHOUT_HOMING
//#define BABYSTEP_ALWAYS_AVAILABLE // Allow babystepping at all times (not just during movement)
#define BABYSTEP_ALWAYS_AVAILABLE // Allow babystepping at all times (not just during movement)
//#define BABYSTEP_XY // Also enable X/Y Babystepping. Not supported on DELTA!
//#define BABYSTEP_INVERT_Z // Enable if Z babysteps should go the other way
//#define BABYSTEP_MILLIMETER_UNITS // Specify BABYSTEP_MULTIPLICATOR_(XY|Z) in mm instead of micro-steps
#define BABYSTEP_MULTIPLICATOR_Z 1 // (steps or mm) Steps or millimeter distance for each Z babystep
#define BABYSTEP_MULTIPLICATOR_Z 25 // (steps or mm) Steps or millimeter distance for each Z babystep
#define BABYSTEP_MULTIPLICATOR_XY 1 // (steps or mm) Steps or millimeter distance for each XY babystep
//#define DOUBLECLICK_FOR_Z_BABYSTEPPING // Double-click on the Status Screen for Z Babystepping.
#define DOUBLECLICK_FOR_Z_BABYSTEPPING // Double-click on the Status Screen for Z Babystepping.
#if ENABLED(DOUBLECLICK_FOR_Z_BABYSTEPPING)
#define DOUBLECLICK_MAX_INTERVAL 1250 // Maximum interval between clicks, in milliseconds.
// Note: Extra time may be added to mitigate controller latency.
@@ -2288,7 +2286,7 @@
//#define BABYSTEP_DISPLAY_TOTAL // Display total babysteps since last G28
//#define BABYSTEP_ZPROBE_OFFSET // Combine M851 Z and Babystepping
#define BABYSTEP_ZPROBE_OFFSET // Combine M851 Z and Babystepping
#if ENABLED(BABYSTEP_ZPROBE_OFFSET)
//#define BABYSTEP_HOTEND_Z_OFFSET // For multiple hotends, babystep relative Z offsets
//#define BABYSTEP_GFX_OVERLAY // Enable graphical overlay on Z-offset editor
@@ -2312,7 +2310,7 @@
*
* See https://marlinfw.org/docs/features/lin_advance.html for full instructions.
*/
//#define LIN_ADVANCE
#define LIN_ADVANCE
#if ENABLED(LIN_ADVANCE)
#if ENABLED(DISTINCT_E_FACTORS)
#define ADVANCE_K { 0.22 } // (mm) Compression length per 1mm/s extruder speed, per extruder
@@ -2505,7 +2503,7 @@
#endif
// G5 Bézier Curve Support with XYZE destination and IJPQ offsets
//#define BEZIER_CURVE_SUPPORT // Requires ~2666 bytes
#define BEZIER_CURVE_SUPPORT // Requires ~2666 bytes
#if ANY(ARC_SUPPORT, BEZIER_CURVE_SUPPORT)
//#define CNC_WORKSPACE_PLANES // Allow G2/G3/G5 to operate in XY, ZX, or YZ planes
@@ -2566,7 +2564,7 @@
*
* Override the default value based on the driver type set in Configuration.h.
*/
//#define MINIMUM_STEPPER_PULSE 2
//#define MINIMUM_STEPPER_PULSE 5
/**
* Maximum stepping rate (in Hz) the stepper driver allows
@@ -2580,7 +2578,7 @@
*
* Override the default value based on the driver type set in Configuration.h.
*/
//#define MAXIMUM_STEPPER_RATE 250000
//#define MAXIMUM_STEPPER_RATE 150000
// @section temperature
@@ -2597,16 +2595,16 @@
#if ALL(HAS_MEDIA, DIRECT_STEPPING)
#define BLOCK_BUFFER_SIZE 8
#elif HAS_MEDIA
#define BLOCK_BUFFER_SIZE 16
#define BLOCK_BUFFER_SIZE 32
#else
#define BLOCK_BUFFER_SIZE 16
#define BLOCK_BUFFER_SIZE 32
#endif
// @section serial
// The ASCII buffer for serial input
#define MAX_CMD_SIZE 96
#define BUFSIZE 4
#define BUFSIZE 16
// Transmission to Host Buffer Size
// To save 386 bytes of flash (and TX_BUFFER_SIZE+3 bytes of RAM) set to 0.
@@ -2653,7 +2651,7 @@
* Currently handles M108, M112, M410, M876
* NOTE: Not yet implemented for all platforms.
*/
//#define EMERGENCY_PARSER
#define EMERGENCY_PARSER
/**
* Realtime Reporting (requires EMERGENCY_PARSER)
@@ -2684,7 +2682,7 @@
//#define NO_TIMEOUTS 1000 // (ms)
// Some clients will have this feature soon. This could make the NO_TIMEOUTS unnecessary.
//#define ADVANCED_OK
#define ADVANCED_OK
// Printrun may have trouble receiving long strings all at once.
// This option inserts short delays between lines of serial output.
@@ -2697,7 +2695,7 @@
* This feature is EXPERIMENTAL so use with caution and test thoroughly.
* Enable this option to receive data on the serial ports via the onboard DMA
* controller for more stable and reliable high-speed serial communication.
* Support is currently limited to some STM32 MCUs and all HC32 MCUs.
* Only some STM32 MCUs are currently supported.
* Note: This has no effect on emulated USB serial ports.
*/
//#define SERIAL_DMA
@@ -2886,7 +2884,7 @@
*
* Enable PARK_HEAD_ON_PAUSE to add the G-code M125 Pause and Park.
*/
//#define ADVANCED_PAUSE_FEATURE
#define ADVANCED_PAUSE_FEATURE
#if ENABLED(ADVANCED_PAUSE_FEATURE)
#define PAUSE_PARK_RETRACT_FEEDRATE 60 // (mm/s) Initial retract feedrate.
#define PAUSE_PARK_RETRACT_LENGTH 2 // (mm) Initial retract.
@@ -2926,11 +2924,11 @@
//#define FILAMENT_CHANGE_RESUME_ON_INSERT // Automatically continue / load filament when runout sensor is triggered again.
//#define PAUSE_REHEAT_FAST_RESUME // Reduce number of waits by not prompting again post-timeout before continuing.
//#define PARK_HEAD_ON_PAUSE // Park the nozzle during pause and filament change.
#define PARK_HEAD_ON_PAUSE // Park the nozzle during pause and filament change.
//#define HOME_BEFORE_FILAMENT_CHANGE // If needed, home before parking for filament change
//#define FILAMENT_LOAD_UNLOAD_GCODES // Add M701/M702 Load/Unload G-codes, plus Load/Unload in the LCD Prepare menu.
//#define FILAMENT_UNLOAD_ALL_EXTRUDERS // Allow M702 to unload all extruders above a minimum target temp (as set by M302)
#define FILAMENT_LOAD_UNLOAD_GCODES // Add M701/M702 Load/Unload G-codes, plus Load/Unload in the LCD Prepare menu.
#define FILAMENT_UNLOAD_ALL_EXTRUDERS // Allow M702 to unload all extruders above a minimum target temp (as set by M302)
#define CONFIGURE_FILAMENT_CHANGE // Add M603 G-code and menu items. Requires ~1.3K bytes of flash.
#endif
@@ -2952,14 +2950,17 @@
* Some boards have simple jumper connections! See your board's documentation.
* - These drivers can also be used with Hardware Serial.
*
* The TMC26XStepper library is required for TMC26X stepper drivers.
* https://github.com/MarlinFirmware/TMC26XStepper
*
* The TMCStepper library is required for other TMC stepper drivers.
* https://github.com/teemuatlut/TMCStepper
*
* @section tmc/config
*/
#if HAS_TRINAMIC_CONFIG
#if HAS_TRINAMIC_CONFIG || HAS_TMC26X
#define HOLD_MULTIPLIER 0.5 // Scales down the holding current from run current
#define HOLD_MULTIPLIER 0.7 // Scales down the holding current from run current
/**
* Interpolate microsteps to 256
@@ -2971,7 +2972,7 @@
#define X_CURRENT 800 // (mA) RMS current. Multiply by 1.414 for peak current.
#define X_CURRENT_HOME X_CURRENT // (mA) RMS current for sensorless homing
#define X_MICROSTEPS 16 // 0..256
#define X_RSENSE 0.11
#define X_RSENSE 0.022 // Multiplied x1000 for TMC26X
#define X_CHAIN_POS -1 // -1..0: Not chained. 1: MCU MOSI connected. 2: Next in chain, ...
//#define X_INTERPOLATE true // Enable to override 'INTERPOLATE' for the X axis
//#define X_HOLD_MULTIPLIER 0.5 // Enable to override 'HOLD_MULTIPLIER' for the X axis
@@ -2991,7 +2992,7 @@
#define Y_CURRENT 800
#define Y_CURRENT_HOME Y_CURRENT
#define Y_MICROSTEPS 16
#define Y_RSENSE 0.11
#define Y_RSENSE 0.022
#define Y_CHAIN_POS -1
//#define Y_INTERPOLATE true
//#define Y_HOLD_MULTIPLIER 0.5
@@ -3108,7 +3109,7 @@
#endif
#if AXIS_IS_TMC_CONFIG(E0)
#define E0_CURRENT 800
#define E0_CURRENT 900
#define E0_MICROSTEPS 16
#define E0_RSENSE 0.11
#define E0_CHAIN_POS -1
@@ -3213,7 +3214,7 @@
* The default SW SPI pins are defined the respective pins files,
* but you can override or define them here.
*/
//#define TMC_USE_SW_SPI
#define TMC_USE_SW_SPI
//#define TMC_SPI_MOSI -1
//#define TMC_SPI_MISO -1
//#define TMC_SPI_SCK -1
@@ -3273,7 +3274,7 @@
* When disabled, Marlin will use spreadCycle stepping mode.
*/
#if HAS_STEALTHCHOP
#define STEALTHCHOP_XY
//#define STEALTHCHOP_XY
#define STEALTHCHOP_Z
#define STEALTHCHOP_I
#define STEALTHCHOP_J
@@ -3281,7 +3282,7 @@
#define STEALTHCHOP_U
#define STEALTHCHOP_V
#define STEALTHCHOP_W
#define STEALTHCHOP_E
//#define STEALTHCHOP_E
#endif
/**
@@ -3299,11 +3300,11 @@
* Define your own with:
* { <off_time[1..15]>, <hysteresis_end[-3..12]>, hysteresis_start[1..8] }
*/
#define CHOPPER_TIMING CHOPPER_DEFAULT_12V // All axes (override below)
//#define CHOPPER_TIMING_X CHOPPER_TIMING // For X Axes (override below)
//#define CHOPPER_TIMING CHOPPER_DEFAULT_36V // All axes (override below)
#define CHOPPER_TIMING_X CHOPPER_DEFAULT_36V // For X Axes (override below)
//#define CHOPPER_TIMING_X2 CHOPPER_TIMING_X
//#define CHOPPER_TIMING_Y CHOPPER_TIMING // For Y Axes (override below)
//#define CHOPPER_TIMING_Y2 CHOPPER_TIMING_Y
#define CHOPPER_TIMING_Y CHOPPER_DEFAULT_36V // For Y Axes (override below)
#define CHOPPER_TIMING_Y2 CHOPPER_TIMING_Y
//#define CHOPPER_TIMING_Z CHOPPER_TIMING // For Z Axes (override below)
//#define CHOPPER_TIMING_Z2 CHOPPER_TIMING_Z
//#define CHOPPER_TIMING_Z3 CHOPPER_TIMING_Z
@@ -3314,7 +3315,7 @@
//#define CHOPPER_TIMING_U CHOPPER_TIMING // For U Axis
//#define CHOPPER_TIMING_V CHOPPER_TIMING // For V Axis
//#define CHOPPER_TIMING_W CHOPPER_TIMING // For W Axis
//#define CHOPPER_TIMING_E CHOPPER_TIMING // For Extruders (override below)
#define CHOPPER_TIMING_E CHOPPER_DEFAULT_24V // For Extruders (override below)
//#define CHOPPER_TIMING_E1 CHOPPER_TIMING_E
//#define CHOPPER_TIMING_E2 CHOPPER_TIMING_E
//#define CHOPPER_TIMING_E3 CHOPPER_TIMING_E
@@ -3336,12 +3337,12 @@
* M912 - Clear stepper driver overtemperature pre-warn condition flag.
* M122 - Report driver parameters (Requires TMC_DEBUG)
*/
//#define MONITOR_DRIVER_STATUS
#define MONITOR_DRIVER_STATUS
#if ENABLED(MONITOR_DRIVER_STATUS)
#define CURRENT_STEP_DOWN 50 // [mA]
#define REPORT_CURRENT_CHANGE
#define STOP_ON_ERROR
//#define STOP_ON_ERROR
#endif
// @section tmc/hybrid
@@ -3443,7 +3444,7 @@
/**
* Step on both rising and falling edge signals (as with a square wave).
*/
//#define EDGE_STEPPING
#define EDGE_STEPPING
/**
* Enable M122 debugging command for TMC stepper drivers.
@@ -3464,7 +3465,7 @@
*/
#define TMC_ADV() { }
#endif // HAS_TRINAMIC_CONFIG
#endif // HAS_TRINAMIC_CONFIG || HAS_TMC26X
// @section i2cbus
@@ -3557,7 +3558,7 @@
* Add the M3, M4, and M5 commands to turn the spindle/laser on and off, and
* to set spindle speed, spindle direction, and laser power.
*
* SuperPID is a router/spindle speed controller used in the CNC milling community.
* SuperPid is a router/spindle speed controller used in the CNC milling community.
* Marlin can be used to turn the spindle on and off. It can also be used to set
* the spindle speed from 5,000 to 30,000 RPM.
*
@@ -4112,14 +4113,14 @@
* Host Prompt Support enables Marlin to use the host for user prompts so
* filament runout and other processes can be managed from the host side.
*/
//#define HOST_ACTION_COMMANDS
#define HOST_ACTION_COMMANDS
#if ENABLED(HOST_ACTION_COMMANDS)
//#define HOST_PAUSE_M76 // Tell the host to pause in response to M76
//#define HOST_PROMPT_SUPPORT // Initiate host prompts to get user feedback
#define HOST_PROMPT_SUPPORT // Initiate host prompts to get user feedback
#if ENABLED(HOST_PROMPT_SUPPORT)
//#define HOST_STATUS_NOTIFICATIONS // Send some status messages to the host as notifications
#define HOST_STATUS_NOTIFICATIONS // Send some status messages to the host as notifications
#endif
//#define HOST_START_MENU_ITEM // Add a menu item that tells the host to start
#define HOST_START_MENU_ITEM // Add a menu item that tells the host to start
//#define HOST_SHUTDOWN_MENU_ITEM // Add a menu item that tells the host to shut down
#endif
@@ -4260,8 +4261,7 @@
/**
* Instant freeze / unfreeze functionality
* Potentially useful for rapid stop that allows being resumed. Halts stepper movement.
* Note this does NOT pause spindles, lasers, fans, heaters or any other auxiliary device.
* Potentially useful for emergency stop that allows being resumed.
* @section interface
*/
//#define FREEZE_FEATURE
@@ -4308,7 +4308,6 @@
// See class CodeProfiler.
//#define MAX7219_DEBUG_MULTISTEPPING 6 // Show multi-stepping 1 to 128 on this LED matrix row.
//#define MAX7219_DEBUG_SLOWDOWN 6 // Count (mod 16) how many times SLOWDOWN has reduced print speed.
//#define MAX7219_REINIT_ON_POWERUP // Re-initialize MAX7129 when power supply turns on
#endif
/**
@@ -4342,7 +4341,7 @@
* Extras for an ESP32-based motherboard with WIFISUPPORT
* These options don't apply to add-on WiFi modules based on ESP32 WiFi101.
*/
#if ANY(WIFISUPPORT, ESP3D_WIFISUPPORT)
#if ENABLED(WIFISUPPORT)
//#define WEBSUPPORT // Start a webserver (which may include auto-discovery) using SPIFFS
//#define OTASUPPORT // Support over-the-air firmware updates
//#define WIFI_CUSTOM_COMMAND // Accept feature config commands (e.g., WiFi ESP3D) from the host
@@ -4489,7 +4488,7 @@
//
// M42 - Set pin states
//
//#define DIRECT_PIN_CONTROL
#define DIRECT_PIN_CONTROL
//
// M43 - display pin status, toggle pins, watch pins, watch endstops & toggle LED, test servo probe
@@ -4525,6 +4524,3 @@
// Report uncleaned reset reason from register r2 instead of MCUSR. Supported by Optiboot on AVR.
//#define OPTIBOOT_RESET_REASON
// Shrink the build for smaller boards by sacrificing some serial feedback
//#define MARLIN_SMALL_BUILD
+1 -2
View File
@@ -53,12 +53,11 @@ typedef uint64_t hal_timer_t;
#if ENABLED(I2S_STEPPER_STREAM)
#define STEPPER_TIMER_PRESCALE 1
#define STEPPER_TIMER_RATE 250000 // 250khz, 4µs pulses of i2s word clock
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs // wrong would be 0.25
#else
#define STEPPER_TIMER_PRESCALE 40
#define STEPPER_TIMER_RATE ((HAL_TIMER_RATE) / (STEPPER_TIMER_PRESCALE)) // frequency of stepper timer, 2MHz
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs
#endif
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs
#define STEP_TIMER_MIN_INTERVAL 8 // minimum time in µs between stepper interrupts
+125
View File
@@ -0,0 +1,125 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifdef TARGET_LPC4078
#include "../../inc/MarlinConfig.h"
#include "../shared/Delay.h"
#include "../../../gcode/parser.h"
DefaultSerial1 USBSerial(false, MCDCSerial0);
uint32_t MarlinHAL::adc_result = 0;
// U8glib required functions
extern "C" {
void u8g_xMicroDelay(uint16_t val) { DELAY_US(val); }
void u8g_MicroDelay() { u8g_xMicroDelay(1); }
void u8g_10MicroDelay() { u8g_xMicroDelay(10); }
void u8g_Delay(uint16_t val) { delay(val); }
}
// return free heap space
int freeMemory() {
char stack_end;
void *heap_start = malloc(sizeof(uint32_t));
if (heap_start == 0) return 0;
uint32_t result = (uint32_t)&stack_end - (uint32_t)heap_start;
free(heap_start);
return result;
}
void MarlinHAL::reboot() { MCUCore::nvic_system_reset(); }
uint8_t MarlinHAL::get_reset_source() {
#if ENABLED(USE_WATCHDOG)
if (watchdog_timed_out()) return RST_WATCHDOG;
#endif
return RST_POWER_ON;
}
void MarlinHAL::clear_reset_source() { watchdog_clear_timeout_flag(); }
void flashFirmware(const int16_t) {
delay(500); // Give OS time to disconnect
//USB_Connect(false); // USB clear connection
delay(1000); // Give OS time to notice
hal.reboot();
}
#if ENABLED(USE_WATCHDOG)
#define WDT_TIMEOUT TERN(WATCHDOG_DURATION_8S, 8.0f, 4.0f) // 4 or 8 second timeout
void MarlinHAL::watchdog_init() {
#if ENABLED(WATCHDOG_RESET_MANUAL)
// We enable the watchdog timer, but only for the interrupt.
// Configure WDT to only trigger an interrupt
// Disable WDT interrupt (just in case, to avoid triggering it!)
NVIC_DisableIRQ(WDT_IRQn);
// We NEED memory barriers to ensure Interrupts are actually disabled!
// ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
__DSB();
__ISB();
// WDT defaults to trigger an interrupt
// Configure and enable WDT interrupt.
NVIC_ClearPendingIRQ(WDT_IRQn);
NVIC_SetPriority(WDT_IRQn, 0); // Use highest priority, so we detect all kinds of lockups
NVIC_EnableIRQ(WDT_IRQn);
#else
MCUI::watchdog_set_timeout_triggers_reset();
#endif
MCUI::watchdog_set_timeout_in_seconds(WDT_TIMEOUT);
MCUI::watchdog_enable();
}
void MarlinHAL::watchdog_refresh() {
MCUI::watchdog_feed();
#if DISABLED(PINS_DEBUGGING) && PIN_EXISTS(LED)
static millis_t next_flash = millis();
if (ELAPSED(millis(), next_flash)) {
next_flash = millis() + 200;
TOGGLE(LED_PIN); // heartbeat indicator
}
#endif
}
// Timeout state
bool MarlinHAL::watchdog_timed_out() { return MCUI::watchdog_has_triggered(); }
void MarlinHAL::watchdog_clear_timeout_flag() { MCUI::watchdog_clear_timeout_flag(); }
#endif // USE_WATCHDOG
// For M42/M43, scan command line for pin code
// return index into pin map array if found and the pin is valid.
// return dval if not found or not a valid pin.
int16_t PARSED_PIN_INDEX(const char code, const int16_t dval) {
const uint16_t val = (uint16_t)parser.intval(code, -1), port = val / 100, pin = val % 100;
const int16_t ind = (port < ((NUM_DIGITAL_PINS) >> 5) && pin < 32) ? ((port << 5) | pin) : -2;
return ind > -1 ? ind : dval;
}
#endif // TARGET_LPC4078
+276
View File
@@ -0,0 +1,276 @@
/**
* Marlin 3D Printer Firmware
*
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
* Copyright (c) 2016 Bob Cousins bobcousins42@googlemail.com
* Copyright (c) 2015-2016 Nico Tonnhofer wurstnase.reprap@gmail.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
/**
* HAL_LPC1768/HAL.h
* Hardware Abstraction Layer for NXP LPC1768
*/
#define CPU_32_BIT
#include <stdint.h>
#include <stdarg.h>
#include <algorithm>
#include "../shared/Marduino.h"
#include "../shared/Delay.h"
#include "../shared/math_32bit.h"
#include "../shared/HAL_SPI.h"
#include "fastio.h"
#include "MarlinSerial.h"
#include <mcu_interface.h>
// ------------------------
// Serial ports
// ------------------------
typedef ForwardSerial1Class< decltype(MCDCSerial0) > DefaultSerial1;
extern DefaultSerial1 USBSerial;
#define _MSERIAL(X) MSerial##X
#define MSERIAL(X) _MSERIAL(X)
#if SERIAL_PORT == -1
#define MYSERIAL1 USBSerial
#elif WITHIN(SERIAL_PORT, 0, 3)
#define MYSERIAL1 MSERIAL(SERIAL_PORT)
#else
#error "SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
#endif
#ifdef SERIAL_PORT_2
#if SERIAL_PORT_2 == -1
#define MYSERIAL2 USBSerial
#elif WITHIN(SERIAL_PORT_2, 0, 3)
#define MYSERIAL2 MSERIAL(SERIAL_PORT_2)
#else
#error "SERIAL_PORT_2 must be from 0 to 3. You can also use -1 if the board supports Native USB."
#endif
#endif
#ifdef SERIAL_PORT_3
#if SERIAL_PORT_3 == -1
#define MYSERIAL3 USBSerial
#elif WITHIN(SERIAL_PORT_3, 0, 3)
#define MYSERIAL3 MSERIAL(SERIAL_PORT_3)
#else
#error "SERIAL_PORT_3 must be from 0 to 3. You can also use -1 if the board supports Native USB."
#endif
#endif
#ifdef MMU2_SERIAL_PORT
#if MMU2_SERIAL_PORT == -1
#define MMU2_SERIAL USBSerial
#elif WITHIN(MMU2_SERIAL_PORT, 0, 3)
#define MMU2_SERIAL MSERIAL(MMU2_SERIAL_PORT)
#else
#error "MMU2_SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
#endif
#endif
#ifdef LCD_SERIAL_PORT
#if LCD_SERIAL_PORT == -1
#define LCD_SERIAL USBSerial
#elif WITHIN(LCD_SERIAL_PORT, 0, 3)
#define LCD_SERIAL MSERIAL(LCD_SERIAL_PORT)
#else
#error "LCD_SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
#endif
#if HAS_DGUS_LCD
#define SERIAL_GET_TX_BUFFER_FREE() LCD_SERIAL.available()
#endif
#endif
//
// Interrupts
//
#define CRITICAL_SECTION_START() const bool irqon = !MCUCore::primask(); MCUCore::nvic_interrupts_disable()
#define CRITICAL_SECTION_END() if (irqon) MCUCore::nvic_interrupts_enable()
#define cli() noInterrupts()
#define sei() interrupts()
//
// ADC
//
#define ADC_MEDIAN_FILTER_SIZE (23) // Higher values increase step delay (phase shift),
// (ADC_MEDIAN_FILTER_SIZE + 1) / 2 sample step delay (12 samples @ 500Hz: 24ms phase shift)
// Memory usage per ADC channel (bytes): (6 * ADC_MEDIAN_FILTER_SIZE) + 16
// 8 * ((6 * 23) + 16 ) = 1232 Bytes for 8 channels
#define ADC_LOWPASS_K_VALUE (2) // Higher values increase rise time
// Rise time sample delays for 100% signal convergence on full range step
// (1 : 13, 2 : 32, 3 : 67, 4 : 139, 5 : 281, 6 : 565, 7 : 1135, 8 : 2273)
// K = 6, 565 samples, 500Hz sample rate, 1.13s convergence on full range step
// Memory usage per ADC channel (bytes): 4 (32 Bytes for 8 channels)
#define HAL_ADC_VREF 3.3 // ADC voltage reference
#define HAL_ADC_RESOLUTION 12 // 15 bit maximum, raw temperature is stored as int16_t
#define HAL_ADC_FILTERED // Disable oversampling done in Marlin as ADC values already filtered in HAL
//
// Pin Mapping for M42, M43, M226
//
// Test whether the pin is valid
constexpr bool VALID_PIN(const pin_t pin) {
return MCUI::pin_is_valid(pin);
}
// Get the analog index for a digital pin
constexpr int8_t DIGITAL_PIN_TO_ANALOG_PIN(const pin_t pin) {
return (MCUI::pin_is_valid(pin) && MCUI::pin_has_adc(pin)) ? pin : -1;
}
//
// Misc. Functions
//
#ifndef analogInputToDigitalPin
#define analogInputToDigitalPin(p) (p)
#endif
// Return the index of a pin number
constexpr int16_t GET_PIN_MAP_INDEX(const pin_t pin) {
return MCUI::pin_index(pin);
}
// Get the pin number at the given index
constexpr pin_t GET_PIN_MAP_PIN(const int16_t index) {
return MCUI::pin_index(index);
}
// Parse a G-code word into a pin index
int16_t PARSED_PIN_INDEX(const char code, const int16_t dval);
// P0.6 thru P0.9 are for the onboard SD card
#define HAL_SENSITIVE_PINS P0_06, P0_07, P0_08, P0_09,
// ------------------------
// Defines
// ------------------------
void flashFirmware(const int16_t);
#define HAL_CAN_SET_PWM_FREQ // This HAL supports PWM Frequency adjustment
// Default graphical display delays
#define CPU_ST7920_DELAY_1 600
#define CPU_ST7920_DELAY_2 750
#define CPU_ST7920_DELAY_3 750
// ------------------------
// Free Memory Accessor
// ------------------------
#pragma GCC diagnostic push
#if GCC_VERSION <= 50000
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
int freeMemory();
#pragma GCC diagnostic pop
// ------------------------
// MarlinHAL Class
// ------------------------
class MarlinHAL {
public:
// Earliest possible init, before setup()
MarlinHAL() {}
static void init(); // Called early in setup()
static void init_board() {} // Called less early in setup()
static void reboot(); // Restart the firmware from 0x0
// Interrupts
static bool isr_state() { return MCUCore::primask(); }
static void isr_on() { MCUCore::nvic_interrupts_enable(); }
static void isr_off() { MCUCore::nvic_interrupts_disable(); }
static void delay_ms(const int ms) { DELAY_US(ms * 1000); }
// Watchdog
static void watchdog_init() IF_DISABLED(USE_WATCHDOG, {});
static void watchdog_refresh() IF_DISABLED(USE_WATCHDOG, {});
static bool watchdog_timed_out() IF_DISABLED(USE_WATCHDOG, { return false; });
static void watchdog_clear_timeout_flag() IF_DISABLED(USE_WATCHDOG, {});
// Tasks, called from idle()
static void idletask();
// Reset
static uint8_t get_reset_source();
static void clear_reset_source();
// Free SRAM
static int freeMemory() { return ::freeMemory(); }
//
// ADC Methods
//
using FilteredADC = MCUI::ADC<ADC_LOWPASS_K_VALUE, ADC_MEDIAN_FILTER_SIZE>;
// Called by Temperature::init once at startup
static void adc_init() {
// Turn on and initialise ADC in burst mode
MCUI::adc_hardware.init();
MCUI::adc_hardware.burst_start();
}
// Called by Temperature::init for each sensor at startup
static void adc_enable(const pin_t pin) {
FilteredADC::enable_channel(pin);
}
// Begin ADC sampling on the given pin. Called from Temperature::isr!
static uint32_t adc_result;
static void adc_start(const pin_t pin) {
adc_result = FilteredADC::read(pin) >> (16 - HAL_ADC_RESOLUTION); // returns 16bit value, reduce to required bits
}
// Is the ADC ready for reading?
static bool adc_ready() { return true; }
// The current value of the ADC register
static uint16_t adc_value() { return uint16_t(adc_result); }
/**
* Set the PWM duty cycle for the pin to the given value.
* Optionally invert the duty cycle [default = false]
* Optionally change the scale of the provided value to enable finer PWM duty control [default = 255]
*/
static void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255, const bool invert=false);
/**
* Set the frequency of the timer corresponding to the provided pin
* All Hardware PWM pins will run at the same frequency and
* All Software PWM pins will run at the same frequency
*/
static void set_pwm_frequency(const pin_t pin, const uint16_t f_desired);
};
+376
View File
@@ -0,0 +1,376 @@
// /**
// * Marlin 3D Printer Firmware
// * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
// *
// * Based on Sprinter and grbl.
// * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
// *
// * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
// * the Free Software Foundation, either version 3 of the License, or
// * (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have received a copy of the GNU General Public License
// * along with this program. If not, see <https://www.gnu.org/licenses/>.
// *
// */
// /**
// * Software SPI functions originally from Arduino Sd2Card Library
// * Copyright (c) 2009 by William Greiman
// */
// /**
// * For TARGET_LPC4078
// */
// /**
// * Hardware SPI and Software SPI implementations are included in this file.
// * The hardware SPI runs faster and has higher throughput but is not compatible
// * with some LCD interfaces/adapters.
// *
// * Control of the slave select pin(s) is handled by the calling routines.
// *
// * Some of the LCD interfaces/adapters result in the LCD SPI and the SD card
// * SPI sharing pins. The SCK, MOSI & MISO pins can NOT be set/cleared with
// * WRITE nor digitalWrite when the hardware SPI module within the LPC17xx is
// * active. If any of these pins are shared then the software SPI must be used.
// *
// * A more sophisticated hardware SPI can be found at the following link.
// * This implementation has not been fully debugged.
// * https://github.com/MarlinFirmware/Marlin/tree/071c7a78f27078fd4aee9a3ef365fcf5e143531e
// */
#ifdef TARGET_LPC4078
#include "../../inc/MarlinConfig.h"
#include <SPI.h>
// Hardware SPI and SPIClass
#include "../shared/HAL_SPI.h"
#define LPC_SOFTWARE_SPI
// ------------------------
// Public functions
// ------------------------
#if ENABLED(LPC_SOFTWARE_SPI)
#include "SoftwareSPI.h"
// Software SPI
static uint8_t SPI_speed = SPI_FULL_SPEED;
static uint8_t spiTransfer(uint8_t b) {
return swSpiTransfer(b, SPI_speed, SD_SCK_PIN, SD_MISO_PIN, SD_MOSI_PIN);
}
void spiBegin() {
swSpiBegin(SD_SCK_PIN, SD_MISO_PIN, SD_MOSI_PIN);
}
void spiInit(uint8_t spiRate) {
SPI_speed = swSpiInit(spiRate, SD_SCK_PIN, SD_MOSI_PIN);
}
uint8_t spiRec() { return spiTransfer(0xFF); }
void spiRead(uint8_t*buf, uint16_t nbyte) {
for (int i = 0; i < nbyte; i++)
buf[i] = spiTransfer(0xFF);
}
void spiSend(uint8_t b) { (void)spiTransfer(b); }
void spiSend(const uint8_t *buf, size_t nbyte) {
for (uint16_t i = 0; i < nbyte; i++)
(void)spiTransfer(buf[i]);
}
void spiSendBlock(uint8_t token, const uint8_t *buf) {
(void)spiTransfer(token);
for (uint16_t i = 0; i < 512; i++)
(void)spiTransfer(buf[i]);
}
#else
#ifdef SD_SPI_SPEED
#define INIT_SPI_SPEED SD_SPI_SPEED
#else
#define INIT_SPI_SPEED SPI_FULL_SPEED
#endif
void spiBegin() { spiInit(INIT_SPI_SPEED); } // Set up SCK, MOSI & MISO pins for SSP0
void spiInit(uint8_t spiRate) {
#if SD_MISO_PIN == BOARD_SPI1_MISO_PIN
SPI.setModule(1);
#elif SD_MISO_PIN == BOARD_SPI2_MISO_PIN
SPI.setModule(2);
#endif
SPI.setDataSize(DATA_SIZE_8BIT);
SPI.setDataMode(SPI_MODE0);
SPI.setClock(SPISettings::spiRate2Clock(spiRate));
SPI.begin();
}
static uint8_t doio(uint8_t b) {
return SPI.transfer(b & 0x00FF) & 0x00FF;
}
void spiSend(uint8_t b) { doio(b); }
void spiSend(const uint8_t *buf, size_t nbyte) {
for (uint16_t i = 0; i < nbyte; i++) doio(buf[i]);
}
void spiSend(uint32_t chan, byte b) {}
void spiSend(uint32_t chan, const uint8_t *buf, size_t nbyte) {}
// Read single byte from SPI
uint8_t spiRec() { return doio(0xFF); }
uint8_t spiRec(uint32_t chan) { return 0; }
// Read from SPI into buffer
void spiRead(uint8_t *buf, uint16_t nbyte) {
for (uint16_t i = 0; i < nbyte; i++) buf[i] = doio(0xFF);
}
uint8_t spiTransfer(uint8_t b) { return doio(b); }
// Write from buffer to SPI
void spiSendBlock(uint8_t token, const uint8_t *buf) {
(void)spiTransfer(token);
for (uint16_t i = 0; i < 512; i++)
(void)spiTransfer(buf[i]);
}
// Begin SPI transaction, set clock, bit order, data mode
void spiBeginTransaction(uint32_t spiClock, uint8_t bitOrder, uint8_t dataMode) {
// TODO: Implement this method
}
#endif // LPC_SOFTWARE_SPI
// /**
// * @brief Wait until TXE (tx empty) flag is set and BSY (busy) flag unset.
// */
static inline void waitSpiTxEnd(void *spi_d) {
// while (SSP_GetStatus(spi_d, SSP_STAT_TXFIFO_EMPTY) == RESET) { /* nada */ } // wait until TXE=1
// while (SSP_GetStatus(spi_d, SSP_STAT_BUSY) == SET) { /* nada */ } // wait until BSY=0
}
// // Retain the pin init state of the SPI, to avoid init more than once,
// // even if more instances of SPIClass exist
static bool spiInitialised[BOARD_NR_SPI] = {};
SPIClass::SPIClass(uint8_t device) {
// // Init things specific to each SPI device
// // clock divider setup is a bit of hack, and needs to be improved at a later date.
#if BOARD_NR_SPI >= 1
_settings[0].device_id = 0;
_settings[0].m_config.pin_miso = BOARD_SPI1_MISO_PIN;
_settings[0].m_config.pin_mosi = BOARD_SPI1_MOSI_PIN;
_settings[0].m_config.pin_sck = BOARD_SPI1_SCK_PIN;
_settings[0].m_config.pin_ssel = BOARD_SPI1_NSS_PIN;
_settings[0].m_config.frequency = 100000;
_settings[0].m_config.data_bits = 8;
_settings[0].m_config.mode = 0;
_settings[0].m_config.format = MCUI::SSP::Config::Format::SPI;
// _settings[0].dataMode = SPI_MODE0;
// _settings[0].dataSize = DATA_SIZE_8BIT;
// _settings[0].clock = SPI_CLOCK_MAX;
// //_settings[0].clockDivider = determine_baud_rate(_settings[0].spi_d, _settings[0].clock);
#endif
#if BOARD_NR_SPI >= 2
_settings[1].device_id = 2;
_settings[1].m_config.pin_miso = BOARD_SPI2_MISO_PIN;
_settings[1].m_config.pin_mosi = BOARD_SPI2_MOSI_PIN;
_settings[1].m_config.pin_sck = BOARD_SPI2_SCK_PIN;
_settings[1].m_config.pin_ssel = BOARD_SPI2_NSS_PIN;
// _settings[1].dataMode = SPI_MODE0;
// _settings[1].dataSize = DATA_SIZE_8BIT;
// _settings[1].clock = SPI_CLOCK_MAX;
// //_settings[1].clockDivider = determine_baud_rate(_settings[1].spi_d, _settings[1].clock);
#endif
#if BOARD_NR_SPI >= 3
_settings[2].device_id = 1;
_settings[2].m_config.pin_miso = BOARD_SPI3_MISO_PIN;
_settings[2].m_config.pin_mosi = BOARD_SPI3_MOSI_PIN;
_settings[2].m_config.pin_sck = BOARD_SPI3_SCK_PIN;
_settings[2].m_config.pin_ssel = BOARD_SPI3_NSS_PIN;
// _settings[1].dataMode = SPI_MODE0;
// _settings[1].dataSize = DATA_SIZE_8BIT;
// _settings[1].clock = SPI_CLOCK_MAX;
// //_settings[1].clockDivider = determine_baud_rate(_settings[1].spi_d, _settings[1].clock);
#endif
setModule(device);
// // Init the GPDMA controller
// // TODO: call once in the constructor? or each time?
// GPDMA_Init();
}
SPIClass::SPIClass(pin_t mosi, pin_t miso, pin_t sclk, pin_t ssel) {
#if BOARD_NR_SPI >= 1
if (mosi == BOARD_SPI1_MOSI_PIN) SPIClass(1);
#endif
#if BOARD_NR_SPI >= 2
if (mosi == BOARD_SPI2_MOSI_PIN) SPIClass(2);
#endif
#if BOARD_NR_SPI >= 3
if (mosi == BOARD_SPI3_MOSI_PIN) SPIClass(3);
#endif
}
void SPIClass::begin() {
// // Init the SPI pins in the first begin call
if ((_currentSetting->device_id == 0 && spiInitialised[0] == false) ||
(_currentSetting->device_id == 1 && spiInitialised[1] == false) ||
(_currentSetting->device_id == 2 && spiInitialised[2] == false)) {
MCUI::SSP::init(_currentSetting->device_id, _currentSetting->m_config);
spiInitialised[_currentSetting->device_id] = true;
}
updateSettings();
}
void SPIClass::beginTransaction(const SPISettings &cfg) {
setBitOrder(cfg.bitOrder);
setDataMode(cfg.dataMode);
setDataSize(cfg.dataSize);
//setClockDivider(determine_baud_rate(_currentSetting->spi_d, settings.clock));
begin();
}
uint8_t SPIClass::transfer(const uint16_t b) {
uint16_t rx_word = 0;
// clear rx fifo
while(MCUI::SSP::read(_currentSetting->device_id, &rx_word) == 1);
MCUI::SSP::write(_currentSetting->device_id, b);
while(MCUI::SSP::read(_currentSetting->device_id, &rx_word) != 1);
return rx_word;
}
uint16_t SPIClass::transfer16(const uint16_t data) {
return (transfer((data >> 8) & 0xFF) << 8) | (transfer(data & 0xFF) & 0xFF);
}
void SPIClass::end() {
// // Neither is needed for Marlin
// //SSP_Cmd(_currentSetting->spi_d, DISABLE);
// //SSP_DeInit(_currentSetting->spi_d);
}
void SPIClass::send(uint8_t data) {
MCUI::SSP::write(_currentSetting->device_id, data);
}
void SPIClass::dmaSend(void *buf, uint16_t length, bool minc) {
// //TODO: LPC dma can only write 0xFFF bytes at once.
// GPDMA_Channel_CFG_Type GPDMACfg;
// /* Configure GPDMA channel 0 -------------------------------------------------------------*/
// /* DMA Channel 0 */
// GPDMACfg.ChannelNum = 0;
// // Source memory
// GPDMACfg.SrcMemAddr = (uint32_t)buf;
// // Destination memory - Not used
// GPDMACfg.DstMemAddr = 0;
// // Transfer size
// GPDMACfg.TransferSize = length;
// // Transfer width
// GPDMACfg.TransferWidth = (_currentSetting->dataSize == DATA_SIZE_16BIT) ? GPDMA_WIDTH_HALFWORD : GPDMA_WIDTH_BYTE;
// // Transfer type
// GPDMACfg.TransferType = GPDMA_TRANSFERTYPE_M2P;
// // Source connection - unused
// GPDMACfg.SrcConn = 0;
// // Destination connection
// GPDMACfg.DstConn = (_currentSetting->spi_d == LPC_SSP0) ? GPDMA_CONN_SSP0_Tx : GPDMA_CONN_SSP1_Tx;
// GPDMACfg.DMALLI = 0;
// // Enable dma on SPI
// SSP_DMACmd(_currentSetting->spi_d, SSP_DMA_TX, ENABLE);
// // Only increase memory if minc is true
// GPDMACfg.MemoryIncrease = (minc ? GPDMA_DMACCxControl_SI : 0);
// // Setup channel with given parameter
// GPDMA_Setup(&GPDMACfg);
// // Enable DMA
// GPDMA_ChannelCmd(0, ENABLE);
// // Wait for data transfer
// while (!GPDMA_IntGetStatus(GPDMA_STAT_RAWINTTC, 0) && !GPDMA_IntGetStatus(GPDMA_STAT_RAWINTERR, 0)) { }
// // Clear err and int
// GPDMA_ClearIntPending (GPDMA_STATCLR_INTTC, 0);
// GPDMA_ClearIntPending (GPDMA_STATCLR_INTERR, 0);
// // Disable DMA
// GPDMA_ChannelCmd(0, DISABLE);
// waitSpiTxEnd(_currentSetting->spi_d);
// SSP_DMACmd(_currentSetting->spi_d, SSP_DMA_TX, DISABLE);
}
uint16_t SPIClass::read() {
uint16_t rx_word = 0;
MCUI::SSP::read(_currentSetting->device_id, &rx_word);
return rx_word;
}
void SPIClass::read(uint8_t *buf, uint32_t len) {
uint16_t rx_word = 0;
// clear rx fifo
while(MCUI::SSP::read(_currentSetting->device_id, &rx_word) == 1);
for (uint16_t i = 0; i < len; i++) {
MCUI::SSP::write(_currentSetting->device_id, 0xFF);
while(MCUI::SSP::read(_currentSetting->device_id, &rx_word) != 1);
buf[i] = rx_word;
}
}
void SPIClass::setClock(uint32_t clock) { _currentSetting->clock = clock; }
void SPIClass::setModule(uint8_t device) { _currentSetting = &_settings[device - 1]; } // SPI channels are called 1, 2, and 3 but the array is zero-indexed
void SPIClass::setBitOrder(uint8_t bitOrder) { _currentSetting->bitOrder = bitOrder; }
void SPIClass::setDataMode(uint8_t dataMode) { _currentSetting->dataMode = dataMode; }
void SPIClass::setDataSize(uint32_t dataSize) { _currentSetting->dataSize = dataSize; }
// /**
// * Set up/tear down
// */
void SPIClass::updateSettings() {
MCUI::SSP::configure(_currentSetting->device_id, _currentSetting->m_config);
}
SPIClass SPI(1);
#if SD_MISO_PIN == BOARD_SPI1_MISO_PIN
SPIClass SPI(1);
#elif SD_MISO_PIN == BOARD_SPI2_MISO_PIN
SPIClass SPI(2);
#endif
#endif // TARGET_LPC4078
+45
View File
@@ -0,0 +1,45 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#include <SPI.h>
/**
* Marlin currently requires 3 SPI classes:
*
* SPIClass:
* This class is normally provided by frameworks and has a semi-default interface.
* This is needed because some libraries reference it globally.
*
* SPISettings:
* Container for SPI configs for SPIClass. As above, libraries may reference it globally.
*
* These two classes are often provided by frameworks so we cannot extend them to add
* useful methods for Marlin.
*
* MarlinSPI:
* Provides the default SPIClass interface plus some Marlin goodies such as a simplified
* interface for SPI DMA transfer.
*
*/
using MarlinSPI = SPIClass;
+78
View File
@@ -0,0 +1,78 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifdef TARGET_LPC4078
#include "MarlinSerial.h"
#include "../../inc/MarlinConfig.h"
MarlinCDCSerial MCDCSerial0;
#define MarlinSerial(ID) \
MarlinSerial _MSerial##ID(ID); \
MSerialT MSerial##ID(true, _MSerial##ID)
#if USING_HW_SERIAL0
MarlinSerial(0);
#endif
#if USING_HW_SERIAL1
MarlinSerial(1);
#endif
#if USING_HW_SERIAL2
MarlinSerial(2);
#endif
#if USING_HW_SERIAL3
MarlinSerial(3);
#endif
#if ENABLED(EMERGENCY_PARSER)
bool MarlinSerial::recv_callback(const char c) {
// Need to figure out which serial port we are and react in consequence (Marlin does not have CONTAINER_OF macro)
if (false) {}
#if USING_HW_SERIAL0
else if (this == &_MSerial0) emergency_parser.update(MSerial0.emergency_state, c);
#endif
#if USING_HW_SERIAL1
else if (this == &_MSerial1) emergency_parser.update(MSerial1.emergency_state, c);
#endif
#if USING_HW_SERIAL2
else if (this == &_MSerial2) emergency_parser.update(MSerial2.emergency_state, c);
#endif
#if USING_HW_SERIAL3
else if (this == &_MSerial3) emergency_parser.update(MSerial3.emergency_state, c);
#endif
return true;
}
#include "../../feature/e_parser.h"
EmergencyParser::State emergency_state;
bool CDC_RecvCallback(const char c) {
emergency_parser.update(emergency_state, c);
return true;
}
#endif
#endif // TARGET_LPC4078
+108
View File
@@ -0,0 +1,108 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#include <mcu_interface.h>
#include <interface/uart.h>
#include <driver/usb_cdc.h>
#include <UART.h>
#include "../../inc/MarlinConfigPre.h"
#if ENABLED(EMERGENCY_PARSER)
#include "../../feature/e_parser.h"
#endif
#include "../../core/serial_hook.h"
#ifndef SERIAL_PORT
#define SERIAL_PORT 0
#endif
#ifndef RX_BUFFER_SIZE
#define RX_BUFFER_SIZE 128
#endif
#ifndef TX_BUFFER_SIZE
#define TX_BUFFER_SIZE 32
#endif
class MarlinCDCSerial : public HardwareSerial {
public:
MarlinCDCSerial() {}
void begin(unsigned long baudrate) override {}
void begin(unsigned long baudrate, uint16_t config) override { }
void end() override { }
int available() override {
return MCUI::CDCSerial0::available();
}
int peek() override { char c = 0; return MCUI::CDCSerial0::peek((uint8_t*)&c)? c : -1; }
int read() override { char c = 0; return MCUI::CDCSerial0::read((uint8_t*)&c, 1)? c : -1; }
void flush() override {};
size_t write(uint8_t c) override { return write(&c, 1); }
size_t write(const uint8_t *buffer, size_t size) override { return MCUI::CDCSerial0::connected() ? MCUI::CDCSerial0::write(buffer, size) : 0; }
using Print::write;
operator bool() override { return true; }
};
extern MarlinCDCSerial MCDCSerial0;
class MarlinSerial : public HardwareSerial {
public:
MarlinSerial(const uint32_t uart_id) : uart_device(uart_id) {}
void begin(unsigned long baudrate) override {
uart_device.configure_pins(P0_02, P0_03);
uart_device.init({ .baud = baudrate });
#if ENABLED(EMERGENCY_PARSER)
uart_device.set_rx_callback([this](char rx_value){ return this->recv_callback(rx_value); } );
#endif
}
void begin(unsigned long baudrate, uint16_t config) override {
begin(baudrate);
}
void end() override { }
int available() override {
return uart_device.rx_available();
}
int peek() override { char c = 0; return uart_device.peek(&c)? c : -1; }
int read() override { char c = 0; return uart_device.read(&c)? c : -1; }
void flush() override {};
size_t write(uint8_t c) override { return write(&c, 1); }
size_t write(const uint8_t *buffer, size_t size) override { return uart_device.write((const char *)buffer, size); }
using Print::write; // pull in write(str) and write(buf, size) from Print
operator bool() override { return true; }
bool recv_callback(char value);
private:
MCUI::BufferedUARTC uart_device;
};
// On LPC176x framework, HardwareSerial does not implement the same interface as Arduino's Serial, so overloads
// of 'available' and 'read' method are not used in this multiple inheritance scenario.
// Instead, use a ForwardSerial here that adapts the interface.
typedef ForwardSerial1Class<MarlinSerial> MSerialT;
extern MSerialT MSerial0;
extern MSerialT MSerial1;
extern MSerialT MSerial2;
extern MSerialT MSerial3;
// Consequently, we can't use a RuntimeSerial either. The workaround would be to use
// a RuntimeSerial<ForwardSerial<MarlinSerial>> type here. Ignore for now until it's actually required.
#if ENABLED(SERIAL_RUNTIME_HOOK)
#error "SERIAL_RUNTIME_HOOK is not yet supported for LPC176x."
#endif
+51
View File
@@ -0,0 +1,51 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifdef TARGET_LPC4078
#include "../../inc/MarlinConfig.h"
#include "HAL.h"
#if ENABLED(POSTMORTEM_DEBUGGING)
#include "../shared/MinSerial.h"
#include <debug_frmwrk.h>
static void TX(char c) { _DBC(c); }
void install_min_serial() { HAL_min_serial_out = &TX; }
#if DISABLED(DYNAMIC_VECTORTABLE)
extern "C" {
__attribute__((naked)) void JumpHandler_ASM() {
__asm__ __volatile__ (
"b CommonHandler_ASM\n"
);
}
void __attribute__((naked, alias("JumpHandler_ASM"))) HardFault_Handler();
void __attribute__((naked, alias("JumpHandler_ASM"))) BusFault_Handler();
void __attribute__((naked, alias("JumpHandler_ASM"))) UsageFault_Handler();
void __attribute__((naked, alias("JumpHandler_ASM"))) MemManage_Handler();
void __attribute__((naked, alias("JumpHandler_ASM"))) NMI_Handler();
}
#endif
#endif // POSTMORTEM_DEBUGGING
#endif // TARGET_LPC4078
+69
View File
@@ -0,0 +1,69 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
/**
* servo.h - Interrupt driven Servo library for Arduino using 16 bit timers- Version 2
* Copyright (c) 2009 Michael Margolis. All right reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
/**
* Based on "servo.h - Interrupt driven Servo library for Arduino using 16 bit timers -
* Version 2 Copyright (c) 2009 Michael Margolis. All right reserved.
*
* The only modification was to update/delete macros to match the LPC176x.
*/
#include <Servo.h>
class libServo: public Servo {
public:
void move(const int value) {
constexpr uint16_t servo_delay[] = SERVO_DELAY;
static_assert(COUNT(servo_delay) == NUM_SERVOS, "SERVO_DELAY must be an array NUM_SERVOS long.");
if (attach(servo_info[servoIndex].Pin.nbr) >= 0) { // try to reattach
write(value);
safe_delay(servo_delay[servoIndex]); // delay to allow servo to reach position
TERN_(DEACTIVATE_SERVOS_AFTER_MOVE, detach());
}
}
};
class libServo;
typedef libServo hal_servo_t;
+47
View File
@@ -0,0 +1,47 @@
#ifdef TARGET_LPC4078
#include <Arduino.h>
#include "SoftwareSPI.h"
#include <mcu_interface.h>
uint8_t swSpiTransfer(uint8_t b, const uint8_t spi_speed, const pin_t sck_pin, const pin_t miso_pin, const pin_t mosi_pin) {
for (uint8_t i = 0; i < 8; i++) {
if (spi_speed == 0) {
MCUI::gpio_set(mosi_pin, !!(b & 0x80));
MCUI::gpio_set(sck_pin, HIGH);
b <<= 1;
if (miso_pin >= 0 && MCUI::gpio_get(miso_pin)) b |= 1;
MCUI::gpio_set(sck_pin, LOW);
}
else {
const uint8_t state = (b & 0x80) ? HIGH : LOW;
for (uint8_t j = 0; j < spi_speed; j++)
MCUI::gpio_set(mosi_pin, state);
for (uint8_t j = 0; j < spi_speed + (miso_pin >= 0 ? 0 : 1); j++)
MCUI::gpio_set(sck_pin, HIGH);
b <<= 1;
if (miso_pin >= 0 && MCUI::gpio_get(miso_pin)) b |= 1;
for (uint8_t j = 0; j < spi_speed; j++)
MCUI::gpio_set(sck_pin, LOW);
}
}
return b;
}
void swSpiBegin(const pin_t sck_pin, const pin_t miso_pin, const pin_t mosi_pin) {
pinMode(sck_pin, OUTPUT);
if (MCUI::pin_is_valid(miso_pin)) pinMode(miso_pin, INPUT);
pinMode(mosi_pin, OUTPUT);
}
uint8_t swSpiInit(const uint8_t spiRate, const pin_t sck_pin, const pin_t mosi_pin) {
MCUI::gpio_set(mosi_pin, HIGH);
MCUI::gpio_set(sck_pin, LOW);
return (SystemCoreClock == 120000000 ? 44 : 38) / std::pow(2, 6 - std::min(spiRate, (uint8_t)6));
}
#endif // TARGET_LPC4078
+5
View File
@@ -0,0 +1,5 @@
#include <mcu_interface.h>
uint8_t swSpiTransfer(uint8_t b, const uint8_t spi_speed, const pin_t sck_pin, const pin_t miso_pin, const pin_t mosi_pin);
void swSpiBegin(const pin_t sck_pin, const pin_t miso_pin, const pin_t mosi_pin);
uint8_t swSpiInit(const uint8_t spiRate, const pin_t sck_pin, const pin_t mosi_pin);
+116
View File
@@ -0,0 +1,116 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifdef TARGET_LPC4078
/**
* Emulate EEPROM storage using Flash Memory
*
* Use a single 32K flash sector to store EEPROM data. To reduce the
* number of erase operations a simple "leveling" scheme is used that
* maintains a number of EEPROM "slots" within the larger flash sector.
* Each slot is used in turn and the entire sector is only erased when all
* slots have been used.
*
* A simple RAM image is used to hold the EEPROM data during I/O operations
* and this is flushed to the next available slot when an update is complete.
* If RAM usage becomes an issue we could store this image in one of the two
* 16Kb I/O buffers (intended to hold DMA USB and Ethernet data, but currently
* unused).
*/
#include "../../inc/MarlinConfig.h"
#include "../shared/eeprom_api.h"
//#include <cstdio>
#ifndef MARLIN_EEPROM_SIZE
#define MARLIN_EEPROM_SIZE 4032 // 4KB
#endif
size_t PersistentStore::capacity() { return 4032; }
constexpr uint32_t page_size = MCUI::EEPROM::page_size;
uint32_t buffered_page = 0;
uint8_t page_buffer[page_size];
bool buffered_page_dirty = false;
bool PersistentStore::access_start() {
MCUI::EEPROM::init();
MCUI::EEPROM::read_page(buffered_page, page_buffer, page_size);
return true;
}
bool PersistentStore::access_finish() {
if (buffered_page_dirty) {
MCUI::EEPROM::write_page(buffered_page, page_buffer, page_size);
}
return true;
}
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
uint32_t address = pos;
//printf("Marlin::eeprom::write(pos = %d, size = %d)\n", pos, size);
uint32_t value_index = 0;
for (uint32_t addr = address; addr < address + size; ++addr) {
uint32_t page_address = addr & 0xFFFFFFC0;
if (page_address != buffered_page) {
//printf("Marlin::eeprom::write(@%ld):: page change new(%ld) != current(%d)\n",addr, page_address, buffered_page);
if (buffered_page_dirty == true) MCUI::EEPROM::write_page(buffered_page, page_buffer, page_size);
buffered_page = page_address;
buffered_page_dirty = false;
MCUI::EEPROM::read_page(buffered_page, page_buffer, page_size);
}
page_buffer[addr & ~0xFFFFFFC0] = value[value_index++];
buffered_page_dirty = true;
}
pos += size;
crc16(crc, value, size);
return false; // return true for any error
}
bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
uint32_t address = pos;
//printf("Marlin::eeprom::read(pos = %d, size = %d, writing = %d)\n", pos, size, writing);
uint32_t value_index = 0;
for (uint32_t addr = address; addr < address + size; ++addr) {
uint32_t page_address = addr & 0xFFFFFFC0;
if (page_address != buffered_page) {
if (buffered_page_dirty) {
MCUI::EEPROM::write_page(buffered_page, page_buffer, page_size);
buffered_page_dirty = false;
}
buffered_page = page_address;
MCUI::EEPROM::read_page(buffered_page, page_buffer, page_size);
}
if (writing) value[value_index++] = page_buffer[addr & ~0xFFFFFFC0];
else crc16(crc, &page_buffer[addr & ~0xFFFFFFC0], 1);
}
if (writing) crc16(crc, value, size);
pos += size;
return false; // return true for any error
}
#endif // TARGET_LPC4078
+191
View File
@@ -0,0 +1,191 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
/**
* Endstop Interrupts
*
* Without endstop interrupts the endstop pins must be polled continually in
* the temperature-ISR via endstops.update(), most of the time finding no change.
* With this feature endstops.update() is called only when we know that at
* least one endstop has changed state, saving valuable CPU cycles.
*
* This feature only works when all used endstop pins can generate an 'external interrupt'.
*
* Test whether pins issue interrupts on your board by flashing 'pin_interrupt_test.ino'.
* (Located in Marlin/buildroot/share/pin_interrupt_test/pin_interrupt_test.ino)
*/
#include "../../module/endstops.h"
// One ISR for all EXT-Interrupts
void endstop_ISR() { endstops.update(); }
void setup_endstop_interrupts() {
#define _ATTACH(P) attachInterrupt(digitalPinToInterrupt(P), endstop_ISR, CHANGE)
#define LPC1768_PIN_INTERRUPT_M(pin) ((pin >> 0x5 & 0x7) == 0 || (pin >> 0x5 & 0x7) == 2)
#if HAS_X_MAX
#if !LPC1768_PIN_INTERRUPT_M(X_MAX_PIN)
#error "X_MAX_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
#endif
_ATTACH(X_MAX_PIN);
#endif
#if HAS_X_MIN
#if !LPC1768_PIN_INTERRUPT_M(X_MIN_PIN)
#error "X_MIN_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
#endif
_ATTACH(X_MIN_PIN);
#endif
#if HAS_Y_MAX
#if !LPC1768_PIN_INTERRUPT_M(Y_MAX_PIN)
#error "Y_MAX_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
#endif
_ATTACH(Y_MAX_PIN);
#endif
#if HAS_Y_MIN
#if !LPC1768_PIN_INTERRUPT_M(Y_MIN_PIN)
#error "Y_MIN_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
#endif
_ATTACH(Y_MIN_PIN);
#endif
#if HAS_Z_MAX
#if !LPC1768_PIN_INTERRUPT_M(Z_MAX_PIN)
#error "Z_MAX_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
#endif
_ATTACH(Z_MAX_PIN);
#endif
#if HAS_Z_MIN
#if !LPC1768_PIN_INTERRUPT_M(Z_MIN_PIN)
#error "Z_MIN_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
#endif
_ATTACH(Z_MIN_PIN);
#endif
#if HAS_Z2_MAX
#if !LPC1768_PIN_INTERRUPT_M(Z2_MAX_PIN)
#error "Z2_MAX_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
#endif
_ATTACH(Z2_MAX_PIN);
#endif
#if HAS_Z2_MIN
#if !LPC1768_PIN_INTERRUPT_M(Z2_MIN_PIN)
#error "Z2_MIN_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
#endif
_ATTACH(Z2_MIN_PIN);
#endif
#if HAS_Z3_MAX
#if !LPC1768_PIN_INTERRUPT_M(Z3_MAX_PIN)
#error "Z3_MIN_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
#endif
_ATTACH(Z3_MAX_PIN);
#endif
#if HAS_Z3_MIN
#if !LPC1768_PIN_INTERRUPT_M(Z3_MIN_PIN)
#error "Z3_MIN_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
#endif
_ATTACH(Z3_MIN_PIN);
#endif
#if HAS_Z4_MAX
#if !LPC1768_PIN_INTERRUPT_M(Z4_MAX_PIN)
#error "Z4_MIN_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
#endif
_ATTACH(Z4_MAX_PIN);
#endif
#if HAS_Z4_MIN
#if !LPC1768_PIN_INTERRUPT_M(Z4_MIN_PIN)
#error "Z4_MIN_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
#endif
_ATTACH(Z4_MIN_PIN);
#endif
#if HAS_Z_MIN_PROBE_PIN
#if !LPC1768_PIN_INTERRUPT_M(Z_MIN_PROBE_PIN)
#error "Z_MIN_PROBE_PIN is not INTERRUPT-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
#endif
_ATTACH(Z_MIN_PROBE_PIN);
#endif
#if HAS_I_MAX
#if !LPC1768_PIN_INTERRUPT_M(I_MAX_PIN)
#error "I_MAX_PIN is not INTERRUPT-capable."
#endif
_ATTACH(I_MAX_PIN);
#elif HAS_I_MIN
#if !LPC1768_PIN_INTERRUPT_M(I_MIN_PIN)
#error "I_MIN_PIN is not INTERRUPT-capable."
#endif
_ATTACH(I_MIN_PIN);
#endif
#if HAS_J_MAX
#if !LPC1768_PIN_INTERRUPT_M(J_MAX_PIN)
#error "J_MAX_PIN is not INTERRUPT-capable."
#endif
_ATTACH(J_MAX_PIN);
#elif HAS_J_MIN
#if !LPC1768_PIN_INTERRUPT_M(J_MIN_PIN)
#error "J_MIN_PIN is not INTERRUPT-capable."
#endif
_ATTACH(J_MIN_PIN);
#endif
#if HAS_K_MAX
#if !LPC1768_PIN_INTERRUPT_M(K_MAX_PIN)
#error "K_MAX_PIN is not INTERRUPT-capable."
#endif
_ATTACH(K_MAX_PIN);
#elif HAS_K_MIN
#if !LPC1768_PIN_INTERRUPT_M(K_MIN_PIN)
#error "K_MIN_PIN is not INTERRUPT-capable."
#endif
_ATTACH(K_MIN_PIN);
#endif
#if HAS_U_MAX
#if !LPC1768_PIN_INTERRUPT_M(U_MAX_PIN)
#error "U_MAX_PIN is not INTERRUPT-capable."
#endif
_ATTACH(U_MAX_PIN);
#elif HAS_U_MIN
#if !LPC1768_PIN_INTERRUPT_M(U_MIN_PIN)
#error "U_MIN_PIN is not INTERRUPT-capable."
#endif
_ATTACH(U_MIN_PIN);
#endif
#if HAS_V_MAX
#if !LPC1768_PIN_INTERRUPT_M(V_MAX_PIN)
#error "V_MAX_PIN is not INTERRUPT-capable."
#endif
_ATTACH(V_MAX_PIN);
#elif HAS_V_MIN
#if !LPC1768_PIN_INTERRUPT_M(V_MIN_PIN)
#error "V_MIN_PIN is not INTERRUPT-capable."
#endif
_ATTACH(V_MIN_PIN);
#endif
#if HAS_W_MAX
#if !LPC1768_PIN_INTERRUPT_M(W_MAX_PIN)
#error "W_MAX_PIN is not INTERRUPT-capable."
#endif
_ATTACH(W_MAX_PIN);
#elif HAS_W_MIN
#if !LPC1768_PIN_INTERRUPT_M(W_MIN_PIN)
#error "W_MIN_PIN is not INTERRUPT-capable."
#endif
_ATTACH(W_MIN_PIN);
#endif
}
+37
View File
@@ -0,0 +1,37 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifdef TARGET_LPC4078
#include "../../inc/MarlinConfig.h"
#include <mcu_interface.h>
void MarlinHAL::set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) {
if (!MCUI::pin_is_valid(pin)) return;
if (MCUI::pwm_attach_pin(pin))
MCUI::pwm_write_ratio(pin, invert ? 1.0f - (float)v / v_size : (float)v / v_size); // map 1-254 onto PWM range
}
void MarlinHAL::set_pwm_frequency(const pin_t pin, const uint16_t f_desired) {
MCUI::pwm_set_frequency(pin, f_desired);
}
#endif // TARGET_LPC4078
+120
View File
@@ -0,0 +1,120 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
/**
* Fast I/O Routines for LPC1768/9
* Use direct port manipulation to save scads of processor time.
* Contributed by Triffid_Hunter and modified by Kliment, thinkyhead, Bob-the-Kuhn, et.al.
*/
/**
* Description: Fast IO functions LPC1768
*
* For TARGET LPC1768
*/
#include "../shared/Marduino.h"
#include <mcu_interface.h>
#define PWM_PIN(P) true // all pins are software PWM capable
#define LPC_PIN(pin) MCUI::gpio_pin(pin)
#define LPC_GPIO(port) MCUI::gpio_port(port)
#define SET_DIR_INPUT(IO) MCUI::gpio_set_input(IO)
#define SET_DIR_OUTPUT(IO) MCUI::gpio_set_output(IO)
#define SET_MODE(IO, mode) pinMode(IO, mode)
#define WRITE_PIN_SET(IO) MCUI::gpio_set(IO)
#define WRITE_PIN_CLR(IO) MCUI::gpio_clear(IO)
#define READ_PIN(IO) MCUI::gpio_get(IO)
#define WRITE_PIN(IO,V) MCUI::gpio_set(IO, V)
/**
* Magic I/O routines
*
* Now you can simply SET_OUTPUT(STEP); WRITE(STEP, HIGH); WRITE(STEP, LOW);
*
* Why double up on these macros? see https://gcc.gnu.org/onlinedocs/gcc-4.8.5/cpp/Stringification.html
*/
/// Read a pin
#define _READ(IO) READ_PIN(IO)
/// Write to a pin
#define _WRITE(IO,V) WRITE_PIN(IO,V)
/// toggle a pin
#define _TOGGLE(IO) MCUI::gpio_toggle(IO)
/// set pin as input
#define _SET_INPUT(IO) SET_DIR_INPUT(IO)
/// set pin as output
#define _SET_OUTPUT(IO) SET_DIR_OUTPUT(IO)
/// set pin as input with pullup mode
#define _PULLUP(IO,V) pinMode(IO, (V) ? INPUT_PULLUP : INPUT)
/// set pin as input with pulldown mode
#define _PULLDOWN(IO,V) pinMode(IO, (V) ? INPUT_PULLDOWN : INPUT)
/// check if pin is an input
#define _IS_INPUT(IO) (!MCUI::gpio_get_dir(IO))
/// check if pin is an output
#define _IS_OUTPUT(IO) (MCUI::gpio_get_dir(IO))
/// Read a pin wrapper
#define READ(IO) _READ(IO)
/// Write to a pin wrapper
#define WRITE(IO,V) _WRITE(IO,V)
/// toggle a pin wrapper
#define TOGGLE(IO) _TOGGLE(IO)
/// set pin as input wrapper
#define SET_INPUT(IO) _SET_INPUT(IO)
/// set pin as input with pullup wrapper
#define SET_INPUT_PULLUP(IO) do{ _SET_INPUT(IO); _PULLUP(IO, HIGH); }while(0)
/// set pin as input with pulldown wrapper
#define SET_INPUT_PULLDOWN(IO) do{ _SET_INPUT(IO); _PULLDOWN(IO, HIGH); }while(0)
/// set pin as output wrapper - reads the pin and sets the output to that value
#define SET_OUTPUT(IO) do{ _WRITE(IO, _READ(IO)); _SET_OUTPUT(IO); }while(0)
// set pin as PWM
#define SET_PWM SET_OUTPUT
/// check if pin is an input wrapper
#define IS_INPUT(IO) _IS_INPUT(IO)
/// check if pin is an output wrapper
#define IS_OUTPUT(IO) _IS_OUTPUT(IO)
// Shorthand
#define OUT_WRITE(IO,V) do{ SET_OUTPUT(IO); WRITE(IO,V); }while(0)
// digitalRead/Write wrappers
#define extDigitalRead(IO) digitalRead(IO)
#define extDigitalWrite(IO,V) digitalWrite(IO,V)
@@ -0,0 +1,22 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
@@ -0,0 +1,26 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#if DISABLED(NO_SD_HOST_DRIVE)
#define HAS_SD_HOST_DRIVE 1
#endif
@@ -0,0 +1,34 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#if USE_FALLBACK_EEPROM
#define FLASH_EEPROM_EMULATION
#elif ANY(I2C_EEPROM, SPI_EEPROM)
#define USE_SHARED_EEPROM 1
#endif
// LPC1768 boards seem to lose steps when saving to EEPROM during print (issue #20785)
// TODO: Which other boards are incompatible?
#if defined(MCU_LPC1768) && ENABLED(FLASH_EEPROM_EMULATION) && PRINTCOUNTER_SAVE_INTERVAL > 0
#define PRINTCOUNTER_SYNC 1
#endif
@@ -0,0 +1,22 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2024 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
+276
View File
@@ -0,0 +1,276 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
// #if PIO_PLATFORM_VERSION < 1001
// #error "nxplpc-arduino-lpc176x package is out of date, Please update the PlatformIO platforms, frameworks and libraries. You may need to remove the platform and let it reinstall automatically."
// #endif
// #if PIO_FRAMEWORK_VERSION < 2006
// #error "framework-arduino-lpc176x package is out of date, Please update the PlatformIO platforms, frameworks and libraries."
// #endif
/**
* Detect an old pins file by checking for old ADC pins values.
*/
#define _OLD_TEMP_PIN(P) PIN_EXISTS(P) && _CAT(P,_PIN) <= 7 && !WITHIN(_CAT(P,_PIN), TERN(LPC1768_IS_SKRV1_3, 0, 2), 3) // Include P0_00 and P0_01 for SKR V1.3 board
#if _OLD_TEMP_PIN(TEMP_BED)
#error "TEMP_BED_PIN must be defined using the Pn_nn or Pn_nn_An format. (See the included pins files)."
#elif _OLD_TEMP_PIN(TEMP_0)
#error "TEMP_0_PIN must be defined using the Pn_nn or Pn_nn_An format. (See the included pins files)."
#elif _OLD_TEMP_PIN(TEMP_1)
#error "TEMP_1_PIN must be defined using the Pn_nn or Pn_nn_An format. (See the included pins files)."
#elif _OLD_TEMP_PIN(TEMP_2)
#error "TEMP_2_PIN must be defined using the Pn_nn or Pn_nn_An format. (See the included pins files)."
#elif _OLD_TEMP_PIN(TEMP_3)
#error "TEMP_3_PIN must be defined using the Pn_nn or Pn_nn_An format. (See the included pins files)."
#elif _OLD_TEMP_PIN(TEMP_4)
#error "TEMP_4_PIN must be defined using the Pn_nn or Pn_nn_An format. (See the included pins files)."
#elif _OLD_TEMP_PIN(TEMP_5)
#error "TEMP_5_PIN must be defined using the Pn_nn or Pn_nn_An format. (See the included pins files)."
#elif _OLD_TEMP_PIN(TEMP_6)
#error "TEMP_6_PIN must be defined using the Pn_nn or Pn_nn_An format. (See the included pins files)."
#elif _OLD_TEMP_PIN(TEMP_7)
#error "TEMP_7_PIN must be defined using the Pn_nn or Pn_nn_An format. (See the included pins files)."
#endif
#undef _OLD_TEMP_PIN
/**
* Because PWM hardware channels all share the same frequency, along with the
* fallback software channels, FAST_PWM_FAN is incompatible with Servos.
*/
static_assert(!(NUM_SERVOS && ENABLED(FAST_PWM_FAN)), "BLTOUCH and Servos are incompatible with FAST_PWM_FAN on LPC176x boards.");
#if SPINDLE_LASER_FREQUENCY
static_assert(!NUM_SERVOS, "BLTOUCH and Servos are incompatible with SPINDLE_LASER_FREQUENCY on LPC176x boards.");
#endif
/**
* Test LPC176x-specific configuration values for errors at compile-time.
*/
//#if ENABLED(SPINDLE_LASER_USE_PWM) && !(SPINDLE_LASER_PWM_PIN == 4 || SPINDLE_LASER_PWM_PIN == 6 || SPINDLE_LASER_PWM_PIN == 11)
// #error "SPINDLE_LASER_PWM_PIN must use SERVO0, SERVO1 or SERVO3 connector"
//#endif
#if MB(RAMPS_14_RE_ARM_EFB, RAMPS_14_RE_ARM_EEB, RAMPS_14_RE_ARM_EFF, RAMPS_14_RE_ARM_EEF, RAMPS_14_RE_ARM_SF)
#if IS_RRD_FG_SC && HAS_DRIVER(TMC2130) && DISABLED(TMC_USE_SW_SPI)
#error "Re-ARM with REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER and TMC2130 requires TMC_USE_SW_SPI."
#endif
#endif
static_assert(DISABLED(BAUD_RATE_GCODE), "BAUD_RATE_GCODE is not yet supported on LPC176x.");
/**
* Flag any serial port conflicts
*
* Port | TX | RX |
* --- | --- | --- |
* Serial | P0_02 | P0_03 |
* Serial1 | P0_15 | P0_16 |
* Serial2 | P0_10 | P0_11 |
* Serial3 | P0_00 | P0_01 |
*/
#define ANY_TX(N,V...) DO(IS_TX##N,||,V)
#define ANY_RX(N,V...) DO(IS_RX##N,||,V)
#if USING_HW_SERIAL0
#define IS_TX0(P) (P == P0_02)
#define IS_RX0(P) (P == P0_03)
#if IS_TX0(TMC_SW_MISO) || IS_RX0(TMC_SW_MOSI)
#error "Serial port pins (0) conflict with Trinamic SPI pins!"
#elif HAS_PRUSA_MMU1 && (IS_TX0(E_MUX1_PIN) || IS_RX0(E_MUX0_PIN))
#error "Serial port pins (0) conflict with Multi-Material-Unit multiplexer pins!"
#elif (AXIS_HAS_SPI(X) && IS_TX0(X_CS_PIN)) || (AXIS_HAS_SPI(Y) && IS_RX0(Y_CS_PIN))
#error "Serial port pins (0) conflict with X/Y axis SPI pins!"
#endif
#undef IS_TX0
#undef IS_RX0
#endif
#if USING_HW_SERIAL1
#define IS_TX1(P) (P == P0_15)
#define IS_RX1(P) (P == P0_16)
#define _IS_TX1_1 IS_TX1
#define _IS_RX1_1 IS_RX1
#if IS_TX1(TMC_SW_SCK)
#error "Serial port pins (1) conflict with other pins!"
#elif HAS_ROTARY_ENCODER
#if IS_TX1(BTN_EN2) || IS_RX1(BTN_EN1)
#error "Serial port pins (1) conflict with Encoder Buttons!"
#elif ANY_TX(1, SD_SCK_PIN, LCD_PINS_D4, DOGLCD_SCK, LCD_RESET_PIN, LCD_PINS_RS, SHIFT_CLK_PIN) \
|| ANY_RX(1, LCD_SDSS, LCD_PINS_RS, SD_MISO_PIN, DOGLCD_A0, SD_SS_PIN, LCD_SDSS, DOGLCD_CS, LCD_RESET_PIN, LCD_BACKLIGHT_PIN)
#error "Serial port pins (1) conflict with LCD pins!"
#endif
#endif
#undef IS_TX1
#undef IS_RX1
#undef _IS_TX1_1
#undef _IS_RX1_1
#endif
#if USING_HW_SERIAL2
#define IS_TX2(P) (P == P0_10)
#define IS_RX2(P) (P == P0_11)
#define _IS_TX2_1 IS_TX2
#define _IS_RX2_1 IS_RX2
#if IS_TX2(X2_ENABLE_PIN) || ANY_RX(2, X2_DIR_PIN, X2_STEP_PIN) || (AXIS_HAS_SPI(X2) && IS_TX2(X2_CS_PIN))
#error "Serial port pins (2) conflict with X2 pins!"
#elif IS_TX2(Y2_ENABLE_PIN) || ANY_RX(2, Y2_DIR_PIN, Y2_STEP_PIN) || (AXIS_HAS_SPI(Y2) && IS_TX2(Y2_CS_PIN))
#error "Serial port pins (2) conflict with Y2 pins!"
#elif IS_TX2(Z2_ENABLE_PIN) || ANY_RX(2, Z2_DIR_PIN, Z2_STEP_PIN) || (AXIS_HAS_SPI(Z2) && IS_TX2(Z2_CS_PIN))
#error "Serial port pins (2) conflict with Z2 pins!"
#elif IS_TX2(Z3_ENABLE_PIN) || ANY_RX(2, Z3_DIR_PIN, Z3_STEP_PIN) || (AXIS_HAS_SPI(Z3) && IS_TX2(Z3_CS_PIN))
#error "Serial port pins (2) conflict with Z3 pins!"
#elif IS_TX2(Z4_ENABLE_PIN) || ANY_RX(2, Z4_DIR_PIN, Z4_STEP_PIN) || (AXIS_HAS_SPI(Z4) && IS_TX2(Z4_CS_PIN))
#error "Serial port pins (2) conflict with Z4 pins!"
#elif ANY_RX(2, X_DIR_PIN, Y_DIR_PIN)
#error "Serial port pins (2) conflict with other pins!"
#elif Y_HOME_TO_MIN && IS_TX2(Y_STOP_PIN)
#error "Serial port pins (2) conflict with Y endstop pin!"
#elif USES_Z_MIN_PROBE_PIN && IS_TX2(Z_MIN_PROBE_PIN)
#error "Serial port pins (2) conflict with probe pin!"
#elif ANY_TX(2, X_ENABLE_PIN, Y_ENABLE_PIN) || ANY_RX(2, X_DIR_PIN, Y_DIR_PIN)
#error "Serial port pins (2) conflict with X/Y stepper pins!"
#elif HAS_MULTI_EXTRUDER && (IS_TX2(E1_ENABLE_PIN) || (AXIS_HAS_SPI(E1) && IS_TX2(E1_CS_PIN)))
#error "Serial port pins (2) conflict with E1 stepper pins!"
#elif EXTRUDERS && ANY_RX(2, E0_DIR_PIN, E0_STEP_PIN)
#error "Serial port pins (2) conflict with E stepper pins!"
#endif
#undef IS_TX2
#undef IS_RX2
#undef _IS_TX2_1
#undef _IS_RX2_1
#endif
#if USING_HW_SERIAL3
#define PIN_IS_TX3(P) (PIN_EXISTS(P) && P##_PIN == P0_00)
#define PIN_IS_RX3(P) (P##_PIN == P0_01)
#if PIN_IS_TX3(X_MIN) || PIN_IS_RX3(X_MAX)
#error "Serial port pins (3) conflict with X endstop pins!"
#elif PIN_IS_TX3(Y_SERIAL_TX) || PIN_IS_TX3(Y_SERIAL_RX) || PIN_IS_RX3(X_SERIAL_TX) || PIN_IS_RX3(X_SERIAL_RX)
#error "Serial port pins (3) conflict with X/Y axis UART pins!"
#elif PIN_IS_TX3(X2_DIR) || PIN_IS_RX3(X2_STEP)
#error "Serial port pins (3) conflict with X2 pins!"
#elif PIN_IS_TX3(Y2_DIR) || PIN_IS_RX3(Y2_STEP)
#error "Serial port pins (3) conflict with Y2 pins!"
#elif PIN_IS_TX3(Z2_DIR) || PIN_IS_RX3(Z2_STEP)
#error "Serial port pins (3) conflict with Z2 pins!"
#elif PIN_IS_TX3(Z3_DIR) || PIN_IS_RX3(Z3_STEP)
#error "Serial port pins (3) conflict with Z3 pins!"
#elif PIN_IS_TX3(Z4_DIR) || PIN_IS_RX3(Z4_STEP)
#error "Serial port pins (3) conflict with Z4 pins!"
#elif HAS_MULTI_EXTRUDER && (PIN_IS_TX3(E1_DIR) || PIN_IS_RX3(E1_STEP))
#error "Serial port pins (3) conflict with E1 pins!"
#endif
#undef PIN_IS_TX3
#undef PIN_IS_RX3
#endif
#undef ANY_TX
#undef ANY_RX
//
// Flag any i2c pin conflicts
//
#if ANY(HAS_MOTOR_CURRENT_I2C, HAS_MOTOR_CURRENT_DAC, EXPERIMENTAL_I2CBUS, I2C_POSITION_ENCODERS, PCA9632, I2C_EEPROM)
#define USEDI2CDEV_M 1 // <Arduino>/Wire.cpp
#if USEDI2CDEV_M == 0 // P0_27 [D57] (AUX-1) .......... P0_28 [D58] (AUX-1)
#define PIN_IS_SDA0(P) (P##_PIN == P0_27)
#define IS_SCL0(P) (P == P0_28)
#if ENABLED(SDSUPPORT) && PIN_IS_SDA0(SD_DETECT)
#error "SDA0 overlaps with SD_DETECT_PIN!"
#elif PIN_IS_SDA0(E0_AUTO_FAN)
#error "SDA0 overlaps with E0_AUTO_FAN_PIN!"
#elif PIN_IS_SDA0(BEEPER)
#error "SDA0 overlaps with BEEPER_PIN!"
#elif IS_SCL0(BTN_ENC)
#error "SCL0 overlaps with Encoder Button!"
#elif IS_SCL0(SD_SS_PIN)
#error "SCL0 overlaps with SD_SS_PIN!"
#elif IS_SCL0(LCD_SDSS)
#error "SCL0 overlaps with LCD_SDSS!"
#endif
#undef PIN_IS_SDA0
#undef IS_SCL0
#elif USEDI2CDEV_M == 1 // P0_00 [D20] (SCA) ............ P0_01 [D21] (SCL)
#define PIN_IS_SDA1(P) (PIN_EXISTS(P) && P##_PIN == P0_00)
#define PIN_IS_SCL1(P) (P##_PIN == P0_01)
#if PIN_IS_SDA1(X_MIN) || PIN_IS_SCL1(X_MAX)
#error "One or more i2c (1) pins overlaps with X endstop pins! Disable i2c peripherals."
#elif PIN_IS_SDA1(X2_DIR) || PIN_IS_SCL1(X2_STEP)
#error "One or more i2c (1) pins overlaps with X2 pins! Disable i2c peripherals."
#elif PIN_IS_SDA1(Y2_DIR) || PIN_IS_SCL1(Y2_STEP)
#error "One or more i2c (1) pins overlaps with Y2 pins! Disable i2c peripherals."
#elif PIN_IS_SDA1(Z2_DIR) || PIN_IS_SCL1(Z2_STEP)
#error "One or more i2c (1) pins overlaps with Z2 pins! Disable i2c peripherals."
#elif PIN_IS_SDA1(Z3_DIR) || PIN_IS_SCL1(Z3_STEP)
#error "One or more i2c (1) pins overlaps with Z3 pins! Disable i2c peripherals."
#elif PIN_IS_SDA1(Z4_DIR) || PIN_IS_SCL1(Z4_STEP)
#error "One or more i2c (1) pins overlaps with Z4 pins! Disable i2c peripherals."
#elif HAS_MULTI_EXTRUDER && (PIN_IS_SDA1(E1_DIR) || PIN_IS_SCL1(E1_STEP))
#error "One or more i2c (1) pins overlaps with E1 pins! Disable i2c peripherals."
#endif
#undef PIN_IS_SDA1
#undef PIN_IS_SCL1
#elif USEDI2CDEV_M == 2 // P0_10 [D38] (X_ENABLE_PIN) ... P0_11 [D55] (X_DIR_PIN)
#define PIN_IS_SDA2(P) (P##_PIN == P0_10)
#define PIN_IS_SCL2(P) (P##_PIN == P0_11)
#if PIN_IS_SDA2(Y_STOP)
#error "i2c SDA2 overlaps with Y endstop pin!"
#elif USES_Z_MIN_PROBE_PIN && PIN_IS_SDA2(Z_MIN_PROBE)
#error "i2c SDA2 overlaps with Z probe pin!"
#elif PIN_IS_SDA2(X_ENABLE) || PIN_IS_SDA2(Y_ENABLE)
#error "i2c SDA2 overlaps with X/Y ENABLE pin!"
#elif AXIS_HAS_SPI(X) && PIN_IS_SDA2(X_CS)
#error "i2c SDA2 overlaps with X CS pin!"
#elif PIN_IS_SDA2(X2_ENABLE)
#error "i2c SDA2 overlaps with X2 enable pin! Disable i2c peripherals."
#elif PIN_IS_SDA2(Y2_ENABLE)
#error "i2c SDA2 overlaps with Y2 enable pin! Disable i2c peripherals."
#elif PIN_IS_SDA2(Z2_ENABLE)
#error "i2c SDA2 overlaps with Z2 enable pin! Disable i2c peripherals."
#elif PIN_IS_SDA2(Z3_ENABLE)
#error "i2c SDA2 overlaps with Z3 enable pin! Disable i2c peripherals."
#elif PIN_IS_SDA2(Z4_ENABLE)
#error "i2c SDA2 overlaps with Z4 enable pin! Disable i2c peripherals."
#elif HAS_MULTI_EXTRUDER && PIN_IS_SDA2(E1_ENABLE)
#error "i2c SDA2 overlaps with E1 enable pin! Disable i2c peripherals."
#elif HAS_MULTI_EXTRUDER && AXIS_HAS_SPI(E1) && PIN_IS_SDA2(E1_CS)
#error "i2c SDA2 overlaps with E1 CS pin! Disable i2c peripherals."
#elif EXTRUDERS && (PIN_IS_SDA2(E0_STEP) || PIN_IS_SDA2(E0_DIR))
#error "i2c SCL2 overlaps with E0 STEP/DIR pin! Disable i2c peripherals."
#elif PIN_IS_SDA2(X_DIR) || PIN_IS_SDA2(Y_DIR)
#error "One or more i2c pins overlaps with X/Y DIR pin! Disable i2c peripherals."
#endif
#undef PIN_IS_SDA2
#undef PIN_IS_SCL2
#endif
#undef USEDI2CDEV_M
#endif
#if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
#error "SERIAL_STATS_MAX_RX_QUEUED is not supported on LPC176x."
#elif ENABLED(SERIAL_STATS_DROPPED_RX)
#error "SERIAL_STATS_DROPPED_RX is not supported on LPX176x."
#endif
+209
View File
@@ -0,0 +1,209 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#include "../../shared/HAL_SPI.h"
#include <stdint.h>
#include <mcu_interface.h>
//#define MSBFIRST 1
#define SPI_MODE0 0
#define SPI_MODE1 1
#define SPI_MODE2 2
#define SPI_MODE3 3
#define SSP_CR0_DSS(n) ((uint32_t)((n-1)&0xF))
#define SSP_DATABIT_4 SSP_CR0_DSS(4) /*!< Databit number = 4 */
#define SSP_DATABIT_5 SSP_CR0_DSS(5) /*!< Databit number = 5 */
#define SSP_DATABIT_6 SSP_CR0_DSS(6) /*!< Databit number = 6 */
#define SSP_DATABIT_7 SSP_CR0_DSS(7) /*!< Databit number = 7 */
#define SSP_DATABIT_8 SSP_CR0_DSS(8) /*!< Databit number = 8 */
#define SSP_DATABIT_9 SSP_CR0_DSS(9) /*!< Databit number = 9 */
#define SSP_DATABIT_10 SSP_CR0_DSS(10) /*!< Databit number = 10 */
#define SSP_DATABIT_11 SSP_CR0_DSS(11) /*!< Databit number = 11 */
#define SSP_DATABIT_12 SSP_CR0_DSS(12) /*!< Databit number = 12 */
#define SSP_DATABIT_13 SSP_CR0_DSS(13) /*!< Databit number = 13 */
#define SSP_DATABIT_14 SSP_CR0_DSS(14) /*!< Databit number = 14 */
#define SSP_DATABIT_15 SSP_CR0_DSS(15) /*!< Databit number = 15 */
#define SSP_DATABIT_16 SSP_CR0_DSS(16) /*!< Databit number = 16 */
#define DATA_SIZE_8BIT SSP_DATABIT_8
#define DATA_SIZE_16BIT SSP_DATABIT_16
#define SPI_CLOCK_MAX_TFT 30000000UL
#define SPI_CLOCK_DIV2 8333333 //(SCR: 2) desired: 8,000,000 actual: 8,333,333 +4.2% SPI_FULL_SPEED
#define SPI_CLOCK_DIV4 4166667 //(SCR: 5) desired: 4,000,000 actual: 4,166,667 +4.2% SPI_HALF_SPEED
#define SPI_CLOCK_DIV8 2083333 //(SCR: 11) desired: 2,000,000 actual: 2,083,333 +4.2% SPI_QUARTER_SPEED
#define SPI_CLOCK_DIV16 1000000 //(SCR: 24) desired: 1,000,000 actual: 1,000,000 SPI_EIGHTH_SPEED
#define SPI_CLOCK_DIV32 500000 //(SCR: 49) desired: 500,000 actual: 500,000 SPI_SPEED_5
#define SPI_CLOCK_DIV64 250000 //(SCR: 99) desired: 250,000 actual: 250,000 SPI_SPEED_6
#define SPI_CLOCK_DIV128 125000 //(SCR:199) desired: 125,000 actual: 125,000 Default from HAL.h
#define SPI_CLOCK_MAX SPI_CLOCK_DIV2
#define BOARD_NR_SPI 3
// SSP0 TMC port
#define BOARD_SPI1_NSS_PIN P_NC
#define BOARD_SPI1_SCK_PIN P1_20
#define BOARD_SPI1_MISO_PIN P1_23
#define BOARD_SPI1_MOSI_PIN P1_24
// SSP2 LCD SD port
#define BOARD_SPI2_NSS_PIN P_NC
#define BOARD_SPI2_SCK_PIN P1_00
#define BOARD_SPI2_MISO_PIN P1_04
#define BOARD_SPI2_MOSI_PIN P1_01
// SSP1 Onboard SD port
#define BOARD_SPI3_NSS_PIN P_NC
#define BOARD_SPI3_SCK_PIN P0_07
#define BOARD_SPI3_MISO_PIN P0_08
#define BOARD_SPI3_MOSI_PIN P0_09
class SPISettings {
public:
SPISettings(uint32_t spiRate, int inBitOrder, int inDataMode) {
init_AlwaysInline(spiRate2Clock(spiRate), inBitOrder, inDataMode, DATA_SIZE_8BIT);
}
SPISettings(uint32_t inClock, uint8_t inBitOrder, uint8_t inDataMode, uint32_t inDataSize) {
if (__builtin_constant_p(inClock))
init_AlwaysInline(inClock, inBitOrder, inDataMode, inDataSize);
else
init_MightInline(inClock, inBitOrder, inDataMode, inDataSize);
}
SPISettings() {
init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT);
}
//uint32_t spiRate() const { return spi_speed; }
static uint32_t spiRate2Clock(uint32_t spiRate) {
uint32_t Marlin_speed[7]; // CPSR is always 2
Marlin_speed[0] = 8333333; //(SCR: 2) desired: 8,000,000 actual: 8,333,333 +4.2% SPI_FULL_SPEED
Marlin_speed[1] = 4166667; //(SCR: 5) desired: 4,000,000 actual: 4,166,667 +4.2% SPI_HALF_SPEED
Marlin_speed[2] = 2083333; //(SCR: 11) desired: 2,000,000 actual: 2,083,333 +4.2% SPI_QUARTER_SPEED
Marlin_speed[3] = 1000000; //(SCR: 24) desired: 1,000,000 actual: 1,000,000 SPI_EIGHTH_SPEED
Marlin_speed[4] = 500000; //(SCR: 49) desired: 500,000 actual: 500,000 SPI_SPEED_5
Marlin_speed[5] = 250000; //(SCR: 99) desired: 250,000 actual: 250,000 SPI_SPEED_6
Marlin_speed[6] = 125000; //(SCR:199) desired: 125,000 actual: 125,000 Default from HAL.h
return Marlin_speed[spiRate > 6 ? 6 : spiRate];
}
private:
void init_MightInline(uint32_t inClock, uint8_t inBitOrder, uint8_t inDataMode, uint32_t inDataSize) {
init_AlwaysInline(inClock, inBitOrder, inDataMode, inDataSize);
}
void init_AlwaysInline(uint32_t inClock, uint8_t inBitOrder, uint8_t inDataMode, uint32_t inDataSize) __attribute__((__always_inline__)) {
clock = inClock;
bitOrder = inBitOrder;
dataMode = inDataMode;
dataSize = inDataSize;
m_config = {};
m_config.frequency = 400000;
}
MCUI::SSP::Config m_config;
//uint32_t spi_speed;
uint32_t clock;
uint32_t dataSize;
//uint32_t clockDivider;
uint8_t bitOrder;
uint8_t dataMode;
uint8_t device_id;
friend class SPIClass;
};
/**
* @brief Wirish SPI interface.
*
* This is the same interface is available across HAL
*
* This implementation uses software slave management, so the caller
* is responsible for controlling the slave select line.
*/
class SPIClass {
public:
/**
* @param spiPortNumber Number of the SPI port to manage.
*/
SPIClass(uint8_t spiPortNumber);
/**
* Init using pins
*/
SPIClass(pin_t mosi, pin_t miso, pin_t sclk, pin_t ssel = (pin_t)-1);
/**
* Select and configure the current selected SPI device to use
*/
void begin();
/**
* Disable the current SPI device
*/
void end();
void beginTransaction(const SPISettings&);
void endTransaction() {}
// Transfer using 1 "Data Size"
uint8_t transfer(uint16_t data);
// Transfer 2 bytes in 8 bit mode
uint16_t transfer16(uint16_t data);
void send(uint8_t data);
uint16_t read();
void read(uint8_t *buf, uint32_t len);
void dmaSend(void *buf, uint16_t length, bool minc);
/**
* @brief Sets the number of the SPI peripheral to be used by
* this HardwareSPI instance.
*
* @param spi_num Number of the SPI port. 1-2 in low density devices
* or 1-3 in high density devices.
*/
void setModule(uint8_t device);
void setClock(uint32_t clock);
void setBitOrder(uint8_t bitOrder);
void setDataMode(uint8_t dataMode);
void setDataSize(uint32_t ds);
inline uint32_t getDataSize() { return _currentSetting->dataSize; }
private:
SPISettings _settings[BOARD_NR_SPI];
SPISettings *_currentSetting;
void updateSettings();
};
extern SPIClass SPI;
+111
View File
@@ -0,0 +1,111 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifdef TARGET_LPC4078
#include "../../inc/MarlinConfig.h"
#include "../../core/millis_t.h"
#include "../../sd/cardreader.h"
#include <mcu_interface.h>
#include <driver/usb_device.h>
TERN_(POSTMORTEM_DEBUGGING, extern void install_min_serial());
void MarlinHAL::init() {
MCUI::pwm_init();
// Init LEDs
#if PIN_EXISTS(LED)
SET_DIR_OUTPUT(LED_PIN);
WRITE_PIN_CLR(LED_PIN);
#if PIN_EXISTS(LED2)
SET_DIR_OUTPUT(LED2_PIN);
WRITE_PIN_CLR(LED2_PIN);
#if PIN_EXISTS(LED3)
SET_DIR_OUTPUT(LED3_PIN);
WRITE_PIN_CLR(LED3_PIN);
#if PIN_EXISTS(LED4)
SET_DIR_OUTPUT(LED4_PIN);
WRITE_PIN_CLR(LED4_PIN);
#endif
#endif
#endif
// Flash status LED 3 times to indicate Marlin has started booting
for(int i = 0; i < 6; ++i) {
TOGGLE(LED_PIN);
delay(100);
}
#endif
// Init Servo Pins
#define INIT_SERVO(N) OUT_WRITE(SERVO##N##_PIN, LOW)
#if HAS_SERVO_0
INIT_SERVO(0);
#endif
#if HAS_SERVO_1
INIT_SERVO(1);
#endif
#if HAS_SERVO_2
INIT_SERVO(2);
#endif
#if HAS_SERVO_3
INIT_SERVO(3);
#endif
#if PIN_EXISTS(SD_SS)
OUT_WRITE(SD_SS_PIN, HIGH);
#endif
#if PIN_EXISTS(ONBOARD_SD_CS) && ONBOARD_SD_CS_PIN != SD_SS_PIN
OUT_WRITE(ONBOARD_SD_CS_PIN, HIGH);
#endif
TERN_(HAS_SD_HOST_DRIVE, MCUI::USBDevice::msc_storage_init()); // Enable USB SD card access
MCUI::USBDevice::connect(2000, LED_PIN);
HAL_timer_init();
TERN_(POSTMORTEM_DEBUGGING, install_min_serial()); // Install the min serial handler
}
// HAL idle task
void MarlinHAL::idletask() {
#if HAS_SHARED_MEDIA
// If Marlin is using the SD card we need to lock it to prevent access from
// a PC via USB.
// Other HALs use IS_SD_PRINTING() and IS_SD_FILE_OPEN() to check for access but
// this will not reliably detect delete operations. To be safe we will lock
// the disk if Marlin has it mounted. Unfortunately there is currently no way
// to unmount the disk from the LCD menu.
// if (IS_SD_PRINTING() || IS_SD_FILE_OPEN())
if (card.isMounted())
MCUI::USBDevice::msc_storage_lock();
else
MCUI::USBDevice::msc_storage_release();
#endif
// Perform USB stack housekeeping
MCUI::USBDevice::msc_run_deferred_commands();
}
#endif // TARGET_LPC4078
+57
View File
@@ -0,0 +1,57 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
/**
* Support routines for LPC1768
*/
/**
* Translation of routines & variables used by pinsDebug.h
*/
#define NUMBER_PINS_TOTAL NUM_DIGITAL_PINS
#define IS_ANALOG(P) (DIGITAL_PIN_TO_ANALOG_PIN(P) >= 0 ? 1 : 0)
#define digitalRead_mod(p) extDigitalRead(p)
#define PRINT_PORT(p)
#define GET_ARRAY_PIN(p) pin_array[p].pin
#define PRINT_ARRAY_NAME(x) do{ sprintf_P(buffer, PSTR("%-" STRINGIFY(MAX_NAME_LENGTH) "s"), pin_array[x].name); SERIAL_ECHO(buffer); }while(0)
#define PRINT_PIN(p) do{ sprintf_P(buffer, PSTR("P%d_%02d"), MCUI::pin_port(p), MCUI::pin_bit(p)); SERIAL_ECHO(buffer); }while(0)
#define PRINT_PIN_ANALOG(p) do{ sprintf_P(buffer, PSTR("_A%d "), MCUI::pin_get_adc_channel(pin)); SERIAL_ECHO(buffer); }while(0)
#define MULTI_NAME_PAD 17 // space needed to be pretty if not first name assigned to a pin
// pins that will cause hang/reset/disconnect in M43 Toggle and Watch utilities
#ifndef M43_NEVER_TOUCH
#define M43_NEVER_TOUCH(Q) ((Q) == P0_29 || (Q) == P0_30 || (Q) == P2_09) // USB pins
#endif
bool GET_PINMODE(const pin_t pin) {
if (!MCUI::pin_is_valid(pin) || MCUI::pin_adc_enabled(pin)) // found an invalid pin or active analog pin
return false;
return MCUI::gpio_direction(pin);
}
#define GET_ARRAY_IS_DIGITAL(x) ((bool) pin_array[x].is_digital)
void print_port(const pin_t) {}
void pwm_details(const pin_t) {}
bool pwm_status(const pin_t) { return false; }
+54
View File
@@ -0,0 +1,54 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#include "../../core/macros.h"
#if ALL(SDSUPPORT, HAS_MARLINUI_U8GLIB) && (LCD_PINS_D4 == SD_SCK_PIN || LCD_PINS_ENABLE == SD_MOSI_PIN || DOGLCD_SCK == SD_SCK_PIN || DOGLCD_MOSI == SD_MOSI_PIN)
#define LPC_SOFTWARE_SPI // If the SD card and LCD adapter share the same SPI pins, then software SPI is currently
// needed due to the speed and mode required for communicating with each device being different.
// This requirement can be removed if the SPI access to these devices is updated to use
// spiBeginTransaction.
#endif
/** onboard SD card */
//#define SD_SCK_PIN P0_07
//#define SD_MISO_PIN P0_08
//#define SD_MOSI_PIN P0_09
//#define SD_SS_PIN P0_06
/** external */
#ifndef SD_SCK_PIN
#define SD_SCK_PIN P0_15
#endif
#ifndef SD_MISO_PIN
#define SD_MISO_PIN P0_17
#endif
#ifndef SD_MOSI_PIN
#define SD_MOSI_PIN P0_18
#endif
#ifndef SD_SS_PIN
#define SD_SS_PIN P1_23
#endif
#if !defined(SDSS) || SDSS == P_NC // gets defaulted in pins.h
#undef SDSS
#define SDSS SD_SS_PIN
#endif
+65
View File
@@ -0,0 +1,65 @@
/**
* Marlin 3D Printer Firmware
*
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
* Copyright (c) 2016 Bob Cousins bobcousins42@googlemail.com
* Copyright (c) 2015-2016 Nico Tonnhofer wurstnase.reprap@gmail.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
/**
* Description:
*
* Timers for LPC1768
*/
#ifdef TARGET_LPC4078
#include "../../inc/MarlinConfig.h"
void HAL_timer_init() {
SBI(MCUI::system_control.PCONP, SBIT_TIMER0); // Power ON Timer 0
STEP_TIMER_REF.PR = (HAL_TIMER_RATE) / (STEPPER_TIMER_RATE) - 1; // Use prescaler to set frequency if needed
SBI(MCUI::system_control.PCONP, SBIT_TIMER1); // Power ON Timer 1
TEMP_TIMER_REF.PR = (HAL_TIMER_RATE) / 1000000 - 1;
}
void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
switch (timer_num) {
case MF_TIMER_STEP:
STEP_TIMER_REF.MCR = _BV(SBIT_MR0I) | _BV(SBIT_MR0R); // Match on MR0, reset on MR0, interrupts when NVIC enables them
STEP_TIMER_REF.MR0 = uint32_t(STEPPER_TIMER_RATE) / frequency; // Match value (period) to set frequency
STEP_TIMER_REF.TCR = _BV(SBIT_CNTEN); // Counter Enable
MCUCore::nvic_set_priority(MCUI::IRQNumber::TIMER0, MCUCore::nvic_encode_priority(0, 1, 0));
MCUCore::nvic_enable_irq(MCUI::IRQNumber::TIMER0);
break;
case MF_TIMER_TEMP:
TEMP_TIMER_REF.MCR = _BV(SBIT_MR0I) | _BV(SBIT_MR0R); // Match on MR0, reset on MR0, interrupts when NVIC enables them
TEMP_TIMER_REF.MR0 = uint32_t(TEMP_TIMER_RATE) / frequency;
TEMP_TIMER_REF.TCR = _BV(SBIT_CNTEN); // Counter Enable
MCUCore::nvic_set_priority(MCUI::IRQNumber::TIMER1, MCUCore::nvic_encode_priority(0, 2, 0));
MCUCore::nvic_enable_irq(MCUI::IRQNumber::TIMER1);
break;
default: break;
}
}
#endif // TARGET_LPC4078
+165
View File
@@ -0,0 +1,165 @@
/**
* Marlin 3D Printer Firmware
*
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
* Copyright (c) 2016 Bob Cousins bobcousins42@googlemail.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
/**
* HAL For LPC1768
*/
#include <stdint.h>
#include <mcu_interface.h>
#include "../../core/macros.h"
#define SBIT_TIMER0 1
#define SBIT_TIMER1 2
#define SBIT_CNTEN 0
#define SBIT_MR0I 0 // Timer 0 Interrupt when TC matches MR0
#define SBIT_MR0R 1 // Timer 0 Reset TC on Match
#define SBIT_MR0S 2 // Timer 0 Stop TC and PC on Match
#define SBIT_MR1I 3
#define SBIT_MR1R 4
#define SBIT_MR1S 5
#define SBIT_MR2I 6
#define SBIT_MR2R 7
#define SBIT_MR2S 8
#define SBIT_MR3I 9
#define SBIT_MR3R 10
#define SBIT_MR3S 11
// ------------------------
// Defines
// ------------------------
#define _HAL_TIMER(T) _CAT(MCUI::timer, T)
#define _HAL_TIMER_IRQ(T) TIMER##T##_IRQn
#define __HAL_TIMER_ISR(T) extern "C" void TIMER##T##_IRQHandler()
#define _HAL_TIMER_ISR(T) __HAL_TIMER_ISR(T)
typedef uint32_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX 0xFFFFFFFF
#define HAL_TIMER_RATE ((F_CPU) / 2) // frequency of timers peripherals
#ifndef MF_TIMER_STEP
#define MF_TIMER_STEP 0 // Timer Index for Stepper
#endif
#ifndef MF_TIMER_PULSE
#define MF_TIMER_PULSE MF_TIMER_STEP
#endif
#ifndef MF_TIMER_TEMP
#define MF_TIMER_TEMP 1 // Timer Index for Temperature
#endif
#ifndef MF_TIMER_PWM
#define MF_TIMER_PWM 3 // Timer Index for PWM
#endif
#define TEMP_TIMER_RATE 1000000
#define TEMP_TIMER_FREQUENCY 1000 // temperature interrupt frequency
#define STEPPER_TIMER_RATE HAL_TIMER_RATE // frequency of stepper timer (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE)
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs
#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US)
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // frequency of pulse timer
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_STEP)
#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(MF_TIMER_STEP)
#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_TEMP)
#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_TEMP)
#ifndef HAL_STEP_TIMER_ISR
#define HAL_STEP_TIMER_ISR() _HAL_TIMER_ISR(MF_TIMER_STEP)
#endif
#ifndef HAL_TEMP_TIMER_ISR
#define HAL_TEMP_TIMER_ISR() _HAL_TIMER_ISR(MF_TIMER_TEMP)
#endif
// Timer references by index
#define STEP_TIMER_REF _HAL_TIMER(MF_TIMER_STEP)
#define TEMP_TIMER_REF _HAL_TIMER(MF_TIMER_TEMP)
// ------------------------
// Public functions
// ------------------------
void HAL_timer_init();
void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency);
FORCE_INLINE static void HAL_timer_set_compare(const uint8_t timer_num, const hal_timer_t compare) {
switch (timer_num) {
case MF_TIMER_STEP: STEP_TIMER_REF.MR0 = compare; break; // Stepper Timer Match Register 0
case MF_TIMER_TEMP: TEMP_TIMER_REF.MR0 = compare; break; // Temp Timer Match Register 0
}
}
FORCE_INLINE static hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) {
switch (timer_num) {
case MF_TIMER_STEP: return STEP_TIMER_REF.MR0; // Stepper Timer Match Register 0
case MF_TIMER_TEMP: return TEMP_TIMER_REF.MR0; // Temp Timer Match Register 0
}
return 0;
}
FORCE_INLINE static hal_timer_t HAL_timer_get_count(const uint8_t timer_num) {
switch (timer_num) {
case MF_TIMER_STEP: return STEP_TIMER_REF.TC; // Stepper Timer Count
case MF_TIMER_TEMP: return TEMP_TIMER_REF.TC; // Temp Timer Count
}
return 0;
}
FORCE_INLINE static void HAL_timer_enable_interrupt(const uint8_t timer_num) {
switch (timer_num) {
case MF_TIMER_STEP: MCUCore::nvic_enable_irq(MCUI::IRQNumber::TIMER0); break; // Enable interrupt handler
case MF_TIMER_TEMP: MCUCore::nvic_enable_irq(MCUI::IRQNumber::TIMER1); break; // Enable interrupt handler
}
}
FORCE_INLINE static void HAL_timer_disable_interrupt(const uint8_t timer_num) {
switch (timer_num) {
case MF_TIMER_STEP: MCUCore::nvic_disable_irq(MCUI::IRQNumber::TIMER0); break; // Disable interrupt handler
case MF_TIMER_TEMP: MCUCore::nvic_disable_irq(MCUI::IRQNumber::TIMER1); break; // Disable interrupt handler
}
}
FORCE_INLINE static bool HAL_timer_interrupt_enabled(const uint8_t timer_num) {
switch (timer_num) {
case MF_TIMER_STEP: return MCUCore::nvic_irq_is_enabled(MCUI::IRQNumber::TIMER0); // Check if interrupt is enabled or not
case MF_TIMER_TEMP: return MCUCore::nvic_irq_is_enabled(MCUI::IRQNumber::TIMER1); // Check if interrupt is enabled or not
}
return false;
}
FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) {
switch (timer_num) {
case MF_TIMER_STEP: SBI(STEP_TIMER_REF.IR, SBIT_CNTEN); break;
case MF_TIMER_TEMP: SBI(TEMP_TIMER_REF.IR, SBIT_CNTEN); break;
}
}
#define HAL_timer_isr_epilogue(T) NOOP
@@ -0,0 +1,89 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
// adapted from I2C/master/master.c example
// https://www-users.cs.york.ac.uk/~pcc/MCP/HAPR-Course-web/CMSIS/examples/html/master_8c_source.html
#ifdef TARGET_LPC1768
#include "../include/i2c_util.h"
#include "../../../core/millis_t.h"
extern int millis();
#ifdef __cplusplus
extern "C" {
#endif
//////////////////////////////////////////////////////////////////////////////////////
#define I2CDEV_S_ADDR 0x78 // From SSD1306 (actual address is 0x3C - shift left 1 with LSB set to 0 to indicate write)
// Send slave address and write bit
uint8_t u8g_i2c_start(const uint8_t sla) {
// Sometimes TX data ACK or NAK status is returned. That mean the start state didn't
// happen which means only the value of the slave address was send. Keep looping until
// the slave address and write bit are actually sent.
do{
_I2C_Stop(I2CDEV_M); // output stop state on I2C bus
_I2C_Start(I2CDEV_M); // output start state on I2C bus
while ((I2C_status != I2C_I2STAT_M_TX_START)
&& (I2C_status != I2C_I2STAT_M_TX_RESTART)
&& (I2C_status != I2C_I2STAT_M_TX_DAT_ACK)
&& (I2C_status != I2C_I2STAT_M_TX_DAT_NACK)); //wait for start to be asserted
LPC_I2C1->I2CONCLR = I2C_I2CONCLR_STAC; // clear start state before tansmitting slave address
LPC_I2C1->I2DAT = I2CDEV_S_ADDR & I2C_I2DAT_BITMASK; // transmit slave address & write bit
LPC_I2C1->I2CONSET = I2C_I2CONSET_AA;
LPC_I2C1->I2CONCLR = I2C_I2CONCLR_SIC;
while ((I2C_status != I2C_I2STAT_M_TX_SLAW_ACK)
&& (I2C_status != I2C_I2STAT_M_TX_SLAW_NACK)
&& (I2C_status != I2C_I2STAT_M_TX_DAT_ACK)
&& (I2C_status != I2C_I2STAT_M_TX_DAT_NACK)); //wait for slaw to finish
}while ( (I2C_status == I2C_I2STAT_M_TX_DAT_ACK) || (I2C_status == I2C_I2STAT_M_TX_DAT_NACK));
return 1;
}
void u8g_i2c_init(const uint8_t clock_option) {
configure_i2c(clock_option);
u8g_i2c_start(0); // Send slave address and write bit
}
uint8_t u8g_i2c_send_byte(uint8_t data) {
#define I2C_TIMEOUT 3
LPC_I2C1->I2DAT = data & I2C_I2DAT_BITMASK; // transmit data
LPC_I2C1->I2CONSET = I2C_I2CONSET_AA;
LPC_I2C1->I2CONCLR = I2C_I2CONCLR_SIC;
const millis_t timeout = millis() + I2C_TIMEOUT;
while ((I2C_status != I2C_I2STAT_M_TX_DAT_ACK) && (I2C_status != I2C_I2STAT_M_TX_DAT_NACK) && PENDING(millis(), timeout)); // wait for xmit to finish
// had hangs with SH1106 so added time out - have seen temporary screen corruption when this happens
return 1;
}
void u8g_i2c_stop() {
}
#ifdef __cplusplus
}
#endif
#endif // TARGET_LPC1768
@@ -0,0 +1,28 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
void u8g_i2c_init(const uint8_t clock_options);
//uint8_t u8g_i2c_wait(uint8_t mask, uint8_t pos);
uint8_t u8g_i2c_start(uint8_t sla);
uint8_t u8g_i2c_send_byte(uint8_t data);
void u8g_i2c_stop();
+46
View File
@@ -0,0 +1,46 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
/**
* LPC1768 LCD-specific defines
*/
#ifndef U8G_HAL_LINKS
#define U8G_COM_SSD_I2C_HAL u8g_com_arduino_ssd_i2c_fn // See U8glib-HAL
#else
uint8_t u8g_com_HAL_LPC1768_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr);
uint8_t u8g_com_HAL_LPC1768_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr);
uint8_t u8g_com_HAL_LPC1768_ST7920_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr);
uint8_t u8g_com_HAL_LPC1768_ST7920_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr);
uint8_t u8g_com_HAL_LPC1768_ssd_hw_i2c_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr);
#define U8G_COM_HAL_SW_SPI_FN u8g_com_HAL_LPC1768_sw_spi_fn
#define U8G_COM_HAL_HW_SPI_FN u8g_com_HAL_LPC1768_hw_spi_fn
#define U8G_COM_ST7920_HAL_SW_SPI u8g_com_HAL_LPC1768_ST7920_sw_spi_fn
#define U8G_COM_ST7920_HAL_HW_SPI u8g_com_HAL_LPC1768_ST7920_hw_spi_fn
#define U8G_COM_SSD_I2C_HAL u8g_com_HAL_LPC1768_ssd_hw_i2c_fn
#endif
+43
View File
@@ -0,0 +1,43 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
/**
* LCD delay routines - used by all the drivers.
*
* These are based on the LPC1768 routines.
*
* Couldn't just call exact copies because the overhead
* results in a one microsecond delay taking about 4µS.
*/
#ifdef __cplusplus
extern "C" {
#endif
void U8g_delay(int msec);
void u8g_MicroDelay();
void u8g_10MicroDelay();
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,59 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
/**
* Low level pin manipulation routines - used by all the drivers.
*
* These are based on the LPC1768 pinMode, digitalRead & digitalWrite routines.
*
* Couldn't just call exact copies because the overhead killed the LCD update speed
* With an intermediate level the softspi was running in the 10-20kHz range which
* resulted in using about about 25% of the CPU's time.
*/
#ifdef TARGET_LPC4078
#include <mcu_interface.h>
extern "C" {
#include "LCD_pin_routines.h"
void u8g_SetPinOutput(uint8_t pin) {
MCUI::gpio_set_output(pin);
}
void u8g_SetPinInput(uint8_t pin) {
MCUI::gpio_set_input(pin);
}
void u8g_SetPinLevel(uint8_t pin, uint8_t pin_status) {
MCUI::gpio_set(pin, pin_status);
}
uint8_t u8g_GetPinLevel(uint8_t pin) {
return MCUI::gpio_get(pin);
}
}
#endif // TARGET_LPC4078
@@ -0,0 +1,37 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
/**
* Low level pin manipulation routines - used by all the drivers.
*
* These are based on the LPC1768 pinMode, digitalRead & digitalWrite routines.
*
* Couldn't just call exact copies because the overhead killed the LCD update speed
* With an intermediate level the softspi was running in the 10-20kHz range which
* resulted in using about about 25% of the CPU's time.
*/
void u8g_SetPinOutput(uint8_t internal_pin_number);
void u8g_SetPinInput(uint8_t internal_pin_number);
void u8g_SetPinLevel(uint8_t pin, uint8_t pin_status);
uint8_t u8g_GetPinLevel(uint8_t pin);
@@ -0,0 +1,129 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
/**
* Based on u8g_com_msp430_hw_spi.c
*
* Universal 8bit Graphics Library
*
* Copyright (c) 2011, olikraus@gmail.com
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef TARGET_LPC4078
#include "../../../inc/MarlinConfigPre.h"
#if HAS_MARLINUI_U8GLIB
#include <U8glib-HAL.h>
#include "../../shared/HAL_SPI.h"
#ifndef LCD_SPI_SPEED
#ifdef SD_SPI_SPEED
#define LCD_SPI_SPEED SD_SPI_SPEED // Assume SPI speed shared with SD
#else
#define LCD_SPI_SPEED SPI_FULL_SPEED // Use full speed if SD speed is not supplied
#endif
#endif
uint8_t u8g_com_HAL_LPC1768_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
switch (msg) {
case U8G_COM_MSG_STOP:
break;
case U8G_COM_MSG_INIT:
u8g_SetPILevel(u8g, U8G_PI_CS, 1);
u8g_SetPILevel(u8g, U8G_PI_A0, 1);
u8g_SetPILevel(u8g, U8G_PI_RESET, 1);
u8g_SetPIOutput(u8g, U8G_PI_CS);
u8g_SetPIOutput(u8g, U8G_PI_A0);
u8g_SetPIOutput(u8g, U8G_PI_RESET);
u8g_Delay(5);
spiBegin();
spiInit(LCD_SPI_SPEED);
break;
case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */
u8g_SetPILevel(u8g, U8G_PI_A0, arg_val);
break;
case U8G_COM_MSG_CHIP_SELECT:
u8g_SetPILevel(u8g, U8G_PI_CS, (arg_val ? 0 : 1));
break;
case U8G_COM_MSG_RESET:
u8g_SetPILevel(u8g, U8G_PI_RESET, arg_val);
break;
case U8G_COM_MSG_WRITE_BYTE:
spiSend((uint8_t)arg_val);
break;
case U8G_COM_MSG_WRITE_SEQ: {
uint8_t *ptr = (uint8_t*) arg_ptr;
while (arg_val > 0) {
spiSend(*ptr++);
arg_val--;
}
}
break;
case U8G_COM_MSG_WRITE_SEQ_P: {
uint8_t *ptr = (uint8_t*) arg_ptr;
while (arg_val > 0) {
spiSend(*ptr++);
arg_val--;
}
}
break;
}
return 1;
}
#endif // HAS_MARLINUI_U8GLIB
#endif // TARGET_LPC4078
@@ -0,0 +1,198 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
/**
* Based on u8g_com_arduino_ssd_i2c.c
*
* COM interface for Arduino (AND ATmega) and the SSDxxxx chip (SOLOMON) variant
* I2C protocol
*
* Universal 8bit Graphics Library
*
* Copyright (c) 2011, olikraus@gmail.com
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* Special pin usage:
* U8G_PI_I2C_OPTION additional options
* U8G_PI_A0_STATE used to store the last value of the command/data register selection
* U8G_PI_SET_A0 1: Signal request to update I2C device with new A0_STATE, 0: Do nothing, A0_STATE matches I2C device
* U8G_PI_SCL clock line (NOT USED)
* U8G_PI_SDA data line (NOT USED)
*
* U8G_PI_RESET reset line (currently disabled, see below)
*
* Protocol:
* SLA, Cmd/Data Selection, Arguments
* The command/data register is selected by a special instruction byte, which is sent after SLA
*
* The continue bit is always 0 so that a (re)start is equired for the change from cmd to/data mode
*/
#ifdef TARGET_LPC1768
#include "../../../inc/MarlinConfigPre.h"
#if HAS_MARLINUI_U8GLIB
#include <U8glib-HAL.h>
#define I2C_SLA (0x3C*2)
//#define I2C_CMD_MODE 0x080
#define I2C_CMD_MODE 0x000
#define I2C_DATA_MODE 0x040
uint8_t u8g_com_ssd_I2C_start_sequence(u8g_t *u8g) {
/* are we requested to set the a0 state? */
if (u8g->pin_list[U8G_PI_SET_A0] == 0) return 1;
/* setup bus, might be a repeated start */
if (u8g_i2c_start(I2C_SLA) == 0) return 0;
if (u8g->pin_list[U8G_PI_A0_STATE] == 0) {
if (u8g_i2c_send_byte(I2C_CMD_MODE) == 0) return 0;
}
else if (u8g_i2c_send_byte(I2C_DATA_MODE) == 0)
return 0;
u8g->pin_list[U8G_PI_SET_A0] = 0;
return 1;
}
uint8_t u8g_com_HAL_LPC1768_ssd_hw_i2c_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
switch (msg) {
case U8G_COM_MSG_INIT:
//u8g_com_arduino_digital_write(u8g, U8G_PI_SCL, HIGH);
//u8g_com_arduino_digital_write(u8g, U8G_PI_SDA, HIGH);
//u8g->pin_list[U8G_PI_A0_STATE] = 0; /* initial RS state: unknown mode */
u8g_i2c_init(u8g->pin_list[U8G_PI_I2C_OPTION]);
u8g_com_ssd_I2C_start_sequence(u8g);
break;
case U8G_COM_MSG_STOP:
break;
case U8G_COM_MSG_RESET:
/* Currently disabled, but it could be enable. Previous restrictions have been removed */
/* u8g_com_arduino_digital_write(u8g, U8G_PI_RESET, arg_val); */
break;
case U8G_COM_MSG_CHIP_SELECT:
u8g->pin_list[U8G_PI_A0_STATE] = 0;
u8g->pin_list[U8G_PI_SET_A0] = 1; /* force a0 to set again, also forces start condition */
if (arg_val == 0 ) {
/* disable chip, send stop condition */
u8g_i2c_stop();
}
else {
/* enable, do nothing: any byte writing will trigger the i2c start */
}
break;
case U8G_COM_MSG_WRITE_BYTE:
//u8g->pin_list[U8G_PI_SET_A0] = 1;
if (u8g_com_ssd_I2C_start_sequence(u8g) == 0) {
u8g_i2c_stop();
return 0;
}
if (u8g_i2c_send_byte(arg_val) == 0) {
u8g_i2c_stop();
return 0;
}
// u8g_i2c_stop();
break;
case U8G_COM_MSG_WRITE_SEQ: {
//u8g->pin_list[U8G_PI_SET_A0] = 1;
if (u8g_com_ssd_I2C_start_sequence(u8g) == 0) {
u8g_i2c_stop();
return 0;
}
uint8_t *ptr = (uint8_t *)arg_ptr;
while (arg_val > 0) {
if (u8g_i2c_send_byte(*ptr++) == 0) {
u8g_i2c_stop();
return 0;
}
arg_val--;
}
}
// u8g_i2c_stop();
break;
case U8G_COM_MSG_WRITE_SEQ_P: {
//u8g->pin_list[U8G_PI_SET_A0] = 1;
if (u8g_com_ssd_I2C_start_sequence(u8g) == 0) {
u8g_i2c_stop();
return 0;
}
uint8_t *ptr = (uint8_t *)arg_ptr;
while (arg_val > 0) {
if (u8g_i2c_send_byte(u8g_pgm_read(ptr)) == 0)
return 0;
ptr++;
arg_val--;
}
}
// u8g_i2c_stop();
break;
case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */
u8g->pin_list[U8G_PI_A0_STATE] = arg_val;
u8g->pin_list[U8G_PI_SET_A0] = 1; /* force a0 to set again */
break;
} // switch
return 1;
}
#endif // HAS_MARLINUI_U8GLIB
#endif // TARGET_LPC1768
@@ -0,0 +1,138 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
/**
* Based on u8g_com_LPC1768_st7920_hw_spi.c
*
* Universal 8bit Graphics Library
*
* Copyright (c) 2011, olikraus@gmail.com
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef TARGET_LPC4078
#include "../../../inc/MarlinConfigPre.h"
#if HAS_MARLINUI_U8GLIB
#include <U8glib-HAL.h>
#include "../../shared/HAL_SPI.h"
#include "../../shared/Delay.h"
void spiBegin();
void spiInit(uint8_t spiRate);
void spiSend(uint8_t b);
void spiSend(const uint8_t *buf, size_t n);
static uint8_t rs_last_state = 255;
static void u8g_com_LPC1768_st7920_write_byte_hw_spi(uint8_t rs, uint8_t val) {
if (rs != rs_last_state) { // Time to send a command/data byte
rs_last_state = rs;
spiSend(rs ? 0x0FA : 0x0F8); // Send data or command
DELAY_US(40); // Give the controller some time: 20 is bad, 30 is OK, 40 is safe
}
spiSend(val & 0xF0);
spiSend(val << 4);
}
uint8_t u8g_com_HAL_LPC1768_ST7920_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
switch (msg) {
case U8G_COM_MSG_INIT:
u8g_SetPILevel(u8g, U8G_PI_CS, 0);
u8g_SetPIOutput(u8g, U8G_PI_CS);
u8g_Delay(5);
spiBegin();
spiInit(SPI_EIGHTH_SPEED); // ST7920 max speed is about 1.1 MHz
u8g->pin_list[U8G_PI_A0_STATE] = 0; // initial RS state: command mode
break;
case U8G_COM_MSG_STOP:
break;
case U8G_COM_MSG_RESET:
u8g_SetPILevel(u8g, U8G_PI_RESET, arg_val);
break;
case U8G_COM_MSG_ADDRESS: // Define cmd (arg_val = 0) or data mode (arg_val = 1)
u8g->pin_list[U8G_PI_A0_STATE] = arg_val;
break;
case U8G_COM_MSG_CHIP_SELECT:
u8g_SetPILevel(u8g, U8G_PI_CS, arg_val); // Note: the ST7920 has an active high chip-select
break;
case U8G_COM_MSG_WRITE_BYTE:
u8g_com_LPC1768_st7920_write_byte_hw_spi(u8g->pin_list[U8G_PI_A0_STATE], arg_val);
break;
case U8G_COM_MSG_WRITE_SEQ: {
uint8_t *ptr = (uint8_t*) arg_ptr;
while (arg_val > 0) {
u8g_com_LPC1768_st7920_write_byte_hw_spi(u8g->pin_list[U8G_PI_A0_STATE], *ptr++);
arg_val--;
}
}
break;
case U8G_COM_MSG_WRITE_SEQ_P: {
uint8_t *ptr = (uint8_t*) arg_ptr;
while (arg_val > 0) {
u8g_com_LPC1768_st7920_write_byte_hw_spi(u8g->pin_list[U8G_PI_A0_STATE], *ptr++);
arg_val--;
}
}
break;
}
return 1;
}
#endif // HAS_MARLINUI_U8GLIB
#endif // TARGET_LPC4078
@@ -0,0 +1,147 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
/**
* Based on u8g_com_st7920_hw_spi.c
*
* Universal 8bit Graphics Library
*
* Copyright (c) 2011, olikraus@gmail.com
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef TARGET_LPC4078
#include "../../../inc/MarlinConfigPre.h"
#if IS_U8GLIB_ST7920
#include <U8glib-HAL.h>
#include "../SoftwareSPI.h"
#include "../../shared/Delay.h"
#include "../../shared/HAL_SPI.h"
#ifndef LCD_SPI_SPEED
#define LCD_SPI_SPEED SPI_EIGHTH_SPEED // About 1 MHz
#endif
static pin_t SCK_pin_ST7920_HAL, MOSI_pin_ST7920_HAL_HAL;
static uint8_t SPI_speed = 0;
static void u8g_com_LPC1768_st7920_write_byte_sw_spi(uint8_t rs, uint8_t val) {
static uint8_t rs_last_state = 255;
if (rs != rs_last_state) {
// Transfer Data (FA) or Command (F8)
swSpiTransfer(rs ? 0x0FA : 0x0F8, SPI_speed, SCK_pin_ST7920_HAL, -1, MOSI_pin_ST7920_HAL_HAL);
rs_last_state = rs;
DELAY_US(40); // Give the controller time to process the data: 20 is bad, 30 is OK, 40 is safe
}
swSpiTransfer(val & 0x0F0, SPI_speed, SCK_pin_ST7920_HAL, -1, MOSI_pin_ST7920_HAL_HAL);
swSpiTransfer(val << 4, SPI_speed, SCK_pin_ST7920_HAL, -1, MOSI_pin_ST7920_HAL_HAL);
}
uint8_t u8g_com_HAL_LPC1768_ST7920_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
switch (msg) {
case U8G_COM_MSG_INIT:
SCK_pin_ST7920_HAL = u8g->pin_list[U8G_PI_SCK];
MOSI_pin_ST7920_HAL_HAL = u8g->pin_list[U8G_PI_MOSI];
u8g_SetPIOutput(u8g, U8G_PI_CS);
u8g_SetPIOutput(u8g, U8G_PI_SCK);
u8g_SetPIOutput(u8g, U8G_PI_MOSI);
u8g_Delay(5);
SPI_speed = swSpiInit(LCD_SPI_SPEED, SCK_pin_ST7920_HAL, MOSI_pin_ST7920_HAL_HAL);
u8g_SetPILevel(u8g, U8G_PI_CS, 0);
u8g_SetPILevel(u8g, U8G_PI_SCK, 0);
u8g_SetPILevel(u8g, U8G_PI_MOSI, 0);
u8g->pin_list[U8G_PI_A0_STATE] = 0; /* initial RS state: command mode */
break;
case U8G_COM_MSG_STOP:
break;
case U8G_COM_MSG_RESET:
if (U8G_PIN_NONE != u8g->pin_list[U8G_PI_RESET]) u8g_SetPILevel(u8g, U8G_PI_RESET, arg_val);
break;
case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */
u8g->pin_list[U8G_PI_A0_STATE] = arg_val;
break;
case U8G_COM_MSG_CHIP_SELECT:
if (U8G_PIN_NONE != u8g->pin_list[U8G_PI_CS]) u8g_SetPILevel(u8g, U8G_PI_CS, arg_val); //note: the st7920 has an active high chip select
break;
case U8G_COM_MSG_WRITE_BYTE:
u8g_com_LPC1768_st7920_write_byte_sw_spi(u8g->pin_list[U8G_PI_A0_STATE], arg_val);
break;
case U8G_COM_MSG_WRITE_SEQ: {
uint8_t *ptr = (uint8_t*) arg_ptr;
while (arg_val > 0) {
u8g_com_LPC1768_st7920_write_byte_sw_spi(u8g->pin_list[U8G_PI_A0_STATE], *ptr++);
arg_val--;
}
}
break;
case U8G_COM_MSG_WRITE_SEQ_P: {
uint8_t *ptr = (uint8_t*) arg_ptr;
while (arg_val > 0) {
u8g_com_LPC1768_st7920_write_byte_sw_spi(u8g->pin_list[U8G_PI_A0_STATE], *ptr++);
arg_val--;
}
}
break;
}
return 1;
}
#endif // IS_U8GLIB_ST7920
#endif // TARGET_LPC4078
@@ -0,0 +1,209 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
/**
* Based on u8g_com_std_sw_spi.c
*
* Universal 8bit Graphics Library
*
* Copyright (c) 2015, olikraus@gmail.com
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef TARGET_LPC4078
#include "../../../inc/MarlinConfigPre.h"
#if HAS_MARLINUI_U8GLIB && !IS_U8GLIB_ST7920
#include <SoftwareSPI.h>
#include "../../shared/HAL_SPI.h"
#ifndef LCD_SPI_SPEED
#define LCD_SPI_SPEED SPI_QUARTER_SPEED // About 2 MHz
#endif
#include <Arduino.h>
#include <algorithm>
#include <LPC17xx.h>
#include <gpio.h>
#include <U8glib-HAL.h>
uint8_t swSpiTransfer_mode_0(uint8_t b, const uint8_t spi_speed, const pin_t sck_pin, const pin_t miso_pin, const pin_t mosi_pin ) {
LOOP_L_N(i, 8) {
if (spi_speed == 0) {
LPC176x::gpio_set(mosi_pin, !!(b & 0x80));
LPC176x::gpio_set(sck_pin, HIGH);
b <<= 1;
if (miso_pin >= 0 && LPC176x::gpio_get(miso_pin)) b |= 1;
LPC176x::gpio_set(sck_pin, LOW);
}
else {
const uint8_t state = (b & 0x80) ? HIGH : LOW;
LOOP_L_N(j, spi_speed)
LPC176x::gpio_set(mosi_pin, state);
LOOP_L_N(j, spi_speed + (miso_pin >= 0 ? 0 : 1))
LPC176x::gpio_set(sck_pin, HIGH);
b <<= 1;
if (miso_pin >= 0 && LPC176x::gpio_get(miso_pin)) b |= 1;
LOOP_L_N(j, spi_speed)
LPC176x::gpio_set(sck_pin, LOW);
}
}
return b;
}
uint8_t swSpiTransfer_mode_3(uint8_t b, const uint8_t spi_speed, const pin_t sck_pin, const pin_t miso_pin, const pin_t mosi_pin ) {
LOOP_L_N(i, 8) {
const uint8_t state = (b & 0x80) ? HIGH : LOW;
if (spi_speed == 0) {
LPC176x::gpio_set(sck_pin, LOW);
LPC176x::gpio_set(mosi_pin, state);
LPC176x::gpio_set(mosi_pin, state); // need some setup time
LPC176x::gpio_set(sck_pin, HIGH);
}
else {
LOOP_L_N(j, spi_speed + (miso_pin >= 0 ? 0 : 1))
LPC176x::gpio_set(sck_pin, LOW);
LOOP_L_N(j, spi_speed)
LPC176x::gpio_set(mosi_pin, state);
LOOP_L_N(j, spi_speed)
LPC176x::gpio_set(sck_pin, HIGH);
}
b <<= 1;
if (miso_pin >= 0 && LPC176x::gpio_get(miso_pin)) b |= 1;
}
return b;
}
static uint8_t SPI_speed = 0;
static void u8g_sw_spi_HAL_LPC1768_shift_out(uint8_t dataPin, uint8_t clockPin, uint8_t val) {
#if ANY(FYSETC_MINI_12864, MKS_MINI_12864)
swSpiTransfer_mode_3(val, SPI_speed, clockPin, -1, dataPin);
#else
swSpiTransfer_mode_0(val, SPI_speed, clockPin, -1, dataPin);
#endif
}
uint8_t u8g_com_HAL_LPC1768_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
switch (msg) {
case U8G_COM_MSG_INIT:
u8g_SetPIOutput(u8g, U8G_PI_SCK);
u8g_SetPIOutput(u8g, U8G_PI_MOSI);
u8g_SetPIOutput(u8g, U8G_PI_CS);
u8g_SetPIOutput(u8g, U8G_PI_A0);
if (U8G_PIN_NONE != u8g->pin_list[U8G_PI_RESET]) u8g_SetPIOutput(u8g, U8G_PI_RESET);
SPI_speed = swSpiInit(LCD_SPI_SPEED, u8g->pin_list[U8G_PI_SCK], u8g->pin_list[U8G_PI_MOSI]);
u8g_SetPILevel(u8g, U8G_PI_SCK, 0);
u8g_SetPILevel(u8g, U8G_PI_MOSI, 0);
break;
case U8G_COM_MSG_STOP:
break;
case U8G_COM_MSG_RESET:
if (U8G_PIN_NONE != u8g->pin_list[U8G_PI_RESET]) u8g_SetPILevel(u8g, U8G_PI_RESET, arg_val);
break;
case U8G_COM_MSG_CHIP_SELECT:
#if ANY(FYSETC_MINI_12864, MKS_MINI_12864) // LCD SPI is running mode 3 while SD card is running mode 0
if (arg_val) { // SCK idle state needs to be set to the proper idle state before
// the next chip select goes active
u8g_SetPILevel(u8g, U8G_PI_SCK, 1); // Set SCK to mode 3 idle state before CS goes active
u8g_SetPILevel(u8g, U8G_PI_CS, LOW);
}
else {
u8g_SetPILevel(u8g, U8G_PI_CS, HIGH);
u8g_SetPILevel(u8g, U8G_PI_SCK, 0); // Set SCK to mode 0 idle state after CS goes inactive
}
#else
u8g_SetPILevel(u8g, U8G_PI_CS, !arg_val);
#endif
break;
case U8G_COM_MSG_WRITE_BYTE:
u8g_sw_spi_HAL_LPC1768_shift_out(u8g->pin_list[U8G_PI_MOSI], u8g->pin_list[U8G_PI_SCK], arg_val);
break;
case U8G_COM_MSG_WRITE_SEQ: {
uint8_t *ptr = (uint8_t *)arg_ptr;
while (arg_val > 0) {
u8g_sw_spi_HAL_LPC1768_shift_out(u8g->pin_list[U8G_PI_MOSI], u8g->pin_list[U8G_PI_SCK], *ptr++);
arg_val--;
}
}
break;
case U8G_COM_MSG_WRITE_SEQ_P: {
uint8_t *ptr = (uint8_t *)arg_ptr;
while (arg_val > 0) {
u8g_sw_spi_HAL_LPC1768_shift_out(u8g->pin_list[U8G_PI_MOSI], u8g->pin_list[U8G_PI_SCK], u8g_pgm_read(ptr));
ptr++;
arg_val--;
}
}
break;
case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */
u8g_SetPILevel(u8g, U8G_PI_A0, arg_val);
break;
}
return 1;
}
#endif // HAS_MARLINUI_U8GLIB && !IS_U8GLIB_ST7920
#endif // TARGET_LPC4078
+1 -1
View File
@@ -41,7 +41,7 @@ typedef uint32_t hal_timer_t;
#define FTM0_TIMER_PRESCALE_BITS 0b011
#define FTM1_TIMER_PRESCALE_BITS 0b010
#define FTM0_TIMER_RATE (F_BUS / (FTM0_TIMER_PRESCALE)) // 60MHz / 8 = 7500kHz
#define FTM0_TIMER_RATE (F_BUS / (FTM0_TIMER_PRESCALE)) // 60MHz / 8 = 7.5MHz
#define FTM1_TIMER_RATE (F_BUS / (FTM1_TIMER_PRESCALE)) // 60MHz / 4 = 15MHz
#define HAL_TIMER_RATE (FTM0_TIMER_RATE)
+2
View File
@@ -37,6 +37,8 @@
#define HAL_PATH(PATH, NAME) XSTR(PATH/HAL/LPC1768/NAME)
#elif defined(ARDUINO_ARCH_HC32)
#define HAL_PATH(PATH, NAME) XSTR(PATH/HAL/HC32/NAME)
#elif defined(TARGET_LPC4078)
#define HAL_PATH(PATH, NAME) XSTR(PATH/HAL/LPC4078/NAME)
#elif defined(__STM32F1__) || defined(TARGET_STM32F1)
#define HAL_PATH(PATH, NAME) XSTR(PATH/HAL/STM32F1/NAME)
#elif defined(ARDUINO_ARCH_STM32)
+2
View File
@@ -76,6 +76,8 @@
#include "../LPC1768/Servo.h"
#elif defined(ARDUINO_ARCH_HC32)
#include "../HC32/Servo.h"
#elif defined(TARGET_LPC4078)
#include "../LPC4078/Servo.h"
#elif defined(__STM32F1__) || defined(TARGET_STM32F1)
#include "../STM32F1/Servo.h"
#elif defined(ARDUINO_ARCH_STM32)
+1
View File
@@ -410,6 +410,7 @@
#define BOARD_TEENSY31_32 5100 // Teensy3.1 and Teensy3.2
#define BOARD_TEENSY35_36 5101 // Teensy3.5 and Teensy3.6
#define BOARD_EBAB 5102
//
// STM32 ARM Cortex-M4F
+1 -1
View File
@@ -89,7 +89,7 @@
#define HYPOT2(x,y) (sq(x)+sq(y))
#define NORMSQ(x,y,z) (sq(x)+sq(y)+sq(z))
#define FLOAT_SQ(I) sq(float(I))
#define FLOAT_SQ(I) float(sq(I))
#define CIRCLE_AREA(R) (float(M_PI) * FLOAT_SQ(R))
#define CIRCLE_CIRC(R) (2 * float(M_PI) * float(R))
+10
View File
@@ -833,6 +833,16 @@ static_assert(COUNT(arm) == LOGICAL_AXES, "AXIS_RELATIVE_MODES must contain " _L
#endif
#endif
/**
* S_CURVE_ACCELERATION
*/
#if ENABLED(S_CURVE_ACCELERATION) && defined(S_CURVE_FACTOR)
#if defined(__AVR__)
#error "S_CURVE_FACTOR is not implemented for AVR yet"
#endif
static_assert(WITHIN(S_CURVE_FACTOR, 0, 1), "S_CURVE_FACTOR must be from 0 to 1");
#endif
/**
* Nonlinear Extrusion requirements
*/
+1 -1
View File
@@ -1343,7 +1343,7 @@ void MarlinUI::draw_status_screen() {
void MenuItem_sdbase::draw(const bool sel, const uint8_t row, FSTR_P const, CardReader &theCard, const bool isDir) {
lcd_put_lchar(0, row, sel ? LCD_STR_ARROW_RIGHT[0] : ' ');
uint8_t n = LCD_WIDTH - 2;
n -= lcd_put_u8str_max(ui.scrolled_filename(theCard, n, row, sel), n);
n -= lcd_put_u8str_max(ui.scrolled_filename(theCard, n, sel), n);
for (; n; --n) lcd_put_u8str(F(" "));
lcd_put_lchar(isDir ? LCD_STR_FOLDER[0] : ' ');
}
+1 -1
View File
@@ -1086,7 +1086,7 @@ void MarlinUI::draw_status_screen() {
lcd_moveto(0, row);
lcd.write(sel ? LCD_STR_ARROW_RIGHT[0] : ' ');
uint8_t n = LCD_WIDTH - 2;
n -= lcd_put_u8str_max(ui.scrolled_filename(theCard, n, row, sel), n);
n -= lcd_put_u8str_max(ui.scrolled_filename(theCard, n, sel), n);
for (; n; --n) lcd.write(' ');
lcd.write(isDir ? LCD_STR_FOLDER[0] : ' ');
lcd.print_line();
+1 -1
View File
@@ -606,7 +606,7 @@ void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop
const uint8_t maxlen = LCD_WIDTH - isDir;
if (isDir) lcd_put_lchar(LCD_STR_FOLDER[0]);
const pixel_len_t pixw = maxlen * (MENU_FONT_WIDTH);
pixel_len_t n = pixw - lcd_put_u8str_max(ui.scrolled_filename(theCard, maxlen, row, sel), pixw);
pixel_len_t n = pixw - lcd_put_u8str_max(ui.scrolled_filename(theCard, maxlen, sel), pixw);
for (; n > MENU_FONT_WIDTH; n -= MENU_FONT_WIDTH) lcd_put_u8str(F(" "));
}
+1 -1
View File
@@ -487,7 +487,7 @@ void MarlinUI::draw_status_message(const bool blink) {
maxlen -= 2;
}
dwin_string.add(ui.scrolled_filename(theCard, maxlen, row, sel), maxlen);
dwin_string.add(ui.scrolled_filename(theCard, maxlen, sel), maxlen);
uint8_t n = maxlen - dwin_string.length;
while (n > 0) { dwin_string.add(' '); --n; }
lcd_moveto(1, row);
+23 -26
View File
@@ -357,25 +357,21 @@ void MarlinUI::init() {
#if HAS_MEDIA
#if MARLINUI_SCROLL_NAME
uint8_t MarlinUI::filename_scroll_pos, MarlinUI::filename_scroll_max;
static uint8_t filename_scroll_pos, filename_scroll_max;
#endif
const char * MarlinUI::scrolled_filename(CardReader &theCard, const uint8_t maxlen, uint8_t hash, const bool doScroll) {
const char * MarlinUI::scrolled_filename(CardReader &theCard, const uint8_t maxlen, const bool doScroll) {
const char *outstr = theCard.longest_filename();
if (theCard.longFilename[0]) {
#if MARLINUI_SCROLL_NAME
if (doScroll) {
for (uint8_t l = FILENAME_LENGTH; l--;)
hash = ((hash << 1) | (hash >> 7)) ^ theCard.filename[l]; // rotate, xor
static uint8_t filename_scroll_hash;
if (filename_scroll_hash != hash) { // If the hash changed...
filename_scroll_hash = hash; // Save the new hash
filename_scroll_max = _MAX(0, utf8_strlen(theCard.longFilename) - maxlen); // Update the scroll limit
filename_scroll_pos = 0; // Reset scroll to the start
lcd_status_update_delay = 8; // Don't scroll right away
filename_scroll_max = _MAX(0, utf8_strlen(theCard.longFilename) - maxlen);
if (filename_scroll_max) {
// Ensure filename_scroll_pos isn't out of bounds even though it should never happen.
if (filename_scroll_pos > filename_scroll_max) filename_scroll_pos = 0;
// Advance byte position corresponding to filename_scroll_pos char position
outstr += TERN(UTF_FILENAME_SUPPORT, utf8_byte_pos_by_char_num(outstr, filename_scroll_pos), filename_scroll_pos);
}
// Advance byte position corresponding to filename_scroll_pos char position
outstr += TERN(UTF_FILENAME_SUPPORT, utf8_byte_pos_by_char_num(outstr, filename_scroll_pos), filename_scroll_pos);
}
#else
theCard.longFilename[
@@ -1003,22 +999,19 @@ void MarlinUI::init() {
#endif // HAS_MARLINUI_MENU
if (ELAPSED(ms, next_lcd_update_ms) || TERN0(HAS_MARLINUI_U8GLIB, drawing_screen)) {
const bool lcd_update_ms_elapsed = ELAPSED(ms, next_lcd_update_ms);
if (lcd_update_ms_elapsed) {
next_lcd_update_ms = ms + LCD_UPDATE_INTERVAL;
#if HAS_TOUCH_BUTTONS
if (on_status_screen()) next_lcd_update_ms += (LCD_UPDATE_INTERVAL) * 2;
TERN_(HAS_ENCODER_ACTION, touch_buttons = touchBt.read_buttons());
#endif
TERN_(LCD_HAS_STATUS_INDICATORS, update_indicators());
#if HAS_ENCODER_ACTION
TERN_(HAS_SLOW_BUTTONS, slow_buttons = read_slow_buttons()); // Buttons that take too long to read in interrupt context
if (TERN0(IS_RRW_KEYPAD, handle_keypad()))
@@ -1083,12 +1076,17 @@ void MarlinUI::init() {
#endif
refresh(LCDVIEW_REDRAW_NOW);
TERN_(HAS_MARLINUI_U8GLIB, drawing_screen = false);
#if MARLINUI_SCROLL_NAME
filename_scroll_max = 0;
filename_scroll_pos = 0;
lcd_status_update_delay = 9;
#endif
#if LED_POWEROFF_TIMEOUT > 0
if (!powerManager.psu_on) leds.reset_timeout(ms);
#endif
} // encoder activity
#endif // HAS_ENCODER_ACTION
// This runs every ~100ms when idling often enough.
@@ -1097,19 +1095,23 @@ void MarlinUI::init() {
lcd_status_update_delay = TERN(HAS_MARLINUI_U8GLIB, 12, 9);
if (max_display_update_time) max_display_update_time--; // Be sure never go to a very big number
refresh(LCDVIEW_REDRAW_NOW);
TERN_(HAS_MARLINUI_U8GLIB, drawing_screen = false);
}
#if ALL(HAS_MARLINUI_MENU, SCROLL_LONG_FILENAMES)
#if MARLINUI_SCROLL_NAME
// If scrolling of long file names is enabled and we are in the sd card menu,
// cause a refresh to occur until all the text has scrolled into view.
if (currentScreen == menu_media && !lcd_status_update_delay--) {
if (currentScreen == menu_media && filename_scroll_max && !lcd_status_update_delay--) {
lcd_status_update_delay = ++filename_scroll_pos >= filename_scroll_max ? 12 : 4; // Long delay at end and start
if (filename_scroll_pos > filename_scroll_max) filename_scroll_pos = 0;
refresh(LCDVIEW_REDRAW_NOW);
TERN_(HAS_MARLINUI_U8GLIB, drawing_screen = false);
reset_status_timeout(ms);
}
#endif
}
if (lcd_update_ms_elapsed || drawing_screen) {
// Then we want to use only 50% of the time
const uint16_t bbr2 = planner.block_buffer_runtime() >> 1;
@@ -1131,7 +1133,6 @@ void MarlinUI::init() {
TERN_(HAS_ADC_BUTTONS, keypad_buttons = 0);
#if HAS_MARLINUI_U8GLIB
#if ENABLED(LIGHTWEIGHT_UI)
const bool in_status = on_status_screen(),
do_u8g_loop = !in_status;
@@ -1160,14 +1161,11 @@ void MarlinUI::init() {
return;
}
}
#else
run_current_screen();
// Apply all DWIN drawing after processing
TERN_(IS_DWIN_MARLINUI, dwinUpdateLCD());
#endif
TERN_(HAS_MARLINUI_MENU, lcd_clicked = false);
@@ -1212,8 +1210,7 @@ void MarlinUI::init() {
case LCDVIEW_CALL_NO_REDRAW:
default: break;
} // switch
} // ELAPSED(ms, next_lcd_update_ms)
}
TERN_(HAS_GRAPHICAL_TFT, tft_idle());
}
+1 -4
View File
@@ -644,10 +644,7 @@ public:
#if ALL(SCROLL_LONG_FILENAMES, HAS_MARLINUI_MENU)
#define MARLINUI_SCROLL_NAME 1
#endif
#if MARLINUI_SCROLL_NAME
static uint8_t filename_scroll_pos, filename_scroll_max;
#endif
static const char * scrolled_filename(CardReader &theCard, const uint8_t maxlen, uint8_t hash, const bool doScroll);
static const char * scrolled_filename(CardReader &theCard, const uint8_t maxlen, const bool doScroll);
#endif
#if HAS_PREHEAT
+7 -7
View File
@@ -523,12 +523,12 @@ void menu_backlash();
// M204 T Travel Acceleration
EDIT_ITEM_FAST(float5_25, MSG_A_TRAVEL, &planner.settings.travel_acceleration, 25, max_accel);
#define EDIT_AMAX(Q,L) EDIT_ITEM_FAST_N(long5_25, _AXIS(Q), MSG_AMAX_N, &planner.settings.max_acceleration_mm_per_s2[_AXIS(Q)], L, max_accel_edit_scaled[_AXIS(Q)], []{ planner.refresh_acceleration_rates(); })
NUM_AXIS_CODE(
EDIT_AMAX(A, 100), EDIT_AMAX(B, 100), EDIT_AMAX(C, 10),
EDIT_AMAX(I, 10), EDIT_AMAX(J, 10), EDIT_AMAX(K, 10),
EDIT_AMAX(U, 10), EDIT_AMAX(V, 10), EDIT_AMAX(W, 10)
);
//#define EDIT_AMAX(Q,L) EDIT_ITEM_FAST_N(long5_25, _AXIS(Q), MSG_AMAX_N, &planner.settings.max_acceleration_mm_per_s2[_AXIS(Q)], L, max_accel_edit_scaled[_AXIS(Q)], []{ planner.refresh_acceleration_rates(); })
//NUM_AXIS_CODE(
// EDIT_AMAX(A, 100), EDIT_AMAX(B, 100), EDIT_AMAX(C, 10),
// EDIT_AMAX(I, 10), EDIT_AMAX(J, 10), EDIT_AMAX(K, 10),
// EDIT_AMAX(U, 10), EDIT_AMAX(V, 10), EDIT_AMAX(W, 10)
//);
#if ENABLED(DISTINCT_E_FACTORS)
EDIT_ITEM_FAST(long5_25, MSG_AMAX_E, &planner.settings.max_acceleration_mm_per_s2[E_AXIS_N(active_extruder)], 100, max_accel_edit_scaled.e, []{ planner.refresh_acceleration_rates(); });
@@ -538,7 +538,7 @@ void menu_backlash();
planner.refresh_acceleration_rates();
});
#elif E_STEPPERS
EDIT_ITEM_FAST(long5_25, MSG_AMAX_E, &planner.settings.max_acceleration_mm_per_s2[E_AXIS], 100, max_accel_edit_scaled.e, []{ planner.refresh_acceleration_rates(); });
//EDIT_ITEM_FAST(long5_25, MSG_AMAX_E, &planner.settings.max_acceleration_mm_per_s2[E_AXIS], 100, max_accel_edit_scaled.e, []{ planner.refresh_acceleration_rates(); });
#endif
#ifdef XY_FREQUENCY_LIMIT
+1 -1
View File
@@ -386,7 +386,7 @@ void MenuItem_static::draw(const uint8_t row, FSTR_P const ftpl, const uint8_t s
menu_item(row, sel);
if (isDir) tft.add_image(MENU_ITEM_ICON_X, MENU_ITEM_ICON_Y, imgDirectory, COLOR_MENU_TEXT, sel ? COLOR_SELECTION_BG : COLOR_BACKGROUND);
uint8_t maxlen = (MENU_ITEM_HEIGHT) - (MENU_TEXT_Y) + 1;
tft.add_text(MENU_ITEM_ICON_SPACE, MENU_TEXT_Y, COLOR_MENU_TEXT, ui.scrolled_filename(theCard, maxlen, row, sel));
tft.add_text(MENU_ITEM_ICON_SPACE, MENU_TEXT_Y, COLOR_MENU_TEXT, ui.scrolled_filename(theCard, maxlen, sel));
}
#endif
+144 -227
View File
@@ -128,7 +128,6 @@ Planner planner;
block_t Planner::block_buffer[BLOCK_BUFFER_SIZE];
volatile uint8_t Planner::block_buffer_head, // Index of the next block to be pushed
Planner::block_buffer_nonbusy, // Index of the first non-busy block
Planner::block_buffer_planned, // Index of the optimally planned block
Planner::block_buffer_tail; // Index of the busy block, if any
uint16_t Planner::cleaning_buffer_counter; // A counter to disable queuing of blocks
uint8_t Planner::delay_before_delivering; // Delay block delivery so initial blocks in an empty queue may merge
@@ -150,7 +149,7 @@ planner_settings_t Planner::settings; // Initialized by settings.load(
const uint8_t laser_power_floor = cutter.pct_to_ocr(SPEED_POWER_MIN);
#endif
uint32_t Planner::max_acceleration_steps_per_s2[DISTINCT_AXES]; // (steps/s^2) Derived from mm_per_s2
uint64_t Planner::max_acceleration_steps_per_s2[DISTINCT_AXES]; // (steps/s^2) Derived from mm_per_s2
#if HAS_JUNCTION_DEVIATION
float Planner::junction_deviation_mm; // (mm) M205 J
@@ -170,7 +169,7 @@ uint32_t Planner::max_acceleration_steps_per_s2[DISTINCT_AXES]; // (steps/s^2) D
#endif
#if ENABLED(DIRECT_STEPPING)
uint32_t Planner::last_page_step_rate = 0;
uint64_t Planner::last_page_step_rate = 0;
AxisBits Planner::last_page_dir; // = 0
#endif
@@ -220,7 +219,7 @@ uint32_t Planner::max_acceleration_steps_per_s2[DISTINCT_AXES]; // (steps/s^2) D
xyze_long_t Planner::position{0};
uint32_t Planner::acceleration_long_cutoff;
uint64_t Planner::acceleration_long_cutoff;
xyze_float_t Planner::previous_speed;
float Planner::previous_nominal_speed;
@@ -248,7 +247,7 @@ float Planner::previous_nominal_speed;
#endif
#if HAS_WIRED_LCD
volatile uint32_t Planner::block_buffer_runtime_us = 0;
volatile uint64_t Planner::block_buffer_runtime_us = 0;
#endif
/**
@@ -338,7 +337,7 @@ void Planner::init() {
* // Compute initial estimation of 0x1000000/x -
* // Get most significant bit set on divider
* uint8_t idx = 0;
* uint32_t nr = d;
* uint64_t nr = d;
* if (!(nr & 0xFF0000)) {
* nr <<= 8; idx += 8;
* if (!(nr & 0xFF0000)) { nr <<= 8; idx += 8; }
@@ -348,16 +347,16 @@ void Planner::init() {
* if (!(nr & 0x800000)) { nr <<= 1; idx += 1; }
*
* // Isolate top 9 bits of the denominator, to be used as index into the initial estimation table
* uint32_t tidx = nr >> 15, // top 9 bits. bit8 is always set
* uint64_t tidx = nr >> 15, // top 9 bits. bit8 is always set
* ie = inv_tab[tidx & 0xFF] + 256, // Get the table value. bit9 is always set
* x = idx <= 8 ? (ie >> (8 - idx)) : (ie << (idx - 8)); // Position the estimation at the proper place
*
* x = uint32_t((x * uint64_t(_BV(25) - x * d)) >> 24); // Refine estimation by newton-raphson. 1 iteration is enough
* const uint32_t r = _BV(24) - x * d; // Estimate remainder
* x = uint64_t((x * uint64_t(_BV(25) - x * d)) >> 24); // Refine estimation by newton-raphson. 1 iteration is enough
* const uint64_t r = _BV(24) - x * d; // Estimate remainder
* if (r >= d) x++; // Check whether to adjust result
* return uint32_t(x); // x holds the proper estimation
* return uint64_t(x); // x holds the proper estimation
*/
static uint32_t get_period_inverse(uint32_t d) {
static uint64_t get_period_inverse(uint64_t d) {
static const uint8_t inv_tab[256] PROGMEM = {
255,253,252,250,248,246,244,242,240,238,236,234,233,231,229,227,
@@ -381,7 +380,7 @@ void Planner::init() {
// For small denominators, it is cheaper to directly store the result.
// For bigger ones, just ONE Newton-Raphson iteration is enough to get
// maximum precision we need
static const uint32_t small_inv_tab[111] PROGMEM = {
static const uint64_t small_inv_tab[111] PROGMEM = {
16777216,16777216,8388608,5592405,4194304,3355443,2796202,2396745,2097152,1864135,1677721,1525201,1398101,1290555,1198372,1118481,
1048576,986895,932067,883011,838860,798915,762600,729444,699050,671088,645277,621378,599186,578524,559240,541200,
524288,508400,493447,479349,466033,453438,441505,430185,419430,409200,399457,390167,381300,372827,364722,356962,
@@ -718,20 +717,18 @@ void Planner::init() {
);
// Return the result
return r11 | (uint16_t(r12) << 8) | (uint32_t(r13) << 16);
return r11 | (uint16_t(r12) << 8) | (uint64_t(r13) << 16);
}
#else
// All other 32-bit MPUs can easily do inverse using hardware division,
// so we don't need to reduce precision or to use assembly language at all.
// This routine, for all other archs, returns 0x100000000 / d ~= 0xFFFFFFFF / d
FORCE_INLINE static uint32_t get_period_inverse(const uint32_t d) {
FORCE_INLINE static uint64_t get_period_inverse(const uint64_t d) {
return d ? 0xFFFFFFFF / d : 0xFFFFFFFF;
}
#endif
#endif
#define MINIMAL_STEP_RATE 120
/**
* Get the current block for processing
* and mark the block as busy.
@@ -768,10 +765,6 @@ block_t* Planner::get_current_block() {
// As this block is busy, advance the nonbusy block pointer
block_buffer_nonbusy = next_block_index(block_buffer_tail);
// Push block_buffer_planned pointer, if encountered.
if (block_buffer_tail == block_buffer_planned)
block_buffer_planned = block_buffer_nonbusy;
// Return the block
return block;
}
@@ -784,33 +777,37 @@ block_t* Planner::get_current_block() {
/**
* Calculate trapezoid parameters, multiplying the entry- and exit-speeds
* by the provided factors. Requires that initial_rate and final_rate are
* no less than sqrt(block->acceleration_steps_per_s2 / 2), which is ensured
* through minimum_planner_speed_sqr in _populate_block().
* by the provided factors. If entry_factor is 0 don't change the initial_rate.
* Assumes that the implied initial_rate and final_rate are no less than
* sqrt(block->acceleration_steps_per_s2 / 2). This is ensured through
* minimum_planner_speed_sqr / min_entry_speed_sqr though note there's one
* exception in recalculate_trapezoids().
**
* ############ VERY IMPORTANT ############
* NOTE that the PRECONDITION to call this function is that the block is
* NOT BUSY and it is marked as RECALCULATE. That WARRANTIES the Stepper ISR
* is not and will not use the block while we modify it, so it is safe to
* alter its values.
* is not and will not use the block while we modify it.
*/
void Planner::calculate_trapezoid_for_block(block_t * const block, const_float_t entry_factor, const_float_t exit_factor) {
void Planner::calculate_trapezoid_for_block(block_t * const block, const_float_t entry_speed, const_float_t exit_speed) {
uint32_t initial_rate = LROUND(block->nominal_rate * entry_factor),
final_rate = LROUND(block->nominal_rate * exit_factor); // (steps per second)
const float spmm = block->steps_per_mm;
uint64_t initial_rate = entry_speed ? _MAX(long(MINIMAL_STEP_RATE), LROUND(entry_speed * spmm)) : block->initial_rate,
final_rate = _MAX(long(MINIMAL_STEP_RATE), LROUND(exit_speed * spmm));
// Legacy check against supposed timer overflow. However Stepper::calc_timer_interval() already
// should protect against it. But removing this code produces judder in direction-switching
// moves. This is because the current discrete stepping math diverges from physical motion under
// constant acceleration when acceleration_steps_per_s2 is large compared to initial/final_rate.
NOLESS(initial_rate, uint32_t(MINIMAL_STEP_RATE)); // Enforce the minimum speed
NOLESS(final_rate, uint32_t(MINIMAL_STEP_RATE));
NOLESS(initial_rate, uint64_t(MINIMAL_STEP_RATE)); // Enforce the minimum speed
NOLESS(final_rate, uint64_t(MINIMAL_STEP_RATE));
NOLESS(block->nominal_rate, MINIMAL_STEP_RATE);
NOMORE(initial_rate, block->nominal_rate); // NOTE: The nominal rate may be less than MINIMAL_STEP_RATE!
NOMORE(final_rate, block->nominal_rate);
#if ANY(S_CURVE_ACCELERATION, LIN_ADVANCE)
// If we have some plateau time, the cruise rate will be the nominal rate
uint32_t cruise_rate = block->nominal_rate;
uint64_t cruise_rate = block->nominal_rate;
#endif
// Steps for acceleration, plateau and deceleration
@@ -827,7 +824,6 @@ void Planner::calculate_trapezoid_for_block(block_t * const block, const_float_t
// Steps required for acceleration, deceleration to/from nominal rate
decelerate_steps_float = half_inverse_accel * (nominal_rate_sq - FLOAT_SQ(final_rate)),
accelerate_steps_float = half_inverse_accel * (nominal_rate_sq - FLOAT_SQ(initial_rate));
// Aims to fully reach nominal and final rates
accelerate_steps = CEIL(accelerate_steps_float);
decelerate_steps = CEIL(decelerate_steps_float);
@@ -853,7 +849,7 @@ void Planner::calculate_trapezoid_for_block(block_t * const block, const_float_t
#if ENABLED(S_CURVE_ACCELERATION)
const float rate_factor = inverse_accel * (STEPPER_TIMER_RATE);
// Jerk controlled speed requires to express speed versus time, NOT steps
uint32_t acceleration_time = rate_factor * float(cruise_rate - initial_rate),
uint64_t acceleration_time = rate_factor * float(cruise_rate - initial_rate),
deceleration_time = rate_factor * float(cruise_rate - final_rate),
// And to offload calculations from the ISR, we also calculate the inverse of those times here
acceleration_time_inverse = get_period_inverse(acceleration_time),
@@ -942,16 +938,16 @@ void Planner::calculate_trapezoid_for_block(block_t * const block, const_float_t
*
* Recalculates the motion plan according to the following basic guidelines:
*
* 1. Go over every feasible block sequentially in reverse order and calculate the junction speeds
* (i.e. current->entry_speed) such that:
* a. No junction speed exceeds the pre-computed maximum junction speed limit or nominal speeds of
* neighboring blocks.
* b. A block entry speed cannot exceed one reverse-computed from its exit speed (next->entry_speed)
* with a maximum allowable deceleration over the block travel distance.
* c. The last (or newest appended) block is planned from safe_exit_speed_sqr.
* 2. Go over every block in chronological (forward) order and dial down junction speed values if
* a. The exit speed exceeds the one forward-computed from its entry speed with the maximum allowable
* acceleration over the block travel distance.
* 1. Go over blocks sequentially in reverse order and maximize the entry junction speed:
* a. Entry speed should stay below/at the pre-computed maximum junction speed limit
* b. Aim for the maximum entry speed which is the one reverse-computed from its exit speed
* (next->entry_speed) if assuming maximum deceleration over the full block travel distance
* c. The last (newest appended) block uses safe_exit_speed exit speed (there's no 'next')
* 2. Go over blocks in chronological (forward) order and fix the exit junction speed:
* a. Exit speed (next->entry_speed) must be below/at the maximum exit speed forward-computed
* from its entry speed if assuming maximum acceleration over the full block travel distance
* b. Exit speed should stay above/at the pre-computed minimum junction speed limit
* 3. Convert entry / exit speeds (mm/s) into final/initial steps/s
*
* When these stages are complete, the planner will have maximized the velocity profiles throughout the all
* of the planner blocks, where every block is operating at its maximum allowable acceleration limits. In
@@ -959,28 +955,22 @@ void Planner::calculate_trapezoid_for_block(block_t * const block, const_float_t
* are possible. If a new block is added to the buffer, the plan is recomputed according to the said
* guidelines for a new optimal plan.
*
* To increase computational efficiency of these guidelines, a set of planner block pointers have been
* created to indicate stop-compute points for when the planner guidelines cannot logically make any further
* changes or improvements to the plan when in normal operation and new blocks are streamed and added to the
* planner buffer. For example, if a subset of sequential blocks in the planner have been planned and are
* bracketed by junction velocities at their maximums (or by the first planner block as well), no new block
* added to the planner buffer will alter the velocity profiles within them. So we no longer have to compute
* them. Or, if a set of sequential blocks from the first block in the planner (or a optimal stop-compute
* point) are all accelerating, they are all optimal and can not be altered by a new block added to the
* planner buffer, as this will only further increase the plan speed to chronological blocks until a maximum
* junction velocity is reached. However, if the operational conditions of the plan changes from infrequently
* used feed holds or feedrate overrides, the stop-compute pointers will be reset and the entire plan is
* recomputed as stated in the general guidelines.
* To increase computational efficiency of these guidelines:
* 1. We keep track of which blocks need calculation (block->flag.recalculate)
* 2. We stop the reverse pass on the first block whose entry_speed == max_entry_speed. As soon
* as that happens, there can be no further increases (ensured by the previous recalculate)
* 3. On the forward pass we skip through to the first block with a modified exit speed
* (next->entry_speed)
* 4. On the forward pass if we encounter a full acceleration block that limits its exit speed
* (next->entry_speed) we also update the maximum for that junction (next->max_entry_speed)
* so it's never updated again
* 5. We use speed squared (ex: entry_speed_sqr in mm^2/s^2) in acceleration limit computations
* 6. We don't recompute sqrt(entry_speed_sqr) if the block's entry speed didn't change
*
* Planner buffer index mapping:
* - block_buffer_tail: Points to the beginning of the planner buffer. First to be executed or being executed.
* - block_buffer_head: Points to the buffer block after the last block in the buffer. Used to indicate whether
* the buffer is full or empty. As described for standard ring buffers, this block is always empty.
* - block_buffer_planned: Points to the first buffer block after the last optimally planned block for normal
* streaming operating conditions. Use for planning optimizations by avoiding recomputing parts of the
* planner buffer that don't change with the addition of a new block, as describe above. In addition,
* this block can never be less than block_buffer_tail and will always be pushed forward and maintain
* this requirement when encountered by the Planner::release_current_block() routine during a cycle.
*
* NOTE: Since the planner only computes on what's in the planner buffer, some motions with many short
* segments (e.g., complex curves) may seem to move slowly. This is because there simply isn't
@@ -1003,7 +993,8 @@ void Planner::calculate_trapezoid_for_block(block_t * const block, const_float_t
*/
// The kernel called by recalculate() when scanning the plan from last to first entry.
void Planner::reverse_pass_kernel(block_t * const current, const block_t * const next, const_float_t safe_exit_speed_sqr) {
// Returns true if it could increase the current block's entry speed.
bool Planner::reverse_pass_kernel(block_t * const current, const block_t * const next, const_float_t safe_exit_speed_sqr) {
// We need to recalculate only for the last block added or if next->entry_speed_sqr changed.
if (!next || next->flag.recalculate) {
// And only if we're not already at max entry speed.
@@ -1021,196 +1012,136 @@ void Planner::reverse_pass_kernel(block_t * const current, const block_t * const
// become BUSY just before being marked RECALCULATE, so check for that!
if (stepper.is_block_busy(current)) {
// Block became busy. Clear the RECALCULATE flag (no point in
// recalculating BUSY blocks). And don't set its speed, as it can't
// be updated at this time.
// recalculating BUSY blocks).
current->flag.recalculate = false;
}
else {
// Block is not BUSY so this is ahead of the Stepper ISR:
// Just Set the new entry speed.
current->entry_speed_sqr = new_entry_speed_sqr;
return true;
}
}
}
}
return false;
}
/**
* recalculate() needs to go over the current plan twice.
* Once in reverse and once forward. This implements the reverse pass.
* Once in reverse and once forward. This implements the reverse pass that
* coarsely maximizes the entry speeds starting from last block.
* Requires there's at least one block with flag.recalculate in the buffer.
*/
void Planner::reverse_pass(const_float_t safe_exit_speed_sqr) {
// Initialize block index to the last block in the planner buffer.
// This last block will have flag.recalculate set.
uint8_t block_index = prev_block_index(block_buffer_head);
// Read the index of the last buffer planned block.
// The ISR may change it so get a stable local copy.
uint8_t planned_block_index = block_buffer_planned;
// The ISR may change block_buffer_nonbusy so get a stable local copy.
uint8_t nonbusy_block_index = block_buffer_nonbusy;
// If there was a race condition and block_buffer_planned was incremented
// or was pointing at the head (queue empty) break loop now and avoid
// planning already consumed blocks
if (planned_block_index == block_buffer_head) return;
// Reverse Pass: Coarsely maximize all possible deceleration curves back-planning from the last
// block in buffer. Cease planning when the last optimal planned or tail pointer is reached.
// NOTE: Forward pass will later refine and correct the reverse pass to create an optimal plan.
const block_t *next = nullptr;
while (block_index != planned_block_index) {
// Perform the reverse pass
// Don't try to change the entry speed of the first non-busy block.
while (block_index != nonbusy_block_index) {
block_t *current = &block_buffer[block_index];
// Only process movement blocks
if (current->is_move()) {
reverse_pass_kernel(current, next, safe_exit_speed_sqr);
// If no entry speed increase was possible we end the reverse pass.
if (!reverse_pass_kernel(current, next, safe_exit_speed_sqr)) return;
next = current;
}
// Advance to the next
block_index = prev_block_index(block_index);
// The ISR could advance the block_buffer_planned while we were doing the reverse pass.
// The ISR could advance block_buffer_nonbusy while we were doing the reverse pass.
// We must try to avoid using an already consumed block as the last one - So follow
// changes to the pointer and make sure to limit the loop to the currently busy block
while (planned_block_index != block_buffer_planned) {
while (nonbusy_block_index != block_buffer_nonbusy) {
// If we reached the busy block or an already processed block, break the loop now
if (block_index == planned_block_index) return;
if (block_index == nonbusy_block_index) return;
// Advance the pointer, following the busy block
planned_block_index = next_block_index(planned_block_index);
nonbusy_block_index = next_block_index(nonbusy_block_index);
}
}
}
// The kernel called by recalculate() when scanning the plan from first to last entry.
void Planner::forward_pass_kernel(const block_t * const previous, block_t * const current, const uint8_t block_index) {
// Check against previous speed only on current->entry_speed_sqr changes (or if first time).
if (current->flag.recalculate) {
// If the previous block is accelerating check if it's too short to complete the full speed
// change then adjust the entry speed accordingly. Entry speeds have already been maximized.
if (previous->entry_speed_sqr < current->entry_speed_sqr) {
float new_entry_speed_sqr = max_allowable_speed_sqr(-previous->acceleration, previous->entry_speed_sqr, previous->millimeters);
// The kernel called during the forward pass. Assumes current->flag.recalculate.
void Planner::forward_pass_kernel(const block_t * const previous, block_t * const current) {
// Check if the previous block is accelerating.
if (previous->entry_speed_sqr < current->entry_speed_sqr) {
// Compute the maximum achievable speed if the previous block was fully accelerating.
float new_exit_speed_sqr = max_allowable_speed_sqr(-previous->acceleration, previous->entry_speed_sqr, previous->millimeters);
// If true, previous block is full-acceleration and we can move the planned pointer forward.
if (new_entry_speed_sqr < current->entry_speed_sqr) {
// Current entry speed limited by full acceleration from previous entry speed.
// Make sure entry speed not lower than minimum_planner_speed_sqr.
NOLESS(new_entry_speed_sqr, current->min_entry_speed_sqr);
current->entry_speed_sqr = new_entry_speed_sqr;
if (new_exit_speed_sqr < current->entry_speed_sqr) {
// Current entry speed limited by full acceleration from previous entry speed.
// Set optimal plan pointer.
block_buffer_planned = block_index;
}
else {
// Previous entry speed has been maximized.
block_buffer_planned = prev_block_index(block_index);
}
// Make sure entry speed not lower than minimum_planner_speed_sqr.
NOLESS(new_exit_speed_sqr, current->min_entry_speed_sqr);
current->entry_speed_sqr = new_exit_speed_sqr;
// Ensure we don't try updating entry_speed_sqr again.
current->max_entry_speed_sqr = new_exit_speed_sqr;
}
// Any block set at its maximum entry speed also creates an optimal plan up to this
// point in the buffer. When the plan is bracketed by either the beginning of the
// buffer and a maximum entry speed or two maximum entry speeds, every block in between
// cannot logically be further improved. Hence, we don't have to recompute them anymore.
if (current->entry_speed_sqr == current->max_entry_speed_sqr)
block_buffer_planned = block_index;
}
// The fully optimized entry speed is our new minimum speed.
current->min_entry_speed_sqr = current->entry_speed_sqr;
}
/**
* recalculate() needs to go over the current plan twice.
* Once in reverse and once forward. This implements the forward pass.
*/
void Planner::forward_pass() {
// Forward Pass: Forward plan the acceleration curve from the planned pointer onward.
// Also scans for optimal plan breakpoints and appropriately updates the planned pointer.
// Begin at buffer planned pointer. Note that block_buffer_planned can be modified
// by the stepper ISR, so read it ONCE. It it guaranteed that block_buffer_planned
// will never lead head, so the loop is safe to execute. Also note that the forward
// pass will never modify the values at the tail.
uint8_t block_index = block_buffer_planned;
block_t *block;
const block_t * previous = nullptr;
while (block_index != block_buffer_head) {
// Perform the forward pass
block = &block_buffer[block_index];
// Only process movement blocks
if (block->is_move()) {
// If there's no previous block or the previous block is not
// BUSY (thus, modifiable) run the forward_pass_kernel. Otherwise,
// the previous block became BUSY, so assume the current block's
// entry speed can't be altered (since that would also require
// updating the exit speed of the previous block).
if (previous && !stepper.is_block_busy(previous))
forward_pass_kernel(previous, block, block_index);
previous = block;
}
// Advance to the previous
block_index = next_block_index(block_index);
}
}
/**
* Recalculate the trapezoid speed profiles for all blocks in the plan
* according to the entry_factor for each junction. Must be called by
* recalculate() after updating the blocks.
* Do the forward pass and recalculate the trapezoid speed profiles for all blocks in the plan
* according to entry/exit speeds.
*/
void Planner::recalculate_trapezoids(const_float_t safe_exit_speed_sqr) {
// The tail may be changed by the ISR so get a local copy.
// Start with the block that's about to execute or is executing.
uint8_t block_index = block_buffer_tail,
head_block_index = block_buffer_head;
// Since there could be a sync block in the head of the queue, and the
// next loop must not recalculate the head block (as it needs to be
// specially handled), scan backwards to the first non-SYNC block.
while (head_block_index != block_index) {
// Go back (head always point to the first free block)
const uint8_t prev_index = prev_block_index(head_block_index);
// Get the pointer to the block
block_t *prev = &block_buffer[prev_index];
// It the block is a move, we're done with this loop
if (prev->is_move()) break;
// Examine the previous block. This and all following are SYNC blocks
head_block_index = prev_index;
}
// Go from the tail (currently executed block) to the first block, without including it)
block_t *block = nullptr, *next = nullptr;
float current_entry_speed = 0.0f, next_entry_speed = 0.0f;
float next_entry_speed = 0.0f;
while (block_index != head_block_index) {
next = &block_buffer[block_index];
// Only process movement blocks
if (next->is_move()) {
next_entry_speed = SQRT(next->entry_speed_sqr);
// Check if the next block's entry speed changed
if (next->flag.recalculate) {
if (!block) {
// 'next' is the first move due to either being the first added move or due to the planner
// having completely fallen behind. Revert any reverse pass change.
next->entry_speed_sqr = next->min_entry_speed_sqr;
next_entry_speed = SQRT(next->min_entry_speed_sqr);
}
else {
// Try to fix exit speed which requires trapezoid recalculation
block->flag.recalculate = true;
if (block) {
// But there is an inherent race condition here, as the block may have
// become BUSY just before being marked RECALCULATE, so check for that!
if (stepper.is_block_busy(block)) {
// Block is BUSY so we can't change the exit speed. Revert any reverse pass change.
next->entry_speed_sqr = next->min_entry_speed_sqr;
if (!next->initial_rate) {
// 'next' was never calculated. Planner is falling behind so for maximum efficiency
// set next's stepping speed directly and forgo checking against min_entry_speed_sqr.
// calculate_trapezoid_for_block() can handle it, albeit sub-optimally.
next->initial_rate = block->final_rate;
}
// Note that at this point next_entry_speed is (still) 0.
}
else {
// Block is not BUSY: we won the race against the ISR or recalculate was already set
// If the next block is marked to RECALCULATE, also mark the previously-fetched one
if (next->flag.recalculate) block->flag.recalculate = true;
if (next->entry_speed_sqr != next->min_entry_speed_sqr)
forward_pass_kernel(block, next);
// Recalculate if current block entry or exit junction speed has changed.
if (block->flag.recalculate) {
const float current_entry_speed = next_entry_speed;
next_entry_speed = SQRT(next->entry_speed_sqr);
// But there is an inherent race condition here, as the block maybe
// became BUSY, just before it was marked as RECALCULATE, so check
// if that is the case!
if (!stepper.is_block_busy(block)) {
// Block is not BUSY, we won the race against the Stepper ISR:
// NOTE: Entry and exit factors always > 0 by all previous logic operations.
const float nomr = 1.0f / block->nominal_speed;
calculate_trapezoid_for_block(block, current_entry_speed * nomr, next_entry_speed * nomr);
calculate_trapezoid_for_block(block, current_entry_speed, next_entry_speed);
}
// Reset current only to ensure next trapezoid is computed - The
@@ -1220,30 +1151,17 @@ void Planner::recalculate_trapezoids(const_float_t safe_exit_speed_sqr) {
}
block = next;
current_entry_speed = next_entry_speed;
}
block_index = next_block_index(block_index);
}
// Last/newest block in buffer. Always recalculated.
if (block) {
// Last/newest block in buffer. The above guarantees it's a move block.
if (block && block->flag.recalculate) {
const float current_entry_speed = next_entry_speed;
next_entry_speed = SQRT(safe_exit_speed_sqr);
// Mark the next(last) block as RECALCULATE, to prevent the Stepper ISR running it.
// As the last block is always recalculated here, there is a chance the block isn't
// marked as RECALCULATE yet. That's the reason for the following line.
block->flag.recalculate = true;
// But there is an inherent race condition here, as the block maybe
// became BUSY, just before it was marked as RECALCULATE, so check
// if that is the case!
if (!stepper.is_block_busy(block)) {
// Block is not BUSY, we won the race against the Stepper ISR:
const float nomr = 1.0f / block->nominal_speed;
calculate_trapezoid_for_block(block, current_entry_speed * nomr, next_entry_speed * nomr);
}
calculate_trapezoid_for_block(block, current_entry_speed, next_entry_speed);
// Reset block to ensure its trapezoid is computed - The stepper is free to use
// the block from now on.
@@ -1251,14 +1169,10 @@ void Planner::recalculate_trapezoids(const_float_t safe_exit_speed_sqr) {
}
}
// Requires there's at least one block with flag.recalculate in the buffer
void Planner::recalculate(const_float_t safe_exit_speed_sqr) {
// Initialize block index to the last block in the planner buffer.
const uint8_t block_index = prev_block_index(block_buffer_head);
// If there is just one block, no planning can be done. Avoid it!
if (block_index != block_buffer_planned) {
reverse_pass(safe_exit_speed_sqr);
forward_pass();
}
reverse_pass(safe_exit_speed_sqr);
// The forward pass is done as part of recalculate_trapezoids()
recalculate_trapezoids(safe_exit_speed_sqr);
}
@@ -1667,7 +1581,7 @@ void Planner::quick_stop() {
const bool was_enabled = stepper.suspend();
// Drop all queue entries
block_buffer_nonbusy = block_buffer_planned = block_buffer_head = block_buffer_tail;
block_buffer_nonbusy = block_buffer_head = block_buffer_tail;
// Restart the block delay for the first movement - As the queue was
// forced to empty, there's no risk the ISR will touch this.
@@ -1995,9 +1909,9 @@ bool Planner::_populate_block(
#if HAS_EXTRUDERS
dm.e = (dist.e > 0);
const float esteps_float = dist.e * e_factor[extruder];
const uint32_t esteps = ABS(esteps_float);
const uint64_t esteps = ABS(esteps_float);
#else
constexpr uint32_t esteps = 0;
constexpr uint64_t esteps = 0;
#endif
// Clear all flags, including the "busy" bit
@@ -2436,7 +2350,8 @@ bool Planner::_populate_block(
// Compute and limit the acceleration rate for the trapezoid generator.
const float steps_per_mm = block->step_event_count * inverse_millimeters;
uint32_t accel;
block->steps_per_mm = steps_per_mm;
uint64_t accel;
#if ENABLED(LIN_ADVANCE)
bool use_advance_lead = false;
#endif
@@ -2446,7 +2361,7 @@ bool Planner::_populate_block(
else {
#define LIMIT_ACCEL_LONG(AXIS,INDX) do{ \
if (block->steps[AXIS] && max_acceleration_steps_per_s2[AXIS+INDX] < accel) { \
const uint32_t max_possible = max_acceleration_steps_per_s2[AXIS+INDX] * block->step_event_count / block->steps[AXIS]; \
const uint64_t max_possible = max_acceleration_steps_per_s2[AXIS+INDX] * block->step_event_count / block->steps[AXIS]; \
NOMORE(accel, max_possible); \
} \
}while(0)
@@ -2490,7 +2405,7 @@ bool Planner::_populate_block(
use_advance_lead = false;
else {
// Scale E acceleration so that it will be possible to jump to the advance speed.
const uint32_t max_accel_steps_per_s2 = MAX_E_JERK(extruder) / (extruder_advance_K[E_INDEX_N(extruder)] * e_D_ratio) * steps_per_mm;
const uint64_t max_accel_steps_per_s2 = MAX_E_JERK(extruder) / (extruder_advance_K[E_INDEX_N(extruder)] * e_D_ratio) * steps_per_mm;
if (accel > max_accel_steps_per_s2) {
accel = max_accel_steps_per_s2;
if (ENABLED(LA_DEBUG)) SERIAL_ECHOLNPGM("Acceleration limited.");
@@ -2520,7 +2435,7 @@ bool Planner::_populate_block(
block->acceleration_steps_per_s2 = accel;
block->acceleration = accel / steps_per_mm;
#if DISABLED(S_CURVE_ACCELERATION)
block->acceleration_rate = (uint32_t)(accel * (float(1UL << 24) / (STEPPER_TIMER_RATE)));
block->acceleration_rate = (uint64_t)(accel * (float(1UL << 24) / (STEPPER_TIMER_RATE)));
#endif
#if ENABLED(LIN_ADVANCE)
@@ -2533,7 +2448,7 @@ bool Planner::_populate_block(
// reduce LA ISR frequency by calling it only often enough to ensure that there will
// never be more than four extruder steps per call
for (uint32_t dividend = block->steps.e << 1; dividend <= (block->step_event_count >> 2); dividend <<= 1)
for (uint64_t dividend = block->steps.e << 1; dividend <= (block->step_event_count >> 2); dividend <<= 1)
block->la_scaling++;
#if ENABLED(LA_DEBUG)
@@ -2546,7 +2461,7 @@ bool Planner::_populate_block(
// Formula for the average speed over a 1 step worth of distance if starting from zero and
// accelerating at the current limit. Since we can only change the speed every step this is a
// good lower limit for the entry and exit speeds. Note that for calculate_trapezoid_for_block()
// to work correctly, this must be accurately set and propagated.
// to work correctly this must be accurately set and propagated.
minimum_planner_speed_sqr = 0.5f * block->acceleration / steps_per_mm;
// Go straight to/from nominal speed if block->acceleration is too high for it.
NOMORE(minimum_planner_speed_sqr, sq(block->nominal_speed));
@@ -2772,7 +2687,7 @@ bool Planner::_populate_block(
// Advance affects E_AXIS speed and therefore jerk. Add a speed correction whenever
// LA is turned OFF. No correction is applied when LA is turned ON (because it didn't
// perform well; it takes more time/effort to push/melt filament than the reverse).
static uint32_t previous_advance_rate;
static uint64_t previous_advance_rate;
static float previous_e_mm_per_step;
if (dist.e < 0 && previous_advance_rate) {
// Retract move after a segment with LA that ended with an E speed decrease.
@@ -2820,7 +2735,7 @@ bool Planner::_populate_block(
#endif // CLASSIC_JERK
// High acceleration limits override low jerk/junction deviation limits (as fixing trapezoids
// or reducing acceleration introduces too much complexity and/or too much compute)
// or reducing acceleration introduces too much complexity and/or too much compute).
NOLESS(vmax_junction_sqr, minimum_planner_speed_sqr);
// Max entry speed of this block equals the max exit speed of the previous block.
@@ -2829,6 +2744,8 @@ bool Planner::_populate_block(
block->entry_speed_sqr = minimum_planner_speed_sqr;
// Set min entry speed. Rarely it could be higher than the previous nominal speed but that's ok.
block->min_entry_speed_sqr = minimum_planner_speed_sqr;
// Zero the initial_rate to indicate that calculate_trapezoid_for_block() hasn't been called yet.
block->initial_rate = 0;
block->flag.recalculate = true;
@@ -3275,7 +3192,7 @@ void Planner::set_position_mm(const xyze_pos_t &xyze) {
// Recalculate the steps/s^2 acceleration rates, based on the mm/s^2
void Planner::refresh_acceleration_rates() {
uint32_t highest_rate = 1;
uint64_t highest_rate = 1;
LOOP_DISTINCT_AXES(i) {
max_acceleration_steps_per_s2[i] = settings.max_acceleration_mm_per_s2[i] * settings.axis_steps_per_mm[i];
if (TERN1(DISTINCT_E_FACTORS, i < E_AXIS || i == E_AXIS_N(active_extruder)))
@@ -3388,7 +3305,7 @@ void Planner::set_max_feedrate(const AxisEnum axis, float inMaxFeedrateMMS) {
const bool was_enabled = stepper.suspend();
#endif
uint32_t bbru = block_buffer_runtime_us;
uint64_t bbru = block_buffer_runtime_us;
#ifdef __AVR__
// Reenable Stepper ISR
+26 -19
View File
@@ -78,6 +78,14 @@
#include "../feature/closedloop.h"
#endif
constexpr uint64_t MINIMAL_STEP_RATE = (
#ifdef CPU_32_BIT
_MAX((STEPPER_TIMER_RATE) / HAL_TIMER_TYPE_MAX, 1U) // 32-bit shouldn't go below 1
#else
(F_CPU) / 500000U // AVR shouldn't go below 32 (16MHz) or 40 (20MHz)
#endif
);
// Feedrate for manual moves
#ifdef MANUAL_FEEDRATE
constexpr xyze_feedrate_t manual_feedrate_mm_m = MANUAL_FEEDRATE,
@@ -219,13 +227,14 @@ typedef struct PlannerBlock {
min_entry_speed_sqr, // Minimum allowable junction entry speed in (mm/sec)^2
max_entry_speed_sqr, // Maximum allowable junction entry speed in (mm/sec)^2
millimeters, // The total travel of this block in mm
steps_per_mm, // steps/mm
acceleration; // acceleration mm/sec^2
union {
abce_ulong_t steps; // Step count along each axis
abce_long_t position; // New position to force when this sync block is executed
};
uint32_t step_event_count; // The number of step events required to complete this block
uint64_t step_event_count; // The number of step events required to complete this block
#if HAS_MULTI_EXTRUDER
uint8_t extruder; // The extruder to move (if E move)
@@ -238,30 +247,30 @@ typedef struct PlannerBlock {
#endif
// Settings for the trapezoid generator
uint32_t accelerate_before, // The index of the step event where cruising starts
uint64_t accelerate_before, // The index of the step event on which to start cruising
decelerate_start; // The index of the step event on which to start decelerating
#if ENABLED(S_CURVE_ACCELERATION)
uint32_t cruise_rate, // The actual cruise rate to use, between end of the acceleration phase and start of deceleration phase
uint64_t cruise_rate, // The actual cruise rate to use, between end of the acceleration phase and start of deceleration phase
acceleration_time, // Acceleration time and deceleration time in STEP timer counts
deceleration_time,
acceleration_time_inverse, // Inverse of acceleration and deceleration periods, expressed as integer. Scale depends on CPU being used
deceleration_time_inverse;
#else
uint32_t acceleration_rate; // Acceleration rate in (2^24 steps)/timer_ticks*s
uint64_t acceleration_rate; // Acceleration rate in (2^24 steps)/timer_ticks*s
#endif
AxisBits direction_bits; // Direction bits set for this block, where 1 is negative motion
// Advance extrusion
#if ENABLED(LIN_ADVANCE)
uint32_t la_advance_rate; // The rate at which steps are added whilst accelerating
uint64_t la_advance_rate; // The rate at which steps are added whilst accelerating
uint8_t la_scaling; // Scale ISR frequency down and step frequency up by 2 ^ la_scaling
uint16_t max_adv_steps, // Max advance steps to get cruising speed pressure
final_adv_steps; // Advance steps for exit speed pressure
#endif
uint32_t nominal_rate, // The nominal step rate for this block in step_events/sec
uint64_t nominal_rate, // The nominal step rate for this block in step_events/sec
initial_rate, // The jerk-adjusted step rate at start of block
final_rate, // The minimal rate at exit
acceleration_steps_per_s2; // acceleration steps/sec^2
@@ -283,11 +292,11 @@ typedef struct PlannerBlock {
#endif
#if HAS_WIRED_LCD
uint32_t segment_time_us;
uint64_t segment_time_us;
#endif
#if ENABLED(POWER_LOSS_RECOVERY)
uint32_t sdpos;
uint64_t sdpos;
xyze_pos_t start_position;
#endif
@@ -338,7 +347,7 @@ constexpr uint8_t block_inc_mod(const uint8_t v1, const uint8_t v2) {
#endif
typedef struct PlannerSettings {
uint32_t max_acceleration_mm_per_s2[DISTINCT_AXES], // (mm/s^2) M201 XYZE
uint64_t max_acceleration_mm_per_s2[DISTINCT_AXES], // (mm/s^2) M201 XYZE
min_segment_time_us; // (µs) M205 B
// (steps) M92 XYZE - Steps per millimeter
@@ -442,7 +451,6 @@ class Planner {
static block_t block_buffer[BLOCK_BUFFER_SIZE];
static volatile uint8_t block_buffer_head, // Index of the next block to be pushed
block_buffer_nonbusy, // Index of the first non busy block
block_buffer_planned, // Index of the optimally planned block
block_buffer_tail; // Index of the busy block, if any
static uint16_t cleaning_buffer_counter; // A counter to disable queuing of blocks
static uint8_t delay_before_delivering; // This counter delays delivery of blocks when queue becomes empty to allow the opportunity of merging blocks
@@ -452,7 +460,7 @@ class Planner {
#endif
#if ENABLED(DIRECT_STEPPING)
static uint32_t last_page_step_rate; // Last page step rate given
static uint64_t last_page_step_rate; // Last page step rate given
static AxisBits last_page_dir; // Last page direction given, where 1 represents forward or positive motion
#endif
@@ -479,7 +487,7 @@ class Planner {
static laser_state_t laser_inline;
#endif
static uint32_t max_acceleration_steps_per_s2[DISTINCT_AXES]; // (steps/s^2) Derived from mm_per_s2
static uint64_t max_acceleration_steps_per_s2[DISTINCT_AXES]; // (steps/s^2) Derived from mm_per_s2
#if ENABLED(EDITABLE_STEPS_PER_UNIT)
static float mm_per_step[DISTINCT_AXES]; // Millimeters per step
@@ -569,7 +577,7 @@ class Planner {
/**
* Limit where 64bit math is necessary for acceleration calculation
*/
static uint32_t acceleration_long_cutoff;
static uint64_t acceleration_long_cutoff;
#ifdef MAX7219_DEBUG_SLOWDOWN
friend class Max7219;
@@ -586,7 +594,7 @@ class Planner {
#endif
#if HAS_WIRED_LCD
volatile static uint32_t block_buffer_runtime_us; // Theoretical block buffer runtime in µs
volatile static uint64_t block_buffer_runtime_us; // Theoretical block buffer runtime in µs
#endif
public:
@@ -804,7 +812,7 @@ class Planner {
FORCE_INLINE static uint8_t nonbusy_movesplanned() { return block_dec_mod(block_buffer_head, block_buffer_nonbusy); }
// Remove all blocks from the buffer
FORCE_INLINE static void clear_block_buffer() { block_buffer_nonbusy = block_buffer_planned = block_buffer_head = block_buffer_tail = 0; }
FORCE_INLINE static void clear_block_buffer() { block_buffer_nonbusy = block_buffer_head = block_buffer_tail = 0; }
// Check if movement queue is full
FORCE_INLINE static bool is_full() { return block_buffer_tail == next_block_index(block_buffer_head); }
@@ -1081,13 +1089,12 @@ class Planner {
}
#endif
static void calculate_trapezoid_for_block(block_t * const block, const_float_t entry_factor, const_float_t exit_factor);
static void calculate_trapezoid_for_block(block_t * const block, const_float_t entry_speed, const_float_t exit_speed);
static void reverse_pass_kernel(block_t * const current, const block_t * const next, const_float_t safe_exit_speed_sqr);
static void forward_pass_kernel(const block_t * const previous, block_t * const current, uint8_t block_index);
static bool reverse_pass_kernel(block_t * const current, const block_t * const next, const_float_t safe_exit_speed_sqr);
static void forward_pass_kernel(const block_t * const previous, block_t * const current);
static void reverse_pass(const_float_t safe_exit_speed_sqr);
static void forward_pass();
static void recalculate_trapezoids(const_float_t safe_exit_speed_sqr);
+227 -99
View File
@@ -58,16 +58,10 @@
*
* time ----->
*
* The speed over time graph forms a TRAPEZOID. The slope of acceleration is calculated by
* v = u + t
* where 't' is the accumulated timer values of the steps so far.
*
* The Stepper ISR dynamically executes acceleration, deceleration, and cruising according to the block parameters.
* - Start at block->initial_rate.
* - Accelerate while step_events_completed < block->accelerate_before.
* - Cruise while step_events_completed < block->decelerate_start.
* - Decelerate after that, until all steps are completed.
* - Reset the trapezoid generator.
* The trapezoid is the shape the speed curve over time. It starts at block->initial_rate, accelerates
* while step_events_completed < block->accelerate_before, then starts cruising at constant speed while
* step_events_completed < block->decelerate_start, then it decelerates until the trapezoid generator is reset.
* The slope of acceleration is calculated using v = u + at where t is the accumulated timer values of the steps so far.
*/
/**
@@ -160,9 +154,9 @@ Stepper stepper; // Singleton
#if HAS_MOTOR_CURRENT_SPI || HAS_MOTOR_CURRENT_PWM
bool Stepper::initialized; // = false
uint32_t Stepper::motor_current_setting[MOTOR_CURRENT_COUNT]; // Initialized by settings.load()
uint64_t Stepper::motor_current_setting[MOTOR_CURRENT_COUNT]; // Initialized by settings.load()
#if HAS_MOTOR_CURRENT_SPI
constexpr uint32_t Stepper::digipot_count[];
constexpr uint64_t Stepper::digipot_count[];
#endif
#endif
@@ -200,7 +194,7 @@ bool Stepper::abort_current_block;
#endif
// In timer_ticks
uint32_t Stepper::acceleration_time, Stepper::deceleration_time;
uint64_t Stepper::acceleration_time, Stepper::deceleration_time;
#if MULTISTEPPING_LIMIT > 1
uint8_t Stepper::steps_per_isr = 1; // Count of steps to perform per Stepper ISR call
@@ -229,7 +223,7 @@ uint32_t Stepper::acceleration_time, Stepper::deceleration_time;
xyze_long_t Stepper::delta_error{0};
xyze_long_t Stepper::advance_dividend{0};
uint32_t Stepper::advance_divisor = 0,
uint64_t Stepper::advance_divisor = 0,
Stepper::step_events_completed = 0, // The number of step events executed in the current block
Stepper::accelerate_before, // The count at which to start cruising
Stepper::decelerate_start, // The count at which to start decelerating
@@ -245,8 +239,8 @@ uint32_t Stepper::advance_divisor = 0,
int32_t __attribute__((used)) Stepper::bezier_A __asm__("bezier_A"); // A coefficient in Bézier speed curve with alias for assembler
int32_t __attribute__((used)) Stepper::bezier_B __asm__("bezier_B"); // B coefficient in Bézier speed curve with alias for assembler
int32_t __attribute__((used)) Stepper::bezier_C __asm__("bezier_C"); // C coefficient in Bézier speed curve with alias for assembler
uint32_t __attribute__((used)) Stepper::bezier_F __asm__("bezier_F"); // F coefficient in Bézier speed curve with alias for assembler
uint32_t __attribute__((used)) Stepper::bezier_AV __asm__("bezier_AV"); // AV coefficient in Bézier speed curve with alias for assembler
uint64_t __attribute__((used)) Stepper::bezier_F __asm__("bezier_F"); // F coefficient in Bézier speed curve with alias for assembler
uint64_t __attribute__((used)) Stepper::bezier_AV __asm__("bezier_AV"); // AV coefficient in Bézier speed curve with alias for assembler
#ifdef __AVR__
bool __attribute__((used)) Stepper::A_negative __asm__("A_negative"); // If A coefficient was negative
#endif
@@ -266,7 +260,7 @@ uint32_t Stepper::advance_divisor = 0,
ne_coeff_t Stepper::ne;
ne_fix_t Stepper::ne_fix;
int32_t Stepper::ne_edividend;
uint32_t Stepper::ne_scale;
uint64_t Stepper::ne_scale;
#endif
#if HAS_ZV_SHAPING
@@ -303,7 +297,7 @@ uint32_t Stepper::advance_divisor = 0,
hal_timer_t Stepper::ticks_nominal = 0;
#if DISABLED(S_CURVE_ACCELERATION)
uint32_t Stepper::acc_step_rate; // needed for deceleration start point
uint64_t Stepper::acc_step_rate; // needed for deceleration start point
#endif
xyz_long_t Stepper::endstops_trigsteps;
@@ -691,7 +685,7 @@ void Stepper::apply_directions() {
* a "linear pop" velocity curve; with pop being the sixth derivative of position:
* velocity - 1st, acceleration - 2nd, jerk - 3rd, snap - 4th, crackle - 5th, pop - 6th
*
* The Bézier curve takes the form:
* The 6th order Bézier curve takes the form:
*
* V(t) = P_0 * B_0(t) + P_1 * B_1(t) + P_2 * B_2(t) + P_3 * B_3(t) + P_4 * B_4(t) + P_5 * B_5(t)
*
@@ -711,7 +705,10 @@ void Stepper::apply_directions() {
* Unfortunately, we cannot use forward-differencing to calculate each position through
* the curve, as Marlin uses variable timer periods. So, we require a formula of the form:
*
* 6th order:
* V_f(t) = A*t^5 + B*t^4 + C*t^3 + D*t^2 + E*t + F
* 4th order:
* V_f(t) = A*t^3 + B*t^2 + C*t + F
*
* Looking at the above B_0(t) through B_5(t) expanded forms, if we take the coefficients of t^5
* through t of the Bézier form of V(t), we can determine that:
@@ -734,15 +731,27 @@ void Stepper::apply_directions() {
* E = 0
* F = P_i
*
* For 4th order we want the initial and final acceleration to be a fixed S_CURVE_FACTOR fraction
* and solving gives us:
*
* A = 2*(1 - S_CURVE_FACTOR)*(P_i - P_t)
* B = 3*(1 - S_CURVE_FACTOR)*(P_t - P_i)
* C = S_CURVE_FACTOR*(P_t - P_i)
* F = P_i
*
* As the t is evaluated in non uniform steps here, there is no other way rather than evaluating
* the Bézier curve at each point:
*
* 6th order:
* V_f(t) = A*t^5 + B*t^4 + C*t^3 + F [0 <= t <= 1]
* 4th order:
* V_f(t) = A*t^3 + B*t^2 + C*t + F [0 <= t <= 1]
*
* Floating point arithmetic execution time cost is prohibitive, so we will transform the math to
* use fixed point values to be able to evaluate it in realtime. Assuming a maximum of 250000 steps
* per second (driver pulses should at least be 2µS hi/2µS lo), and allocating 2 bits to avoid
* overflows on the evaluation of the Bézier curve, means we can use
* use fixed point values to be able to evaluate it in realtime.
*
* 6th order: Assumes a maximum of 250000 steps/s (driver pulses down to 2µS hi/2µS lo),
* and allocates 2 bits to avoid overflows on the evaluation of the Bézier curve:
*
* t: unsigned Q0.32 (0 <= t < 1) |range 0 to 0xFFFFFFFF unsigned
* A: signed Q24.7 , |range = +/- 250000 * 6 * 128 = +/- 192000000 = 0x0B71B000 | 28 bits + sign
@@ -750,6 +759,8 @@ void Stepper::apply_directions() {
* C: signed Q24.7 , |range = +/- 250000 *10 * 128 = +/- 320000000 = 0x1312D000 | 29 bits + sign
* F: signed Q24.7 , |range = +/- 250000 * 128 = 32000000 = 0x01E84800 | 25 bits + sign
*
* 4th order: With B coefficient at least 5x smaller the maximum will be ~1250000 steps/s.
*
* The trapezoid generator state contains the following information, that we will use to create and evaluate
* the Bézier curve:
*
@@ -764,42 +775,48 @@ void Stepper::apply_directions() {
*
* At the start of each trapezoid, calculate the coefficients A,B,C,F and Advance [AV], as follows:
*
* 6th order:
* A = 6*128*(VF - VI) = 768*(VF - VI)
* B = 15*128*(VI - VF) = 1920*(VI - VF)
* C = 10*128*(VF - VI) = 1280*(VF - VI)
* 4th order:
* A = 2*(1-S_CURVE_FACTOR)*128*(VI - VF)
* B = 3*(1-S_CURVE_FACTOR)*128*(VF - VI)
* C = S_CURVE_FACTOR*128*(VF - VI)
* both:
* F = 128*VI = 128*VI
* AV = (1<<32)/TS ~= 0xFFFFFFFF / TS (To use ARM UDIV, that is 32 bits) (this is computed at the planner, to offload expensive calculations from the ISR)
*
* And for each point, evaluate the curve with the following sequence:
*
* void lsrs(uint32_t& d, uint32_t s, int cnt) {
* void lsrs(uint64_t& d, uint64_t s, int cnt) {
* d = s >> cnt;
* }
* void lsls(uint32_t& d, uint32_t s, int cnt) {
* void lsls(uint64_t& d, uint64_t s, int cnt) {
* d = s << cnt;
* }
* void lsrs(int32_t& d, uint32_t s, int cnt) {
* d = uint32_t(s) >> cnt;
* void lsrs(int32_t& d, uint64_t s, int cnt) {
* d = uint64_t(s) >> cnt;
* }
* void lsls(int32_t& d, uint32_t s, int cnt) {
* d = uint32_t(s) << cnt;
* void lsls(int32_t& d, uint64_t s, int cnt) {
* d = uint64_t(s) << cnt;
* }
* void umull(uint32_t& rlo, uint32_t& rhi, uint32_t op1, uint32_t op2) {
* void umull(uint64_t& rlo, uint64_t& rhi, uint64_t op1, uint64_t op2) {
* uint64_t res = uint64_t(op1) * op2;
* rlo = uint32_t(res & 0xFFFFFFFF);
* rhi = uint32_t((res >> 32) & 0xFFFFFFFF);
* rlo = uint64_t(res & 0xFFFFFFFF);
* rhi = uint64_t((res >> 32) & 0xFFFFFFFF);
* }
* void smlal(int32_t& rlo, int32_t& rhi, int32_t op1, int32_t op2) {
* int64_t mul = int64_t(op1) * op2;
* int64_t s = int64_t(uint32_t(rlo) | ((uint64_t(uint32_t(rhi)) << 32U)));
* int64_t s = int64_t(uint64_t(rlo) | ((uint64_t(uint64_t(rhi)) << 32U)));
* mul += s;
* rlo = int32_t(mul & 0xFFFFFFFF);
* rhi = int32_t((mul >> 32) & 0xFFFFFFFF);
* }
* int32_t _eval_bezier_curve_arm(uint32_t curr_step) {
* uint32_t flo = 0;
* uint32_t fhi = bezier_AV * curr_step;
* uint32_t t = fhi;
* int32_t _eval_bezier_curve_arm(uint64_t curr_step) {
* uint64_t flo = 0;
* uint64_t fhi = bezier_AV * curr_step;
* uint64_t t = fhi;
* int32_t alo = bezier_F;
* int32_t ahi = 0;
* int32_t A = bezier_A;
@@ -849,7 +866,7 @@ void Stepper::apply_directions() {
*
* And for each curve, estimate its coefficients with:
*
* void _calc_bezier_curve_coeffs(int32_t v0, int32_t v1, uint32_t av) {
* void _calc_bezier_curve_coeffs(int32_t v0, int32_t v1, uint64_t av) {
* // Calculate the Bézier coefficients
* if (v1 < v0) {
* A_negative = true;
@@ -874,14 +891,14 @@ void Stepper::apply_directions() {
* }
* // unsigned multiplication of 16 bits x 16bits, return upper 16 bits
* void umul16x16to16hi(uint16_t& r, uint16_t op1, uint16_t op2) {
* r = (uint32_t(op1) * op2) >> 16;
* r = (uint64_t(op1) * op2) >> 16;
* }
* // unsigned multiplication of 16 bits x 24bits, return upper 24 bits
* void umul16x24to24hi(uint24_t& r, uint16_t op1, uint24_t op2) {
* r = uint24_t((uint64_t(op1) * op2) >> 16);
* }
*
* int32_t _eval_bezier_curve(uint32_t curr_step) {
* int32_t _eval_bezier_curve(uint64_t curr_step) {
* // To save computing, the first step is always the initial speed
* if (!curr_step)
* return bezier_F;
@@ -923,7 +940,7 @@ void Stepper::apply_directions() {
#ifdef __AVR__
// For AVR we use assembly to maximize speed
void Stepper::_calc_bezier_curve_coeffs(const int32_t v0, const int32_t v1, const uint32_t av) {
void Stepper::_calc_bezier_curve_coeffs(const int32_t v0, const int32_t v1, const uint64_t av) {
// Store advance
bezier_AV = av;
@@ -1025,7 +1042,7 @@ void Stepper::apply_directions() {
);
}
FORCE_INLINE int32_t Stepper::_eval_bezier_curve(const uint32_t curr_step) {
FORCE_INLINE int32_t Stepper::_eval_bezier_curve(const uint64_t curr_step) {
// If dealing with the first step, save expensive computing and return the initial speed
if (!curr_step)
@@ -1407,28 +1424,36 @@ void Stepper::apply_directions() {
:
:"cc","r0","r1"
);
return (r2 | (uint16_t(r3) << 8)) | (uint32_t(r4) << 16);
return (r2 | (uint16_t(r3) << 8)) | (uint64_t(r4) << 16);
}
#else
// For all the other 32bit CPUs
FORCE_INLINE void Stepper::_calc_bezier_curve_coeffs(const int32_t v0, const int32_t v1, const uint32_t av) {
FORCE_INLINE void Stepper::_calc_bezier_curve_coeffs(const int32_t v0, const int32_t v1, const uint64_t av) {
// Calculate the Bézier coefficients
bezier_A = 768 * (v1 - v0);
bezier_B = 1920 * (v0 - v1);
bezier_C = 1280 * (v1 - v0);
#ifndef S_CURVE_FACTOR
bezier_A = 768 * (v1 - v0);
bezier_B = 1920 * (v0 - v1);
bezier_C = 1280 * (v1 - v0);
#else
// Must convert from S_CURVE_FACTOR to int only once.
constexpr int FACTOR128 = S_CURVE_FACTOR * 128;
bezier_A = (2 * (128 - FACTOR128)) * (v0 - v1);
bezier_B = (3 * (128 - FACTOR128)) * (v1 - v0);
bezier_C = FACTOR128 * (v1 - v0);
#endif
bezier_F = 128 * v0;
bezier_AV = av;
}
FORCE_INLINE int32_t Stepper::_eval_bezier_curve(const uint32_t curr_step) {
FORCE_INLINE int32_t Stepper::_eval_bezier_curve(const uint64_t curr_step) {
#if (defined(__arm__) || defined(__thumb__)) && __ARM_ARCH >= 6 && !defined(STM32G0B1xx) // TODO: Test define STM32G0xx versus STM32G0B1xx
// For ARM Cortex M3/M4 CPUs, we have the optimized assembler version, that takes 43 cycles to execute
uint32_t flo = 0;
uint32_t fhi = bezier_AV * curr_step;
uint32_t t = fhi;
uint64_t flo = 0;
uint64_t fhi = bezier_AV * curr_step;
uint64_t t = fhi;
int32_t alo = bezier_F;
int32_t ahi = 0;
int32_t A = bezier_A;
@@ -1439,8 +1464,10 @@ void Stepper::apply_directions() {
".syntax unified" "\n\t" // is to prevent CM0,CM1 non-unified syntax
A("lsrs %[ahi],%[alo],#1") // a = F << 31 1 cycles
A("lsls %[alo],%[alo],#31") // 1 cycles
A("umull %[flo],%[fhi],%[fhi],%[t]") // f *= t 5 cycles [fhi:flo=64bits]
A("umull %[flo],%[fhi],%[fhi],%[t]") // f>>=32; f*=t 5 cycles [fhi:flo=64bits]
#ifndef S_CURVE_FACTOR
A("umull %[flo],%[fhi],%[fhi],%[t]") // f *= t 5 cycles [fhi:flo=64bits]
A("umull %[flo],%[fhi],%[fhi],%[t]") // f>>=32; f*=t 5 cycles [fhi:flo=64bits]
#endif
A("lsrs %[flo],%[fhi],#1") // 1 cycles [31bits]
A("smlal %[alo],%[ahi],%[flo],%[C]") // a+=(f>>33)*C; 5 cycles
A("umull %[flo],%[fhi],%[fhi],%[t]") // f>>=32; f*=t 5 cycles [fhi:flo=64bits]
@@ -1468,20 +1495,22 @@ void Stepper::apply_directions() {
// For non ARM targets, we provide a fallback implementation. Really doubt it
// will be useful, unless the processor is fast and 32bit
uint32_t t = bezier_AV * curr_step; // t: Range 0 - 1^32 = 32 bits
uint64_t t = bezier_AV * curr_step; // t: Range 32 bits
uint64_t f = t;
f *= t; // Range 32*2 = 64 bits (unsigned)
f >>= 32; // Range 32 bits (unsigned)
f *= t; // Range 32*2 = 64 bits (unsigned)
f >>= 32; // Range 32 bits : f = t^3 (unsigned)
#ifndef S_CURVE_FACTOR
f *= t; // Range 32*2 = 64 bits (unsigned)
f >>= 32; // Range 32 bits (unsigned)
f *= t; // Range 32*2 = 64 bits (unsigned)
f >>= 32; // Range 32 bits : f = t^3 (unsigned)
#endif
int64_t acc = (int64_t) bezier_F << 31; // Range 63 bits (signed)
acc += ((uint32_t) f >> 1) * (int64_t) bezier_C; // Range 29bits + 31 = 60bits (plus sign)
acc += ((uint64_t) f >> 1) * (int64_t) bezier_C; // Range 29bits + 31 = 60bits (plus sign)
f *= t; // Range 32*2 = 64 bits
f >>= 32; // Range 32 bits : f = t^3 (unsigned)
acc += ((uint32_t) f >> 1) * (int64_t) bezier_B; // Range 29bits + 31 = 60bits (plus sign)
acc += ((uint64_t) f >> 1) * (int64_t) bezier_B; // Range 29bits + 31 = 60bits (plus sign)
f *= t; // Range 32*2 = 64 bits
f >>= 32; // Range 32 bits : f = t^3 (unsigned)
acc += ((uint32_t) f >> 1) * (int64_t) bezier_A; // Range 28bits + 31 = 59bits (plus sign)
acc += ((uint64_t) f >> 1) * (int64_t) bezier_A; // Range 28bits + 31 = 59bits (plus sign)
acc >>= (31 + 7); // Range 24bits (plus sign)
return (int32_t) acc;
@@ -1496,7 +1525,14 @@ void Stepper::apply_directions() {
* Directly pulses the stepper motors at high frequency.
*/
HAL_STEP_TIMER_ISR() {
extern "C" [[gnu::section(".ramcode")]] void TIMER0_IRQHandler() {
#ifndef __AVR__
// Disable interrupts, to avoid ISR preemption while we reprogram the period
// (AVR enters the ISR with global interrupts disabled, so no need to do it here)
hal.isr_off();
#endif
HAL_timer_isr_prologue(MF_TIMER_STEP);
Stepper::isr();
@@ -1514,12 +1550,6 @@ void Stepper::isr() {
static hal_timer_t nextMainISR = 0; // Interval until the next main Stepper Pulse phase (0 = Now)
#ifndef __AVR__
// Disable interrupts, to avoid ISR preemption while we reprogram the period
// (AVR enters the ISR with global interrupts disabled, so no need to do it here)
hal.isr_off();
#endif
// Program timer compare for the maximum period, so it does NOT
// flag an interrupt while this ISR is running - So changes from small
// periods to big periods are respected and the timer does not reset to 0
@@ -1540,8 +1570,6 @@ void Stepper::isr() {
// We need this variable here to be able to use it in the following loop
hal_timer_t min_ticks;
do {
// Enable ISRs to reduce USART processing latency
hal.isr_on();
hal_timer_t interval = 0;
@@ -1562,6 +1590,9 @@ void Stepper::isr() {
NOLESS(nextBabystepISR, nextMainISR / 2); // TODO: Only look at axes enabled for baby-stepping
#endif
// Enable ISRs to reduce latency for higher priority ISRs, or all ISRs if no prioritization.
hal.isr_on();
interval = nextMainISR; // Interval is either some old nextMainISR or FTM_MIN_TICKS
TERN_(BABYSTEPPING, NOMORE(interval, nextBabystepISR)); // Come back early for Babystepping?
@@ -1590,6 +1621,9 @@ void Stepper::isr() {
if (is_babystep) nextBabystepISR = babystepping_isr();
#endif
// Enable ISRs to reduce latency for higher priority ISRs, or all ISRs if no prioritization.
hal.isr_on();
// ^== Time critical. NOTHING besides pulse generation should be above here!!!
if (!nextMainISR) nextMainISR = block_phase_isr(); // Manage acc/deceleration, get next block
@@ -1603,7 +1637,7 @@ void Stepper::isr() {
#endif
// Get the interval to the next ISR call
interval = _MIN(nextMainISR, uint32_t(HAL_TIMER_TYPE_MAX)); // Time until the next Pulse / Block phase
interval = _MIN(nextMainISR, uint64_t(HAL_TIMER_TYPE_MAX)); // Time until the next Pulse / Block phase
TERN_(INPUT_SHAPING_X, NOMORE(interval, ShapingQueue::peek_x())); // Time until next input shaping echo for X
TERN_(INPUT_SHAPING_Y, NOMORE(interval, ShapingQueue::peek_y())); // Time until next input shaping echo for Y
TERN_(INPUT_SHAPING_Z, NOMORE(interval, ShapingQueue::peek_z())); // Time until next input shaping echo for Z
@@ -1723,7 +1757,7 @@ void Stepper::isr() {
#if MINIMUM_STEPPER_PULSE || MAXIMUM_STEPPER_RATE
#define ISR_PULSE_CONTROL 1
#endif
#if ISR_PULSE_CONTROL && DISABLED(I2S_STEPPER_STREAM)
#if ISR_PULSE_CONTROL && MULTISTEPPING_LIMIT > 1 && DISABLED(I2S_STEPPER_STREAM)
#define ISR_MULTI_STEPS 1
#endif
@@ -1766,17 +1800,15 @@ void Stepper::pulse_phase_isr() {
if (TERN0(FREEZE_FEATURE, frozen)) return;
// Count of pending loops and events for this iteration
const uint32_t pending_events = step_event_count - step_events_completed;
const uint64_t pending_events = step_event_count - step_events_completed;
uint8_t events_to_do = _MIN(pending_events, steps_per_isr);
// Just update the value we will get at the end of the loop
step_events_completed += events_to_do;
TERN_(ISR_PULSE_CONTROL, USING_TIMED_PULSE());
// Take multiple steps per interrupt (For high speed moves)
#if ISR_MULTI_STEPS
bool firstStep = true;
USING_TIMED_PULSE();
#endif
TERN_(ISR_MULTI_STEPS, bool firstStep = true);
// Direct Stepping page?
const bool is_page = current_block->is_page();
@@ -1965,7 +1997,7 @@ void Stepper::pulse_phase_isr() {
if (!is_page) {
// Give the compiler a clue to store advance_divisor in registers for what follows
const uint32_t advance_divisor_cached = advance_divisor;
const uint64_t advance_divisor_cached = advance_divisor;
// Determine if pulses are needed
#if HAS_X_STEP
@@ -2081,7 +2113,7 @@ void Stepper::pulse_phase_isr() {
TERN_(I2S_STEPPER_STREAM, i2s_push_sample());
// TODO: need to deal with MINIMUM_STEPPER_PULSE over i2s
#if ISR_MULTI_STEPS
#if ISR_PULSE_CONTROL
START_TIMED_PULSE();
AWAIT_HIGH_PULSE();
#endif
@@ -2196,24 +2228,24 @@ void Stepper::pulse_phase_isr() {
#endif // HAS_ZV_SHAPING
// Calculate timer interval, with all limits applied.
hal_timer_t Stepper::calc_timer_interval(uint32_t step_rate) {
hal_timer_t Stepper::calc_timer_interval(uint64_t step_rate) {
constexpr uint64_t min_step_rate = MINIMAL_STEP_RATE;
#ifdef CPU_32_BIT
// A fast processor can just do integer division
constexpr uint32_t min_step_rate = uint32_t(STEPPER_TIMER_RATE) / HAL_TIMER_TYPE_MAX;
return step_rate > min_step_rate ? uint32_t(STEPPER_TIMER_RATE) / step_rate : HAL_TIMER_TYPE_MAX;
return step_rate > min_step_rate ? uint64_t(STEPPER_TIMER_RATE) / step_rate : HAL_TIMER_TYPE_MAX;
#else
constexpr uint32_t min_step_rate = (F_CPU) / 500000U; // i.e., 32 or 40
if (step_rate >= 0x0800) { // higher step rate
// AVR is able to keep up at around 65kHz Stepping ISR rate at most.
// So values for step_rate > 65535 might as well be truncated.
// Handle it as quickly as possible. i.e., assume highest byte is zero
// because non-zero would represent a step rate far beyond AVR capabilities.
if (uint8_t(step_rate >> 16))
return uint32_t(STEPPER_TIMER_RATE) / 0x10000;
return uint64_t(STEPPER_TIMER_RATE) / 0x10000;
const uintptr_t table_address = uintptr_t(&speed_lookuptable_fast[uint8_t(step_rate >> 8)]);
const uint16_t base = uint16_t(pgm_read_word(table_address));
@@ -2233,8 +2265,8 @@ hal_timer_t Stepper::calc_timer_interval(uint32_t step_rate) {
}
#if ENABLED(NONLINEAR_EXTRUSION)
void Stepper::calc_nonlinear_e(uint32_t step_rate) {
const uint32_t velocity = ne_scale * step_rate; // Scale step_rate first so all intermediate values stay in range of 8.24 fixed point math
void Stepper::calc_nonlinear_e(uint64_t step_rate) {
const uint64_t velocity = ne_scale * step_rate; // Scale step_rate first so all intermediate values stay in range of 8.24 fixed point math
int32_t vd = (((int64_t)ne_fix.A * velocity) >> 24) + (((((int64_t)ne_fix.B * velocity) >> 24) * velocity) >> 24);
NOLESS(vd, 0);
@@ -2243,19 +2275,19 @@ hal_timer_t Stepper::calc_timer_interval(uint32_t step_rate) {
#endif
// Get the timer interval and the number of loops to perform per tick
hal_timer_t Stepper::calc_multistep_timer_interval(uint32_t step_rate) {
hal_timer_t Stepper::calc_multistep_timer_interval(uint64_t step_rate) {
#if ENABLED(OLD_ADAPTIVE_MULTISTEPPING)
#if MULTISTEPPING_LIMIT == 1
// Just make sure the step rate is doable
NOMORE(step_rate, uint32_t(MAX_STEP_ISR_FREQUENCY_1X));
NOMORE(step_rate, uint64_t(MAX_STEP_ISR_FREQUENCY_1X));
#else
// The stepping frequency limits for each multistepping rate
static const uint32_t limit[] PROGMEM = {
static const uint64_t limit[] PROGMEM = {
( MAX_STEP_ISR_FREQUENCY_1X )
, (((F_CPU) / ISR_EXECUTION_CYCLES(1)) >> 1)
#if MULTISTEPPING_LIMIT >= 4
@@ -2280,7 +2312,7 @@ hal_timer_t Stepper::calc_multistep_timer_interval(uint32_t step_rate) {
// Find a doable step rate using multistepping
uint8_t multistep = 1;
for (uint8_t i = 0; i < COUNT(limit) && step_rate > uint32_t(pgm_read_dword(&limit[i])); ++i) {
for (uint8_t i = 0; i < COUNT(limit) && step_rate > uint64_t(pgm_read_dword(&limit[i])); ++i) {
step_rate >>= 1;
multistep <<= 1;
}
@@ -2439,7 +2471,7 @@ hal_timer_t Stepper::block_phase_isr() {
#if ENABLED(S_CURVE_ACCELERATION)
// Get the next speed to use (Jerk limited!)
uint32_t acc_step_rate = acceleration_time < current_block->acceleration_time
uint64_t acc_step_rate = acceleration_time < current_block->acceleration_time
? _eval_bezier_curve(acceleration_time)
: current_block->cruise_rate;
#else
@@ -2460,7 +2492,7 @@ hal_timer_t Stepper::block_phase_isr() {
#if ENABLED(LIN_ADVANCE)
if (la_active) {
const uint32_t la_step_rate = la_advance_steps < current_block->max_adv_steps ? current_block->la_advance_rate : 0;
const uint64_t la_step_rate = la_advance_steps < current_block->max_adv_steps ? current_block->la_advance_rate : 0;
la_interval = calc_timer_interval((acc_step_rate + la_step_rate) >> current_block->la_scaling);
}
#endif
@@ -2490,7 +2522,7 @@ hal_timer_t Stepper::block_phase_isr() {
}
// Are we in Deceleration phase ?
else if (step_events_completed >= decelerate_start) {
uint32_t step_rate;
uint64_t step_rate;
#if ENABLED(S_CURVE_ACCELERATION)
// If this is the 1st time we process the 2nd half of the trapezoid...
@@ -2525,7 +2557,7 @@ hal_timer_t Stepper::block_phase_isr() {
#if ENABLED(LIN_ADVANCE)
if (la_active) {
const uint32_t la_step_rate = la_advance_steps > current_block->final_adv_steps ? current_block->la_advance_rate : 0;
const uint64_t la_step_rate = la_advance_steps > current_block->final_adv_steps ? current_block->la_advance_rate : 0;
if (la_step_rate != step_rate) {
const bool forward_e = la_step_rate < step_rate;
la_interval = calc_timer_interval((forward_e ? step_rate - la_step_rate : la_step_rate - step_rate) >> current_block->la_scaling);
@@ -2600,6 +2632,25 @@ hal_timer_t Stepper::block_phase_isr() {
// The timer interval is just the nominal value for the nominal speed
interval = ticks_nominal;
}
/**
* Adjust Laser Power - Cruise
* power - direct or floor adjusted active laser power.
*/
#if ENABLED(LASER_POWER_TRAP)
if (cutter.cutter_mode == CUTTER_MODE_CONTINUOUS) {
if (step_events_completed + 1 == accelerate_before) {
if (planner.laser_inline.status.isPowered && planner.laser_inline.status.isEnabled) {
if (current_block->laser.trap_ramp_entry_incr > 0) {
current_block->laser.trap_ramp_active_pwr = current_block->laser.power;
cutter.apply_power(current_block->laser.power);
}
}
// Not a powered move.
else cutter.apply_power(0);
}
}
#endif
}
#if ENABLED(LASER_FEATURE)
@@ -2691,8 +2742,85 @@ hal_timer_t Stepper::block_phase_isr() {
}
#endif
// Set flags for all moving axes, accounting for kinematics
set_axis_moved_for_current_block();
// Flag all moving axes for proper endstop handling
#if IS_CORE
// Define conditions for checking endstops
#define S_(N) current_block->steps[CORE_AXIS_##N]
#define D_(N) current_block->direction_bits[CORE_AXIS_##N]
#endif
#if CORE_IS_XY || CORE_IS_XZ
/**
* Head direction in -X axis for CoreXY and CoreXZ bots.
*
* If steps differ, both axes are moving.
* If DeltaA == -DeltaB, the movement is only in the 2nd axis (Y or Z, handled below)
* If DeltaA == DeltaB, the movement is only in the 1st axis (X)
*/
#if ANY(COREXY, COREXZ)
#define X_CMP(A,B) ((A)==(B))
#else
#define X_CMP(A,B) ((A)!=(B))
#endif
#define X_MOVE_TEST ( S_(1) != S_(2) || (S_(1) > 0 && X_CMP(D_(1),D_(2))) )
#elif ENABLED(MARKFORGED_XY)
#define X_MOVE_TEST (current_block->steps.a != current_block->steps.b)
#else
#define X_MOVE_TEST !!current_block->steps.a
#endif
#if CORE_IS_XY || CORE_IS_YZ
/**
* Head direction in -Y axis for CoreXY / CoreYZ bots.
*
* If steps differ, both axes are moving
* If DeltaA == DeltaB, the movement is only in the 1st axis (X or Y)
* If DeltaA == -DeltaB, the movement is only in the 2nd axis (Y or Z)
*/
#if ANY(COREYX, COREYZ)
#define Y_CMP(A,B) ((A)==(B))
#else
#define Y_CMP(A,B) ((A)!=(B))
#endif
#define Y_MOVE_TEST ( S_(1) != S_(2) || (S_(1) > 0 && Y_CMP(D_(1),D_(2))) )
#elif ENABLED(MARKFORGED_YX)
#define Y_MOVE_TEST (current_block->steps.a != current_block->steps.b)
#else
#define Y_MOVE_TEST !!current_block->steps.b
#endif
#if CORE_IS_XZ || CORE_IS_YZ
/**
* Head direction in -Z axis for CoreXZ or CoreYZ bots.
*
* If steps differ, both axes are moving
* If DeltaA == DeltaB, the movement is only in the 1st axis (X or Y, already handled above)
* If DeltaA == -DeltaB, the movement is only in the 2nd axis (Z)
*/
#if ANY(COREZX, COREZY)
#define Z_CMP(A,B) ((A)==(B))
#else
#define Z_CMP(A,B) ((A)!=(B))
#endif
#define Z_MOVE_TEST ( S_(1) != S_(2) || (S_(1) > 0 && Z_CMP(D_(1),D_(2))) )
#else
#define Z_MOVE_TEST !!current_block->steps.c
#endif
AxisBits didmove;
NUM_AXIS_CODE(
if (X_MOVE_TEST) didmove.a = true,
if (Y_MOVE_TEST) didmove.b = true,
if (Z_MOVE_TEST) didmove.c = true,
if (!!current_block->steps.i) didmove.i = true,
if (!!current_block->steps.j) didmove.j = true,
if (!!current_block->steps.k) didmove.k = true,
if (!!current_block->steps.u) didmove.u = true,
if (!!current_block->steps.v) didmove.v = true,
if (!!current_block->steps.w) didmove.w = true
);
axis_did_move = didmove;
#if ENABLED(ADAPTIVE_STEP_SMOOTHING)
// Nonlinear Extrusion needs at least 2x oversampling to permit increase of E step rate
@@ -2701,7 +2829,7 @@ hal_timer_t Stepper::block_phase_isr() {
// Decide if axis smoothing is possible
if (stepper.adaptive_step_smoothing_enabled) {
uint32_t max_rate = current_block->nominal_rate; // Get the step event rate
uint64_t max_rate = current_block->nominal_rate; // Get the step event rate
while (max_rate < MIN_STEP_ISR_FREQUENCY) { // As long as more ISRs are possible...
max_rate <<= 1; // Try to double the rate
if (max_rate < MIN_STEP_ISR_FREQUENCY) // Don't exceed the estimated ISR limit
@@ -2852,7 +2980,7 @@ hal_timer_t Stepper::block_phase_isr() {
#if ENABLED(LIN_ADVANCE)
if (la_active) {
const uint32_t la_step_rate = la_advance_steps < current_block->max_adv_steps ? current_block->la_advance_rate : 0;
const uint64_t la_step_rate = la_advance_steps < current_block->max_adv_steps ? current_block->la_advance_rate : 0;
la_interval = calc_timer_interval((current_block->initial_rate + la_step_rate) >> current_block->la_scaling);
}
#endif
@@ -3272,7 +3400,7 @@ void Stepper::init() {
const bool was_on = hal.isr_state();
hal.isr_off();
const shaping_time_t delay = freq ? float(uint32_t(STEPPER_TIMER_RATE) / 2) / freq : shaping_time_t(-1);
const shaping_time_t delay = freq ? float(uint64_t(STEPPER_TIMER_RATE) / 2) / freq : shaping_time_t(-1);
#define SHAPING_SET_FREQ_FOR_AXIS(AXISN, AXISL) \
if (axis == AXISN) { \
ShapingQueue::set_delay(AXISN, delay); \
@@ -3757,7 +3885,7 @@ void Stepper::report_positions() {
#if EXTRA_CYCLES_BABYSTEP > 20
#define _SAVE_START() const hal_timer_t pulse_start = HAL_timer_get_count(MF_TIMER_PULSE)
#define _PULSE_WAIT() while (EXTRA_CYCLES_BABYSTEP > uint32_t(HAL_timer_get_count(MF_TIMER_PULSE) - pulse_start) * (PULSE_TIMER_PRESCALE)) { /* nada */ }
#define _PULSE_WAIT() while (EXTRA_CYCLES_BABYSTEP > uint64_t(HAL_timer_get_count(MF_TIMER_PULSE) - pulse_start) * (PULSE_TIMER_PRESCALE)) { /* nada */ }
#else
#define _SAVE_START() NOOP
#if EXTRA_CYCLES_BABYSTEP > 0
+19 -19
View File
@@ -309,11 +309,11 @@ class Stepper {
#endif
#define MOTOR_CURRENT_COUNT 3
#elif HAS_MOTOR_CURRENT_SPI
static constexpr uint32_t digipot_count[] = DIGIPOT_MOTOR_CURRENT;
static constexpr uint64_t digipot_count[] = DIGIPOT_MOTOR_CURRENT;
#define MOTOR_CURRENT_COUNT COUNT(Stepper::digipot_count)
#endif
static bool initialized;
static uint32_t motor_current_setting[MOTOR_CURRENT_COUNT]; // Initialized by settings.load()
static uint64_t motor_current_setting[MOTOR_CURRENT_COUNT]; // Initialized by settings.load()
#endif
// Last-moved extruder, as set when the last movement was fetched from planner
@@ -363,7 +363,7 @@ class Stepper {
;
#endif
static uint32_t acceleration_time, deceleration_time; // time measured in Stepper Timer ticks
static uint64_t acceleration_time, deceleration_time; // time measured in Stepper Timer ticks
#if MULTISTEPPING_LIMIT == 1
static constexpr uint8_t steps_per_isr = 1; // Count of steps to perform per Stepper ISR call
@@ -384,10 +384,10 @@ class Stepper {
// Delta error variables for the Bresenham line tracer
static xyze_long_t delta_error;
static xyze_long_t advance_dividend;
static uint32_t advance_divisor,
static uint64_t advance_divisor,
step_events_completed, // The number of step events executed in the current block
accelerate_before, // The count at which to start cruising
decelerate_start, // The count at which to start decelerating
accelerate_before, // The point from where we need to stop acceleration
decelerate_start, // The point from where we need to start decelerating
step_event_count; // The total event count for the current block
#if ANY(HAS_MULTI_EXTRUDER, MIXING_EXTRUDER)
@@ -400,7 +400,7 @@ class Stepper {
static int32_t bezier_A, // A coefficient in Bézier speed curve
bezier_B, // B coefficient in Bézier speed curve
bezier_C; // C coefficient in Bézier speed curve
static uint32_t bezier_F, // F coefficient in Bézier speed curve
static uint64_t bezier_F, // F/free coefficient in Bézier speed curve
bezier_AV; // AV coefficient in Bézier speed curve
#ifdef __AVR__
static bool A_negative; // If A coefficient was negative
@@ -432,7 +432,7 @@ class Stepper {
#if ENABLED(NONLINEAR_EXTRUSION)
static int32_t ne_edividend;
static uint32_t ne_scale;
static uint64_t ne_scale;
static ne_fix_t ne_fix;
#endif
@@ -447,7 +447,7 @@ class Stepper {
static hal_timer_t ticks_nominal;
#if DISABLED(S_CURVE_ACCELERATION)
static uint32_t acc_step_rate; // needed for deceleration start point
static uint64_t acc_step_rate; // needed for deceleration start point
#endif
// Exact steps at which an endstop was triggered
@@ -478,21 +478,21 @@ class Stepper {
}
// The ISR scheduler
static void isr();
FORCE_INLINE static void isr();
// The stepper pulse ISR phase
static void pulse_phase_isr();
FORCE_INLINE static void pulse_phase_isr();
// The stepper block processing ISR phase
static hal_timer_t block_phase_isr();
FORCE_INLINE static hal_timer_t block_phase_isr();
#if HAS_ZV_SHAPING
static void shaping_isr();
FORCE_INLINE static void shaping_isr();
#endif
#if ENABLED(LIN_ADVANCE)
// The Linear advance ISR phase
static void advance_isr();
FORCE_INLINE static void advance_isr();
#endif
#if ENABLED(BABYSTEPPING)
@@ -677,21 +677,21 @@ class Stepper {
static void _set_position(const abce_long_t &spos);
// Calculate the timing interval for the given step rate
static hal_timer_t calc_timer_interval(uint32_t step_rate);
static hal_timer_t calc_timer_interval(uint64_t step_rate);
// Calculate timing interval and steps-per-ISR for the given step rate
static hal_timer_t calc_multistep_timer_interval(uint32_t step_rate);
static hal_timer_t calc_multistep_timer_interval(uint64_t step_rate);
// Evaluate axis motions and set bits in axis_did_move
static void set_axis_moved_for_current_block();
#if ENABLED(NONLINEAR_EXTRUSION)
static void calc_nonlinear_e(uint32_t step_rate);
static void calc_nonlinear_e(uint64_t step_rate);
#endif
#if ENABLED(S_CURVE_ACCELERATION)
static void _calc_bezier_curve_coeffs(const int32_t v0, const int32_t v1, const uint32_t av);
static int32_t _eval_bezier_curve(const uint32_t curr_step);
static void _calc_bezier_curve_coeffs(const int32_t v0, const int32_t v1, const uint64_t av);
static int32_t _eval_bezier_curve(const uint64_t curr_step);
#endif
#if HAS_MOTOR_CURRENT_SPI || HAS_MOTOR_CURRENT_PWM
+604
View File
@@ -0,0 +1,604 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#ifndef BOARD_INFO_NAME
#define BOARD_INFO_NAME "Extra Big Ass Board"
#endif
#ifndef DEFAULT_MACHINE_NAME
#define DEFAULT_MACHINE_NAME "XtraBigAssBoard"
#endif
#define LED_PIN P3_18 // PWM0_3
// EXTRA PINS
#define FIL_RUNOUT_PIN P1_12
// DRIVERS EXTRA PINS
#define DRIVERS_SCK P1_20
#define DRIVERS_MISO P1_23
#define DRIVERS_MOSI P1_24
//
// Servos
//
#define SERVO0_PIN P2_05 // PWM1_6
#define SERVO1_PIN P2_04 // PWM1_5
#define SERVO2_PIN P2_03 // PWM1_4
#define SERVO3_PIN P2_02 // PWM1_3
//
// Limit Switches
//
#define X_MIN_PIN P0_19
#define X_MAX_PIN P0_18
#define Y_MIN_PIN P0_20
#define Y_MAX_PIN P0_17
#define Z_MIN_PIN P0_21
#define Z_MAX_PIN P0_15
//
// Z Probe (when not Z_MIN_PIN)
//
#ifndef Z_MIN_PROBE_PIN
#define Z_MIN_PROBE_PIN P0_21
#endif
//
// Steppers
//
#define X_STEP_PIN P0_10
#define X_DIR_PIN P4_03
#define X_ENABLE_PIN P0_01
#define X_CS_PIN P0_00
#define X_DIAG_PIN P2_17
#define Y_STEP_PIN P1_29
#define Y_DIR_PIN P2_14
#define Y_ENABLE_PIN P1_28
#define Y_CS_PIN P2_22
#define Y_DIAG_PIN P2_16
#define Z_STEP_PIN P4_02
#define Z_DIR_PIN P1_26
#define Z_ENABLE_PIN P1_25
#define Z_CS_PIN P4_01
#define Z_DIAG_PIN P2_21
#define E0_STEP_PIN P1_19
#define E0_DIR_PIN P0_14
#define E0_ENABLE_PIN P1_22
#define E0_CS_PIN P4_00
#define E0_DIAG_PIN P2_20
#define E1_STEP_PIN P2_23
#define E1_DIR_PIN P2_18
#define E1_ENABLE_PIN P3_23
#define E1_CS_PIN P1_18
#define E1_DIAG_PIN P2_19
#define E2_STEP_PIN P3_26
#define E2_DIR_PIN P2_25
#define E2_ENABLE_PIN P3_25
#define E2_CS_PIN P3_24
#define E2_DIAG_PIN P2_26
#define E3_STEP_PIN P4_19
#define E3_DIR_PIN P4_20
#define E3_ENABLE_PIN P4_26
#define E3_CS_PIN P4_21
#define E3_DIAG_PIN P0_22
#define E4_STEP_PIN P4_17
#define E4_DIR_PIN P4_18
#define E4_ENABLE_PIN P4_05
#define E4_CS_PIN P2_12
#define E4_DIAG_PIN P2_11
#define E5_STEP_PIN P0_11
#define E5_DIR_PIN P2_15
#define E5_ENABLE_PIN P4_04
#define E5_CS_PIN P4_16
#define E5_DIAG_PIN P2_13
#define E6_STEP_PIN P2_28
#define E6_DIR_PIN P0_28
#define E6_ENABLE_PIN P0_31
#define E6_CS_PIN P0_27
#define E6_DIAG_PIN P2_24
#define E7_STEP_PIN P1_30
#define E7_DIR_PIN P0_12
#define E7_ENABLE_PIN P0_13
#define E7_CS_PIN P2_29
#define E7_DIAG_PIN P2_27
#define E8_STEP_PIN P3_15
#define E8_DIR_PIN P3_07
#define E8_ENABLE_PIN P2_30
#define E8_CS_PIN P5_01
#define E8_DIAG_PIN P2_31
#if HAS_TMC_UART
#define X_SERIAL_TX_PIN P0_00
#define X_SERIAL_RX_PIN P0_00
#define Y_SERIAL_TX_PIN P2_22
#define Y_SERIAL_RX_PIN P2_22
#define Z_SERIAL_TX_PIN P4_01
#define Z_SERIAL_RX_PIN P4_01
#define E0_SERIAL_TX_PIN P4_00
#define E0_SERIAL_RX_PIN P4_00
#define E1_SERIAL_TX_PIN P1_18
#define E1_SERIAL_RX_PIN P1_18
#define E2_SERIAL_TX_PIN P3_24
#define E2_SERIAL_RX_PIN P3_24
#define E3_SERIAL_TX_PIN P4_21
#define E3_SERIAL_RX_PIN P4_21
#define E4_SERIAL_TX_PIN P2_12
#define E4_SERIAL_RX_PIN P2_12
#define E5_SERIAL_TX_PIN P4_16
#define E5_SERIAL_RX_PIN P4_16
#define E6_SERIAL_TX_PIN P0_27
#define E6_SERIAL_RX_PIN P0_27
#define E7_SERIAL_TX_PIN P2_29
#define E7_SERIAL_RX_PIN P2_29
#define E8_SERIAL_TX_PIN P5_01
#define E8_SERIAL_RX_PIN P5_01
// Reduce baud rate to improve software serial reliability
#define TMC_BAUD_RATE 19200
#endif // HAS_TMC_UART
//
// Temperature Sensors
//
#define TEMP_0_PIN P0_23
#define TEMP_1_PIN P0_24
#define TEMP_2_PIN P0_25
#define TEMP_3_PIN P0_26
#define TEMP_BED_PIN P1_31
//
// Heaters / Fans
//
#define HEATER_0_PIN P1_02
#define HEATER_1_PIN P1_10
#define HEATER_2_PIN P4_30
#define HEATER_3_PIN P1_09
#define HEATER_BED_PIN P4_23
#define FAN0_PIN P3_08
#define FAN1_PIN P3_00
#define FAN2_PIN P3_27 //PWM1_4
#define FAN3_PIN P5_04
#define EFAN0_PIN P1_08
#define EFAN1_PIN P4_31
#define EFAN2_PIN P3_01
#define EFAN3_PIN P3_10
//
// Misc. Functions
//
#if SD_CONNECTION_IS(LCD)
#define SD_DETECT_PIN P3_02
#define SD_SCK_PIN P1_00
#define SD_MISO_PIN P1_04
#define SD_MOSI_PIN P1_01
#define SD_SS_PIN P3_03
#define SDSS SD_SS_PIN
#elif SD_CONNECTION_IS(ONBOARD)
#define SD_DETECT_PIN P_NC
#define SD_SCK_PIN P0_07
#define SD_MISO_PIN P0_08
#define SD_MOSI_PIN P0_09
#define ONBOARD_SD_CS_PIN P0_06
#define SD_SS_PIN ONBOARD_SD_CS_PIN
#define SDSS SD_SS_PIN
#endif
#ifndef NEOPIXEL_PIN
#define NEOPIXEL_PIN P_NC
#endif
#ifndef FILWIDTH_PIN
#define FILWIDTH_PIN P_NC
#endif
#ifndef FIL_RUNOUT_PIN
#define FIL_RUNOUT_PIN P_NC
#endif
#ifndef PS_ON_PIN
//#define PS_ON_PIN P_NC
#endif
//
// Průša i3 MK2 Multiplexer Support
//
#if HAS_PRUSA_MMU1
#ifndef E_MUX0_PIN
#define E_MUX0_PIN P_NC
#endif
#ifndef E_MUX1_PIN
#define E_MUX1_PIN P_NC
#endif
#ifndef E_MUX2_PIN
#define E_MUX2_PIN P_NC
#endif
#endif
/**
* Default pins for TMC software SPI
*/
#if ENABLED(TMC_USE_SW_SPI)
#ifndef TMC_SPI_MOSI
#define TMC_SPI_MOSI P1_24
#endif
#ifndef TMC_SPI_MISO
#define TMC_SPI_MISO P1_23
#endif
#ifndef TMC_SPI_SCK
#define TMC_SPI_SCK P1_20
#endif
#endif
//////////////////////////
// LCDs and Controllers //
//////////////////////////
#if ANY(TFT_COLOR_UI, TFT_CLASSIC_UI, TFT_LVGL_UI)
#define TFT_A0_PIN 43
#define TFT_CS_PIN 49
#define TFT_DC_PIN 43
#define TFT_SCK_PIN SD_SCK_PIN
#define TFT_MOSI_PIN SD_MOSI_PIN
#define TFT_MISO_PIN SD_MISO_PIN
#define LCD_USE_DMA_SPI
#define BTN_EN1 40
#define BTN_EN2 63
#define BTN_ENC 59
#define BEEPER_PIN 42
#define TOUCH_CS_PIN 33
#define SD_DETECT_PIN 41
#define SPI_FLASH
#if ENABLED(SPI_FLASH)
#define SPI_DEVICE 1
#define SPI_FLASH_SIZE 0x1000000 // 16MB
#define SPI_FLASH_CS_PIN 31
#define SPI_FLASH_MOSI_PIN SD_MOSI_PIN
#define SPI_FLASH_MISO_PIN SD_MISO_PIN
#define SPI_FLASH_SCK_PIN SD_SCK_PIN
#endif
#define TFT_BUFFER_SIZE 0xFFFF
#ifndef TFT_DRIVER
#define TFT_DRIVER ST7796
#endif
#ifndef TOUCH_SCREEN_CALIBRATION
#if ENABLED(TFT_RES_320x240)
#ifndef TOUCH_CALIBRATION_X
#define TOUCH_CALIBRATION_X 20525
#endif
#ifndef TOUCH_CALIBRATION_Y
#define TOUCH_CALIBRATION_Y 15335
#endif
#ifndef TOUCH_OFFSET_X
#define TOUCH_OFFSET_X -1
#endif
#ifndef TOUCH_OFFSET_Y
#define TOUCH_OFFSET_Y 0
#endif
#elif ENABLED(TFT_RES_480x272)
#ifndef TOUCH_CALIBRATION_X
#define TOUCH_CALIBRATION_X 30715
#endif
#ifndef TOUCH_CALIBRATION_Y
#define TOUCH_CALIBRATION_Y 17415
#endif
#ifndef TOUCH_OFFSET_X
#define TOUCH_OFFSET_X 0
#endif
#ifndef TOUCH_OFFSET_Y
#define TOUCH_OFFSET_Y -1
#endif
#elif ENABLED(TFT_RES_480x320)
#ifndef TOUCH_CALIBRATION_X
#define TOUCH_CALIBRATION_X 30595
#endif
#ifndef TOUCH_CALIBRATION_Y
#define TOUCH_CALIBRATION_Y 20415
#endif
#ifndef TOUCH_OFFSET_X
#define TOUCH_OFFSET_X 2
#endif
#ifndef TOUCH_OFFSET_Y
#define TOUCH_OFFSET_Y 1
#endif
#elif ENABLED(TFT_RES_1024x600)
#ifndef TOUCH_CALIBRATION_X
#define TOUCH_CALIBRATION_X 65533
#endif
#ifndef TOUCH_CALIBRATION_Y
#define TOUCH_CALIBRATION_Y 38399
#endif
#ifndef TOUCH_OFFSET_X
#define TOUCH_OFFSET_X 2
#endif
#ifndef TOUCH_OFFSET_Y
#define TOUCH_OFFSET_Y 1
#endif
#endif
#endif
#define BTN_BACK 70
#elif HAS_WIRED_LCD
//
// LCD Display output pins
//
#if ENABLED(REPRAPWORLD_GRAPHICAL_LCD)
#define LCD_PINS_RS P3_06 // CS chip select /SS chip slave select
#define LCD_PINS_EN P3_14 // SID (MOSI)
#define LCD_PINS_D4 P3_30 // SCK (CLK) clock
#elif ALL(IS_NEWPANEL, PANEL_ONE)
#define LCD_PINS_RS 40
#define LCD_PINS_EN 42
#define LCD_PINS_D4 65
#define LCD_PINS_D5 66
#define LCD_PINS_D6 44
#define LCD_PINS_D7 64
#else
#if ENABLED(CR10_STOCKDISPLAY)
#define LCD_PINS_RS 27
#define LCD_PINS_EN 29
#define LCD_PINS_D4 25
#if !IS_NEWPANEL
#define BEEPER_PIN 37
#endif
#elif ENABLED(ZONESTAR_LCD)
#define LCD_PINS_RS 64
#define LCD_PINS_EN 44
#define LCD_PINS_D4 63
#define LCD_PINS_D5 40
#define LCD_PINS_D6 42
#define LCD_PINS_D7 65
#else
#if ANY(MKS_12864OLED, MKS_12864OLED_SSD1306)
#define LCD_PINS_DC 25 // Set as output on init
#define LCD_PINS_RS 27 // Pull low for 1s to init
// DOGM SPI LCD Support
#define DOGLCD_CS 16
#define DOGLCD_MOSI 17
#define DOGLCD_SCK 23
#define DOGLCD_A0 LCD_PINS_DC
#else
#define LCD_PINS_RS P3_06
#define LCD_PINS_EN P3_14
#define LCD_PINS_D4 P3_30
#define LCD_PINS_D5 P3_05
#define LCD_PINS_D6 P3_29
#endif
#define LCD_PINS_D7 P5_00
#if !IS_NEWPANEL
#define BEEPER_PIN 33
#endif
#endif
#if !IS_NEWPANEL
// Buttons attached to a shift register
// Not wired yet
//#define SHIFT_CLK_PIN 38
//#define SHIFT_LD_PIN 42
//#define SHIFT_OUT_PIN 40
//#define SHIFT_EN_PIN 17
#endif
#endif
//
// LCD Display input pins
//
#if IS_NEWPANEL
#if ENABLED(REPRAP_DISCOUNT_SMART_CONTROLLER)
#define BEEPER_PIN P3_31
#if ENABLED(CR10_STOCKDISPLAY)
#define BTN_EN1 17
#define BTN_EN2 23
#else
#define BTN_EN1 P3_11
#define BTN_EN2 P3_12
#endif
#define BTN_ENC P3_28
#define SD_DETECT_PIN P3_02
//#define KILL_PIN P_NC
#if ENABLED(BQ_LCD_SMART_CONTROLLER)
#define LCD_BACKLIGHT_PIN 39
#endif
#elif ENABLED(REPRAPWORLD_GRAPHICAL_LCD)
#define BTN_EN1 64
#define BTN_EN2 59
#define BTN_ENC 63
#define SD_DETECT_PIN 42
#elif ENABLED(LCD_I2C_PANELOLU2)
#define BTN_EN1 47
#define BTN_EN2 43
#define BTN_ENC 32
#define LCD_SDSS SDSS
#define KILL_PIN 41
#elif ENABLED(LCD_I2C_VIKI)
#define BTN_EN1 22 // https://files.panucatt.com/datasheets/viki_wiring_diagram.pdf explains 40/42.
#define BTN_EN2 7 // 22/7 are unused on RAMPS_14. 22 is unused and 7 the SERVO0_PIN on RAMPS_13.
#define BTN_ENC -1
#define LCD_SDSS SDSS
#define SD_DETECT_PIN 49
#elif ANY(VIKI2, miniVIKI)
#define DOGLCD_CS 45
#define DOGLCD_A0 44
#define BEEPER_PIN 33
#define STAT_LED_RED_PIN 32
#define STAT_LED_BLUE_PIN 35
#define BTN_EN1 22
#define BTN_EN2 7
#define BTN_ENC 39
#define SD_DETECT_PIN -1 // Pin 49 for display sd interface, 72 for easy adapter board
#define KILL_PIN 31
#define LCD_SCREEN_ROTATE 180 // 0, 90, 180, 270
#elif ENABLED(ELB_FULL_GRAPHIC_CONTROLLER)
#define DOGLCD_CS 29
#define DOGLCD_A0 27
#define BEEPER_PIN 23
#define LCD_BACKLIGHT_PIN 33
#define BTN_EN1 35
#define BTN_EN2 37
#define BTN_ENC 31
#define LCD_SDSS SDSS
#define SD_DETECT_PIN 49
#define KILL_PIN 41
#elif ENABLED(MKS_MINI_12864)
#define DOGLCD_A0 27
#define DOGLCD_CS 25
#define BEEPER_PIN 37
// not connected to a pin
#define LCD_BACKLIGHT_PIN 65 // backlight LED on A11/D65
#define BTN_EN1 31
#define BTN_EN2 33
#define BTN_ENC 35
#define SD_DETECT_PIN 49
#define KILL_PIN 64
//#define LCD_SCREEN_ROTATE 180 // 0, 90, 180, 270
#elif ENABLED(MINIPANEL)
#define BEEPER_PIN 42
// not connected to a pin
#define LCD_BACKLIGHT_PIN 65 // backlight LED on A11/D65
#define DOGLCD_A0 44
#define DOGLCD_CS 66
#define BTN_EN1 40
#define BTN_EN2 63
#define BTN_ENC 59
#define SD_DETECT_PIN 49
#define KILL_PIN 64
//#define LCD_SCREEN_ROTATE 180 // 0, 90, 180, 270
#elif ENABLED(ZONESTAR_LCD)
#define ADC_KEYPAD_PIN 12
#elif ENABLED(AZSMZ_12864)
// Pins only defined for RAMPS_SMART currently
#else
// Beeper on AUX-4
#define BEEPER_PIN P3_31
// Buttons are directly attached to AUX-2
#if IS_RRW_KEYPAD
#define SHIFT_OUT_PIN 40
#define SHIFT_CLK_PIN 44
#define SHIFT_LD_PIN 42
#define BTN_EN1 64
#define BTN_EN2 59
#define BTN_ENC 63
#elif ENABLED(PANEL_ONE)
#define BTN_EN1 59 // AUX2 PIN 3
#define BTN_EN2 63 // AUX2 PIN 4
#define BTN_ENC 49 // AUX3 PIN 7
#else
#define BTN_EN1 P3_11
#define BTN_EN2 P3_12
#define BTN_ENC P3_28
#endif
#if ENABLED(G3D_PANEL)
#define SD_DETECT_PIN 49
#define KILL_PIN 41
#endif
#endif
// CUSTOM SIMULATOR INPUTS
#define BTN_BACK 70
#endif // IS_NEWPANEL
#endif // HAS_WIRED_LCD
+151 -163
View File
@@ -22,11 +22,31 @@
#pragma once
/**
* Native with a RAMPS like board with additional pins
* Arduino Mega with RAMPS v1.4 (or v1.3) pin assignments
*
* Applies to the following boards:
*
* RAMPS_14_EFB (Hotend, Fan, Bed)
* RAMPS_14_EEB (Hotend0, Hotend1, Bed)
* RAMPS_14_EFF (Hotend, Fan0, Fan1)
* RAMPS_14_EEF (Hotend0, Hotend1, Fan)
* RAMPS_14_SF (Spindle, Controller Fan)
*
* RAMPS_13_EFB (Hotend, Fan, Bed)
* RAMPS_13_EEB (Hotend0, Hotend1, Bed)
* RAMPS_13_EFF (Hotend, Fan0, Fan1)
* RAMPS_13_EEF (Hotend0, Hotend1, Fan)
* RAMPS_13_SF (Spindle, Controller Fan)
*
* Other pins_MYBOARD.h files may override these defaults
*
* Differences between
* RAMPS_13 | RAMPS_14
* 7 | 11
*/
#ifndef BOARD_INFO_NAME
#define BOARD_INFO_NAME "RAMPS Native"
#define BOARD_INFO_NAME "RAMPS 1.4"
#endif
#ifndef DEFAULT_MACHINE_NAME
@@ -40,24 +60,28 @@
//
// Servos
//
#define SERVO0_PIN 151
#define SERVO1_PIN 152
#define SERVO2_PIN 153
#ifdef IS_RAMPS_13
#define SERVO0_PIN 7 // RAMPS_13 // Will conflict with BTN_EN2 on LCD_I2C_VIKI
#else
#define SERVO0_PIN 11
#endif
#define SERVO1_PIN 6
#define SERVO2_PIN 5
#ifndef SERVO3_PIN
#define SERVO3_PIN 154
#define SERVO3_PIN 4
#endif
//
// Limit Switches
//
#define X_MIN_PIN 155
#define X_MIN_PIN 3
#ifndef X_MAX_PIN
#define X_MAX_PIN 156
#define X_MAX_PIN 2
#endif
#define Y_MIN_PIN 157
#define Y_MAX_PIN 158
#define Z_MIN_PIN 159
#define Z_MAX_PIN 160
#define Y_MIN_PIN 14
#define Y_MAX_PIN 15
#define Z_MIN_PIN 18
#define Z_MAX_PIN 19
//
// Z Probe (when not Z_MIN_PIN)
@@ -104,60 +128,24 @@
#define E1_CS_PIN 44
#endif
#define E2_STEP_PIN 100
#define E2_DIR_PIN 101
#define E2_ENABLE_PIN 102
#ifndef E2_CS_PIN
#define E2_CS_PIN 103
#endif
#define Z4_STEP_PIN 13
#define Z4_DIR_PIN 71
#define Z4_ENABLE_PIN 12
#define E3_STEP_PIN 104
#define E3_DIR_PIN 105
#define E3_ENABLE_PIN 106
#ifndef E3_CS_PIN
#define E3_CS_PIN 107
#endif
#define Z2_STEP_PIN 4
#define Z2_DIR_PIN 5
#define Z2_ENABLE_PIN 6
#define E4_STEP_PIN 108
#define E4_DIR_PIN 109
#define E4_ENABLE_PIN 110
#ifndef E4_CS_PIN
#define E4_CS_PIN 111
#endif
#define E5_STEP_PIN 112
#define E5_DIR_PIN 113
#define E5_ENABLE_PIN 114
#ifndef E5_CS_PIN
#define E5_CS_PIN 115
#endif
#define E6_STEP_PIN 116
#define E6_DIR_PIN 117
#define E6_ENABLE_PIN 118
#ifndef E6_CS_PIN
#define E6_CS_PIN 119
#endif
#define E7_STEP_PIN 120
#define E7_DIR_PIN 121
#define E7_ENABLE_PIN 122
#ifndef E7_CS_PIN
#define E7_CS_PIN 123
#endif
#define Z3_STEP_PIN 12
#define Z3_DIR_PIN 40
#define Z3_ENABLE_PIN 44
//
// Temperature Sensors
//
#define TEMP_0_PIN 0 // Analog Input
#define TEMP_1_PIN 1 // Analog Input
#define TEMP_2_PIN 2 // Analog Input
#define TEMP_3_PIN 3 // Analog Input
#define TEMP_4_PIN 4 // Analog Input
#define TEMP_5_PIN 5 // Analog Input
#define TEMP_6_PIN 6 // Analog Input
#define TEMP_7_PIN 7 // Analog Input
#define TEMP_BED_PIN 8 // Analog Input
#define TEMP_BED_PIN 2 // Analog Input
// SPI for MAX Thermocouple
#if !HAS_MEDIA
@@ -169,33 +157,55 @@
//
// Heaters / Fans
//
#define HEATER_0_PIN 10
#define HEATER_1_PIN 9
#define HEATER_2_PIN 8
#define HEATER_3_PIN 125
#define HEATER_4_PIN 126
#define HEATER_5_PIN 127
#define HEATER_6_PIN 128
#define HEATER_7_PIN 129
#define HEATER_BED_PIN 108
#ifndef MOSFET_A_PIN
#define MOSFET_A_PIN 10
#endif
#ifndef MOSFET_B_PIN
#define MOSFET_B_PIN 9
#endif
#ifndef MOSFET_C_PIN
#define MOSFET_C_PIN 8
#endif
#ifndef MOSFET_D_PIN
#define MOSFET_D_PIN -1
#endif
#define HEATER_0_PIN MOSFET_A_PIN
#if FET_ORDER_EFB // Hotend, Fan, Bed
#define FAN0_PIN MOSFET_B_PIN
#define HEATER_BED_PIN MOSFET_C_PIN
#elif FET_ORDER_EEF // Hotend, Hotend, Fan
#define HEATER_1_PIN MOSFET_B_PIN
#define FAN0_PIN MOSFET_C_PIN
#elif FET_ORDER_EEB // Hotend, Hotend, Bed
#define HEATER_1_PIN MOSFET_B_PIN
#define HEATER_BED_PIN MOSFET_C_PIN
#elif FET_ORDER_EFF // Hotend, Fan, Fan
#define FAN0_PIN MOSFET_B_PIN
#define FAN1_PIN MOSFET_C_PIN
#elif FET_ORDER_SF // Spindle, Fan
#define FAN0_PIN MOSFET_C_PIN
#else // Non-specific are "EFB" (i.e., "EFBF" or "EFBE")
#define FAN0_PIN MOSFET_B_PIN
#define HEATER_BED_PIN MOSFET_C_PIN
#if HOTENDS == 1 && DISABLED(HEATERS_PARALLEL)
#define FAN1_PIN MOSFET_D_PIN
#else
#define HEATER_1_PIN MOSFET_D_PIN
#endif
#endif
#ifndef FAN0_PIN
#define FAN0_PIN 161 // IO pin. Buffer needed
#define FAN0_PIN 4 // IO pin. Buffer needed
#endif
#define FAN1_PIN 162 // IO pin. Buffer needed
#define FAN2_PIN 163 // IO pin. Buffer needed
#define FAN3_PIN 164 // IO pin. Buffer needed
#define FAN4_PIN 165 // IO pin. Buffer needed
#define FAN5_PIN 166 // IO pin. Buffer needed
#define FAN6_PIN 167 // IO pin. Buffer needed
#define FAN7_PIN 168 // IO pin. Buffer needed
//
// Misc. Functions
//
#define SDSS 53
#define LED_PIN 13
#define BOARD_NEOPIXEL_PIN 71
#define NEOPIXEL_PIN 71
#ifndef FILWIDTH_PIN
#define FILWIDTH_PIN 5 // Analog Input on AUX2
@@ -373,37 +383,9 @@
#endif
#endif
/** Faux Expansion Headers
* ------ ------
* (BEEP) 37 | 1 2 | 35 (ENC) (MISO) 50 | 1 2 | 52 (SCK)
* (LCD_EN) 17 | 3 4 | 16 (LCD_RS) (EN1) 31 | 3 4 | 53 (SDSS)
* (LCD_D4) 23 5 6 | 25 (LCD_D5) (EN2) 33 5 6 | 51 (MOSI)
* (LCD_D6) 27 | 7 8 | 29 (LCD_D7) (SD_DET) 49 | 7 8 | 41 (KILL)
* -- | 9 10 | -- -- | 9 10 | --
* ------ ------
* EXP1 EXP2
*/
#define EXP1_01_PIN 37 // BEEPER
#define EXP1_02_PIN 35 // ENC
#define EXP1_03_PIN 17 // LCD_EN
#define EXP1_04_PIN 16 // LCD_RS
#define EXP1_05_PIN 23 // LCD_D4
#define EXP1_06_PIN 25 // LCD_D5
#define EXP1_07_PIN 27 // LCD_D6
#define EXP1_08_PIN 29 // LCD_D7
#define EXP2_01_PIN 50 // MISO
#define EXP2_02_PIN 52 // SCK
#define EXP2_03_PIN 31 // EN1
#define EXP2_04_PIN 53 // SDSS
#define EXP2_05_PIN 33 // EN2
#define EXP2_06_PIN 51 // MOSI
#define EXP2_07_PIN 49 // SD_DET
#define EXP2_08_PIN 41 // KILL
//
// LCD / Controller
//
//////////////////////////
// LCDs and Controllers //
//////////////////////////
#if ANY(TFT_COLOR_UI, TFT_CLASSIC_UI, TFT_LVGL_UI)
@@ -415,11 +397,10 @@
#define TFT_MOSI_PIN SD_MOSI_PIN
#define LCD_USE_DMA_SPI
#define BEEPER_PIN 42
#define BTN_ENC 59
#define BTN_EN1 40
#define BTN_EN2 63
#define BTN_ENC 59
#define BEEPER_PIN 42
#define TOUCH_CS_PIN 33
@@ -504,9 +485,9 @@
//
#if ENABLED(REPRAPWORLD_GRAPHICAL_LCD)
#define LCD_PINS_RS EXP2_07_PIN // CS chip select /SS chip slave select
#define LCD_PINS_EN EXP2_06_PIN // SID (MOSI)
#define LCD_PINS_D4 EXP2_02_PIN // SCK (CLK) clock
#define LCD_PINS_RS 49 // CS chip select /SS chip slave select
#define LCD_PINS_EN 51 // SID (MOSI)
#define LCD_PINS_D4 52 // SCK (CLK) clock
#elif ALL(IS_NEWPANEL, PANEL_ONE)
@@ -521,12 +502,12 @@
#if ENABLED(CR10_STOCKDISPLAY)
#define LCD_PINS_RS EXP1_07_PIN
#define LCD_PINS_EN EXP1_08_PIN
#define LCD_PINS_D4 EXP1_06_PIN
#define LCD_PINS_RS 27
#define LCD_PINS_EN 29
#define LCD_PINS_D4 25
#if !IS_NEWPANEL
#define BEEPER_PIN EXP1_01_PIN
#define BEEPER_PIN 37
#endif
#elif ENABLED(ZONESTAR_LCD)
@@ -541,28 +522,38 @@
#else
#if ANY(MKS_12864OLED, MKS_12864OLED_SSD1306)
#define LCD_PINS_DC EXP1_06_PIN // Set as output on init
#define LCD_PINS_RS EXP1_07_PIN // Pull low for 1s to init
#define LCD_PINS_DC 25 // Set as output on init
#define LCD_PINS_RS 27 // Pull low for 1s to init
// DOGM SPI LCD Support
#define DOGLCD_CS EXP1_04_PIN
#define DOGLCD_MOSI EXP1_03_PIN
#define DOGLCD_SCK EXP1_05_PIN
#define DOGLCD_CS 16
#define DOGLCD_MOSI 17
#define DOGLCD_SCK 23
#define DOGLCD_A0 LCD_PINS_DC
#else
#define LCD_PINS_RS EXP1_04_PIN
#define LCD_PINS_EN EXP1_03_PIN
#define LCD_PINS_D4 EXP1_05_PIN
#define LCD_PINS_D5 EXP1_06_PIN
#define LCD_PINS_D6 EXP1_07_PIN
#define LCD_PINS_RS 16
#define LCD_PINS_EN 17
#define LCD_PINS_D4 23
#define LCD_PINS_D5 25
#define LCD_PINS_D6 27
#endif
#define LCD_PINS_D7 EXP1_08_PIN
#define LCD_PINS_D7 29
#if !IS_NEWPANEL
#define BEEPER_PIN EXP2_05_PIN
#define BEEPER_PIN 33
#endif
#endif
#if !IS_NEWPANEL
// Buttons attached to a shift register
// Not wired yet
//#define SHIFT_CLK_PIN 38
//#define SHIFT_LD_PIN 42
//#define SHIFT_OUT_PIN 40
//#define SHIFT_EN_PIN 17
#endif
#endif
//
@@ -572,19 +563,19 @@
#if ENABLED(REPRAP_DISCOUNT_SMART_CONTROLLER)
#define BEEPER_PIN EXP1_01_PIN
#define BEEPER_PIN 37
#if ENABLED(CR10_STOCKDISPLAY)
#define BTN_EN1 EXP1_03_PIN
#define BTN_EN2 EXP1_05_PIN
#define BTN_EN1 17
#define BTN_EN2 23
#else
#define BTN_EN1 EXP2_03_PIN
#define BTN_EN2 EXP2_05_PIN
#define BTN_EN1 31
#define BTN_EN2 33
#endif
#define BTN_ENC EXP1_02_PIN
#define SD_DETECT_PIN EXP2_07_PIN
#define KILL_PIN EXP2_08_PIN
#define BTN_ENC 35
#define SD_DETECT_PIN 49
#define KILL_PIN 41
#if ENABLED(BQ_LCD_SMART_CONTROLLER)
#define LCD_BACKLIGHT_PIN 39
@@ -634,34 +625,34 @@
#elif ENABLED(ELB_FULL_GRAPHIC_CONTROLLER)
#define DOGLCD_CS EXP1_08_PIN
#define DOGLCD_A0 EXP1_07_PIN
#define DOGLCD_CS 29
#define DOGLCD_A0 27
#define BEEPER_PIN EXP1_05_PIN
#define LCD_BACKLIGHT_PIN EXP2_05_PIN
#define BEEPER_PIN 23
#define LCD_BACKLIGHT_PIN 33
#define BTN_EN1 EXP1_02_PIN
#define BTN_EN2 EXP1_01_PIN
#define BTN_ENC EXP2_03_PIN
#define BTN_EN1 35
#define BTN_EN2 37
#define BTN_ENC 31
#define LCD_SDSS SDSS
#define SD_DETECT_PIN EXP2_07_PIN
#define KILL_PIN EXP2_08_PIN
#define SD_DETECT_PIN 49
#define KILL_PIN 41
#elif ENABLED(MKS_MINI_12864)
#define DOGLCD_A0 EXP1_07_PIN
#define DOGLCD_CS EXP1_06_PIN
#define DOGLCD_A0 27
#define DOGLCD_CS 25
#define BEEPER_PIN EXP1_01_PIN
#define BEEPER_PIN 37
// not connected to a pin
#define LCD_BACKLIGHT_PIN 65 // backlight LED on A11/D65
#define BTN_EN1 EXP2_03_PIN
#define BTN_EN2 EXP2_05_PIN
#define BTN_ENC EXP1_02_PIN
#define BTN_EN1 31
#define BTN_EN2 33
#define BTN_ENC 35
#define SD_DETECT_PIN EXP2_07_PIN
#define SD_DETECT_PIN 49
#define KILL_PIN 64
//#define LCD_SCREEN_ROTATE 180 // 0, 90, 180, 270
@@ -694,6 +685,7 @@
#else
// Beeper on AUX-4
#define BEEPER_PIN 33
// Buttons are directly attached to AUX-2
@@ -709,15 +701,15 @@
#define BTN_EN2 63 // AUX2 PIN 4
#define BTN_ENC 49 // AUX3 PIN 7
#else
#define BTN_EN1 EXP1_01_PIN
#define BTN_EN2 EXP1_02_PIN
#define BTN_ENC EXP2_03_PIN
#define SD_DETECT_PIN EXP2_08_PIN
#define BTN_EN1 37
#define BTN_EN2 35
#define BTN_ENC 31
#define SD_DETECT_PIN 41
#endif
#if ENABLED(G3D_PANEL)
#define SD_DETECT_PIN EXP2_07_PIN
#define KILL_PIN EXP2_08_PIN
#define SD_DETECT_PIN 49
#define KILL_PIN 41
#endif
#endif
@@ -727,7 +719,3 @@
#endif // IS_NEWPANEL
#endif // HAS_WIRED_LCD
#ifndef KILL_PIN
#define KILL_PIN EXP2_08_PIN
#endif
+7
View File
@@ -504,6 +504,13 @@
#include "lpc1769/pins_BTT_SKR_E3_TURBO.h" // LPC1769 env:LPC1769
#elif MB(FLY_CDY)
#include "lpc1769/pins_FLY_CDY.h" // LPC1769 env:LPC1769
//
// LPC4078 ARM Cortex M4
//
#elif MB(EBAB)
#include "lpc4078/pins_EBAB.h" // LPC4078 env:LPC4078
//
// Due (ATSAM) boards
+1 -1
View File
@@ -477,7 +477,7 @@
#undef PS_ON_PIN
#define PS_ON_PIN -1
#endif
#if DISABLED(PSU_OFF_REDUNDANT) || !defined(PS_ON1_PIN)
#if DISABLED(PSU_OFF_REDUNDANT) || DISABLED(PSU_CONTROL) || !defined(PS_ON1_PIN)
#undef PS_ON1_PIN
#define PS_ON1_PIN -1
#endif
+25
View File
@@ -42,3 +42,28 @@ board = nxp_lpc1768
[env:LPC1769]
extends = common_LPC
board = nxp_lpc1769
#
# NXP LPC4078 ARM Cortex-M4
#
[env:LPC4078]
board = nxp_lpc4078
#platform = symlink:///home/p3p/workspace/EBAB_workspace/platform-mcui
#platform_packages = framework-arduino-mcui@symlink:///home/p3p/workspace/EBAB_workspace/framework-arduino-mcui
platform = https://github.com/p3p/pio-platform-mcui/archive/refs/heads/master.zip
framework = arduino
upload_protocol = jlink
debug_tool = jlink
monitor_speed = 500000
lib_ldf_mode = off
lib_compat_mode = strict
extra_scripts = ${common.extra_scripts}
Marlin/src/HAL/LPC1768/upload_extra_script.py
build_src_filter = ${common.default_src_filter} +<src/HAL/LPC4078> +<src/HAL/shared/backtrace>
build_flags = ${common.build_flags} -IMarlin/src/HAL/LPC4078/include -DTARGET_LPC4078 -DU8G_HAL_LINKS -IMarlin/src/HAL/LPC4078/u8g -DPLATFORM_M997_SUPPORT -O3
build_unflags = -Os
lib_deps = ${common.lib_deps}
Servo
SoftwareSerial
custom_marlin.USES_LIQUIDCRYSTAL = arduino-libraries/LiquidCrystal@~1.0.7
custom_marlin.NEOPIXEL_LED = Adafruit NeoPixel=https://github.com/p3p/Adafruit_NeoPixel/archive/1.5.0.zip
+1 -1
View File
@@ -13,7 +13,7 @@
[platformio]
src_dir = Marlin
boards_dir = buildroot/share/PlatformIO/boards
default_envs = mega2560
default_envs = LPC4078
include_dir = Marlin
extra_configs =
Marlin/config.ini