mirror of
https://github.com/bdring/Grbl_Esp32.git
synced 2025-09-01 18:32:37 +02:00
Baby steps toward better steps
Created beginLowLatency() and endLowLatency() to eliminate switch_stepper()
This commit is contained in:
@@ -503,7 +503,7 @@ static void IRAM_ATTR i2sOutTask(void* parameter) {
|
||||
} else if (i2s_out_pulser_status == WAITING) {
|
||||
if (dma_desc->qe.stqe_next == NULL) {
|
||||
// Tail of the DMA descriptor found
|
||||
// I2S TX module has alrewdy stopped by ISR
|
||||
// I2S TX module has already stopped by ISR
|
||||
i2s_out_stop();
|
||||
i2s_clear_o_dma_buffers(0); // 0 for static I2S control mode (right ch. data is always 0)
|
||||
// You need to set the status before calling i2s_out_start()
|
||||
@@ -546,6 +546,7 @@ void IRAM_ATTR i2s_out_delay() {
|
||||
} else {
|
||||
// Just wait until the data now registered in the DMA descripter
|
||||
// is reflected in the I2S TX module via FIFO.
|
||||
// XXX perhaps just wait until I2SO.conf1.tx_start == 0
|
||||
delay(I2S_OUT_DELAY_MS);
|
||||
}
|
||||
I2S_OUT_PULSER_EXIT_CRITICAL();
|
||||
|
@@ -133,6 +133,7 @@ namespace Machine {
|
||||
|
||||
auto wait_direction = config->_directionDelayMicroSeconds;
|
||||
if (wait_direction > 0) {
|
||||
// stepping->turnaround(wait_direction);
|
||||
// Stepper drivers need some time between changing direction and doing a pulse.
|
||||
switch (config->_stepType) {
|
||||
case stepper_id_t::ST_I2S_STREAM:
|
||||
@@ -213,6 +214,35 @@ namespace Machine {
|
||||
return SIZE_MAX;
|
||||
}
|
||||
|
||||
// Wait for motion to complete; the axes can still be moving
|
||||
// after the data has been sent to the stepping engine, due
|
||||
// to queuing delays.
|
||||
void Axes::synchronize() {
|
||||
if (config->_stepType == ST_I2S_STREAM) {
|
||||
// XXX instead of a delay, we could sense when the DMA and
|
||||
// FIFO have drained. It might be as simple as waiting for
|
||||
// I2SO.conf1.tx_start == 0, while yielding.
|
||||
delay_ms(I2S_OUT_DELAY_MS);
|
||||
}
|
||||
}
|
||||
void Axes::beginLowLatency() {
|
||||
_switchedStepper = config->_stepType == ST_I2S_STREAM;
|
||||
if (_switchedStepper) {
|
||||
config->_stepType = ST_I2S_STATIC;
|
||||
}
|
||||
}
|
||||
void Axes::endLowLatency() {
|
||||
if (_switchedStepper) {
|
||||
if (i2s_out_get_pulser_status() != PASSTHROUGH) {
|
||||
// Called during streaming. Stop streaming.
|
||||
debug_serial("Stop the I2S streaming and switch to the passthrough mode.");
|
||||
i2s_out_set_passthrough();
|
||||
i2s_out_delay(); // Wait for a change in mode.
|
||||
}
|
||||
config->_stepType = ST_I2S_STREAM;
|
||||
}
|
||||
}
|
||||
|
||||
// Configuration helpers:
|
||||
|
||||
void Axes::group(Configuration::HandlerBase& handler) {
|
||||
|
@@ -30,6 +30,8 @@ namespace Machine {
|
||||
static const int MAX_NUMBER_AXIS = 6;
|
||||
static constexpr const char* _names = "XYZABC";
|
||||
|
||||
bool _switchedStepper = false;
|
||||
|
||||
public:
|
||||
Axes();
|
||||
|
||||
@@ -65,6 +67,10 @@ namespace Machine {
|
||||
return false;
|
||||
}
|
||||
|
||||
void synchronize(); // Wait for motion to complete
|
||||
void beginLowLatency();
|
||||
void endLowLatency();
|
||||
|
||||
// These are used for setup and to talk to the motors as a group.
|
||||
void init();
|
||||
void read_settings(); // more like 'after read settings, before init'. Oh well...
|
||||
|
@@ -274,12 +274,6 @@ bool mc_dwell(int32_t milliseconds) {
|
||||
return delay_msec(milliseconds, DwellMode::Dwell);
|
||||
}
|
||||
|
||||
inline void RESTORE_STEPPER(int save_stepper) {
|
||||
if (save_stepper == ST_I2S_STREAM && config->_stepType != ST_I2S_STREAM) {
|
||||
Stepper::switch_mode(ST_I2S_STREAM); /* Put the stepper back on. */
|
||||
}
|
||||
}
|
||||
|
||||
// Perform homing cycle to locate and set machine zero. Only '$H' executes this command.
|
||||
// NOTE: There should be no motions in the buffer and Grbl must be in an idle state before
|
||||
// executing the homing cycle. This prevents incorrect buffered plans after homing.
|
||||
@@ -337,10 +331,7 @@ GCUpdatePos mc_probe_cycle(float* target, plan_line_data_t* pl_data, uint8_t par
|
||||
|
||||
int save_stepper = config->_stepType; /* remember the stepper */
|
||||
|
||||
// Switch stepper mode to the I2S static (realtime mode)
|
||||
if (save_stepper == ST_I2S_STREAM) {
|
||||
Stepper::switch_mode(ST_I2S_STATIC); /* Change the stepper to reduce the delay for accurate probing. */
|
||||
}
|
||||
config->_axes->beginLowLatency();
|
||||
|
||||
// Initialize probing control variables
|
||||
bool is_probe_away = bit_istrue(parser_flags, GCParserProbeIsAway);
|
||||
@@ -352,7 +343,7 @@ GCUpdatePos mc_probe_cycle(float* target, plan_line_data_t* pl_data, uint8_t par
|
||||
if (config->_probe->tripped()) {
|
||||
sys_rt_exec_alarm = ExecAlarm::ProbeFailInitial;
|
||||
protocol_execute_realtime();
|
||||
RESTORE_STEPPER(save_stepper); // Switch the stepper mode to the previous mode
|
||||
config->_axes->endLowLatency();
|
||||
return GCUpdatePos::None; // Nothing else to do but bail.
|
||||
}
|
||||
// Setup and queue probing motion. Auto cycle-start should not start the cycle.
|
||||
@@ -365,13 +356,12 @@ GCUpdatePos mc_probe_cycle(float* target, plan_line_data_t* pl_data, uint8_t par
|
||||
do {
|
||||
protocol_execute_realtime();
|
||||
if (sys.abort) {
|
||||
RESTORE_STEPPER(save_stepper); // Switch the stepper mode to the previous mode
|
||||
config->_axes->endLowLatency();
|
||||
return GCUpdatePos::None; // Check for system abort
|
||||
}
|
||||
} while (sys.state != State::Idle);
|
||||
|
||||
// Switch the stepper mode to the previous mode
|
||||
RESTORE_STEPPER(save_stepper);
|
||||
config->_axes->endLowLatency();
|
||||
|
||||
// Probing cycle complete!
|
||||
// Set state variables and error out, if the probe failed and cycle with error is enabled.
|
||||
|
@@ -57,6 +57,7 @@ namespace Motors {
|
||||
|
||||
_dir_pin.setAttr(Pin::Attr::Output);
|
||||
|
||||
// stepping->init(_step_pin);
|
||||
if (config->_stepType == ST_RMT) {
|
||||
rmtConfig.rmt_mode = RMT_MODE_TX;
|
||||
rmtConfig.clk_div = 20;
|
||||
|
@@ -272,16 +272,11 @@ Error home(int cycle) {
|
||||
}
|
||||
sys.state = State::Homing; // Set system state variable
|
||||
|
||||
int save_stepper = config->_stepType;
|
||||
if (save_stepper == ST_I2S_STREAM) {
|
||||
Stepper::switch_mode(ST_I2S_STATIC);
|
||||
}
|
||||
config->_axes->beginLowLatency();
|
||||
|
||||
mc_homing_cycle(cycle);
|
||||
|
||||
if (save_stepper == ST_I2S_STREAM && config->_stepType != ST_I2S_STREAM) {
|
||||
Stepper::switch_mode(ST_I2S_STREAM);
|
||||
}
|
||||
config->_axes->endLowLatency();
|
||||
|
||||
if (!sys.abort) { // Execute startup scripts after successful homing.
|
||||
sys.state = State::Idle; // Set to IDLE when complete.
|
||||
|
@@ -348,17 +348,19 @@ static void IRAM_ATTR pulse_func() {
|
||||
}
|
||||
}
|
||||
|
||||
auto pulseMicros = config->_pulseMicroSeconds;
|
||||
// stepping->unStep(pulseMicros);
|
||||
uint64_t endMicros;
|
||||
switch (config->_stepType) {
|
||||
case ST_I2S_STREAM:
|
||||
// Generate the number of pulses needed to span pulse_microseconds
|
||||
i2s_out_push_sample(pulseMicros);
|
||||
i2s_out_push_sample(config->_pulseMicroSeconds);
|
||||
config->_axes->unstep();
|
||||
break;
|
||||
case ST_I2S_STATIC:
|
||||
case ST_TIMED:
|
||||
endMicros = config->_pulseMicroSeconds + step_pulse_start_time;
|
||||
// wait for step pulse time to complete...some time expired during code above
|
||||
while (esp_timer_get_time() - step_pulse_start_time < pulseMicros) {
|
||||
while ((esp_timer_get_time() - endMicros) < 0) {
|
||||
NOP(); // spin here until time to turn off step
|
||||
}
|
||||
config->_axes->unstep();
|
||||
@@ -373,6 +375,7 @@ void Stepper::init() {
|
||||
|
||||
info_serial("Axis count %d", config->_axes->_numberAxis);
|
||||
info_serial("Step type:%s Pulse:%dus Dsbl Delay:%dus Dir Delay:%dus",
|
||||
// stepping->name(),
|
||||
stepTypes[config->_stepType].name,
|
||||
config->_pulseMicroSeconds,
|
||||
config->_disableDelayMicroSeconds,
|
||||
@@ -382,25 +385,6 @@ void Stepper::init() {
|
||||
timerInit();
|
||||
}
|
||||
|
||||
void Stepper::switch_mode(stepper_id_t new_stepper) {
|
||||
debug_serial("Switch stepper: %s -> %s", stepTypes[config->_stepType].name, stepTypes[new_stepper].name);
|
||||
if (config->_stepType == new_stepper) {
|
||||
// do not need to change
|
||||
return;
|
||||
}
|
||||
|
||||
if (config->_stepType == ST_I2S_STREAM) {
|
||||
if (i2s_out_get_pulser_status() != PASSTHROUGH) {
|
||||
// Called during streaming. Stop streaming.
|
||||
debug_serial("Stop the I2S streaming and switch to the passthrough mode.");
|
||||
i2s_out_set_passthrough();
|
||||
i2s_out_delay(); // Wait for a change in mode.
|
||||
}
|
||||
}
|
||||
|
||||
config->_stepType = new_stepper;
|
||||
}
|
||||
|
||||
// enabled. Startup init and limits call this function but shouldn't start the cycle.
|
||||
void Stepper::wake_up() {
|
||||
//info_serial("st_wake_up");
|
||||
@@ -415,6 +399,7 @@ void Stepper::wake_up() {
|
||||
// Reset and clear stepper subsystem variables
|
||||
void Stepper::reset() {
|
||||
// Initialize stepper driver idle state.
|
||||
// stepping->reset();
|
||||
if (config->_stepType == ST_I2S_STREAM) {
|
||||
i2s_out_reset();
|
||||
}
|
||||
@@ -930,6 +915,7 @@ float Stepper::get_realtime_rate() {
|
||||
|
||||
// The argument is in units of ticks of the timer that generates ISRs
|
||||
static void IRAM_ATTR timerWritePeriod(uint16_t timerTicks) {
|
||||
// stepping->setPeriod(uint16_t timerTicks);
|
||||
if (config->_stepType == ST_I2S_STREAM) {
|
||||
// 1 tick = fTimers / fStepperTimer
|
||||
// Pulse ISR is called for each tick of alarm_val.
|
||||
@@ -956,6 +942,7 @@ static void IRAM_ATTR timerInit() {
|
||||
}
|
||||
|
||||
static void IRAM_ATTR timerStart() {
|
||||
// stepping->start();
|
||||
if (config->_stepType == ST_I2S_STREAM) {
|
||||
i2s_out_set_stepping();
|
||||
} else {
|
||||
@@ -965,6 +952,7 @@ static void IRAM_ATTR timerStart() {
|
||||
}
|
||||
|
||||
static void IRAM_ATTR timerStop() {
|
||||
// stepping->stop();
|
||||
if (config->_stepType == ST_I2S_STREAM) {
|
||||
i2s_out_set_passthrough();
|
||||
} else if (stepTimer) {
|
||||
|
Reference in New Issue
Block a user