Protected buffer works! Vast improvements to planner efficiency. Many things still broken with overhaul.
Development push. Lots still broken. - Protected planner concept works! This is a critical precursor to enabling feedrate overrides in allowing the planner buffer and the stepper execution operate atomically. This is done through a intermediary segment buffer. - Still lots of work to be done, as this was a complete overhaul of the planner and stepper subsystems. The code can be cleaned up quite a bit, re-enabling some of the broken features like feed holds, and finishing up some of the concepts - Pushed some of the fixes from the master and edge branch to here, as this will likely replace the edge branch when done.
This commit is contained in:
267
stepper.c
267
stepper.c
@ -42,7 +42,7 @@
|
||||
#define ST_DECEL 2
|
||||
#define ST_DECEL_EOB 3
|
||||
|
||||
#define SEGMENT_BUFFER_SIZE 10
|
||||
#define SEGMENT_BUFFER_SIZE 6
|
||||
|
||||
// Stepper state variable. Contains running data and trapezoid variables.
|
||||
typedef struct {
|
||||
@ -50,11 +50,11 @@ typedef struct {
|
||||
int32_t counter_x, // Counter variables for the bresenham line tracer
|
||||
counter_y,
|
||||
counter_z;
|
||||
uint8_t segment_steps_remaining; // Steps remaining in line motion
|
||||
uint8_t segment_steps_remaining; // Steps remaining in line segment motion
|
||||
|
||||
// Used by inverse time algorithm to track step rate
|
||||
int32_t counter_d; // Inverse time distance traveled since last step event
|
||||
uint32_t delta_d; // Inverse time distance traveled per interrupt tick
|
||||
int32_t counter_d; // Inverse time distance traveled since last step event
|
||||
uint32_t delta_d; // Inverse time distance traveled per interrupt tick
|
||||
uint32_t d_per_tick;
|
||||
|
||||
// Used by the stepper driver interrupt
|
||||
@ -68,9 +68,11 @@ typedef struct {
|
||||
} stepper_t;
|
||||
static stepper_t st;
|
||||
|
||||
// Stores stepper buffer common data. Can change planner mid-block in special conditions.
|
||||
// Stores stepper buffer common data for a planner block. Data can change mid-block when the planner
|
||||
// updates the remaining block velocity profile with a more optimal plan or a feedrate override occurs.
|
||||
// NOTE: Normally, this buffer is only partially used, but can fill up completely in certain conditions.
|
||||
typedef struct {
|
||||
int32_t step_events_remaining; // Tracks step event count for the executing planner block
|
||||
int32_t step_events_remaining; // Tracks step event count for the executing planner block
|
||||
uint32_t d_next; // Scaled distance to next step
|
||||
uint32_t initial_rate; // Initialized step rate at re/start of a planner block
|
||||
uint32_t nominal_rate; // The nominal step rate for this block in step_events/minute
|
||||
@ -80,16 +82,17 @@ typedef struct {
|
||||
} st_data_t;
|
||||
static st_data_t segment_data[SEGMENT_BUFFER_SIZE];
|
||||
|
||||
// Primary stepper motion buffer
|
||||
// Primary stepper buffer. Contains small, short line segments for the stepper algorithm to execute checked
|
||||
// out incrementally from the first block in the planner buffer. These step segments
|
||||
typedef struct {
|
||||
uint8_t n_step;
|
||||
uint8_t st_data_index;
|
||||
uint8_t flag;
|
||||
uint8_t n_step; // Number of step events to be executed for this segment
|
||||
uint8_t st_data_index; // Stepper buffer common data index. Uses this information to execute this segment.
|
||||
uint8_t flag; // Stepper algorithm execution flag to notify special conditions.
|
||||
} st_segment_t;
|
||||
static st_segment_t segment_buffer[SEGMENT_BUFFER_SIZE];
|
||||
|
||||
static volatile uint8_t segment_buffer_tail;
|
||||
static uint8_t segment_buffer_head;
|
||||
static volatile uint8_t segment_buffer_head;
|
||||
static uint8_t segment_next_head;
|
||||
|
||||
static volatile uint8_t busy; // Used to avoid ISR nesting of the "Stepper Driver Interrupt". Should never occur though.
|
||||
@ -97,11 +100,16 @@ static plan_block_t *pl_current_block; // A pointer to the planner block curren
|
||||
static st_segment_t *st_current_segment;
|
||||
static st_data_t *st_current_data;
|
||||
|
||||
// Pointers for the step segment being prepped from the planner buffer. Accessed only by the
|
||||
// main program. Pointers may be planning segments or planner blocks ahead of what being executed.
|
||||
static plan_block_t *pl_prep_block; // A pointer to the planner block being prepped into the stepper buffer
|
||||
static uint8_t pl_prep_index;
|
||||
static st_data_t *st_prep_data;
|
||||
static uint8_t st_data_prep_index;
|
||||
|
||||
static uint8_t pl_partial_block_flag;
|
||||
|
||||
|
||||
|
||||
// Returns the index of the next block in the ring buffer
|
||||
// NOTE: Removed modulo (%) operator, which uses an expensive divide and multiplication.
|
||||
@ -115,7 +123,7 @@ static uint8_t next_block_index(uint8_t block_index)
|
||||
static uint8_t next_block_pl_index(uint8_t block_index)
|
||||
{
|
||||
block_index++;
|
||||
if (block_index == 18) { block_index = 0; }
|
||||
if (block_index == BLOCK_BUFFER_SIZE) { block_index = 0; }
|
||||
return(block_index);
|
||||
}
|
||||
|
||||
@ -255,22 +263,20 @@ ISR(TIMER2_COMPA_vect)
|
||||
|
||||
// Initialize inverse time and step rate counter data
|
||||
st.counter_d = st_current_data->d_next; // d_next always greater than delta_d.
|
||||
if (st.delta_d < MINIMUM_STEP_RATE) { st.d_per_tick = MINIMUM_STEP_RATE; }
|
||||
else { st.d_per_tick = st.delta_d; }
|
||||
|
||||
// During feed hold, do not update rate or ramp type. Keep decelerating.
|
||||
// if (sys.state == STATE_CYCLE) {
|
||||
st.delta_d = st_current_data->initial_rate;
|
||||
// if (st.delta_d == st_current_data->nominal_rate) {
|
||||
// st.ramp_type = RAMP_NOOP_CRUISE;
|
||||
st.ramp_type = RAMP_ACCEL;
|
||||
st.ramp_count = ISR_TICKS_PER_ACCELERATION_TICK/2; // Set ramp counter for trapezoid
|
||||
// }
|
||||
if (st.delta_d == st_current_data->nominal_rate) { st.ramp_type = RAMP_NOOP_CRUISE; }
|
||||
else { st.ramp_type = RAMP_ACCEL; }
|
||||
// }
|
||||
if (st.delta_d < MINIMUM_STEP_RATE) { st.d_per_tick = MINIMUM_STEP_RATE; }
|
||||
else { st.d_per_tick = st.delta_d; }
|
||||
|
||||
}
|
||||
|
||||
// Acceleration and cruise handled by ramping. Just check for deceleration.
|
||||
// Acceleration and cruise handled by ramping. Just check if deceleration needs to begin.
|
||||
if (st_current_segment->flag == ST_DECEL || st_current_segment->flag == ST_DECEL_EOB) {
|
||||
if (st.ramp_type == RAMP_NOOP_CRUISE) {
|
||||
st.ramp_count = ISR_TICKS_PER_ACCELERATION_TICK/2; // Set ramp counter for trapezoid
|
||||
@ -292,6 +298,8 @@ ISR(TIMER2_COMPA_vect)
|
||||
}
|
||||
|
||||
// Adjust inverse time counter for ac/de-celerations
|
||||
// NOTE: Accelerations are handled by the stepper algorithm as it's thought to be more computationally
|
||||
// efficient on the Arduino AVR. This could change eventually, but it definitely will with ARM development.
|
||||
if (st.ramp_type) {
|
||||
st.ramp_count--; // Tick acceleration ramp counter
|
||||
if (st.ramp_count == 0) { // Adjust step rate when its time
|
||||
@ -396,14 +404,20 @@ ISR(TIMER0_OVF_vect)
|
||||
void st_reset()
|
||||
{
|
||||
memset(&st, 0, sizeof(st));
|
||||
pl_current_block = NULL;
|
||||
pl_prep_block = NULL;
|
||||
pl_prep_index = 0;
|
||||
st_data_prep_index = 0;
|
||||
|
||||
st.load_flag = LOAD_BLOCK;
|
||||
busy = false;
|
||||
|
||||
pl_current_block = NULL; // Planner block pointer used by stepper algorithm
|
||||
pl_prep_block = NULL; // Planner block pointer used by segment buffer
|
||||
pl_prep_index = 0; // Planner buffer indices are also reset to zero.
|
||||
st_data_prep_index = 0;
|
||||
|
||||
segment_buffer_tail = 0;
|
||||
segment_buffer_head = 0; // empty = tail
|
||||
segment_next_head = 1;
|
||||
|
||||
pl_partial_block_flag = false;
|
||||
}
|
||||
|
||||
|
||||
@ -485,7 +499,7 @@ void st_cycle_reinitialize()
|
||||
}
|
||||
|
||||
|
||||
/* Preps stepper buffer. Called from main program.
|
||||
/* Prepares step segment buffer. Continuously called from main program.
|
||||
|
||||
NOTE: There doesn't seem to be a great way to figure out how many steps occur within
|
||||
a set number of ISR ticks. Numerical round-off and CPU overhead always seems to be a
|
||||
@ -510,41 +524,75 @@ void st_cycle_reinitialize()
|
||||
been doing here limit this phase issue by truncating some of the ramp timing for certain
|
||||
events like deceleration initialization and end of block.
|
||||
*/
|
||||
|
||||
// !!! Need to make sure when a single partially completed block can be re-computed here with
|
||||
// new deceleration point and the segment manager begins accelerating again immediately.
|
||||
void st_prep_buffer()
|
||||
{
|
||||
while (segment_buffer_tail != segment_next_head) { // Check if we need to fill the buffer.
|
||||
|
||||
// Determine if we need to load a new planner block.
|
||||
if (pl_prep_block == NULL) {
|
||||
pl_prep_block = plan_get_block_by_index(pl_prep_index);
|
||||
if (pl_prep_block == NULL) { return; } // No more planner blocks. Let stepper finish out.
|
||||
pl_prep_block = plan_get_block_by_index(pl_prep_index); // Query planner for a queued block
|
||||
if (pl_prep_block == NULL) { return; } // No planner blocks. Exit.
|
||||
|
||||
// Prepare commonly shared planner block data for the ensuing step buffer moves
|
||||
st_data_prep_index = next_block_index(st_data_prep_index);
|
||||
st_prep_data = &segment_data[st_data_prep_index];
|
||||
|
||||
// Initialize Bresenham variables
|
||||
st_prep_data->step_events_remaining = pl_prep_block->step_event_count;
|
||||
// Check if the planner has re-computed this block mid-execution. If so, push the old segment block
|
||||
// data Otherwise, prepare a new segment block data.
|
||||
if (pl_partial_block_flag) {
|
||||
|
||||
// Prepare new shared segment block data and copy the relevant last segment block data.
|
||||
st_data_t *last_st_prep_data;
|
||||
last_st_prep_data = &segment_data[st_data_prep_index];
|
||||
st_data_prep_index = next_block_index(st_data_prep_index);
|
||||
st_prep_data = &segment_data[st_data_prep_index];
|
||||
|
||||
st_prep_data->step_events_remaining = last_st_prep_data->step_events_remaining;
|
||||
st_prep_data->rate_delta = last_st_prep_data->rate_delta;
|
||||
st_prep_data->d_next = last_st_prep_data->d_next;
|
||||
st_prep_data->nominal_rate = last_st_prep_data->nominal_rate; // TODO: Recompute with feedrate overrides.
|
||||
|
||||
st_prep_data->mm_per_step = last_st_prep_data->mm_per_step;
|
||||
|
||||
// Convert new block to stepper variables.
|
||||
// NOTE: This data can change mid-block from normal planner updates and feedrate overrides. Must
|
||||
// be maintained as these execute.
|
||||
// TODO: If the planner updates this block, particularly from a deceleration to an acceleration,
|
||||
// we must reload the initial rate data, such that the velocity profile is re-constructed correctly.
|
||||
st_prep_data->initial_rate = ceil(sqrt(pl_prep_block->entry_speed_sqr)*(INV_TIME_MULTIPLIER/(60*ISR_TICKS_PER_SECOND))); // (mult*mm/isr_tic)
|
||||
st_prep_data->nominal_rate = ceil(sqrt(pl_prep_block->nominal_speed_sqr)*(INV_TIME_MULTIPLIER/(60.0*ISR_TICKS_PER_SECOND))); // (mult*mm/isr_tic)
|
||||
|
||||
// This data doesn't change. Could be performed in the planner, but fits nicely here.
|
||||
// Although, acceleration can change for S-curves. So keep it here.
|
||||
st_prep_data->rate_delta = ceil(pl_prep_block->acceleration*
|
||||
((INV_TIME_MULTIPLIER/(60.0*60.0))/(ISR_TICKS_PER_SECOND*ACCELERATION_TICKS_PER_SECOND))); // (mult*mm/isr_tic/accel_tic)
|
||||
// This definitely doesn't change, but could be precalculated in a way to help some of the
|
||||
// math in this handler, i.e. millimeters per step event data.
|
||||
st_prep_data->d_next = ceil((pl_prep_block->millimeters*INV_TIME_MULTIPLIER)/pl_prep_block->step_event_count); // (mult*mm/step)
|
||||
st_prep_data->mm_per_step = pl_prep_block->millimeters/pl_prep_block->step_event_count;
|
||||
|
||||
// Calculate trapezoid data from planner.
|
||||
st_prep_data->decelerate_after = calculate_trapezoid_for_block(pl_prep_index);
|
||||
pl_partial_block_flag = false; // Reset flag
|
||||
|
||||
// TODO: If the planner updates this block, particularly from a deceleration to an acceleration,
|
||||
// we must reload the initial rate data, such that the velocity profile is re-constructed correctly.
|
||||
// The stepper algorithm must be flagged to adjust the acceleration counters.
|
||||
|
||||
} else {
|
||||
|
||||
// Prepare commonly shared planner block data for the ensuing segment buffer moves ad-hoc, since
|
||||
// the planner buffer can dynamically change the velocity profile data as blocks are added.
|
||||
st_data_prep_index = next_block_index(st_data_prep_index);
|
||||
st_prep_data = &segment_data[st_data_prep_index];
|
||||
|
||||
// Initialize Bresenham variables
|
||||
st_prep_data->step_events_remaining = pl_prep_block->step_event_count;
|
||||
|
||||
// Convert planner block velocity profile data to stepper rate and step distance data.
|
||||
st_prep_data->nominal_rate = ceil(sqrt(pl_prep_block->nominal_speed_sqr)*(INV_TIME_MULTIPLIER/(60.0*ISR_TICKS_PER_SECOND))); // (mult*mm/isr_tic)
|
||||
st_prep_data->rate_delta = ceil(pl_prep_block->acceleration*
|
||||
((INV_TIME_MULTIPLIER/(60.0*60.0))/(ISR_TICKS_PER_SECOND*ACCELERATION_TICKS_PER_SECOND))); // (mult*mm/isr_tic/accel_tic)
|
||||
st_prep_data->d_next = ceil((pl_prep_block->millimeters*INV_TIME_MULTIPLIER)/pl_prep_block->step_event_count); // (mult*mm/step)
|
||||
|
||||
// TODO: Check if we really need to store this.
|
||||
st_prep_data->mm_per_step = pl_prep_block->millimeters/pl_prep_block->step_event_count;
|
||||
|
||||
}
|
||||
|
||||
// Convert planner entry speed to stepper initial rate.
|
||||
st_prep_data->initial_rate = ceil(sqrt(pl_prep_block->entry_speed_sqr)*(INV_TIME_MULTIPLIER/(60.0*ISR_TICKS_PER_SECOND))); // (mult*mm/isr_tic)
|
||||
|
||||
// TODO: Nominal rate changes with feedrate override.
|
||||
// st_prep_data->nominal_rate = ceil(sqrt(pl_prep_block->nominal_speed_sqr)*(INV_TIME_MULTIPLIER/(60.0*ISR_TICKS_PER_SECOND))); // (mult*mm/isr_tic)
|
||||
|
||||
// Calculate the planner block velocity profile type and determine deceleration point.
|
||||
float mm_decelerate_after = plan_calculate_velocity_profile(pl_prep_index);
|
||||
if (mm_decelerate_after == pl_prep_block->millimeters) {
|
||||
st_prep_data->decelerate_after = st_prep_data->step_events_remaining;
|
||||
} else {
|
||||
st_prep_data->decelerate_after = ceil( mm_decelerate_after/st_prep_data->mm_per_step );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -564,77 +612,108 @@ void st_prep_buffer()
|
||||
- From deceleration to acceleration, i.e. common with jogging when new blocks are added.
|
||||
*/
|
||||
|
||||
st_segment_t *st_prep_segment = &segment_buffer[segment_buffer_head];
|
||||
st_prep_segment->st_data_index = st_data_prep_index;
|
||||
st_segment_t *new_segment = &segment_buffer[segment_buffer_head];
|
||||
new_segment->st_data_index = st_data_prep_index;
|
||||
|
||||
// TODO: How do you cheaply compute n_step without a sqrt()? Could be performed as 'bins'.
|
||||
st_prep_segment->n_step = 250; //floor( (exit_speed*approx_time)/mm_per_step );
|
||||
// st_segment->n_step = max(st_segment->n_step,MINIMUM_STEPS_PER_BLOCK); // Ensure it moves for very slow motions?
|
||||
// st_segment->n_step = min(st_segment->n_step,MAXIMUM_STEPS_PER_BLOCK); // Prevent unsigned int8 overflow.
|
||||
// The basic equation is: s = u*t + 0.5*a*t^2
|
||||
// For the most part, we can store the acceleration portion in the st_data buffer and all
|
||||
// we would need to do is track the current approximate speed per loop with: v = u + a*t
|
||||
// Each loop would require 3 multiplication and 2 additions, since most of the variables
|
||||
// are constants and would get compiled out.
|
||||
|
||||
//!!! Doesn't work as is. Requires last_velocity and acceleration in terms of steps, not mm.
|
||||
// new_segment->n_step = ceil(last_velocity*TIME_PER_SEGMENT/mm_per_step);
|
||||
// if (st_prep_data->decelerate_after > 0) {
|
||||
// new_segment->n_step += ceil(pl_prep_block->acceleration*(0.5*TIME_PER_SEGMENT*TIME_PER_SEGMENT/(60*60))/mm_per_step);
|
||||
// } else {
|
||||
// new_segment->n_step -= ceil(pl_prep_block->acceleration*(0.5*TIME_PER_SEGMENT*TIME_PER_SEGMENT/(60*60))/mm_per_step);
|
||||
// }
|
||||
|
||||
new_segment->n_step = 7; //floor( (exit_speed*approx_time)/mm_per_step );
|
||||
// new_segment->n_step = max(new_segment->n_step,MINIMUM_STEPS_PER_BLOCK); // Ensure it moves for very slow motions?
|
||||
// new_segment->n_step = min(new_segment->n_step,MAXIMUM_STEPS_PER_BLOCK); // Prevent unsigned int8 overflow.
|
||||
|
||||
|
||||
// Check if n_step exceeds steps remaining in planner block. If so, truncate.
|
||||
if (st_prep_segment->n_step > st_prep_data->step_events_remaining) {
|
||||
st_prep_segment->n_step = st_prep_data->step_events_remaining;
|
||||
if (new_segment->n_step > st_prep_data->step_events_remaining) {
|
||||
new_segment->n_step = st_prep_data->step_events_remaining;
|
||||
|
||||
// Don't need to compute last velocity, since it will be refreshed with a new block.
|
||||
}
|
||||
|
||||
// Check if n_step exceeds decelerate point in block. Need to perform this so that the
|
||||
// ramp counters are reset correctly in the stepper algorithm. Can be 1 step, but should
|
||||
// be OK since it is likely moving at a fast rate already.
|
||||
if (st_prep_data->decelerate_after > 0) {
|
||||
if (st_prep_segment->n_step > st_prep_data->decelerate_after) {
|
||||
st_prep_segment->n_step = st_prep_data->decelerate_after;
|
||||
}
|
||||
}
|
||||
|
||||
// float distance, exit_speed_sqr;
|
||||
// distance = st_prep_segment->n_step*st_prep_data->mm_per_step; // Always greater than zero
|
||||
// if (st_prep_data->step_events_remaining >= pl_prep_block->decelerate_after) {
|
||||
// exit_speed_sqr = pl_prep_block->entry_speed_sqr - 2*pl_prep_block->acceleration*distance;
|
||||
// } else { // Acceleration or cruising ramp
|
||||
// if (pl_prep_block->entry_speed_sqr < pl_prep_block->nominal_speed_sqr) {
|
||||
// exit_speed_sqr = pl_prep_block->entry_speed_sqr + 2*pl_prep_block->acceleration*distance;
|
||||
// if (exit_speed_sqr > pl_prep_block->nominal_speed_sqr) { exit_speed_sqr = pl_prep_block->nominal_speed_sqr; }
|
||||
// } else {
|
||||
// exit_speed_sqr = pl_prep_block->nominal_speed_sqr;
|
||||
if (new_segment->n_step > st_prep_data->decelerate_after) {
|
||||
new_segment->n_step = st_prep_data->decelerate_after;
|
||||
}
|
||||
// !!! Doesn't work. Remove if not using.
|
||||
// if (last_velocity < last_nominal_v) {
|
||||
// // !!! Doesn't work since distance changes and gets truncated.
|
||||
// last_velocity += pl_prep_block->acceleration*(TIME_PER_SEGMENT/(60*60)); // In acceleration ramp.
|
||||
// if {last_velocity > last_nominal_v) { last_velocity = last_nominal_v; } // Set to cruising.
|
||||
// }
|
||||
// }
|
||||
|
||||
// Update planner block variables.
|
||||
// pl_prep_block->entry_speed_sqr = max(0.0,exit_speed_sqr);
|
||||
// pl_prep_block->max_entry_speed_sqr = exit_speed_sqr; // ??? Overwrites the corner speed. May need separate variable.
|
||||
// pl_prep_block->millimeters -= distance; // Potential round-off error near end of block.
|
||||
// pl_prep_block->millimeters = max(0.0,pl_prep_block->millimeters); // Shouldn't matter.
|
||||
// } else { // In deceleration ramp
|
||||
// last_velocity -= pl_prep_block->acceleration*(TIME_PER_SEGMENT/(60*60));
|
||||
}
|
||||
|
||||
// Update stepper block variables.
|
||||
st_prep_data->step_events_remaining -= st_prep_segment->n_step;
|
||||
st_prep_data->step_events_remaining -= new_segment->n_step;
|
||||
if ( st_prep_data->step_events_remaining == 0 ) {
|
||||
// Move planner pointer to next block
|
||||
if (st_prep_data->decelerate_after == 0) {
|
||||
st_prep_segment->flag = ST_DECEL_EOB;
|
||||
new_segment->flag = ST_DECEL_EOB; // Flag when deceleration begins and ends at EOB. Could rewrite to use bit flags too.
|
||||
} else {
|
||||
st_prep_segment->flag = ST_END_OF_BLOCK;
|
||||
new_segment->flag = ST_END_OF_BLOCK;
|
||||
}
|
||||
pl_prep_index = next_block_pl_index(pl_prep_index);
|
||||
pl_prep_block = NULL;
|
||||
printString("EOB");
|
||||
} else {
|
||||
// Current segment is mid-planner block. Just set the DECEL/NOOP acceleration flags.
|
||||
if (st_prep_data->decelerate_after == 0) {
|
||||
st_prep_segment->flag = ST_DECEL;
|
||||
new_segment->flag = ST_DECEL;
|
||||
} else {
|
||||
st_prep_segment->flag = ST_NOOP;
|
||||
new_segment->flag = ST_NOOP;
|
||||
}
|
||||
printString("x");
|
||||
st_prep_data->decelerate_after -= new_segment->n_step;
|
||||
}
|
||||
st_prep_data->decelerate_after -= st_prep_segment->n_step;
|
||||
|
||||
|
||||
// New step block completed. Increment step buffer indices.
|
||||
// New step segment completed. Increment segment buffer indices.
|
||||
segment_buffer_head = segment_next_head;
|
||||
segment_next_head = next_block_index(segment_buffer_head);
|
||||
|
||||
printInteger((long)st_prep_segment->n_step);
|
||||
printString(" ");
|
||||
printInteger((long)st_prep_data->decelerate_after);
|
||||
printString(" ");
|
||||
printInteger((long)st_prep_data->step_events_remaining);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t st_get_prep_block_index()
|
||||
{
|
||||
// Returns only the index but doesn't state if the block has been partially executed. How do we simply check for this?
|
||||
return(pl_prep_index);
|
||||
}
|
||||
|
||||
void st_fetch_partial_block_parameters(uint8_t block_index, float *millimeters_remaining, uint8_t *is_decelerating)
|
||||
{
|
||||
// if called, can we assume that this always changes and needs to be updated? if so, then
|
||||
// we can perform all of the segment buffer setup tasks here to make sure the next time
|
||||
// the segments are loaded, the st_data buffer is updated correctly.
|
||||
// !!! Make sure that this is always pointing to the correct st_prep_data block.
|
||||
|
||||
// When a mid-block acceleration occurs, we have to make sure the ramp counters are updated
|
||||
// correctly, much in the same fashion as the deceleration counters. Need to think about this
|
||||
// make sure this is right, but i'm pretty sure it is.
|
||||
|
||||
// TODO: NULL means that the segment buffer has completed the block. Need to clean this up a bit.
|
||||
if (pl_prep_block != NULL) {
|
||||
*millimeters_remaining = st_prep_data->step_events_remaining*st_prep_data->mm_per_step;
|
||||
if (st_prep_data->decelerate_after > 0) { *is_decelerating = false; }
|
||||
else { *is_decelerating = true; }
|
||||
|
||||
// Flag for new prep_block when st_prep_buffer() is called after the planner recomputes.
|
||||
pl_partial_block_flag = true;
|
||||
pl_prep_block = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
Reference in New Issue
Block a user