Skip to content

Commit b106f59

Browse files
🐛 Refine FT Motion, I2S Stepping (MarlinFirmware#26628)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
1 parent 38f483c commit b106f59

15 files changed

+133
-72
lines changed

Marlin/src/HAL/ESP32/i2s.cpp

+38-20
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@
3434
#include <freertos/queue.h>
3535
#include "../../module/stepper.h"
3636

37+
#if ENABLED(FT_MOTION)
38+
#include "../../module/ft_motion.h"
39+
#endif
40+
3741
#define DMA_BUF_COUNT 8 // number of DMA buffers to store data
3842
#define DMA_BUF_LEN 4092 // maximum size in bytes
3943
#define I2S_SAMPLE_SIZE 4 // 4 bytes, 32 bits per sample
@@ -134,8 +138,8 @@ static void IRAM_ATTR i2s_intr_handler_default(void *arg) {
134138

135139
if (high_priority_task_awoken == pdTRUE) portYIELD_FROM_ISR();
136140

137-
// clear interrupt
138-
I2S0.int_clr.val = I2S0.int_st.val; //clear pending interrupt
141+
// Clear pending interrupt
142+
I2S0.int_clr.val = I2S0.int_st.val;
139143
}
140144

141145
void stepperTask(void *parameter) {
@@ -148,29 +152,43 @@ void stepperTask(void *parameter) {
148152
xQueueReceive(dma.queue, &dma.current, portMAX_DELAY);
149153
dma.rw_pos = 0;
150154

155+
const bool using_ftMotion = TERN0(FT_MOTION, ftMotion.cfg.mode);
156+
151157
while (dma.rw_pos < DMA_SAMPLE_COUNT) {
152-
if (!nextMainISR) {
153-
Stepper::pulse_phase_isr();
154-
nextMainISR = Stepper::block_phase_isr();
155-
}
156-
#if ENABLED(LIN_ADVANCE)
157-
else if (!nextAdvanceISR) {
158-
Stepper::advance_isr();
159-
nextAdvanceISR = Stepper::la_interval;
160-
}
161-
#endif
162-
else
163-
i2s_push_sample();
164158

165-
nextMainISR--;
159+
#if ENABLED(FT_MOTION)
166160

167-
#if ENABLED(LIN_ADVANCE)
168-
if (nextAdvanceISR == Stepper::LA_ADV_NEVER)
169-
nextAdvanceISR = Stepper::la_interval;
161+
if (using_ftMotion) {
162+
if (!nextMainISR) stepper.ftMotion_stepper();
163+
nextMainISR = 0;
164+
}
170165

171-
if (nextAdvanceISR && nextAdvanceISR != Stepper::LA_ADV_NEVER)
172-
nextAdvanceISR--;
173166
#endif
167+
168+
if (!using_ftMotion) {
169+
if (!nextMainISR) {
170+
Stepper::pulse_phase_isr();
171+
nextMainISR = Stepper::block_phase_isr();
172+
}
173+
#if ENABLED(LIN_ADVANCE)
174+
else if (!nextAdvanceISR) {
175+
Stepper::advance_isr();
176+
nextAdvanceISR = Stepper::la_interval;
177+
}
178+
#endif
179+
else
180+
i2s_push_sample();
181+
182+
nextMainISR--;
183+
184+
#if ENABLED(LIN_ADVANCE)
185+
if (nextAdvanceISR == Stepper::LA_ADV_NEVER)
186+
nextAdvanceISR = Stepper::la_interval;
187+
188+
if (nextAdvanceISR && nextAdvanceISR != Stepper::LA_ADV_NEVER)
189+
nextAdvanceISR--;
190+
#endif
191+
}
174192
}
175193
}
176194
}

Marlin/src/inc/Conditionals_adv.h

+6
Original file line numberDiff line numberDiff line change
@@ -1309,6 +1309,12 @@
13091309
#define HAS_ZV_SHAPING 1
13101310
#endif
13111311

1312+
// FT Motion unified window and batch size
1313+
#if ALL(FT_MOTION, FTM_UNIFIED_BWS)
1314+
#define FTM_WINDOW_SIZE FTM_BW_SIZE
1315+
#define FTM_BATCH_SIZE FTM_BW_SIZE
1316+
#endif
1317+
13121318
// Toolchange Event G-code
13131319
#if !HAS_MULTI_EXTRUDER || !(defined(EVENT_GCODE_TOOLCHANGE_T0) || defined(EVENT_GCODE_TOOLCHANGE_T1) || defined(EVENT_GCODE_TOOLCHANGE_T2) || defined(EVENT_GCODE_TOOLCHANGE_T3) || defined(EVENT_GCODE_TOOLCHANGE_T4) || defined(EVENT_GCODE_TOOLCHANGE_T5) || defined(EVENT_GCODE_TOOLCHANGE_T6) || defined(EVENT_GCODE_TOOLCHANGE_T7))
13141320
#undef TC_GCODE_USE_GLOBAL_X

Marlin/src/inc/SanityCheck.h

+6-2
Original file line numberDiff line numberDiff line change
@@ -4123,8 +4123,12 @@ static_assert(_PLUS_TEST(3), "DEFAULT_MAX_ACCELERATION values must be positive."
41234123
/**
41244124
* Fixed-Time Motion limitations
41254125
*/
4126-
#if ALL(FT_MOTION, MIXING_EXTRUDER)
4127-
#error "FT_MOTION does not currently support MIXING_EXTRUDER."
4126+
#if ENABLED(FT_MOTION)
4127+
#if ENABLED(MIXING_EXTRUDER)
4128+
#error "FT_MOTION does not currently support MIXING_EXTRUDER."
4129+
#elif DISABLED(FTM_UNIFIED_BWS)
4130+
#error "FT_MOTION requires FTM_UNIFIED_BWS to be enabled because FBS is not yet implemented."
4131+
#endif
41284132
#endif
41294133

41304134
// Multi-Stepping Limit

Marlin/src/inc/Warnings.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -826,3 +826,10 @@
826826
#if PIN_EXISTS(BEEPER) && ALL(SPEAKER, NO_SPEAKER)
827827
#warning "The BEEPER cannot produce tones so you can disable SPEAKER."
828828
#endif
829+
830+
/**
831+
* Fixed-Time Motion
832+
*/
833+
#if ALL(FT_MOTION, I2S_STEPPER_STREAM)
834+
#warning "FT_MOTION has not been tested with I2S_STEPPER_STREAM."
835+
#endif

Marlin/src/module/ft_motion.cpp

+23-12
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ FTMotion ftMotion;
5555
ft_config_t FTMotion::cfg;
5656
bool FTMotion::busy; // = false
5757
ft_command_t FTMotion::stepperCmdBuff[FTM_STEPPERCMD_BUFF_SIZE] = {0U}; // Stepper commands buffer.
58-
uint32_t FTMotion::stepperCmdBuff_produceIdx = 0, // Index of next stepper command write to the buffer.
59-
FTMotion::stepperCmdBuff_consumeIdx = 0; // Index of next stepper command read from the buffer.
58+
int32_t FTMotion::stepperCmdBuff_produceIdx = 0, // Index of next stepper command write to the buffer.
59+
FTMotion::stepperCmdBuff_consumeIdx = 0; // Index of next stepper command read from the buffer.
6060

6161
bool FTMotion::sts_stepperBusy = false; // The stepper buffer has items and is in use.
6262

@@ -123,6 +123,8 @@ uint32_t FTMotion::interpIdx = 0, // Index of current data point b
123123
float FTMotion::e_advanced_z1 = 0.0f; // (ms) Unit delay of advanced extruder position.
124124
#endif
125125

126+
constexpr uint32_t last_batchIdx = (FTM_WINDOW_SIZE) - (FTM_BATCH_SIZE);
127+
126128
//-----------------------------------------------------------------
127129
// Function definitions.
128130
//-----------------------------------------------------------------
@@ -145,8 +147,16 @@ void FTMotion::runoutBlock() {
145147
ratio.reset();
146148

147149
max_intervals = cfg.modeHasShaper() ? shaper_intervals : 0;
148-
if (max_intervals <= TERN(FTM_UNIFIED_BWS, FTM_BW_SIZE, min_max_intervals - (FTM_BATCH_SIZE))) max_intervals = min_max_intervals;
149-
max_intervals += TERN(FTM_UNIFIED_BWS, FTM_BW_SIZE, FTM_WINDOW_SIZE) - makeVector_batchIdx;
150+
if (max_intervals <= TERN(FTM_UNIFIED_BWS, FTM_BATCH_SIZE, min_max_intervals - (FTM_BATCH_SIZE)))
151+
max_intervals = min_max_intervals;
152+
153+
max_intervals += (
154+
#if ENABLED(FTM_UNIFIED_BWS)
155+
FTM_WINDOW_SIZE - makeVector_batchIdx
156+
#else
157+
FTM_WINDOW_SIZE - ((last_batchIdx < (FTM_BATCH_SIZE)) ? 0 : makeVector_batchIdx)
158+
#endif
159+
);
150160
blockProcRdy = blockDataIsRunout = true;
151161
runoutEna = blockProcDn = false;
152162
}
@@ -198,7 +208,7 @@ void FTMotion::loop() {
198208
);
199209

200210
// Shift the time series back in the window
201-
#define TSHIFT(A) memcpy(traj.A, &traj.A[FTM_BATCH_SIZE], (FTM_WINDOW_SIZE - FTM_BATCH_SIZE) * sizeof(traj.A[0]))
211+
#define TSHIFT(A) memcpy(traj.A, &traj.A[FTM_BATCH_SIZE], last_batchIdx * sizeof(traj.A[0]))
202212
LOGICAL_AXIS_CODE(
203213
TSHIFT(e),
204214
TSHIFT(x), TSHIFT(y), TSHIFT(z),
@@ -219,7 +229,7 @@ void FTMotion::loop() {
219229
&& (interpIdx - interpIdx_z1 < (FTM_STEPS_PER_LOOP))
220230
) {
221231
convertToSteps(interpIdx);
222-
if (++interpIdx == TERN(FTM_UNIFIED_BWS, FTM_BW_SIZE, FTM_BATCH_SIZE)) {
232+
if (++interpIdx == FTM_BATCH_SIZE) {
223233
batchRdyForInterp = false;
224234
interpIdx = 0;
225235
}
@@ -449,7 +459,7 @@ void FTMotion::reset() {
449459
endPosn_prevBlock.reset();
450460

451461
makeVector_idx = makeVector_idx_z1 = 0;
452-
makeVector_batchIdx = 0;
462+
makeVector_batchIdx = TERN(FTM_UNIFIED_BWS, 0, _MAX(last_batchIdx, FTM_BATCH_SIZE));
453463

454464
steps.reset();
455465
interpIdx = interpIdx_z1 = 0;
@@ -464,10 +474,11 @@ void FTMotion::reset() {
464474
}
465475

466476
// Private functions.
477+
467478
// Auxiliary function to get number of step commands in the buffer.
468-
uint32_t FTMotion::stepperCmdBuffItems() {
469-
const uint32_t udiff = stepperCmdBuff_produceIdx - stepperCmdBuff_consumeIdx;
470-
return stepperCmdBuff_produceIdx < stepperCmdBuff_consumeIdx ? (FTM_STEPPERCMD_BUFF_SIZE) + udiff : udiff;
479+
int32_t FTMotion::stepperCmdBuffItems() {
480+
const int32_t udiff = stepperCmdBuff_produceIdx - stepperCmdBuff_consumeIdx;
481+
return (udiff < 0) ? udiff + (FTM_STEPPERCMD_BUFF_SIZE) : udiff;
471482
}
472483

473484
// Initializes storage variables before startup.
@@ -677,8 +688,8 @@ void FTMotion::makeVector() {
677688
#endif
678689

679690
// Filled up the queue with regular and shaped steps
680-
if (++makeVector_batchIdx == TERN(FTM_UNIFIED_BWS, FTM_BW_SIZE, (FTM_WINDOW_SIZE - FTM_BATCH_SIZE))) {
681-
makeVector_batchIdx = 0;
691+
if (++makeVector_batchIdx == FTM_WINDOW_SIZE) {
692+
makeVector_batchIdx = last_batchIdx;
682693
batchRdy = true;
683694
}
684695

Marlin/src/module/ft_motion.h

+7-8
Original file line numberDiff line numberDiff line change
@@ -102,12 +102,11 @@ class FTMotion {
102102
}
103103

104104
static ft_command_t stepperCmdBuff[FTM_STEPPERCMD_BUFF_SIZE]; // Buffer of stepper commands.
105-
static uint32_t stepperCmdBuff_produceIdx, // Index of next stepper command write to the buffer.
106-
stepperCmdBuff_consumeIdx; // Index of next stepper command read from the buffer.
105+
static int32_t stepperCmdBuff_produceIdx, // Index of next stepper command write to the buffer.
106+
stepperCmdBuff_consumeIdx; // Index of next stepper command read from the buffer.
107107

108108
static bool sts_stepperBusy; // The stepper buffer has items and is in use.
109109

110-
111110
// Public methods
112111
static void init();
113112
static void startBlockProc(); // Set controller states to begin processing a block.
@@ -153,10 +152,10 @@ class FTMotion {
153152
static uint32_t N1, N2, N3;
154153
static uint32_t max_intervals;
155154

156-
static constexpr uint32_t _ftm_size = TERN(FTM_UNIFIED_BWS, FTM_BW_SIZE, FTM_BATCH_SIZE),
157-
_ftm_wind = TERN(FTM_UNIFIED_BWS, 2, CEIL((FTM_WINDOW_SIZE) / _ftm_size)),
158-
shaper_intervals = _ftm_size * CEIL((FTM_ZMAX) / _ftm_size),
159-
min_max_intervals = _ftm_size * _ftm_wind;
155+
#define _DIVCEIL(A,B) (((A) + (B) - 1) / (B))
156+
static constexpr uint32_t _ftm_ratio = TERN(FTM_UNIFIED_BWS, 2, _DIVCEIL(FTM_WINDOW_SIZE, FTM_BATCH_SIZE)),
157+
shaper_intervals = (FTM_BATCH_SIZE) * _DIVCEIL(FTM_ZMAX, FTM_BATCH_SIZE),
158+
min_max_intervals = (FTM_BATCH_SIZE) * _ftm_ratio;
160159

161160
// Make vector variables.
162161
static uint32_t makeVector_idx,
@@ -203,7 +202,7 @@ class FTMotion {
203202
#endif
204203

205204
// Private methods
206-
static uint32_t stepperCmdBuffItems();
205+
static int32_t stepperCmdBuffItems();
207206
static void loadBlockData(block_t *const current_block);
208207
static void makeVector();
209208
static void convertToSteps(const uint32_t idx);

Marlin/src/module/ft_types.h

+2-7
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,8 @@ enum dynFreqMode_t : uint8_t {
4444

4545
#define IS_EI_MODE(N) WITHIN(N, ftMotionMode_EI, ftMotionMode_3HEI)
4646

47-
#if ENABLED(FTM_UNIFIED_BWS)
48-
typedef struct XYZEarray<float, FTM_BW_SIZE> xyze_trajectory_t;
49-
typedef struct XYZEarray<float, FTM_BW_SIZE> xyze_trajectoryMod_t;
50-
#else
51-
typedef struct XYZEarray<float, FTM_WINDOW_SIZE> xyze_trajectory_t;
52-
typedef struct XYZEarray<float, FTM_BATCH_SIZE> xyze_trajectoryMod_t;
53-
#endif
47+
typedef struct XYZEarray<float, FTM_WINDOW_SIZE> xyze_trajectory_t;
48+
typedef struct XYZEarray<float, FTM_BATCH_SIZE> xyze_trajectoryMod_t;
5449

5550
enum {
5651
LIST_N(DOUBLE(LOGICAL_AXES),

Marlin/src/module/stepper.cpp

+15-8
Original file line numberDiff line numberDiff line change
@@ -1508,14 +1508,12 @@ void Stepper::isr() {
15081508
#if ENABLED(FT_MOTION)
15091509

15101510
if (using_ftMotion) {
1511-
if (!nextMainISR) {
1512-
nextMainISR = FTM_MIN_TICKS;
1513-
ftMotion_stepper();
1514-
endstops.update();
1515-
TERN_(BABYSTEPPING, if (babystep.has_steps()) babystepping_isr());
1511+
if (!nextMainISR) { // Main ISR is ready to fire during this iteration?
1512+
nextMainISR = FTM_MIN_TICKS; // Set to minimum interval (a limit on the top speed)
1513+
ftMotion_stepper(); // Run FTM Stepping
15161514
}
1517-
interval = nextMainISR;
1518-
nextMainISR -= interval;
1515+
interval = nextMainISR; // Interval is either some old nextMainISR or FTM_MIN_TICKS
1516+
nextMainISR = 0; // For FT Motion fire again ASAP
15191517
}
15201518

15211519
#endif
@@ -3448,7 +3446,8 @@ void Stepper::report_positions() {
34483446
// Use one byte to restore one stepper command in the format:
34493447
// |X_step|X_direction|Y_step|Y_direction|Z_step|Z_direction|E_step|E_direction|
34503448
const ft_command_t command = ftMotion.stepperCmdBuff[ftMotion.stepperCmdBuff_consumeIdx];
3451-
if (++ftMotion.stepperCmdBuff_consumeIdx == (FTM_STEPPERCMD_BUFF_SIZE)) ftMotion.stepperCmdBuff_consumeIdx = 0U;
3449+
if (++ftMotion.stepperCmdBuff_consumeIdx == (FTM_STEPPERCMD_BUFF_SIZE))
3450+
ftMotion.stepperCmdBuff_consumeIdx = 0;
34523451

34533452
if (abort_current_block) return;
34543453

@@ -3492,6 +3491,8 @@ void Stepper::report_positions() {
34923491
U_APPLY_STEP(axis_did_move.u, false), V_APPLY_STEP(axis_did_move.v, false), W_APPLY_STEP(axis_did_move.w, false)
34933492
);
34943493

3494+
TERN_(I2S_STEPPER_STREAM, i2s_push_sample());
3495+
34953496
// Begin waiting for the minimum pulse duration
34963497
START_TIMED_PULSE();
34973498

@@ -3533,6 +3534,12 @@ void Stepper::report_positions() {
35333534
U_APPLY_STEP(!STEP_STATE_U, false), V_APPLY_STEP(!STEP_STATE_V, false), W_APPLY_STEP(!STEP_STATE_W, false)
35343535
);
35353536

3537+
// Check endstops on every step
3538+
IF_DISABLED(ENDSTOP_INTERRUPTS_FEATURE, endstops.update());
3539+
3540+
// Also handle babystepping here
3541+
TERN_(BABYSTEPPING, if (babystep.has_steps()) babystepping_isr());
3542+
35363543
} // Stepper::ftMotion_stepper
35373544

35383545
void Stepper::ftMotion_blockQueueUpdate() {

Marlin/src/pins/esp32/pins_ENWI_ESPNP.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@
3434
//
3535
// I2S (steppers & other output-only pins)
3636
//
37-
#define I2S_STEPPER_STREAM
37+
#ifndef I2S_STEPPER_STREAM
38+
#define I2S_STEPPER_STREAM
39+
#endif
3840
#if ENABLED(I2S_STEPPER_STREAM)
3941
#define I2S_WS 17
4042
#define I2S_BCK 22

Marlin/src/pins/esp32/pins_ESP32.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@
3232
//
3333
// I2S (steppers & other output-only pins)
3434
//
35-
#define I2S_STEPPER_STREAM
35+
#ifndef I2S_STEPPER_STREAM
36+
#define I2S_STEPPER_STREAM
37+
#endif
3638
#if ENABLED(I2S_STEPPER_STREAM)
3739
#define I2S_WS 25
3840
#define I2S_BCK 26

Marlin/src/pins/esp32/pins_MKS_TINYBEE.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@
5656
//
5757
// Enable I2S stepper stream
5858
//
59-
#define I2S_STEPPER_STREAM
59+
#ifndef I2S_STEPPER_STREAM
60+
#define I2S_STEPPER_STREAM
61+
#endif
6062
#if ENABLED(I2S_STEPPER_STREAM)
6163
#define I2S_WS 26
6264
#define I2S_BCK 25

Marlin/src/pins/esp32/pins_MM_JOKER.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,9 @@
8585
//
8686
// Enable I2S stepper stream
8787
//
88-
#define I2S_STEPPER_STREAM
88+
#ifndef I2S_STEPPER_STREAM
89+
#define I2S_STEPPER_STREAM
90+
#endif
8991
#if ENABLED(I2S_STEPPER_STREAM)
9092
#define I2S_WS 26
9193
#define I2S_BCK 25

Marlin/src/pins/esp32/pins_MRR_ESPE.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@
5151
//
5252
// Enable I2S stepper stream
5353
//
54-
#define I2S_STEPPER_STREAM
54+
#ifndef I2S_STEPPER_STREAM
55+
#define I2S_STEPPER_STREAM
56+
#endif
5557
#if ENABLED(I2S_STEPPER_STREAM)
5658
#define I2S_WS 26
5759
#define I2S_BCK 25

Marlin/src/pins/esp32/pins_RESP32_CUSTOM.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,6 @@
3434
//
3535
// I2S (steppers & other output-only pins)
3636
//
37-
#define I2S_STEPPER_STREAM
37+
#ifndef I2S_STEPPER_STREAM
38+
#define I2S_STEPPER_STREAM
39+
#endif

0 commit comments

Comments
 (0)