diff --git a/main/driver.c b/main/driver.c index becbfc1..24c52c5 100644 --- a/main/driver.c +++ b/main/driver.c @@ -35,6 +35,7 @@ #include "./driver.h" #include "uart_serial.h" +#include "timers.h" #include "nvs.h" #include "esp_log.h" #include "sdkconfig.h" @@ -433,6 +434,20 @@ static bool IOInitDone = false, rtc_started = false; static portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED; static pin_group_pins_t limit_inputs = {0}; static on_execute_realtime_ptr on_execute_realtime; +static struct { + uint32_t length; + uint32_t delay; + axes_signals_t out; +#if STEP_INJECT_ENABLE + struct { + hal_timer_t timer; + axes_signals_t claimed; + volatile axes_signals_t axes; + volatile axes_signals_t out; + } inject; +#endif +} step_pulse = {0}; + #if PROBE_ENABLE static probe_state_t probe = { .connected = On @@ -531,7 +546,7 @@ IRAM_ATTR static void driver_delay_ms (uint32_t ms, void (*callback)(void)) } // Enable/disable steppers -static void stepperEnable (axes_signals_t enable) +static void stepperEnable (axes_signals_t enable, bool hold) { enable.mask ^= settings.steppers.enable_invert.mask; @@ -579,7 +594,7 @@ static void stepperEnable (axes_signals_t enable) static void stepperWakeUp (void) { // Enable stepper drivers. - hal.stepper.enable((axes_signals_t){AXES_BITMASK}); + hal.stepper.enable((axes_signals_t){AXES_BITMASK}, false); timer_set_counter_value(STEP_TIMER_GROUP, STEP_TIMER_INDEX, 0x00000000ULL); // timer_set_alarm_value(STEP_TIMER_GROUP, STEP_TIMER_INDEX, 5000ULL); @@ -619,36 +634,93 @@ IRAM_ATTR static void stepperCyclesPerTick (uint32_t cycles_per_tick) // Set stepper direction output pins // NOTE: see note for set_step_outputs() -inline IRAM_ATTR static void set_dir_outputs (axes_signals_t dir_outbits) +inline IRAM_ATTR static void set_dir_outputs (axes_signals_t dir_out) { - dir_outbits.value ^= settings.steppers.dir_invert.mask; + dir_out.bits ^= settings.steppers.dir_invert.bits; + +#if STEP_INJECT_ENABLE + + axes_signals_t axes = { .bits = step_pulse.inject.axes.bits }; + + if(axes.bits) { + + uint_fast8_t idx, mask = 1; + + for(idx = 0; idx < N_AXIS; idx++) { + + if(!(axes.bits & mask)) switch(idx) { + + case X_AXIS: + DIGITAL_OUT(X_DIRECTION_PIN, dir_out.x); +#if X_GANGED + DIGITAL_OUT(X2_DIRECTION_PIN, dir_out.x ^ settings.steppers.ganged_dir_invert.x); +#endif + break; + + case Y_AXIS: + DIGITAL_OUT(Y_DIRECTION_PIN, dir_out.y); +#if Y_GANGED + DIGITAL_OUT(Y2_DIRECTION_PIN, dir_out.y ^ settings.steppers.ganged_dir_invert.y); +#endif + break; - DIGITAL_OUT(X_DIRECTION_PIN, dir_outbits.x); - DIGITAL_OUT(Y_DIRECTION_PIN, dir_outbits.y); #ifdef Z_DIRECTION_PIN - DIGITAL_OUT(Z_DIRECTION_PIN, dir_outbits.z); + case Z_AXIS: + DIGITAL_OUT(Z_DIRECTION_PIN, dir_out.z); + #if Z_GANGED + DIGITAL_OUT(Z2_DIRECTION_PIN, dir_out.z ^ settings.steppers.ganged_dir_invert.z); + #endif + break; #endif + #ifdef A_AXIS - DIGITAL_OUT(A_DIRECTION_PIN, dir_outbits.a); + case A_AXIS: + DIGITAL_OUT(A_DIRECTION_PIN, dir_out.a); + break; #endif #ifdef B_AXIS - DIGITAL_OUT(B_DIRECTION_PIN, dir_outbits.b); + case B_AXIS: + DIGITAL_OUT(B_DIRECTION_PIN, dir_out.b); + break; #endif #ifdef C_AXIS - DIGITAL_OUT(C_DIRECTION_PIN, dir_outbits.c); + case C_AXIS: + DIGITAL_OUT(C_DIRECTION_PIN, dir_out.c); + break; #endif -#ifdef GANGING_ENABLED - dir_outbits.mask ^= settings.steppers.ganged_dir_invert.mask; - #ifdef X2_DIRECTION_PIN - DIGITAL_OUT(X2_DIRECTION_PIN, dir_outbits.x); - #endif - #ifdef Y2_DIRECTION_PIN - DIGITAL_OUT(Y2_DIRECTION_PIN, dir_outbits.y); - #endif - #ifdef Z2_DIRECTION_PIN - DIGITAL_OUT(Z2_DIRECTION_PIN, dir_outbits.z); + } + mask <<= 1; + } + } else { + +#endif // STEP_INJECT_ENABLE + + DIGITAL_OUT(X_DIRECTION_PIN, dir_out.x); +#if X_GANGED + DIGITAL_OUT(X2_DIRECTION_PIN, dir_out.x ^ settings.steppers.ganged_dir_invert.x); +#endif + DIGITAL_OUT(Y_DIRECTION_PIN, dir_out.y); +#if Y_GANGED + DIGITAL_OUT(Y2_DIRECTION_PIN, dir_out.y ^ settings.steppers.ganged_dir_invert.y); +#endif +#ifdef Z_DIRECTION_PIN + DIGITAL_OUT(Z_DIRECTION_PIN, dir_out.z); + #if Z_GANGED + DIGITAL_OUT(Z2_DIRECTION_PIN, dir_out.z ^ settings.steppers.ganged_dir_invert.z); #endif #endif +#ifdef A_AXIS + DIGITAL_OUT(A_DIRECTION_PIN, dir_out.a); +#endif +#ifdef B_AXIS + DIGITAL_OUT(B_DIRECTION_PIN, dir_out.b); +#endif +#ifdef C_AXIS + DIGITAL_OUT(C_DIRECTION_PIN, dir_out.c); +#endif +#if STEP_INJECT_ENABLE + } +#endif } #ifdef SQUARING_ENABLED @@ -794,94 +866,6 @@ inline __attribute__((always_inline)) IRAM_ATTR static void i2s_set_step_outputs #endif // !SQUARING_ENABLED -#if STEP_INJECT_ENABLE - -void stepperOutputStep (axes_signals_t step_outbits, axes_signals_t dir_outbits) -{ - if(step_outbits.value) { - - step_outbits.value ^= settings.steppers.step_invert.value; - dir_outbits.value ^= settings.steppers.dir_invert.value; - #ifdef GANGING_ENABLED - axes_signals_t dir_outbits_2; - dir_outbits_2.value = dir_outbits.value ^ settings.steppers.ganged_dir_invert.value; - #endif - - if(step_outbits.x) { - DIGITAL_OUT(X_DIRECTION_PIN, dir_outbits.x); - #if X_GANGED - DIGITAL_OUT(X2_DIRECTION_PIN, dir_outbits_2.x); - #endif - } - - if(step_outbits.y) { - DIGITAL_OUT(Y_DIRECTION_PIN, dir_outbits.y); - #if Y_GANGED - DIGITAL_OUT(Y2_DIRECTION_PIN, dir_outbits_2.y); - #endif - } - #ifdef Z_DIRECTION_PIN - if(step_outbits.z) { - DIGITAL_OUT(Z_DIRECTION_PIN, dir_outbits.z); - #if Z_GANGED - DIGITAL_OUT(Z2_DIRECTION_PIN, dir_outbits_2.z); - #endif - } - #endif -#ifdef A_AXIS - if(step_outbits.a) - DIGITAL_OUT(A_DIRECTION_PIN, dir_outbits.a); -#endif -#ifdef B_AXIS - if(step_outbits.b) - DIGITAL_OUT(B_DIRECTION_PIN, dir_outbits.b); -#endif -#ifdef C_AXIS - if(step_outbits.c) - DIGITAL_OUT(C_DIRECTION_PIN, dir_outbits.c); -#endif - - if(step_outbits.x) { - DIGITAL_OUT(X_STEP_PIN, step_outbits.x); - #ifdef X2_STEP_PIN - DIGITAL_OUT(X2_STEP_PIN, step_outbits.x); - #endif - } - - if(step_outbits.y) { - DIGITAL_OUT(Y_STEP_PIN, step_outbits.y); - #ifdef Y2_STEP_PIN - DIGITAL_OUT(Y2_STEP_PIN, step_outbits.y); - #endif - } - #ifdef Z_STEP_PIN - if(step_outbits.z) { - DIGITAL_OUT(Z_STEP_PIN, step_outbits.z); - #ifdef Z2_STEP_PIN - DIGITAL_OUT(Z2_STEP_PIN, step_outbits.z); - #endif - } - #endif -#ifdef A_AXIS - if(step_outbits.a) - DIGITAL_OUT(A_STEP_PIN, step_outbits.a); -#endif -#ifdef B_AXIS - if(step_outbits.b) - DIGITAL_OUT(B_STEP_PIN, step_outbits.b); -#endif -#ifdef C_AXIS - if(step_outbits.c) - DIGITAL_OUT(C_STEP_PIN, step_outbits.c); -#endif -// delay_us(i2s_step_length); - i2s_out_push_sample(i2s_step_samples); - i2s_set_step_outputs((axes_signals_t){0}); - } -} - -#endif // STEP_INJECT_ENABLE - void i2s_step_sink (void) { //NOOP @@ -1007,41 +991,118 @@ void initRMT (settings_t *settings) #ifdef SQUARING_ENABLED // Set stepper pulse output pins -inline IRAM_ATTR static void set_step_outputs (axes_signals_t step_outbits_1) +inline IRAM_ATTR static void set_step_outputs (axes_signals_t step_out1) { - axes_signals_t step_outbits_2; - step_outbits_2.mask = (step_outbits_1.mask & motors_2.mask) ^ settings.steppers.step_invert.mask; - step_outbits_1.mask = (step_outbits_1.mask & motors_1.mask) ^ settings.steppers.step_invert.mask; + axes_signals_t step_out2; + + step_out2.bits = step_out1.bits & motors_2.bits; + step_out1.bits = step_out1.bits & motors_1.bits; + +#if STEP_INJECT_ENABLE + + axes_signals_t axes = { .bits = step_pulse.inject.axes.bits }; + + if(axes.bits) { + + uint_fast8_t idx, mask = 1; + + for(idx = 0; idx < N_AXIS; idx++) { + + if(!(axes.bits & mask)) { + + if(step_out2.bits & mask) switch(idx) { +#if X_GANGED + case X_AXIS: + rmt_ll_tx_reset_pointer(&RMT, X2_MOTOR); + rmt_ll_tx_start(&RMT, X2_MOTOR); + break; +#endif +#if Y_GANGED + case Y_AXIS: + rmt_ll_tx_reset_pointer(&RMT, Y2_MOTOR); + rmt_ll_tx_start(&RMT, Y2_MOTOR); + break; +#endif +#if Z_GANGED && defined(Z2_STEP_PIN) + case Z_AXIS: + rmt_ll_tx_reset_pointer(&RMT, Z2_MOTOR); + rmt_ll_tx_start(&RMT, Z2_MOTOR); + break; +#endif + } + + if(step_out1.bits & mask) switch(idx) { + + case X_AXIS: + rmt_ll_tx_reset_pointer(&RMT, X_AXIS); + rmt_ll_tx_start(&RMT, X_AXIS); + break; + + case Y_AXIS: + rmt_ll_tx_reset_pointer(&RMT, Y_AXIS); + rmt_ll_tx_start(&RMT, Y_AXIS); + break; +#ifdef Z_STEP_PIN + case Z_AXIS: + rmt_ll_tx_reset_pointer(&RMT, Z_AXIS); + rmt_ll_tx_start(&RMT, Z_AXIS); + break; +#endif +#ifdef A_AXIS + case A_AXIS: + rmt_ll_tx_reset_pointer(&RMT, A_AXIS); + rmt_ll_tx_start(&RMT, A_AXIS); + break; +#endif +#ifdef B_AXIS + case B_AXIS: + rmt_ll_tx_reset_pointer(&RMT, B_AXIS); + rmt_ll_tx_start(&RMT, B_AXIS); + break; +#endif +#ifdef C_AXIS + case C_AXIS: + rmt_ll_tx_reset_pointer(&RMT, C_AXIS); + rmt_ll_tx_start(&RMT, C_AXIS); + break; +#endif + } + } + mask <<= 1; + } + } else { - if(step_outbits_1.x) { +#endif // STEP_INJECT_ENABLE + + if(step_out1.x) { rmt_ll_tx_reset_pointer(&RMT, X_AXIS); rmt_ll_tx_start(&RMT, X_AXIS); } #ifdef X2_STEP_PIN - if(step_outbits_2.x) { + if(step_out2.x) { rmt_ll_tx_reset_pointer(&RMT, X2_MOTOR); rmt_ll_tx_start(&RMT, X2_MOTOR); } #endif - if(step_outbits_1.y) { + if(step_out1.y) { rmt_ll_tx_reset_pointer(&RMT, Y_AXIS); rmt_ll_tx_start(&RMT, Y_AXIS); } #ifdef Y2_STEP_PIN - if(step_outbits_2.y) { + if(step_out2.y) { rmt_ll_tx_reset_pointer(&RMT, Y2_MOTOR); rmt_ll_tx_start(&RMT, Y2_MOTOR); } #endif #ifdef Z_STEP_PIN - if(step_outbits_1.z) { + if(step_out1.z) { rmt_ll_tx_reset_pointer(&RMT, Z_AXIS); rmt_ll_tx_start(&RMT, Z_AXIS); } #ifdef Z2_STEP_PIN - if(step_outbits_2.z) { + if(step_out2.z) { rmt_ll_tx_reset_pointer(&RMT, Z2_MOTOR); rmt_ll_tx_start(&RMT, Z2_MOTOR); } @@ -1049,55 +1110,133 @@ inline IRAM_ATTR static void set_step_outputs (axes_signals_t step_outbits_1) #endif // Z_STEP_PIN #ifdef A_STEP_PIN - if(step_outbits_1.a) { + if(step_out1.a) { rmt_ll_tx_reset_pointer(&RMT, A_AXIS); rmt_ll_tx_start(&RMT, A_AXIS); } #endif #ifdef B_STEP_PIN - if(step_outbits_1.b) { + if(step_out1.b) { rmt_ll_tx_reset_pointer(&RMT, B_AXIS); rmt_ll_tx_start(&RMT, B_AXIS); } #endif #ifdef C_STEP_PIN - if(step_outbits_1.c) { + if(step_out1.c) { rmt_ll_tx_reset_pointer(&RMT, C_AXIS); rmt_ll_tx_start(&RMT, C_AXIS); } #endif +#if STEP_INJECT_ENABLE +} +#endif } #else // !SQUARING_ENABLED // Set stepper pulse output pins -inline IRAM_ATTR static void set_step_outputs (axes_signals_t step_outbits) +inline IRAM_ATTR static void set_step_outputs (axes_signals_t step_out) { - if(step_outbits.x) { +#if STEP_INJECT_ENABLE +/* + uint32_t mask; + + if(step_pulse.inject.out.z) { + mask = 1 << (Z_AXIS * 3); + if(RMT.int_raw.val & mask) { + step_pulse.inject.out.z = Off; + RMT.int_raw.val = mask; + } + step_pulse.inject.axes.bits = step_pulse.inject.claimed.bits; + } +*/ + axes_signals_t axes = { .bits = step_pulse.inject.axes.bits }; + + if(axes.bits) { + + uint_fast8_t idx, mask = 1; + + for(idx = 0; idx < N_AXIS; idx++) { + + if((step_out.bits & mask) && !(axes.bits & mask)) switch(idx) { + + case X_AXIS: + rmt_ll_tx_reset_pointer(&RMT, X_AXIS); + rmt_ll_tx_start(&RMT, X_AXIS); +#if X_GANGED + rmt_ll_tx_reset_pointer(&RMT, X2_MOTOR); + rmt_ll_tx_start(&RMT, X2_MOTOR); +#endif + break; + + case Y_AXIS: + rmt_ll_tx_reset_pointer(&RMT, Y_AXIS); + rmt_ll_tx_start(&RMT, Y_AXIS); +#if Y_GANGED + rmt_ll_tx_reset_pointer(&RMT, Y2_MOTOR); + rmt_ll_tx_start(&RMT, Y2_MOTOR); +#endif + break; +#if Z_GANGED && defined(Z_STEP_PIN) + case Z_AXIS: + rmt_ll_tx_reset_pointer(&RMT, Z_AXIS); + rmt_ll_tx_start(&RMT, Z_AXIS); + #ifdef Z2_STEP_PIN + rmt_ll_tx_reset_pointer(&RMT, Z2_MOTOR); + rmt_ll_tx_start(&RMT, Z2_MOTOR); + #endif + break; +#endif +#ifdef A_AXIS + case A_AXIS: + rmt_ll_tx_reset_pointer(&RMT, A_AXIS); + rmt_ll_tx_start(&RMT, A_AXIS); + break; +#endif +#ifdef B_AXIS + case B_AXIS: + rmt_ll_tx_reset_pointer(&RMT, B_AXIS); + rmt_ll_tx_start(&RMT, B_AXIS); + break; +#endif +#ifdef C_AXIS + case C_AXIS: + rmt_ll_tx_reset_pointer(&RMT, C_AXIS); + rmt_ll_tx_start(&RMT, C_AXIS); + break; +#endif + } + mask <<= 1; + } + } else { + +#endif // STEP_INJECT_ENABLE + + if(step_out.x) { rmt_ll_tx_reset_pointer(&RMT, X_AXIS); rmt_ll_tx_start(&RMT, X_AXIS); -#ifdef X2_STEP_PIN +#if X_GANGED rmt_ll_tx_reset_pointer(&RMT, X2_MOTOR); rmt_ll_tx_start(&RMT, X2_MOTOR); #endif } - if(step_outbits.y) { + if(step_out.y) { rmt_ll_tx_reset_pointer(&RMT, Y_AXIS); rmt_ll_tx_start(&RMT, Y_AXIS); -#ifdef Y2_STEP_PIN +#if Y_GANGED rmt_ll_tx_reset_pointer(&RMT, Y2_MOTOR); rmt_ll_tx_start(&RMT, Y2_MOTOR); #endif } #ifdef Z_STEP_PIN - if(step_outbits.z) { + if(step_out.z) { rmt_ll_tx_reset_pointer(&RMT, Z_AXIS); rmt_ll_tx_start(&RMT, Z_AXIS); - #ifdef Z2_STEP_PIN + #if Z_GANGED rmt_ll_tx_reset_pointer(&RMT, Z2_MOTOR); rmt_ll_tx_start(&RMT, Z2_MOTOR); #endif @@ -1105,122 +1244,126 @@ inline IRAM_ATTR static void set_step_outputs (axes_signals_t step_outbits) #endif #ifdef A_STEP_PIN - if(step_outbits.a) { + if(step_out.a) { rmt_ll_tx_reset_pointer(&RMT, A_AXIS); rmt_ll_tx_start(&RMT, A_AXIS); } #endif #ifdef B_STEP_PIN - if(step_outbits.b) { + if(step_out.b) { rmt_ll_tx_reset_pointer(&RMT, B_AXIS); rmt_ll_tx_start(&RMT, B_AXIS); } #endif #ifdef C_STEP_PIN - if(step_outbits.c) { + if(step_out.c) { rmt_ll_tx_reset_pointer(&RMT, C_AXIS); rmt_ll_tx_start(&RMT, C_AXIS); } #endif +#if STEP_INJECT_ENABLE +} +#endif } #endif // !SQUARING_ENABLED #if STEP_INJECT_ENABLE -void stepperOutputStep (axes_signals_t step_outbits, axes_signals_t dir_outbits) +static void stepperClaimMotor (uint_fast8_t axis_id, bool claim) { - if(step_outbits.value) { + if(claim) + step_pulse.inject.claimed.mask |= ((1 << axis_id) & AXES_BITMASK); + else { + step_pulse.inject.claimed.mask &= ~(1 << axis_id); + step_pulse.inject.axes.bits = step_pulse.inject.claimed.bits; // For now... + } +} - dir_outbits.value ^= settings.steppers.dir_invert.value; - #ifdef GANGING_ENABLED - axes_signals_t dir_outbits_2; - dir_outbits_2.value = dir_outbits.value ^ settings.steppers.ganged_dir_invert.value; - #endif +void stepperOutputStep (axes_signals_t step_out, axes_signals_t dir_out) +{ + if(step_out.bits) { - if(step_outbits.x) { - DIGITAL_OUT(X_DIRECTION_PIN, dir_outbits.x); - #if X_GANGED - DIGITAL_OUT(X2_DIRECTION_PIN, dir_outbits_2.x); - #endif - } + uint_fast8_t idx = N_AXIS - 1, mask = 1 << (N_AXIS - 1); + axes_signals_t axes = { .bits = step_out.bits }; - if(step_outbits.y) { - DIGITAL_OUT(Y_DIRECTION_PIN, dir_outbits.y); - #if Y_GANGED - DIGITAL_OUT(Y2_DIRECTION_PIN, dir_outbits_2.y); - #endif - } - #ifdef Z_DIRECTION_PIN - if(step_outbits.z) { - DIGITAL_OUT(Z_DIRECTION_PIN, dir_outbits.z); - #if Z_GANGED - DIGITAL_OUT(Z2_DIRECTION_PIN, dir_outbits_2.z); - #endif - } - #endif -#ifdef A_AXIS - if(step_outbits.a) - DIGITAL_OUT(A_DIRECTION_PIN, dir_outbits.a); -#endif -#ifdef B_AXIS - if(step_outbits.b) - DIGITAL_OUT(B_DIRECTION_PIN, dir_outbits.b); + step_pulse.inject.out = step_out; + step_pulse.inject.axes.bits = step_pulse.inject.claimed.bits; // | step_out.bits; // It looks like the RMT enqueues step pulses... + dir_out.bits ^= settings.steppers.dir_invert.bits; + + do { + if(axes.bits & mask) { + + axes.bits ^= mask; + + switch(idx) { + + case X_AXIS: + DIGITAL_OUT(X_DIRECTION_PIN, dir_out.x); +#if X_GANGED + DIGITAL_OUT(X2_DIRECTION_PIN, dir_out.x ^ settings.steppers.ganged_dir_invert.x); #endif -#ifdef C_AXIS - if(step_outbits.c) - DIGITAL_OUT(C_DIRECTION_PIN, dir_outbits.c); + rmt_ll_tx_reset_pointer(&RMT, X_AXIS); + rmt_ll_tx_start(&RMT, X_AXIS); +#if X_GANGED + rmt_ll_tx_reset_pointer(&RMT, X2_MOTOR); + rmt_ll_tx_start(&RMT, X2_MOTOR); #endif + break; - if(step_outbits.x) { - rmt_ll_tx_reset_pointer(&RMT, X_AXIS); - rmt_ll_tx_start(&RMT, X_AXIS); -#ifdef X2_STEP_PIN - rmt_ll_tx_reset_pointer(&RMT, X2_MOTOR); - rmt_ll_tx_start(&RMT, X2_MOTOR); + case Y_AXIS: + DIGITAL_OUT(Y_DIRECTION_PIN, dir_out.y); +#if Y_GANGED + DIGITAL_OUT(Y2_DIRECTION_PIN, dir_out.y ^ settings.steppers.ganged_dir_invert.y); #endif - } - - if(step_outbits.y) { - rmt_ll_tx_reset_pointer(&RMT, Y_AXIS); - rmt_ll_tx_start(&RMT, Y_AXIS); -#ifdef Y2_STEP_PIN - rmt_ll_tx_reset_pointer(&RMT, Y2_MOTOR); - rmt_ll_tx_start(&RMT, Y2_MOTOR); + rmt_ll_tx_reset_pointer(&RMT, Y_AXIS); + rmt_ll_tx_start(&RMT, Y_AXIS); +#if Y_GANGED + rmt_ll_tx_reset_pointer(&RMT, Y2_MOTOR); + rmt_ll_tx_start(&RMT, Y2_MOTOR); #endif - } + break; #ifdef Z_STEP_PIN - if(step_outbits.z) { - rmt_ll_tx_reset_pointer(&RMT, Z_AXIS); - rmt_ll_tx_start(&RMT, Z_AXIS); - #ifdef Z2_STEP_PIN - rmt_ll_tx_reset_pointer(&RMT, Z2_MOTOR); - rmt_ll_tx_start(&RMT, Z2_MOTOR); + case Z_AXIS: + DIGITAL_OUT(Z_DIRECTION_PIN, dir_out.z); + #if Z_GANGED + DIGITAL_OUT(Z2_DIRECTION_PIN, dir_out.z ^ settings.steppers.ganged_dir_invert.z); #endif - } + rmt_ll_tx_reset_pointer(&RMT, Z_AXIS); + rmt_ll_tx_start(&RMT, Z_AXIS); + #if Z_GANGED + rmt_ll_tx_reset_pointer(&RMT, Z2_MOTOR); + rmt_ll_tx_start(&RMT, Z2_MOTOR); + #endif + break; #endif - #ifdef A_AXIS - if(step_outbits.a) { - rmt_ll_tx_reset_pointer(&RMT, A_AXIS); - rmt_ll_tx_start(&RMT, A_AXIS); - } + case A_AXIS: + DIGITAL_OUT(A_DIRECTION_PIN, dir_out.a); + rmt_ll_tx_reset_pointer(&RMT, A_AXIS); + rmt_ll_tx_start(&RMT, A_AXIS); + break; #endif - #ifdef B_AXIS - if(step_outbits.b) { - rmt_ll_tx_reset_pointer(&RMT, B_AXIS); - rmt_ll_tx_start(&RMT, B_AXIS); - } + case B_AXIS: + DIGITAL_OUT(B_DIRECTION_PIN, dir_out.b); + rmt_ll_tx_reset_pointer(&RMT, B_AXIS); + rmt_ll_tx_start(&RMT, B_AXIS); + break; #endif - #ifdef C_AXIS - if(step_outbits.c) { - rmt_ll_tx_reset_pointer(&RMT, C_AXIS); - rmt_ll_tx_start(&RMT, C_AXIS); - } + case C_AXIS: + DIGITAL_OUT(C_DIRECTION_PIN, dir_out.c); + rmt_ll_tx_reset_pointer(&RMT, C_AXIS); + rmt_ll_tx_start(&RMT, C_AXIS); + break; #endif + } + } + idx--; + mask >>= 1; + } while(axes.bits); } } @@ -1286,7 +1429,7 @@ IRAM_ATTR static void stepperPulseStart (stepper_t *stepper) if(stepper->step_outbits.value) { #if USE_I2S_OUT - i2s_set_step_outputs(stepper->step_outbits); + i2s_set_step_outpustep_outstep_outbits); i2s_out_commit(i2s_step_samples, add_dir_delay ? i2s_delay_samples : 0); add_dir_delay = false; #else @@ -1866,6 +2009,26 @@ bool spindleConfig (spindle_ptrs_t *spindle) return true; } +#if PPI_ENABLE + +#include "laser/ppi.h" + +static hal_timer_t ppi_timer; + +static void spindlePulseOff (void *context) +{ + spindle_off(); +} + +static void spindlePulseOn (uint_fast16_t pulse_length) +{ + hal.timer.start(ppi_timer, pulse_length); + + spindle_on(); +} + +#endif // PPI_ENABLE + #endif // DRIVER_SPINDLE_PWM_ENABLE // Returns spindle state in a spindle_state_t variable @@ -2034,7 +2197,6 @@ static void settings_changed (settings_t *settings, settings_changed_flags_t cha } neopixel.num_leds = hal.rgb0.num_devices; - hal.rgb0.write = neopixel.num_leds > 1 ? neopixels_write : NULL; } #endif @@ -2445,7 +2607,7 @@ static char *sdcard_mount (FATFS **fs) // https://github.com/adafruit/Adafruit_NeoPixel/blob/master/esp.c #ifndef NEOPIXELS_NUM -#define NEOPIXELS_NUM 1 +#define NEOPIXELS_NUM 0 #endif #if CONFIG_IDF_TARGET_ESP32S3 @@ -2539,7 +2701,8 @@ void _neopixels_write (void) void neopixels_write (void) { - _neopixels_write(); + if(neopixel.num_bytes > 1) + _neopixels_write(); } static void neopixel_out_masked (uint16_t device, rgb_color_t color, rgb_color_mask_t mask) @@ -2563,7 +2726,6 @@ uint8_t neopixels_set_intensity (uint8_t value) uint8_t prev = neopixel.intensity; if(neopixel.intensity != value) { - neopixel.intensity = value; _neopixels_write(); } @@ -2819,7 +2981,7 @@ bool driver_init (void) #else hal.info = "ESP32"; #endif - hal.driver_version = "240903"; + hal.driver_version = "240921"; hal.driver_url = GRBL_URL "/ESP32"; #ifdef BOARD_NAME hal.board = BOARD_NAME; @@ -2834,6 +2996,12 @@ bool driver_init (void) hal.rx_buffer_size = RX_BUFFER_SIZE; hal.get_free_mem = esp_get_free_heap_size; hal.delay_ms = driver_delay_ms; + + hal.timer.claim = timerClaim; + hal.timer.configure = timerCfg; + hal.timer.start = timerStart; + hal.timer.stop = timerStop; + hal.settings_changed = settings_changed; #if USE_I2S_OUT @@ -2852,6 +3020,7 @@ bool driver_init (void) #endif #if STEP_INJECT_ENABLE hal.stepper.output_step = stepperOutputStep; + hal.stepper.claim_motor = stepperClaimMotor; #endif hal.stepper.motor_iterator = motor_iterator; #ifdef GANGING_ENABLED @@ -2927,6 +3096,11 @@ bool driver_init (void) static const spindle_ptrs_t spindle = { .type = SpindleType_PWM, +#if DRIVER_SPINDLE_DIR_ENABLE + .ref_id = SPINDLE_PWM0, +#else + .ref_id = SPINDLE_PWM0_NODIR, +#endif .config = spindleConfig, .set_state = spindleSetStateVariable, .get_state = spindleGetState, @@ -2951,10 +3125,29 @@ bool driver_init (void) } }; + #if PPI_ENABLE + + static timer_cfg_t cfg = { + .single_shot = On, + .timeout_callback = spindlePulseOff + }; + + if((ppi_timer = hal.timer.claim((timer_cap_t){ .periodic = Off }, 1000))) { + hal.timer.configure(ppi_timer, &cfg); + ppi_init(); + } + + #endif + #else static const spindle_ptrs_t spindle = { .type = SpindleType_Basic, +#if DRIVER_SPINDLE_DIR_ENABLE + .ref_id = SPINDLE_ONOFF0_DIR, +#else + .ref_id = SPINDLE_ONOFF0, +#endif .set_state = spindleSetState, .get_state = spindleGetState, .esp32_off = spindleOffBasic, @@ -3083,7 +3276,9 @@ bool driver_init (void) hal.rgb0.out = neopixel_out; hal.rgb0.out_masked = neopixel_out_masked; hal.rgb0.set_intensity = neopixels_set_intensity; + hal.rgb0.write = neopixels_write; hal.rgb0.num_devices = NEOPIXELS_NUM; + hal.rgb0.flags = (rgb_properties_t){ .is_blocking = On, .is_strip = On }; hal.rgb0.cap = (rgb_color_t){ .R = 255, .G = 255, .B = 255 }; const periph_pin_t neopixels = { diff --git a/main/driver.h b/main/driver.h index dc55240..740d4f6 100644 --- a/main/driver.h +++ b/main/driver.h @@ -61,6 +61,10 @@ #error "Cannot use static IP for station when soft AP is enabled!" #endif +#if PPI_ENABLE +#error "PPI mode not supported due to framework not supporting FPU access in interrupt context!" +#endif + #ifndef GRBLHAL_TASK_PRIORITY #define GRBLHAL_TASK_PRIORITY 5 #endif @@ -169,6 +173,10 @@ typedef struct { #error "Pins 34 - 39 are input only!" #endif +#if USE_I2S_OUT && STEP_INJECT_ENABLE +#error "Step injection not yet possible with I2S streaming!" +#endif + #if DRIVER_SPINDLE_PWM_ENABLE && !defined(SPINDLE_PWM_PIN) #warning "PWM spindle is not supported by board map!" #undef DRIVER_SPINDLE_PWM_ENABLE @@ -181,6 +189,13 @@ typedef struct { #define SAFETY_DOOR_ENABLE 0 #endif +#ifndef STEP_TIMER_GROUP +#define STEP_TIMER_GROUP TIMER_GROUP_0 +#endif +#ifndef STEP_TIMER_INDEX +#define STEP_TIMER_INDEX TIMER_0 +#endif + #if IOEXPAND_ENABLE || EEPROM_ENABLE || KEYPAD_ENABLE == 1 || I2C_STROBE_ENABLE || (TRINAMIC_ENABLE && TRINAMIC_I2C) #undef I2C_ENABLE #define I2C_ENABLE 1 @@ -307,7 +322,7 @@ extern SemaphoreHandle_t i2cBusy; #else #define USE_I2S_OUT 0 #define DIGITAL_IN(pin) gpio_ll_get_level(&GPIO, pin) -#define DIGITAL_OUT(pin, state) gpio_ll_set_level(&GPIO, pin, state) +#define DIGITAL_OUT(pin, state) gpio_ll_set_level(&GPIO, pin, (state)) #endif typedef enum diff --git a/main/my_machine.h b/main/my_machine.h index 595dbb8..7fa86cd 100644 --- a/main/my_machine.h +++ b/main/my_machine.h @@ -73,7 +73,6 @@ // 2: Mode switching is by the CMD_MPG_ENABLE_TOGGLE (0x8B) command character. //#define KEYPAD_ENABLE 1 // 1: uses a I2C keypad for input. // 2: uses a serial stream for input. If MPG_ENABLE is set > 0 the serial stream is shared with the MPG. -//#define PPI_ENABLE 1 // Laser PPI plugin. To be completed. //#define LASER_COOLANT_ENABLE 1 // Laser coolant plugin. To be completed. //#define LB_CLUSTERS_ENABLE 1 // LaserBurn cluster support. //#define FANS_ENABLE 1 // Enable fan control via M106/M107. Enables fans plugin. diff --git a/main/timers.c b/main/timers.c new file mode 100644 index 0000000..d56d329 --- /dev/null +++ b/main/timers.c @@ -0,0 +1,139 @@ +/* + + timers.c - driver code for ESP32 processors + + Part of grblHAL + + Copyright (c) 2024 Terje Io + + grblHAL 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. + + grblHAL 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 grblHAL. If not, see . +*/ + +#include "driver.h" + +typedef struct { + uint32_t group; + uint32_t index; + timer_resolution_t resolution; + bool claimed; + timer_cfg_t cfg; + timer_cap_t cap; + uint32_t freq_hz; + uint32_t timebase; + void (*isr)(void * arg); +} dtimer_t; + +IRAM_ATTR static void timer01_isr (void *arg) +{ +#if CONFIG_IDF_TARGET_ESP32S3 + TIMERG0.int_clr_timers.t1_int_clr = 1; +#else + TIMERG0.int_clr_timers.t1 = 1; +#endif + ((dtimer_t *)arg)->cfg.timeout_callback(((dtimer_t *)arg)->cfg.context); +} + +IRAM_ATTR static void timer10_isr (void *arg) +{ +#if CONFIG_IDF_TARGET_ESP32S3 + TIMERG1.int_clr_timers.t0_int_clr = 1; +#else + TIMERG1.int_clr_timers.t0 = 1; +#endif + ((dtimer_t *)arg)->cfg.timeout_callback(((dtimer_t *)arg)->cfg.context); +} + +IRAM_ATTR static void timer11_isr (void *arg) +{ +#if CONFIG_IDF_TARGET_ESP32S3 + TIMERG1.int_clr_timers.t1_int_clr = 1; +#else + TIMERG1.int_clr_timers.t1 = 1; +#endif + ((dtimer_t *)arg)->cfg.timeout_callback(((dtimer_t *)arg)->cfg.context); +} + +static dtimer_t timers[] = { + { .group = 0, .index = 1, .freq_hz = 80000000, .isr = timer01_isr }, + { .group = 1, .index = 0, .freq_hz = 80000000, .isr = timer10_isr }, + { .group = 1, .index = 1, .freq_hz = 80000000, .isr = timer11_isr } +}; + +hal_timer_t timerClaim (timer_cap_t cap, uint32_t timebase) +{ + hal_timer_t t; + uint_fast8_t idx, n_timers = sizeof(timers) / sizeof(dtimer_t); + + for(idx = 0; idx < n_timers; idx++) { + if((t = timers[idx].claimed ? NULL : &timers[idx])) { + timers[idx].claimed = true; + timers[idx].timebase = timebase; + break; + } + } + + return t; +} + +bool timerCfg (hal_timer_t timer, timer_cfg_t *cfg) +{ + bool ok; + + if((ok = timer != NULL)) { + + dtimer_t *dtimer = (dtimer_t *)timer; + + memcpy(&dtimer->cfg, cfg, sizeof(timer_cfg_t)); + + timer_config_t timerConfig = { + .counter_dir = TIMER_COUNT_UP, + .counter_en = TIMER_PAUSE, + .alarm_en = TIMER_ALARM_EN, + .intr_type = TIMER_INTR_LEVEL + }; + + timerConfig.auto_reload = !cfg->single_shot; + timerConfig.divider = ((dtimer->freq_hz / 1000) * dtimer->timebase) / 1000000; + + timer_init(dtimer->group, dtimer->index, &timerConfig); + timer_set_counter_value(dtimer->group, dtimer->index, 0ULL); + timer_isr_register(dtimer->group, dtimer->index, dtimer->isr, timer, ESP_INTR_FLAG_IRAM, NULL); + timer_enable_intr(dtimer->group, dtimer->index); + } + + return ok; +} + +bool timerStart (hal_timer_t timer, uint32_t period) +{ + dtimer_t *dtimer = (dtimer_t *)timer; + + timer_set_counter_value(dtimer->group, dtimer->index, 0x00000000ULL); + timer_set_alarm_value(dtimer->group, dtimer->index, (uint64_t)period); + timer_start(dtimer->group, dtimer->index); +#if CONFIG_IDF_TARGET_ESP32S3 + TIMERG0.hw_timer[dtimer->index].config.tn_alarm_en = TIMER_ALARM_EN; +#else + TIMERG0.hw_timer[dtimer->index].config.alarm_en = TIMER_ALARM_EN; +#endif + + return true; +} + +bool timerStop (hal_timer_t timer) +{ + timer_pause(((dtimer_t *)timer)->group, ((dtimer_t *)timer)->index); + + return true; +} diff --git a/main/timers.h b/main/timers.h new file mode 100644 index 0000000..bac016f --- /dev/null +++ b/main/timers.h @@ -0,0 +1,32 @@ +/* + + timers.h - driver code for STM32F7xx ARM processors + + Part of grblHAL + + Copyright (c) 2024 Terje Io + + grblHAL 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. + + grblHAL 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 grblHAL. If not, see . +*/ + +#pragma once + +#include "grbl/hal.h" + +hal_timer_t timerClaim (timer_cap_t cap, uint32_t timebase); +bool timerCfg (hal_timer_t timer, timer_cfg_t *cfg); +bool timerStart (hal_timer_t timer, uint32_t period); +bool timerStop (hal_timer_t timer); + +/**/