@@ -45,14 +45,10 @@ static st_block_t st_block_buffer[SEGMENT_BUFFER_SIZE - 1];
4545// the planner, where the remaining planner block steps still can.
4646typedef struct {
4747 uint16_t n_step; // Number of step events to be executed for this segment
48- uint16_t cycles_per_tick ; // Step distance traveled per ISR tick, aka step rate.
48+ uint16_t isrPeriod ; // Time to next ISR tick, in units of timer ticks
4949 uint8_t st_block_index; // Stepper block data index. Uses this information to execute this segment.
50- #ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING
51- uint8_t amass_level; // Indicates AMASS level for the ISR to execute this segment
52- #else
53- uint8_t prescaler; // Without AMASS, a prescaler is required to adjust for slow timing.
54- #endif
55- uint16_t spindle_rpm; // TODO get rid of this.
50+ uint8_t amass_level; // AMASS level for the ISR to execute this segment
51+ uint16_t spindle_rpm; // TODO get rid of this.
5652} segment_t ;
5753static segment_t segment_buffer[SEGMENT_BUFFER_SIZE];
5854
@@ -70,9 +66,7 @@ typedef struct {
7066 uint8_t step_pulse_time; // Step pulse reset time after step rise
7167 uint8_t step_outbits; // The next stepping-bits to be output
7268 uint8_t dir_outbits;
73- #ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING
7469 uint32_t steps[MAX_N_AXIS];
75- #endif
7670
7771 uint16_t step_count; // Steps remaining in line segment motion
7872 uint8_t exec_block_index; // Tracks the current st_block index. Change indicates new block.
@@ -94,7 +88,7 @@ static volatile uint8_t busy;
9488static plan_block_t * pl_block; // Pointer to the planner block being prepped
9589static st_block_t * st_prep_block; // Pointer to the stepper block data being prepped
9690
97- // esp32 work around for diable in main loop
91+ // esp32 work around for disable in main loop
9892uint64_t stepper_idle_counter; // used to count down until time to disable stepper drivers
9993bool stepper_idle;
10094
@@ -243,7 +237,7 @@ static void stepper_pulse_func() {
243237 // Initialize new step segment and load number of steps to execute
244238 st.exec_segment = &segment_buffer[segment_buffer_tail];
245239 // Initialize step segment timing per step and load number of steps to execute.
246- Stepper_Timer_WritePeriod (st.exec_segment ->cycles_per_tick );
240+ Stepper_Timer_WritePeriod (st.exec_segment ->isrPeriod );
247241 st.step_count = st.exec_segment ->n_step ; // NOTE: Can sometimes be zero when moving slow.
248242 // If the new segment starts a new planner block, initialize stepper variables and counters.
249243 // NOTE: When the segment data index changes, this indicates a new planner block.
@@ -258,12 +252,10 @@ static void stepper_pulse_func() {
258252 // TODO ABC
259253 }
260254 st.dir_outbits = st.exec_block ->direction_bits ;
261- #ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING
262- // With AMASS enabled, adjust Bresenham axis increment counters according to AMASS level.
255+ // Adjust Bresenham axis increment counters according to AMASS level.
263256 for (int axis = 0 ; axis < n_axis; axis++) {
264257 st.steps [axis] = st.exec_block ->steps [axis] >> st.exec_segment ->amass_level ;
265258 }
266- #endif
267259 // Set real-time spindle output as segment is loaded, just prior to the first step.
268260 spindle->set_rpm (st.exec_segment ->spindle_rpm );
269261 } else {
@@ -374,7 +366,7 @@ void st_wake_up() {
374366 // Step pulse delay handling is not require with ESP32...the RMT function does it.
375367#else // Normal operation
376368 // Set step pulse time. Ad hoc computation from oscilloscope. Uses two's complement.
377- st.step_pulse_time = -(((pulse_microseconds->get () - 2 ) * TICKS_PER_MICROSECOND ) >> 3 );
369+ st.step_pulse_time = -(((pulse_microseconds->get () - 2 ) * ticksPerMicrosecond ) >> 3 );
378370#endif
379371 // Enable Stepper Driver Interrupt
380372 Stepper_Timer_Start ();
@@ -538,20 +530,15 @@ void st_prep_buffer() {
538530 st_prep_block->direction_bits = pl_block->direction_bits ;
539531 uint8_t idx;
540532 auto n_axis = number_axis->get ();
541- #ifndef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING
542- for (idx = 0 ; idx < n_axis; idx++) {
543- st_prep_block->steps [idx] = pl_block->steps [idx];
544- }
545- st_prep_block->step_event_count = pl_block->step_event_count ;
546- #else
547- // With AMASS enabled, simply bit-shift multiply all Bresenham data by the max AMASS
548- // level, such that we never divide beyond the original data anywhere in the algorithm.
533+
534+ // Bit-shift multiply all Bresenham data by the max AMASS level so that
535+ // we never divide beyond the original data anywhere in the algorithm.
549536 // If the original data is divided, we can lose a step from integer roundoff.
550537 for (idx = 0 ; idx < n_axis; idx++) {
551- st_prep_block->steps [idx] = pl_block->steps [idx] << MAX_AMASS_LEVEL ;
538+ st_prep_block->steps [idx] = pl_block->steps [idx] << maxAmassLevel ;
552539 }
553- st_prep_block->step_event_count = pl_block->step_event_count << MAX_AMASS_LEVEL ;
554- # endif
540+ st_prep_block->step_event_count = pl_block->step_event_count << maxAmassLevel ;
541+
555542 // Initialize segment buffer data for generating the segments.
556543 prep.steps_remaining = (float )pl_block->step_event_count ;
557544 prep.step_per_mm = prep.steps_remaining / pl_block->millimeters ;
@@ -839,49 +826,28 @@ void st_prep_buffer() {
839826 // outputs the exact acceleration and velocity profiles as computed by the planner.
840827
841828 dt += prep.dt_remainder ; // Apply previous segment partial step execute time
829+ // dt is in minutes so inv_rate is in minutes
842830 float inv_rate = dt / (last_n_steps_remaining - step_dist_remaining); // Compute adjusted step rate inverse
843831
844832 // Compute CPU cycles per step for the prepped segment.
845- uint32_t cycles = ceil ((TICKS_PER_MICROSECOND * 1000000 * 60 ) * inv_rate); // (cycles/step)
833+ // fStepperTimer is in units of timerTicks/sec, so the dimensional analysis is
834+ // timerTicks/sec * 60 sec/minute * minutes = timerTicks
835+ uint32_t timerTicks = ceil ((fStepperTimer * 60 ) * inv_rate); // (timerTicks/step)
836+ int level;
846837
847- #ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING
848838 // Compute step timing and multi-axis smoothing level.
849- // NOTE: AMASS overdrives the timer with each level, so only one prescalar is required.
850- if (cycles < AMASS_LEVEL1) {
851- prep_segment->amass_level = 0 ;
852- } else {
853- if (cycles < AMASS_LEVEL2) {
854- prep_segment->amass_level = 1 ;
855- } else if (cycles < AMASS_LEVEL3) {
856- prep_segment->amass_level = 2 ;
857- } else {
858- prep_segment->amass_level = 3 ;
859- }
860- cycles >>= prep_segment->amass_level ;
861- prep_segment->n_step <<= prep_segment->amass_level ;
862- }
863- if (cycles < (1UL << 16 )) {
864- prep_segment->cycles_per_tick = cycles; // < 65536 (4.1ms @ 16MHz)
865- } else {
866- prep_segment->cycles_per_tick = 0xffff ; // Just set the slowest speed possible.
867- }
868- #else
869- // Compute step timing and timer prescalar for normal step generation.
870- if (cycles < (1UL << 16 )) { // < 65536 (4.1ms @ 16MHz)
871- prep_segment->prescaler = 1 ; // prescaler: 0
872- prep_segment->cycles_per_tick = cycles;
873- } else if (cycles < (1UL << 19 )) { // < 524288 (32.8ms@16MHz)
874- prep_segment->prescaler = 2 ; // prescaler: 8
875- prep_segment->cycles_per_tick = cycles >> 3 ;
876- } else {
877- prep_segment->prescaler = 3 ; // prescaler: 64
878- if (cycles < (1UL << 22 )) { // < 4194304 (262ms@16MHz)
879- prep_segment->cycles_per_tick = cycles >> 6 ;
880- } else { // Just set the slowest speed possible. (Around 4 step/sec.)
881- prep_segment->cycles_per_tick = 0xffff ;
839+ for (level = 0 ; level < maxAmassLevel; level++) {
840+ if (timerTicks < amassThreshold) {
841+ break ;
882842 }
843+ timerTicks >>= 1 ;
883844 }
884- #endif
845+ prep_segment->amass_level = level;
846+ prep_segment->n_step <<= level;
847+ // isrPeriod is stored as 16 bits, so limit timerTicks to the
848+ // largest value that will fit in a uint16_t.
849+ prep_segment->isrPeriod = timerTicks > 0xffff ? 0xffff : timerTicks;
850+
885851 // Segment complete! Increment segment buffer indices, so stepper ISR can immediately execute it.
886852 segment_buffer_head = segment_next_head;
887853 if (++segment_next_head == SEGMENT_BUFFER_SIZE) {
@@ -935,21 +901,23 @@ float st_get_realtime_rate() {
935901 }
936902}
937903
938- void IRAM_ATTR Stepper_Timer_WritePeriod (uint64_t alarm_val) {
904+ // The argument is in units of ticks of the timer that generates ISRs
905+ void IRAM_ATTR Stepper_Timer_WritePeriod (uint16_t timerTicks) {
939906 if (current_stepper == ST_I2S_STREAM) {
940907#ifdef USE_I2S_STEPS
941- // 1 tick = F_TIMERS / F_STEPPER_TIMER
908+ // 1 tick = fTimers / fStepperTimer
942909 // Pulse ISR is called for each tick of alarm_val.
943- i2s_out_set_pulse_period (alarm_val);
910+ // The argument to i2s_out_set_pulse_period is in units of microseconds
911+ i2s_out_set_pulse_period (((uint32_t )timerTicks) / ticksPerMicrosecond);
944912#endif
945913 } else {
946- timer_set_alarm_value (STEP_TIMER_GROUP, STEP_TIMER_INDEX, alarm_val );
914+ timer_set_alarm_value (STEP_TIMER_GROUP, STEP_TIMER_INDEX, ( uint64_t )timerTicks );
947915 }
948916}
949917
950918void IRAM_ATTR Stepper_Timer_Init () {
951919 timer_config_t config;
952- config.divider = F_TIMERS / F_STEPPER_TIMER ;
920+ config.divider = fTimers / fStepperTimer ;
953921 config.counter_dir = TIMER_COUNT_UP;
954922 config.counter_en = TIMER_PAUSE;
955923 config.alarm_en = TIMER_ALARM_EN;
0 commit comments