🧑‍💻 FxdTiCtrl => FTMotion

This commit is contained in:
Scott Lahteine 2023-10-12 09:44:46 -05:00
parent a7a3abb9bf
commit e7e77d9612
12 changed files with 186 additions and 205 deletions

View file

@ -862,7 +862,7 @@ void idle(const bool no_stepper_sleep/*=false*/) {
TERN_(HAS_TFT_LVGL_UI, LV_TASK_HANDLER());
// Manage Fixed-time Motion Control
TERN_(FT_MOTION, fxdTiCtrl.loop());
TERN_(FT_MOTION, ftMotion.loop());
IDLE_DONE:
TERN_(MARLIN_DEV_MODE, idle_depth--);
@ -1632,7 +1632,7 @@ void setup() {
#endif
#if ENABLED(FT_MOTION)
SETUP_RUN(fxdTiCtrl.init());
SETUP_RUN(ftMotion.init());
#endif
marlin_state = MF_RUNNING;

View file

@ -29,13 +29,13 @@
void say_shaping() {
// FT Enabled
SERIAL_ECHO_TERNARY(fxdTiCtrl.cfg.mode, "Fixed-Time Motion ", "en", "dis", "abled");
SERIAL_ECHO_TERNARY(ftMotion.cfg.mode, "Fixed-Time Motion ", "en", "dis", "abled");
// FT Shaping
#if HAS_X_AXIS
if (fxdTiCtrl.cfg.mode > ftMotionMode_ENABLED) {
if (ftMotion.cfg.mode > ftMotionMode_ENABLED) {
SERIAL_ECHOPGM(" with ");
switch (fxdTiCtrl.cfg.mode) {
switch (ftMotion.cfg.mode) {
default: break;
case ftMotionMode_ZV: SERIAL_ECHOPGM("ZV"); break;
case ftMotionMode_ZVD: SERIAL_ECHOPGM("ZVD"); break;
@ -51,15 +51,15 @@ void say_shaping() {
#endif
SERIAL_ECHOLNPGM(".");
const bool z_based = TERN0(HAS_DYNAMIC_FREQ_MM, fxdTiCtrl.cfg.dynFreqMode == dynFreqMode_Z_BASED),
g_based = TERN0(HAS_DYNAMIC_FREQ_G, fxdTiCtrl.cfg.dynFreqMode == dynFreqMode_MASS_BASED),
const bool z_based = TERN0(HAS_DYNAMIC_FREQ_MM, ftMotion.cfg.dynFreqMode == dynFreqMode_Z_BASED),
g_based = TERN0(HAS_DYNAMIC_FREQ_G, ftMotion.cfg.dynFreqMode == dynFreqMode_MASS_BASED),
dynamic = z_based || g_based;
// FT Dynamic Frequency Mode
if (fxdTiCtrl.cfg.modeHasShaper()) {
if (ftMotion.cfg.modeHasShaper()) {
#if HAS_DYNAMIC_FREQ
SERIAL_ECHOPGM("Dynamic Frequency Mode ");
switch (fxdTiCtrl.cfg.dynFreqMode) {
switch (ftMotion.cfg.dynFreqMode) {
default:
case dynFreqMode_DISABLED: SERIAL_ECHOPGM("disabled"); break;
#if HAS_DYNAMIC_FREQ_MM
@ -74,32 +74,32 @@ void say_shaping() {
#if HAS_X_AXIS
SERIAL_ECHO_TERNARY(dynamic, "X/A ", "base dynamic", "static", " compensator frequency: ");
SERIAL_ECHO(p_float_t(fxdTiCtrl.cfg.baseFreq[X_AXIS], 2), F("Hz"));
SERIAL_ECHO(p_float_t(ftMotion.cfg.baseFreq[X_AXIS], 2), F("Hz"));
#if HAS_DYNAMIC_FREQ
if (dynamic) SERIAL_ECHO(" scaling: ", p_float_t(fxdTiCtrl.cfg.dynFreqK[X_AXIS], 8), F("Hz/"), z_based ? F("mm") : F("g"));
if (dynamic) SERIAL_ECHO(" scaling: ", p_float_t(ftMotion.cfg.dynFreqK[X_AXIS], 8), F("Hz/"), z_based ? F("mm") : F("g"));
#endif
SERIAL_EOL();
#endif
#if HAS_Y_AXIS
SERIAL_ECHO_TERNARY(dynamic, "Y/B ", "base dynamic", "static", " compensator frequency: ");
SERIAL_ECHO(p_float_t(fxdTiCtrl.cfg.baseFreq[Y_AXIS], 2), F(" Hz"));
SERIAL_ECHO(p_float_t(ftMotion.cfg.baseFreq[Y_AXIS], 2), F(" Hz"));
#if HAS_DYNAMIC_FREQ
if (dynamic) SERIAL_ECHO(F(" scaling: "), p_float_t(fxdTiCtrl.cfg.dynFreqK[Y_AXIS], 8), F("Hz/"), z_based ? F("mm") : F("g"));
if (dynamic) SERIAL_ECHO(F(" scaling: "), p_float_t(ftMotion.cfg.dynFreqK[Y_AXIS], 8), F("Hz/"), z_based ? F("mm") : F("g"));
#endif
SERIAL_EOL();
#endif
}
#if HAS_EXTRUDERS
SERIAL_ECHO_TERNARY(fxdTiCtrl.cfg.linearAdvEna, "Linear Advance ", "en", "dis", "abled");
SERIAL_ECHOLN(F(". Gain: "), p_float_t(fxdTiCtrl.cfg.linearAdvK, 5));
SERIAL_ECHO_TERNARY(ftMotion.cfg.linearAdvEna, "Linear Advance ", "en", "dis", "abled");
SERIAL_ECHOLN(F(". Gain: "), p_float_t(ftMotion.cfg.linearAdvK, 5));
#endif
}
void GcodeSuite::M493_report(const bool forReplay/*=true*/) {
report_heading_etc(forReplay, F(STR_FT_MOTION));
const ft_config_t &c = fxdTiCtrl.cfg;
const ft_config_t &c = ftMotion.cfg;
SERIAL_ECHOPGM(" M493 S", c.mode);
#if HAS_X_AXIS
SERIAL_ECHOPGM(" A", c.baseFreq[X_AXIS]);
@ -160,7 +160,7 @@ void GcodeSuite::M493() {
// Parse 'S' mode parameter.
if (parser.seenval('S')) {
const ftMotionMode_t oldmm = fxdTiCtrl.cfg.mode,
const ftMotionMode_t oldmm = ftMotion.cfg.mode,
newmm = (ftMotionMode_t)parser.value_byte();
if (newmm != oldmm) {
@ -179,7 +179,7 @@ void GcodeSuite::M493() {
#endif
case ftMotionMode_DISABLED:
case ftMotionMode_ENABLED:
fxdTiCtrl.cfg.mode = newmm;
ftMotion.cfg.mode = newmm;
flag.report_h = true;
if (oldmm == ftMotionMode_DISABLED) flag.reset_ft = true;
break;
@ -192,7 +192,7 @@ void GcodeSuite::M493() {
// Pressure control (linear advance) parameter.
if (parser.seen('P')) {
const bool val = parser.value_bool();
fxdTiCtrl.cfg.linearAdvEna = val;
ftMotion.cfg.linearAdvEna = val;
SERIAL_ECHO_TERNARY(val, "Linear Advance ", "en", "dis", "abled.\n");
}
@ -200,7 +200,7 @@ void GcodeSuite::M493() {
if (parser.seenval('K')) {
const float val = parser.value_float();
if (val >= 0.0f) {
fxdTiCtrl.cfg.linearAdvK = val;
ftMotion.cfg.linearAdvK = val;
flag.report_h = true;
}
else // Value out of range.
@ -213,22 +213,22 @@ void GcodeSuite::M493() {
// Dynamic frequency mode parameter.
if (parser.seenval('D')) {
if (fxdTiCtrl.cfg.modeHasShaper()) {
if (ftMotion.cfg.modeHasShaper()) {
const dynFreqMode_t val = dynFreqMode_t(parser.value_byte());
switch (val) {
case dynFreqMode_DISABLED:
fxdTiCtrl.cfg.dynFreqMode = val;
ftMotion.cfg.dynFreqMode = val;
flag.report_h = true;
break;
#if HAS_DYNAMIC_FREQ_MM
case dynFreqMode_Z_BASED:
fxdTiCtrl.cfg.dynFreqMode = val;
ftMotion.cfg.dynFreqMode = val;
flag.report_h = true;
break;
#endif
#if HAS_DYNAMIC_FREQ_G
case dynFreqMode_MASS_BASED:
fxdTiCtrl.cfg.dynFreqMode = val;
ftMotion.cfg.dynFreqMode = val;
flag.report_h = true;
break;
#endif
@ -243,8 +243,8 @@ void GcodeSuite::M493() {
}
const bool modeUsesDynFreq = (
TERN0(HAS_DYNAMIC_FREQ_MM, fxdTiCtrl.cfg.dynFreqMode == dynFreqMode_Z_BASED)
|| TERN0(HAS_DYNAMIC_FREQ_G, fxdTiCtrl.cfg.dynFreqMode == dynFreqMode_MASS_BASED)
TERN0(HAS_DYNAMIC_FREQ_MM, ftMotion.cfg.dynFreqMode == dynFreqMode_Z_BASED)
|| TERN0(HAS_DYNAMIC_FREQ_G, ftMotion.cfg.dynFreqMode == dynFreqMode_MASS_BASED)
);
#endif // HAS_DYNAMIC_FREQ
@ -253,11 +253,11 @@ void GcodeSuite::M493() {
// Parse frequency parameter (X axis).
if (parser.seenval('A')) {
if (fxdTiCtrl.cfg.modeHasShaper()) {
if (ftMotion.cfg.modeHasShaper()) {
const float val = parser.value_float();
// TODO: Frequency minimum is dependent on the shaper used; the above check isn't always correct.
if (WITHIN(val, FTM_MIN_SHAPE_FREQ, (FTM_FS) / 2)) {
fxdTiCtrl.cfg.baseFreq[X_AXIS] = val;
ftMotion.cfg.baseFreq[X_AXIS] = val;
flag.update_n = flag.reset_ft = flag.report_h = true;
}
else // Frequency out of range.
@ -271,7 +271,7 @@ void GcodeSuite::M493() {
// Parse frequency scaling parameter (X axis).
if (parser.seenval('F')) {
if (modeUsesDynFreq) {
fxdTiCtrl.cfg.dynFreqK[X_AXIS] = parser.value_float();
ftMotion.cfg.dynFreqK[X_AXIS] = parser.value_float();
flag.report_h = true;
}
else
@ -285,10 +285,10 @@ void GcodeSuite::M493() {
// Parse frequency parameter (Y axis).
if (parser.seenval('B')) {
if (fxdTiCtrl.cfg.modeHasShaper()) {
if (ftMotion.cfg.modeHasShaper()) {
const float val = parser.value_float();
if (WITHIN(val, FTM_MIN_SHAPE_FREQ, (FTM_FS) / 2)) {
fxdTiCtrl.cfg.baseFreq[Y_AXIS] = val;
ftMotion.cfg.baseFreq[Y_AXIS] = val;
flag.update_n = flag.reset_ft = flag.report_h = true;
}
else // Frequency out of range.
@ -302,7 +302,7 @@ void GcodeSuite::M493() {
// Parse frequency scaling parameter (Y axis).
if (parser.seenval('H')) {
if (modeUsesDynFreq) {
fxdTiCtrl.cfg.dynFreqK[Y_AXIS] = parser.value_float();
ftMotion.cfg.dynFreqK[Y_AXIS] = parser.value_float();
flag.report_h = true;
}
else
@ -313,10 +313,10 @@ void GcodeSuite::M493() {
#endif // HAS_Y_AXIS
#if HAS_X_AXIS
if (flag.update_n) fxdTiCtrl.refreshShapingN();
if (flag.update_a) fxdTiCtrl.updateShapingA();
if (flag.update_n) ftMotion.refreshShapingN();
if (flag.update_a) ftMotion.updateShapingA();
#endif
if (flag.reset_ft) fxdTiCtrl.reset();
if (flag.reset_ft) ftMotion.reset();
if (flag.report_h) say_shaping();
}

View file

@ -319,13 +319,13 @@ void menu_move() {
#include "../../gcode/gcode.h"
void ftm_menu_setShaping(const ftMotionMode_t s) {
fxdTiCtrl.cfg.mode = s;
fxdTiCtrl.refreshShapingN();
ftMotion.cfg.mode = s;
ftMotion.refreshShapingN();
ui.go_back();
}
inline void menu_ftm_mode() {
const ftMotionMode_t mode = fxdTiCtrl.cfg.mode;
const ftMotionMode_t mode = ftMotion.cfg.mode;
START_MENU();
BACK_ITEM(MSG_FIXED_TIME_MOTION);
@ -349,17 +349,17 @@ void menu_move() {
#if HAS_DYNAMIC_FREQ
inline void menu_ftm_dyn_mode() {
const dynFreqMode_t dmode = fxdTiCtrl.cfg.dynFreqMode;
const dynFreqMode_t dmode = ftMotion.cfg.dynFreqMode;
START_MENU();
BACK_ITEM(MSG_FIXED_TIME_MOTION);
if (dmode != dynFreqMode_DISABLED) ACTION_ITEM(MSG_LCD_OFF, []{ fxdTiCtrl.cfg.dynFreqMode = dynFreqMode_DISABLED; ui.go_back(); });
if (dmode != dynFreqMode_DISABLED) ACTION_ITEM(MSG_LCD_OFF, []{ ftMotion.cfg.dynFreqMode = dynFreqMode_DISABLED; ui.go_back(); });
#if HAS_DYNAMIC_FREQ_MM
if (dmode != dynFreqMode_Z_BASED) ACTION_ITEM(MSG_FTM_Z_BASED, []{ fxdTiCtrl.cfg.dynFreqMode = dynFreqMode_Z_BASED; ui.go_back(); });
if (dmode != dynFreqMode_Z_BASED) ACTION_ITEM(MSG_FTM_Z_BASED, []{ ftMotion.cfg.dynFreqMode = dynFreqMode_Z_BASED; ui.go_back(); });
#endif
#if HAS_DYNAMIC_FREQ_G
if (dmode != dynFreqMode_MASS_BASED) ACTION_ITEM(MSG_FTM_MASS_BASED, []{ fxdTiCtrl.cfg.dynFreqMode = dynFreqMode_MASS_BASED; ui.go_back(); });
if (dmode != dynFreqMode_MASS_BASED) ACTION_ITEM(MSG_FTM_MASS_BASED, []{ ftMotion.cfg.dynFreqMode = dynFreqMode_MASS_BASED; ui.go_back(); });
#endif
END_MENU();
@ -368,7 +368,7 @@ void menu_move() {
#endif // HAS_DYNAMIC_FREQ
void menu_ft_motion() {
ft_config_t &c = fxdTiCtrl.cfg;
ft_config_t &c = ftMotion.cfg;
FSTR_P ftmode;
switch (c.mode) {
@ -403,16 +403,16 @@ void menu_move() {
if (c.modeHasShaper()) {
#if HAS_X_AXIS
EDIT_ITEM_FAST_N(float42_52, X_AXIS, MSG_FTM_BASE_FREQ_N, &c.baseFreq[X_AXIS], FTM_MIN_SHAPE_FREQ, (FTM_FS) / 2, fxdTiCtrl.refreshShapingN);
EDIT_ITEM_FAST_N(float42_52, X_AXIS, MSG_FTM_BASE_FREQ_N, &c.baseFreq[X_AXIS], FTM_MIN_SHAPE_FREQ, (FTM_FS) / 2, ftMotion.refreshShapingN);
#endif
#if HAS_Y_AXIS
EDIT_ITEM_FAST_N(float42_52, Y_AXIS, MSG_FTM_BASE_FREQ_N, &c.baseFreq[Y_AXIS], FTM_MIN_SHAPE_FREQ, (FTM_FS) / 2, fxdTiCtrl.refreshShapingN);
EDIT_ITEM_FAST_N(float42_52, Y_AXIS, MSG_FTM_BASE_FREQ_N, &c.baseFreq[Y_AXIS], FTM_MIN_SHAPE_FREQ, (FTM_FS) / 2, ftMotion.refreshShapingN);
#endif
EDIT_ITEM_FAST(float42_52, MSG_FTM_ZETA, &c.zeta, 0.0f, 1.0f, fxdTiCtrl.refreshShapingN);
EDIT_ITEM_FAST(float42_52, MSG_FTM_ZETA, &c.zeta, 0.0f, 1.0f, ftMotion.refreshShapingN);
if (WITHIN(c.mode, ftMotionMode_EI, ftMotionMode_3HEI))
EDIT_ITEM_FAST(float42_52, MSG_FTM_VTOL, &c.vtol, 0.0f, 1.0f, fxdTiCtrl.refreshShapingN);
EDIT_ITEM_FAST(float42_52, MSG_FTM_VTOL, &c.vtol, 0.0f, 1.0f, ftMotion.refreshShapingN);
#if HAS_DYNAMIC_FREQ
SUBMENU(MSG_FTM_DYN_MODE, menu_ftm_dyn_mode);

View file

@ -27,7 +27,7 @@
#include "ft_motion.h"
#include "stepper.h" // Access stepper block queue function and abort status.
FxdTiCtrl fxdTiCtrl;
FTMotion ftMotion;
#if !HAS_X_AXIS
static_assert(FTM_DEFAULT_MODE == ftMotionMode_ZV, "ftMotionMode_ZV requires at least one linear axis.");
@ -50,66 +50,67 @@ FxdTiCtrl fxdTiCtrl;
// Public variables.
ft_config_t FxdTiCtrl::cfg;
ft_command_t FxdTiCtrl::stepperCmdBuff[FTM_STEPPERCMD_BUFF_SIZE] = {0U}; // Buffer of stepper commands.
hal_timer_t FxdTiCtrl::stepperCmdBuff_StepRelativeTi[FTM_STEPPERCMD_BUFF_SIZE] = {0U}; // Buffer of the stepper command timing.
uint8_t FxdTiCtrl::stepperCmdBuff_ApplyDir[FTM_STEPPERCMD_DIR_SIZE] = {0U}; // Buffer of whether DIR needs to be updated.
uint32_t FxdTiCtrl::stepperCmdBuff_produceIdx = 0, // Index of next stepper command write to the buffer.
FxdTiCtrl::stepperCmdBuff_consumeIdx = 0; // Index of next stepper command read from the buffer.
ft_config_t FTMotion::cfg;
bool FTMotion::busy; // = false
ft_command_t FTMotion::stepperCmdBuff[FTM_STEPPERCMD_BUFF_SIZE] = {0U}; // Buffer of stepper commands.
hal_timer_t FTMotion::stepperCmdBuff_StepRelativeTi[FTM_STEPPERCMD_BUFF_SIZE] = {0U}; // Buffer of the stepper command timing.
uint8_t FTMotion::stepperCmdBuff_ApplyDir[FTM_STEPPERCMD_DIR_SIZE] = {0U}; // Buffer of whether DIR needs to be updated.
uint32_t FTMotion::stepperCmdBuff_produceIdx = 0, // Index of next stepper command write to the buffer.
FTMotion::stepperCmdBuff_consumeIdx = 0; // Index of next stepper command read from the buffer.
bool FxdTiCtrl::sts_stepperBusy = false; // The stepper buffer has items and is in use.
bool FTMotion::sts_stepperBusy = false; // The stepper buffer has items and is in use.
// Private variables.
// NOTE: These are sized for Ulendo FBS use.
xyze_trajectory_t FxdTiCtrl::traj; // = {0.0f} Storage for fixed-time-based trajectory.
xyze_trajectoryMod_t FxdTiCtrl::trajMod; // = {0.0f} Storage for modified fixed-time-based trajectory.
xyze_trajectory_t FTMotion::traj; // = {0.0f} Storage for fixed-time-based trajectory.
xyze_trajectoryMod_t FTMotion::trajMod; // = {0.0f} Storage for modified fixed-time-based trajectory.
block_t* FxdTiCtrl::current_block_cpy = nullptr; // Pointer to current block being processed.
bool FxdTiCtrl::blockProcRdy = false, // Indicates a block is ready to be processed.
FxdTiCtrl::blockProcRdy_z1 = false, // Storage for the previous indicator.
FxdTiCtrl::blockProcDn = false; // Indicates current block is done being processed.
bool FxdTiCtrl::batchRdy = false; // Indicates a batch of the fixed time trajectory
// has been generated, is now available in the upper -
// half of traj.x[], y, z ... e vectors, and is ready to be
// post processed, if applicable, then interpolated.
bool FxdTiCtrl::batchRdyForInterp = false; // Indicates the batch is done being post processed,
// if applicable, and is ready to be converted to step commands.
bool FxdTiCtrl::runoutEna = false; // True if runout of the block hasn't been done and is allowed.
bool FxdTiCtrl::runout = false; // Indicates if runout is in progress.
block_t* FTMotion::current_block_cpy = nullptr; // Pointer to current block being processed.
bool FTMotion::blockProcRdy = false, // Indicates a block is ready to be processed.
FTMotion::blockProcRdy_z1 = false, // Storage for the previous indicator.
FTMotion::blockProcDn = false; // Indicates current block is done being processed.
bool FTMotion::batchRdy = false; // Indicates a batch of the fixed time trajectory
// has been generated, is now available in the upper -
// half of traj.x[], y, z ... e vectors, and is ready to be
// post processed, if applicable, then interpolated.
bool FTMotion::batchRdyForInterp = false; // Indicates the batch is done being post processed,
// if applicable, and is ready to be converted to step commands.
bool FTMotion::runoutEna = false; // True if runout of the block hasn't been done and is allowed.
bool FTMotion::runout = false; // Indicates if runout is in progress.
// Trapezoid data variables.
xyze_pos_t FxdTiCtrl::startPosn, // (mm) Start position of block
FxdTiCtrl::endPosn_prevBlock = { 0.0f }; // (mm) End position of previous block
xyze_float_t FxdTiCtrl::ratio; // (ratio) Axis move ratio of block
float FxdTiCtrl::accel_P, // Acceleration prime of block. [mm/sec/sec]
FxdTiCtrl::decel_P, // Deceleration prime of block. [mm/sec/sec]
FxdTiCtrl::F_P, // Feedrate prime of block. [mm/sec]
FxdTiCtrl::f_s, // Starting feedrate of block. [mm/sec]
FxdTiCtrl::s_1e, // Position after acceleration phase of block.
FxdTiCtrl::s_2e; // Position after acceleration and coasting phase of block.
xyze_pos_t FTMotion::startPosn, // (mm) Start position of block
FTMotion::endPosn_prevBlock = { 0.0f }; // (mm) End position of previous block
xyze_float_t FTMotion::ratio; // (ratio) Axis move ratio of block
float FTMotion::accel_P, // Acceleration prime of block. [mm/sec/sec]
FTMotion::decel_P, // Deceleration prime of block. [mm/sec/sec]
FTMotion::F_P, // Feedrate prime of block. [mm/sec]
FTMotion::f_s, // Starting feedrate of block. [mm/sec]
FTMotion::s_1e, // Position after acceleration phase of block.
FTMotion::s_2e; // Position after acceleration and coasting phase of block.
uint32_t FxdTiCtrl::N1, // Number of data points in the acceleration phase.
FxdTiCtrl::N2, // Number of data points in the coasting phase.
FxdTiCtrl::N3; // Number of data points in the deceleration phase.
uint32_t FTMotion::N1, // Number of data points in the acceleration phase.
FTMotion::N2, // Number of data points in the coasting phase.
FTMotion::N3; // Number of data points in the deceleration phase.
uint32_t FxdTiCtrl::max_intervals; // Total number of data points that will be generated from block.
uint32_t FTMotion::max_intervals; // Total number of data points that will be generated from block.
// Make vector variables.
uint32_t FxdTiCtrl::makeVector_idx = 0, // Index of fixed time trajectory generation of the overall block.
FxdTiCtrl::makeVector_idx_z1 = 0, // Storage for the previously calculated index above.
FxdTiCtrl::makeVector_batchIdx = FTM_BATCH_SIZE; // Index of fixed time trajectory generation within the batch.
uint32_t FTMotion::makeVector_idx = 0, // Index of fixed time trajectory generation of the overall block.
FTMotion::makeVector_idx_z1 = 0, // Storage for the previously calculated index above.
FTMotion::makeVector_batchIdx = FTM_BATCH_SIZE; // Index of fixed time trajectory generation within the batch.
// Interpolation variables.
xyze_long_t FxdTiCtrl::steps = { 0 }; // Step count accumulator.
xyze_stepDir_t FxdTiCtrl::dirState = LOGICAL_AXIS_ARRAY_1(stepDirState_NOT_SET); // Memory of the currently set step direction of the axis.
xyze_long_t FTMotion::steps = { 0 }; // Step count accumulator.
xyze_stepDir_t FTMotion::dirState = LOGICAL_AXIS_ARRAY_1(stepDirState_NOT_SET); // Memory of the currently set step direction of the axis.
uint32_t FxdTiCtrl::interpIdx = 0, // Index of current data point being interpolated.
FxdTiCtrl::interpIdx_z1 = 0; // Storage for the previously calculated index above.
hal_timer_t FxdTiCtrl::nextStepTicks = FTM_MIN_TICKS; // Accumulator for the next step time (in ticks).
uint32_t FTMotion::interpIdx = 0, // Index of current data point being interpolated.
FTMotion::interpIdx_z1 = 0; // Storage for the previously calculated index above.
hal_timer_t FTMotion::nextStepTicks = FTM_MIN_TICKS; // Accumulator for the next step time (in ticks).
// Shaping variables.
#if HAS_X_AXIS
FxdTiCtrl::shaping_t FxdTiCtrl::shaping = {
FTMotion::shaping_t FTMotion::shaping = {
0, 0,
x:{ { 0.0f }, { 0.0f }, { 0 } }, // d_zi, Ai, Ni
#if HAS_Y_AXIS
@ -120,8 +121,8 @@ hal_timer_t FxdTiCtrl::nextStepTicks = FTM_MIN_TICKS; // Accumulator for the nex
#if HAS_EXTRUDERS
// Linear advance variables.
float FxdTiCtrl::e_raw_z1 = 0.0f; // (ms) Unit delay of raw extruder position.
float FxdTiCtrl::e_advanced_z1 = 0.0f; // (ms) Unit delay of advanced extruder position.
float FTMotion::e_raw_z1 = 0.0f; // (ms) Unit delay of raw extruder position.
float FTMotion::e_advanced_z1 = 0.0f; // (ms) Unit delay of advanced extruder position.
#endif
constexpr uint32_t last_batchIdx = (FTM_WINDOW_SIZE) - (FTM_BATCH_SIZE);
@ -133,15 +134,15 @@ constexpr uint32_t last_batchIdx = (FTM_WINDOW_SIZE) - (FTM_BATCH_SIZE);
// Public functions.
// Sets controller states to begin processing a block.
void FxdTiCtrl::startBlockProc(block_t * const current_block) {
void FTMotion::startBlockProc(block_t * const current_block) {
current_block_cpy = current_block;
blockProcRdy = true;
blockProcDn = false;
runoutEna = true;
}
// Moves any free data points to the stepper buffer even if a full batch isn't ready.
void FxdTiCtrl::runoutBlock() {
// Move any free data points to the stepper buffer even if a full batch isn't ready.
void FTMotion::runoutBlock() {
if (runoutEna && !batchRdy) { // If the window is full already (block intervals was a multiple of
// the batch size), or runout is not enabled, no runout is needed.
@ -170,7 +171,7 @@ void FxdTiCtrl::runoutBlock() {
}
// Controller main, to be invoked from non-isr task.
void FxdTiCtrl::loop() {
void FTMotion::loop() {
if (!cfg.mode) return;
@ -188,7 +189,7 @@ void FxdTiCtrl::loop() {
}
// Planner processing and block conversion.
if (!blockProcRdy && !runout) stepper.fxdTiCtrl_BlockQueueUpdate();
if (!blockProcRdy && !runout) stepper.ftMotion_BlockQueueUpdate();
if (blockProcRdy) {
if (!blockProcRdy_z1) loadBlockData(current_block_cpy); // One-shot.
@ -264,7 +265,7 @@ void FxdTiCtrl::loop() {
}
// Report busy status to planner.
planner.fxdTiCtrl_busy = (sts_stepperBusy || ((!blockProcDn && blockProcRdy) || batchRdy || batchRdyForInterp || runoutEna));
busy = (sts_stepperBusy || ((!blockProcDn && blockProcRdy) || batchRdy || batchRdyForInterp || runoutEna));
blockProcRdy_z1 = blockProcRdy;
makeVector_idx_z1 = makeVector_idx;
@ -276,7 +277,7 @@ void FxdTiCtrl::loop() {
// Refresh the gains used by shaping functions.
// To be called on init or mode or zeta change.
void FxdTiCtrl::Shaping::updateShapingA(const_float_t zeta/*=cfg.zeta*/, const_float_t vtol/*=cfg.vtol*/) {
void FTMotion::Shaping::updateShapingA(const_float_t zeta/*=cfg.zeta*/, const_float_t vtol/*=cfg.vtol*/) {
const float K = exp(-zeta * M_PI / sqrt(1.0f - sq(zeta))),
K2 = sq(K);
@ -345,14 +346,14 @@ void FxdTiCtrl::loop() {
#endif
}
void FxdTiCtrl::updateShapingA(const_float_t zeta/*=cfg.zeta*/, const_float_t vtol/*=cfg.vtol*/) {
void FTMotion::updateShapingA(const_float_t zeta/*=cfg.zeta*/, const_float_t vtol/*=cfg.vtol*/) {
shaping.updateShapingA(zeta, vtol);
}
// Refresh the indices used by shaping functions.
// To be called when frequencies change.
void FxdTiCtrl::AxisShaping::updateShapingN(const_float_t f, const_float_t df) {
void FTMotion::AxisShaping::updateShapingN(const_float_t f, const_float_t df) {
// Protections omitted for DBZ and for index exceeding array length.
switch (cfg.mode) {
case ftMotionMode_ZV:
@ -382,7 +383,7 @@ void FxdTiCtrl::loop() {
}
}
void FxdTiCtrl::updateShapingN(const_float_t xf OPTARG(HAS_Y_AXIS, const_float_t yf), const_float_t zeta/*=cfg.zeta*/) {
void FTMotion::updateShapingN(const_float_t xf OPTARG(HAS_Y_AXIS, const_float_t yf), const_float_t zeta/*=cfg.zeta*/) {
const float df = sqrt(1.0f - sq(zeta));
shaping.x.updateShapingN(xf, df);
TERN_(HAS_Y_AXIS, shaping.y.updateShapingN(yf, df));
@ -391,12 +392,12 @@ void FxdTiCtrl::loop() {
#endif // HAS_X_AXIS
// Reset all trajectory processing variables.
void FxdTiCtrl::reset() {
void FTMotion::reset() {
stepperCmdBuff_produceIdx = stepperCmdBuff_consumeIdx = 0;
traj.reset(); // Reset trajectory history
trajMod.reset(); // Reset modified trajectory history
traj.reset(); // Reset trajectory history
trajMod.reset(); // Reset modified trajectory history
blockProcRdy = blockProcRdy_z1 = blockProcDn = false;
batchRdy = batchRdyForInterp = false;
@ -424,13 +425,13 @@ void FxdTiCtrl::reset() {
// Private functions.
// Auxiliary function to get number of step commands in the buffer.
uint32_t FxdTiCtrl::stepperCmdBuffItems() {
uint32_t FTMotion::stepperCmdBuffItems() {
const uint32_t udiff = stepperCmdBuff_produceIdx - stepperCmdBuff_consumeIdx;
return stepperCmdBuff_produceIdx < stepperCmdBuff_consumeIdx ? (FTM_STEPPERCMD_BUFF_SIZE) + udiff : udiff;
}
// Initializes storage variables before startup.
void FxdTiCtrl::init() {
void FTMotion::init() {
#if HAS_X_AXIS
refreshShapingN();
updateShapingA();
@ -439,7 +440,7 @@ void FxdTiCtrl::init() {
}
// Loads / converts block data from planner to fixed-time control variables.
void FxdTiCtrl::loadBlockData(block_t * const current_block) {
void FTMotion::loadBlockData(block_t * const current_block) {
const float totalLength = current_block->millimeters,
oneOverLength = 1.0f / totalLength;
@ -489,6 +490,7 @@ void FxdTiCtrl::loadBlockData(block_t * const current_block) {
const float fdiff = feSqByTwoD - fsSqByTwoA, // (mm) Coasting distance if nominal speed is reached
odiff = oneby2a - oneby2d, // (i.e., oneby2a * 2) (mm/s) Change in speed for one second of acceleration
ldiff = totalLength - fdiff; // (mm) Distance to travel if nominal speed is reached
float T2 = (1.0f / F_n) * (ldiff - odiff * sq(F_n)); // (s) Coasting duration after nominal speed reached
if (T2 < 0.0f) {
T2 = 0.0f;
@ -496,7 +498,6 @@ void FxdTiCtrl::loadBlockData(block_t * const current_block) {
}
const float T1 = (F_n - f_s) / a, // (s) Accel Time = difference in feedrate over acceleration
T3 = (F_n - f_e) / a; // (s) Decel Time = difference in feedrate over acceleration
N1 = ceil(T1 * (FTM_FS)); // Accel datapoints based on Hz frequency
N2 = ceil(T2 * (FTM_FS)); // Coast
@ -536,7 +537,7 @@ void FxdTiCtrl::loadBlockData(block_t * const current_block) {
}
// Generate data points of the trajectory.
void FxdTiCtrl::makeVector() {
void FTMotion::makeVector() {
float accel_k = 0.0f; // (mm/s^2) Acceleration K factor
float tau = (makeVector_idx + 1) * (FTM_TS); // (s) Time since start of block
float dist = 0.0f; // (mm) Distance traveled
@ -653,7 +654,7 @@ void FxdTiCtrl::makeVector() {
}
// Interpolates single data point to stepper commands.
void FxdTiCtrl::convertToSteps(const uint32_t idx) {
void FTMotion::convertToSteps(const uint32_t idx) {
xyze_long_t err_P = { 0 };
//#define STEPS_ROUNDING

View file

@ -64,12 +64,13 @@ typedef struct FTConfig {
#endif
} ft_config_t;
class FxdTiCtrl {
class FTMotion {
public:
// Public variables
static ft_config_t cfg;
static bool busy;
static void set_defaults() {
cfg.mode = FTM_DEFAULT_MODE;
@ -77,8 +78,8 @@ class FxdTiCtrl {
TERN_(HAS_X_AXIS, cfg.baseFreq[X_AXIS] = FTM_SHAPING_DEFAULT_X_FREQ);
TERN_(HAS_Y_AXIS, cfg.baseFreq[Y_AXIS] = FTM_SHAPING_DEFAULT_Y_FREQ);
cfg.zeta = FTM_SHAPING_ZETA;
cfg.vtol = FTM_SHAPING_V_TOL;
cfg.zeta = FTM_SHAPING_ZETA; // Damping factor
cfg.vtol = FTM_SHAPING_V_TOL; // Vibration Level
#if HAS_DYNAMIC_FREQ
cfg.dynFreqMode = FTM_DEFAULT_DYNFREQ_MODE;
@ -114,7 +115,6 @@ class FxdTiCtrl {
static void runoutBlock(); // Move any free data points to the stepper buffer even if a full batch isn't ready.
static void loop(); // Controller main, to be invoked from non-isr task.
#if HAS_X_AXIS
// Refresh the gains used by shaping functions.
// To be called on init or mode or zeta change.
@ -168,6 +168,7 @@ class FxdTiCtrl {
static hal_timer_t nextStepTicks;
// Shaping variables.
#if HAS_X_AXIS
typedef struct AxisShaping {
@ -202,10 +203,10 @@ class FxdTiCtrl {
// Private methods
static uint32_t stepperCmdBuffItems();
static void loadBlockData(block_t * const current_block);
static void loadBlockData(block_t *const current_block);
static void makeVector();
static void convertToSteps(const uint32_t idx);
}; // class fxdTiCtrl
}; // class FTMotion
extern FxdTiCtrl fxdTiCtrl;
extern FTMotion ftMotion;

View file

@ -56,15 +56,9 @@ typedef struct XYZEval<stepDirState_t> xyze_stepDir_t;
enum {
LIST_N(DOUBLE(LOGICAL_AXES),
FT_BIT_DIR_E, FT_BIT_STEP_E,
FT_BIT_DIR_X, FT_BIT_STEP_X,
FT_BIT_DIR_Y, FT_BIT_STEP_Y,
FT_BIT_DIR_Z, FT_BIT_STEP_Z,
FT_BIT_DIR_I, FT_BIT_STEP_I,
FT_BIT_DIR_J, FT_BIT_STEP_J,
FT_BIT_DIR_K, FT_BIT_STEP_K,
FT_BIT_DIR_U, FT_BIT_STEP_U,
FT_BIT_DIR_V, FT_BIT_STEP_V,
FT_BIT_DIR_W, FT_BIT_STEP_W
FT_BIT_DIR_X, FT_BIT_STEP_X, FT_BIT_DIR_Y, FT_BIT_STEP_Y, FT_BIT_DIR_Z, FT_BIT_STEP_Z,
FT_BIT_DIR_I, FT_BIT_STEP_I, FT_BIT_DIR_J, FT_BIT_STEP_J, FT_BIT_DIR_K, FT_BIT_STEP_K,
FT_BIT_DIR_U, FT_BIT_STEP_U, FT_BIT_DIR_V, FT_BIT_STEP_V, FT_BIT_DIR_W, FT_BIT_STEP_W
),
FT_BIT_COUNT
};

View file

@ -2100,12 +2100,12 @@ void prepare_line_to_destination() {
struct OnExit {
ftMotionMode_t oldmm;
OnExit() {
oldmm = fxdTiCtrl.cfg.mode;
fxdTiCtrl.cfg.mode = ftMotionMode_DISABLED;
oldmm = ftMotion.cfg.mode;
ftMotion.cfg.mode = ftMotionMode_DISABLED;
}
~OnExit() {
fxdTiCtrl.cfg.mode = oldmm;
fxdTiCtrl.init();
ftMotion.cfg.mode = oldmm;
ftMotion.init();
}
} on_exit;
#endif

View file

@ -229,10 +229,6 @@ float Planner::previous_nominal_speed;
int32_t Planner::xy_freq_min_interval_us = LROUND(1000000.0f / (XY_FREQUENCY_LIMIT));
#endif
#if ENABLED(FT_MOTION)
bool Planner::fxdTiCtrl_busy = false;
#endif
#if ENABLED(LIN_ADVANCE)
float Planner::extruder_advance_K[DISTINCT_E]; // Initialized by settings.load()
#endif
@ -1692,7 +1688,7 @@ void Planner::quick_stop() {
// Restart the block delay for the first movement - As the queue was
// forced to empty, there's no risk the ISR will touch this.
delay_before_delivering = TERN_(FT_MOTION, fxdTiCtrl.cfg.mode ? BLOCK_DELAY_NONE :) BLOCK_DELAY_FOR_1ST_MOVE;
delay_before_delivering = TERN_(FT_MOTION, ftMotion.cfg.mode ? BLOCK_DELAY_NONE :) BLOCK_DELAY_FOR_1ST_MOVE;
TERN_(HAS_WIRED_LCD, clear_block_buffer_runtime()); // Clear the accumulated runtime
@ -1738,7 +1734,7 @@ bool Planner::busy() {
return (has_blocks_queued() || cleaning_buffer_counter
|| TERN0(EXTERNAL_CLOSED_LOOP_CONTROLLER, CLOSED_LOOP_WAITING())
|| TERN0(HAS_ZV_SHAPING, stepper.input_shaping_busy())
|| TERN0(FT_MOTION, fxdTiCtrl_busy)
|| TERN0(FT_MOTION, ftMotion.busy)
);
}
@ -1851,7 +1847,7 @@ bool Planner::_buffer_steps(const xyze_long_t &target
// As there are no queued movements, the Stepper ISR will not touch this
// variable, so there is no risk setting this here (but it MUST be done
// before the following line!!)
delay_before_delivering = TERN_(FT_MOTION, fxdTiCtrl.cfg.mode ? BLOCK_DELAY_NONE :) BLOCK_DELAY_FOR_1ST_MOVE;
delay_before_delivering = TERN_(FT_MOTION, ftMotion.cfg.mode ? BLOCK_DELAY_NONE :) BLOCK_DELAY_FOR_1ST_MOVE;
}
// Move buffer head
@ -2924,7 +2920,7 @@ void Planner::buffer_sync_block(const BlockFlagBit sync_flag/*=BLOCK_BIT_SYNC_PO
// As there are no queued movements, the Stepper ISR will not touch this
// variable, so there is no risk setting this here (but it MUST be done
// before the following line!!)
delay_before_delivering = TERN_(FT_MOTION, fxdTiCtrl.cfg.mode ? BLOCK_DELAY_NONE :) BLOCK_DELAY_FOR_1ST_MOVE;
delay_before_delivering = TERN_(FT_MOTION, ftMotion.cfg.mode ? BLOCK_DELAY_NONE :) BLOCK_DELAY_FOR_1ST_MOVE;
}
block_buffer_head = next_buffer_head;
@ -3217,7 +3213,7 @@ bool Planner::buffer_line(const xyze_pos_t &cart, const_feedRate_t fr_mm_s
// As there are no queued movements, the Stepper ISR will not touch this
// variable, so there is no risk setting this here (but it MUST be done
// before the following line!!)
delay_before_delivering = TERN_(FT_MOTION, fxdTiCtrl.cfg.mode ? BLOCK_DELAY_NONE :) BLOCK_DELAY_FOR_1ST_MOVE;
delay_before_delivering = TERN_(FT_MOTION, ftMotion.cfg.mode ? BLOCK_DELAY_NONE :) BLOCK_DELAY_FOR_1ST_MOVE;
}
// Move buffer head

View file

@ -529,10 +529,6 @@ class Planner {
}
#endif
#if ENABLED(FT_MOTION)
static bool fxdTiCtrl_busy;
#endif
private:
/**

View file

@ -612,7 +612,7 @@ typedef struct SettingsDataStruct {
// Fixed-Time Motion
//
#if ENABLED(FT_MOTION)
ft_config_t fxdTiCtrl_cfg; // M493
ft_config_t ftMotion_cfg; // M493
#endif
//
@ -1711,8 +1711,8 @@ void MarlinSettings::postprocess() {
// Fixed-Time Motion
//
#if ENABLED(FT_MOTION)
_FIELD_TEST(fxdTiCtrl_cfg);
EEPROM_WRITE(fxdTiCtrl.cfg);
_FIELD_TEST(ftMotion_cfg);
EEPROM_WRITE(ftMotion.cfg);
#endif
//
@ -2785,8 +2785,8 @@ void MarlinSettings::postprocess() {
// Fixed-Time Motion
//
#if ENABLED(FT_MOTION)
_FIELD_TEST(fxdTiCtrl_cfg);
EEPROM_READ(fxdTiCtrl.cfg);
_FIELD_TEST(ftMotion_cfg);
EEPROM_READ(ftMotion.cfg);
#endif
//
@ -3614,7 +3614,7 @@ void MarlinSettings::reset() {
//
// Fixed-Time Motion
//
TERN_(FT_MOTION, fxdTiCtrl.set_defaults());
TERN_(FT_MOTION, ftMotion.set_defaults());
//
// Nonlinear Extrusion

View file

@ -1492,11 +1492,14 @@ void Stepper::isr() {
uint8_t max_loops = 10;
#if ENABLED(FT_MOTION)
static bool fxdTiCtrl_stepCmdRdy = false; // Indicates a step command was loaded from the
// buffers and is ready to be output.
static bool fxdTiCtrl_applyDir = false; // Indicates the DIR output should be set.
static ft_command_t fxdTiCtrl_stepCmd = 0U; // Storage for the step command to be output.
static uint32_t fxdTiCtrl_nextAuxISR = 0U; // Storage for the next ISR of the auxilliary tasks.
static bool ftMotion_stepCmdRdy = false; // Indicates a step command was loaded from the
// buffers and is ready to be output.
static bool ftMotion_applyDir = false; // Indicates the DIR output should be set.
static ft_command_t ftMotion_stepCmd = 0U; // Storage for the step command to be output.
static uint32_t ftMotion_nextAuxISR = 0U; // Storage for the next ISR of the auxilliary tasks.
const bool using_ftMotion = ftMotion.cfg.mode;
#else
constexpr bool using_ftMotion = false;
#endif
// We need this variable here to be able to use it in the following loop
@ -1509,64 +1512,58 @@ void Stepper::isr() {
#if ENABLED(FT_MOTION)
// NOTE STEPPER_TIMER_RATE is equal to 2000000, not what VSCode shows
const bool using_fxtictrl = fxdTiCtrl.cfg.mode;
if (using_fxtictrl) {
if (using_ftMotion) {
if (!nextMainISR) {
if (abort_current_block) {
fxdTiCtrl_stepCmdRdy = false; // If a command was ready, cancel it.
fxdTiCtrl.sts_stepperBusy = false; // Set busy false to allow a reset.
ftMotion_stepCmdRdy = false; // If a command was ready, cancel it.
ftMotion.sts_stepperBusy = false; // Set busy false to allow a reset.
nextMainISR = 0.01f * (STEPPER_TIMER_RATE); // Come back in 10 msec.
}
else { // !(abort_current_block)
if (fxdTiCtrl_stepCmdRdy) {
fxdTiCtrl_stepper(fxdTiCtrl_applyDir, fxdTiCtrl_stepCmd);
fxdTiCtrl_stepCmdRdy = false;
if (ftMotion_stepCmdRdy) {
ftMotion_stepper(ftMotion_applyDir, ftMotion_stepCmd);
ftMotion_stepCmdRdy = false;
}
// Check if there is data in the buffers.
if (fxdTiCtrl.stepperCmdBuff_produceIdx != fxdTiCtrl.stepperCmdBuff_consumeIdx) {
if (ftMotion.stepperCmdBuff_produceIdx != ftMotion.stepperCmdBuff_consumeIdx) {
fxdTiCtrl.sts_stepperBusy = true;
ftMotion.sts_stepperBusy = true;
// "Pop" one command from the command buffer.
fxdTiCtrl_stepCmd = fxdTiCtrl.stepperCmdBuff[fxdTiCtrl.stepperCmdBuff_consumeIdx];
const uint8_t dir_index = fxdTiCtrl.stepperCmdBuff_consumeIdx >> 3,
dir_bit = fxdTiCtrl.stepperCmdBuff_consumeIdx & 0x7;
fxdTiCtrl_applyDir = TEST(fxdTiCtrl.stepperCmdBuff_ApplyDir[dir_index], dir_bit);
nextMainISR = fxdTiCtrl.stepperCmdBuff_StepRelativeTi[fxdTiCtrl.stepperCmdBuff_consumeIdx];
fxdTiCtrl_stepCmdRdy = true;
ftMotion_stepCmd = ftMotion.stepperCmdBuff[ftMotion.stepperCmdBuff_consumeIdx];
const uint8_t dir_index = ftMotion.stepperCmdBuff_consumeIdx >> 3,
dir_bit = ftMotion.stepperCmdBuff_consumeIdx & 0x7;
ftMotion_applyDir = TEST(ftMotion.stepperCmdBuff_ApplyDir[dir_index], dir_bit);
nextMainISR = ftMotion.stepperCmdBuff_StepRelativeTi[ftMotion.stepperCmdBuff_consumeIdx];
ftMotion_stepCmdRdy = true;
if (++fxdTiCtrl.stepperCmdBuff_consumeIdx == (FTM_STEPPERCMD_BUFF_SIZE))
fxdTiCtrl.stepperCmdBuff_consumeIdx = 0;
if (++ftMotion.stepperCmdBuff_consumeIdx == (FTM_STEPPERCMD_BUFF_SIZE))
ftMotion.stepperCmdBuff_consumeIdx = 0;
}
else { // Buffer empty.
fxdTiCtrl.sts_stepperBusy = false;
ftMotion.sts_stepperBusy = false;
nextMainISR = 0.01f * (STEPPER_TIMER_RATE); // Come back in 10 msec.
}
} // !(abort_current_block)
} // if (!nextMainISR)
// Define 2.5 msec task for auxilliary functions.
if (!fxdTiCtrl_nextAuxISR) {
// Define 2.5 msec task for auxiliary functions.
if (!ftMotion_nextAuxISR) {
endstops.update();
TERN_(BABYSTEPPING, if (babystep.has_steps()) babystepping_isr());
fxdTiCtrl_refreshAxisDidMove();
fxdTiCtrl_nextAuxISR = 0.0025f * (STEPPER_TIMER_RATE);
ftMotion_refreshAxisDidMove();
ftMotion_nextAuxISR = 0.0025f * (STEPPER_TIMER_RATE);
}
interval = _MIN(nextMainISR, fxdTiCtrl_nextAuxISR);
interval = _MIN(nextMainISR, ftMotion_nextAuxISR);
nextMainISR -= interval;
fxdTiCtrl_nextAuxISR -= interval;
ftMotion_nextAuxISR -= interval;
}
#else
constexpr bool using_fxtictrl = false;
#endif
if (!using_fxtictrl) {
if (!using_ftMotion) {
TERN_(HAS_ZV_SHAPING, shaping_isr()); // Do Shaper stepping, if needed
@ -3436,12 +3433,8 @@ void Stepper::report_a_position(const xyz_long_t &pos) {
TERN(SAYS_A, PSTR(STR_COUNT_A), PSTR(STR_COUNT_X)), pos.x,
TERN(SAYS_B, PSTR("B:"), SP_Y_LBL), pos.y,
TERN(SAYS_C, PSTR("C:"), SP_Z_LBL), pos.z,
SP_I_LBL, pos.i,
SP_J_LBL, pos.j,
SP_K_LBL, pos.k,
SP_U_LBL, pos.u,
SP_V_LBL, pos.v,
SP_W_LBL, pos.w
SP_I_LBL, pos.i, SP_J_LBL, pos.j, SP_K_LBL, pos.k,
SP_U_LBL, pos.u, SP_V_LBL, pos.v, SP_W_LBL, pos.w
)
);
#endif
@ -3466,7 +3459,7 @@ void Stepper::report_positions() {
#if ENABLED(FT_MOTION)
// Set stepper I/O for fixed time controller.
void Stepper::fxdTiCtrl_stepper(const bool applyDir, const ft_command_t command) {
void Stepper::ftMotion_stepper(const bool applyDir, const ft_command_t command) {
USING_TIMED_PULSE();
@ -3558,13 +3551,13 @@ void Stepper::report_positions() {
if (axis_step.w) W_APPLY_STEP(!STEP_STATE_W, false)
);
} // Stepper::fxdTiCtrl_stepper
} // Stepper::ftMotion_stepper
void Stepper::fxdTiCtrl_BlockQueueUpdate() {
void Stepper::ftMotion_BlockQueueUpdate() {
if (current_block) {
// If the current block is not done processing, return right away
if (!fxdTiCtrl.getBlockProcDn()) return;
if (!ftMotion.getBlockProcDn()) return;
axis_did_move.reset();
current_block = nullptr;
@ -3591,21 +3584,21 @@ void Stepper::report_positions() {
// update it here, even though it will may be out of sync with step commands
last_direction_bits = current_block->direction_bits;
fxdTiCtrl.startBlockProc(current_block);
ftMotion.startBlockProc(current_block);
}
else {
fxdTiCtrl.runoutBlock();
ftMotion.runoutBlock();
return; // No queued blocks
}
} // if (!current_block)
} // Stepper::fxdTiCtrl_BlockQueueUpdate()
} // Stepper::ftMotion_BlockQueueUpdate()
// Debounces the axis move indication to account for potential
// delay between the block information and the stepper commands
void Stepper::fxdTiCtrl_refreshAxisDidMove() {
void Stepper::ftMotion_refreshAxisDidMove() {
// Set the debounce time in seconds.
#define AXIS_DID_MOVE_DEB 5 // TODO: The debounce time should be calculated if possible,

View file

@ -294,7 +294,7 @@ constexpr ena_mask_t enable_overlap[] = {
//
class Stepper {
friend class Max7219;
friend class FxdTiCtrl;
friend class FTMotion;
friend void stepperTask(void *);
public:
@ -535,7 +535,7 @@ class Stepper {
if (current_block->is_page()) page_manager.free_page(current_block->page_idx);
#endif
current_block = nullptr;
axis_did_move = 0;
axis_did_move.reset();
planner.release_current_block();
TERN_(LIN_ADVANCE, la_interval = nextAdvanceISR = LA_ADV_NEVER);
}
@ -654,7 +654,7 @@ class Stepper {
#if ENABLED(FT_MOTION)
// Manage the planner
static void fxdTiCtrl_BlockQueueUpdate();
static void ftMotion_BlockQueueUpdate();
#endif
#if HAS_ZV_SHAPING
@ -693,8 +693,8 @@ class Stepper {
#endif
#if ENABLED(FT_MOTION)
static void fxdTiCtrl_stepper(const bool applyDir, const ft_command_t command);
static void fxdTiCtrl_refreshAxisDidMove();
static void ftMotion_stepper(const bool applyDir, const ft_command_t command);
static void ftMotion_refreshAxisDidMove();
#endif
};