mirror of
https://github.com/synthetos/g2.git
synced 2026-09-26 01:02:30 +08:00
Checkpoint - generalizing planner buffer handling
This commit is contained in:
Executable → Regular
+1
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* hardware.h - system hardware configuration
|
||||
* for: /board/g2v9
|
||||
* THIS FILE IS HARDWARE PLATFORM SPECIFIC - ARM version
|
||||
*
|
||||
* This file is part of the g2core project
|
||||
|
||||
@@ -537,6 +537,17 @@ stat_t mp_exec_aline(mpBuf_t *bf)
|
||||
return (status);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* mp_plan_feedhold_move() - plan Z lift moves for feedhold
|
||||
*/
|
||||
|
||||
stat_t mp_plan_feedhold_move()
|
||||
{
|
||||
|
||||
return (STAT_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* mp_exit_hold_state() - end a feedhold
|
||||
*
|
||||
|
||||
+17
-16
@@ -129,16 +129,15 @@ bool mp_runtime_is_idle() { return (!st_runtime_isbusy()); }
|
||||
* Controlling jerk smooths transitions between moves and allows for faster feeds while
|
||||
* controlling machine oscillations and other undesirable side-effects.
|
||||
*
|
||||
* Note All math is done in absolute coordinates using single precision floating point (float).
|
||||
* Note: All math is done in absolute coordinates using single precision floating point (float).
|
||||
*
|
||||
* Note: Returning a status that is not STAT_OK means the endpoint is NOT advanced. So lines
|
||||
* that are too short to move will accumulate and get executed once the accumulated error
|
||||
* exceeds the minimums.
|
||||
*/
|
||||
|
||||
stat_t mp_aline(GCodeState_t* gm_in)
|
||||
stat_t mp_aline(GCodeState_t* gm_in)
|
||||
{
|
||||
mpBuf_t* bf; // current move pointer
|
||||
float target_rotated[AXES] = {0, 0, 0, 0, 0, 0};
|
||||
float axis_square[AXES] = {0, 0, 0, 0, 0, 0};
|
||||
float axis_length[AXES];
|
||||
@@ -191,33 +190,35 @@ stat_t mp_aline(GCodeState_t* gm_in)
|
||||
|
||||
// exit if the move has zero movement. At all.
|
||||
if (fp_ZERO(length)) {
|
||||
sr_request_status_report(SR_REQUEST_TIMED_FULL); // Was SR_REQUEST_IMMEDIATE_FULL
|
||||
sr_request_status_report(SR_REQUEST_TIMED_FULL); // Was SR_REQUEST_IMMEDIATE_FULL
|
||||
return (STAT_MINIMUM_LENGTH_MOVE);
|
||||
}
|
||||
|
||||
// get a cleared buffer and copy in the Gcode model state
|
||||
if ((bf = mp_get_write_buffer()) == NULL) { // never supposed to fail
|
||||
mpBuf_t* bf = mp_get_write_buffer();
|
||||
if (bf == NULL) { // never supposed to fail
|
||||
// if ((bf = mp_get_write_buffer()) == NULL) { // never supposed to fail
|
||||
return (cm_panic(STAT_FAILED_GET_PLANNER_BUFFER, "aline()"));
|
||||
}
|
||||
memcpy(&bf->gm, gm_in, sizeof(GCodeState_t));
|
||||
// Since bf->gm.target is being used all over the place, we'll make it the rotated target
|
||||
copy_vector(bf->gm.target, target_rotated); // copy the rotated taget in place
|
||||
copy_vector(bf->gm.target, target_rotated); // copy the rotated taget in place
|
||||
|
||||
// setup the buffer
|
||||
bf->bf_func = mp_exec_aline; // register the callback to the exec function
|
||||
bf->length = length; // record the length
|
||||
for (uint8_t axis = 0; axis < AXES; axis++) { // compute the unit vector and set flags
|
||||
if ((bf->axis_flags[axis] = flags[axis])) { // yes, this is supposed to be = and not ==
|
||||
bf->unit[axis] = axis_length[axis] / length; // nb: bf-> unit was cleared by mp_get_write_buffer()
|
||||
bf->bf_func = mp_exec_aline; // register the callback to the exec function
|
||||
bf->length = length; // record the length
|
||||
for (uint8_t axis = 0; axis < AXES; axis++) { // compute the unit vector and set flags
|
||||
if ((bf->axis_flags[axis] = flags[axis])) { // yes, this is supposed to be = and not ==
|
||||
bf->unit[axis] = axis_length[axis] / length;// nb: bf-> unit was cleared by mp_get_write_buffer()
|
||||
}
|
||||
}
|
||||
_calculate_jerk(bf); // compute bf->jerk values
|
||||
_calculate_vmaxes(bf, axis_length, axis_square); // compute cruise_vmax and absolute_vmax
|
||||
_set_bf_diagnostics(bf); //+++++DIAGNOSTIC
|
||||
_calculate_jerk(bf); // compute bf->jerk values
|
||||
_calculate_vmaxes(bf, axis_length, axis_square); // compute cruise_vmax and absolute_vmax
|
||||
_set_bf_diagnostics(bf); //+++++DIAGNOSTIC
|
||||
|
||||
// Note: these next lines must remain in exact order. Position must update before committing the buffer.
|
||||
copy_vector(mp.position, bf->gm.target); // set the planner position
|
||||
mp_commit_write_buffer(BLOCK_TYPE_ALINE); // commit current block (must follow the position update)
|
||||
copy_vector(mp.position, bf->gm.target); // set the planner position
|
||||
mp_commit_write_buffer(BLOCK_TYPE_ALINE); // commit current block (must follow the position update)
|
||||
return (STAT_OK);
|
||||
}
|
||||
|
||||
|
||||
Executable → Regular
+60
-8
@@ -65,9 +65,10 @@
|
||||
#include "xio.h" //+++++ DIAGNOSTIC - only needed if xio_writeline() direct prints are used
|
||||
|
||||
// Allocate planner structures
|
||||
mpBufferPool_t mb; // buffer pool management
|
||||
mpMotionPlannerSingleton_t mp; // context for block planning
|
||||
mpMotionRuntimeSingleton_t mr; // context for block runtime
|
||||
mpBufferPool_t mb; // buffer pool management
|
||||
mpBuf_t mb_pool0[PLANNER_BUFFER_POOL_SIZE]; // storage allocation for pool #1 buffers
|
||||
mpMotionPlannerSingleton_t mp; // context for block planning
|
||||
mpMotionRuntimeSingleton_t mr; // context for block runtime
|
||||
|
||||
#define JSON_COMMAND_BUFFER_SIZE 3
|
||||
|
||||
@@ -700,15 +701,68 @@ static inline void _clear_buffer(mpBuf_t *bf)
|
||||
bf->clear();
|
||||
}
|
||||
|
||||
void mp_init_buffers(void)
|
||||
void _init_buffers(mpBuf_t *base, uint8_t size)
|
||||
{
|
||||
mpBuf_t *pv, *nx;
|
||||
uint8_t i, nx_i;
|
||||
|
||||
memset(&mb, 0, sizeof(mb)); // clear all values, pointers and status
|
||||
// memset(base, 0, sizeof(mpBuf_t * size)); // clear all buffers in pool
|
||||
mb.bf = base; // link the buffer pool first
|
||||
mb.w = mb.bf; // init all buffer pointers
|
||||
mb.r = mb.bf;
|
||||
mb.queue_size = size-1;
|
||||
mb.buffers_available = size;
|
||||
|
||||
pv = &mb.bf[size-1];
|
||||
for (i=0; i < size-1; i++) {
|
||||
mb.bf[i].buffer_number = i; //+++++ number it for diagnostics only (otherwise not used)
|
||||
|
||||
nx_i = ((i<size-1) ? (i+1) : 0); // buffer increment & wrap
|
||||
nx = &mb.bf[nx_i];
|
||||
mb.bf[i].nx = nx; // setup circular list pointers
|
||||
mb.bf[i].pv = pv;
|
||||
pv = &mb.bf[i];
|
||||
}
|
||||
}
|
||||
|
||||
void mp_init_buffers(void)
|
||||
{
|
||||
// mpBuf_t *pv, *nx;
|
||||
// uint8_t i, nx_i;
|
||||
|
||||
// memset(&mb_pool0, 0, sizeof(mb_pool0)); // clear all buffers in pool
|
||||
memset(&mb, 0, sizeof(mb)); // clear values, pointers and status
|
||||
mb.magic_start = MAGICNUM;
|
||||
mb.magic_end = MAGICNUM;
|
||||
|
||||
_init_buffers(mb_pool0, PLANNER_BUFFER_POOL_SIZE);
|
||||
/*
|
||||
mb.bf = mb_pool0; // link the buffer pool first
|
||||
mb.w = mb.bf; // init all buffer pointers
|
||||
mb.r = mb.bf;
|
||||
mb.buffers_total = PLANNER_BUFFER_POOL_SIZE-1;
|
||||
|
||||
pv = &mb.bf[PLANNER_BUFFER_POOL_SIZE-1];
|
||||
for (i=0; i < mb.buffers_total; i++) {
|
||||
mb.bf[i].buffer_number = i; //+++++ number it for diagnostics only (otherwise not used)
|
||||
|
||||
nx_i = ((i<mb.buffers_total) ? (i+1) : 0); // buffer increment & wrap
|
||||
nx = &mb.bf[nx_i];
|
||||
mb.bf[i].nx = nx; // setup ring pointers
|
||||
mb.bf[i].pv = pv;
|
||||
|
||||
pv = &mb.bf[i];
|
||||
}
|
||||
mb.buffers_available = PLANNER_BUFFER_POOL_SIZE;
|
||||
*/
|
||||
// Now handle the two "stub buffers" in the runtime structure.
|
||||
mr.bf[0].nx = &mr.bf[1];
|
||||
mr.bf[1].nx = &mr.bf[0];
|
||||
mr.r = &mr.bf[0];
|
||||
mr.p = &mr.bf[1];
|
||||
}
|
||||
|
||||
/*
|
||||
mb.w = &mb.bf[0]; // init all buffer pointers
|
||||
mb.r = &mb.bf[0];
|
||||
pv = &mb.bf[PLANNER_BUFFER_POOL_SIZE-1];
|
||||
@@ -724,15 +778,13 @@ void mp_init_buffers(void)
|
||||
}
|
||||
mb.buffers_available = PLANNER_BUFFER_POOL_SIZE;
|
||||
|
||||
// mb.entry_changed = false;
|
||||
|
||||
// Now handle the two "stub buffers" in the runtime structure.
|
||||
mr.bf[0].nx = &mr.bf[1];
|
||||
mr.bf[1].nx = &mr.bf[0];
|
||||
mr.r = &mr.bf[0];
|
||||
mr.p = &mr.bf[1];
|
||||
}
|
||||
|
||||
*/
|
||||
/*
|
||||
* These GET functions are defined here but we use the macros in planner.h instead
|
||||
*
|
||||
|
||||
Executable → Regular
+14
-1
@@ -125,6 +125,7 @@ typedef enum {
|
||||
|
||||
#define PLANNER_BUFFER_POOL_SIZE ((uint8_t)48) // Suggest 12 min. Limit is 255
|
||||
#define PLANNER_BUFFER_HEADROOM ((uint8_t)4) // Buffers to reserve in planner before processing new input line
|
||||
#define SECONDARY_BUFFER_POOL_SIZE ((uint8_t)4) // Secondary planner queue for feedhold operations
|
||||
#define JERK_MULTIPLIER ((float)1000000) // DO NOT CHANGE - must always be 1 million
|
||||
|
||||
#define JUNCTION_INTEGRATION_MIN (0.05) // minimum allowable setting
|
||||
@@ -241,7 +242,7 @@ typedef struct mpBuffer : mpBuffer_to_clear { // See Planning Velocity Notes for
|
||||
struct mpBuffer *nx; // static pointer to next buffer
|
||||
uint8_t buffer_number; //+++++ DIAGNOSTIC for easier debugging
|
||||
} mpBuf_t;
|
||||
|
||||
/*
|
||||
typedef struct mpBufferPool { // ring buffer for sub-moves
|
||||
magic_t magic_start; // magic number to test memory integrity
|
||||
|
||||
@@ -249,7 +250,19 @@ typedef struct mpBufferPool { // ring buffer for sub-moves
|
||||
mpBuf_t *w; // write buffer pointer
|
||||
uint8_t buffers_available; // running count of available buffers
|
||||
mpBuf_t bf[PLANNER_BUFFER_POOL_SIZE];// buffer storage
|
||||
|
||||
magic_t magic_end;
|
||||
} mpBufferPool_t;
|
||||
*/
|
||||
typedef struct mpBufferPool { // one or more planner buffer queues
|
||||
magic_t magic_start; // magic number to test memory integrity
|
||||
|
||||
mpBuf_t *r; // run buffer pointer
|
||||
mpBuf_t *w; // write buffer pointer
|
||||
uint8_t queue_size; // total number of buffers, zero-based (e.g. 47 not 48)
|
||||
uint8_t buffers_available; // running count of available buffers
|
||||
mpBuf_t *bf; // pointer to buffer storage array
|
||||
|
||||
magic_t magic_end;
|
||||
} mpBufferPool_t;
|
||||
|
||||
|
||||
+14
-13
@@ -430,28 +430,29 @@ static void _load_move()
|
||||
// Be aware that dda_ticks_downcount must equal zero for the loader to run.
|
||||
// So the initial load must also have this set to zero as part of initialization
|
||||
if (st_runtime_isbusy()) {
|
||||
return; // exit if the runtime is busy
|
||||
return; // exit if the runtime is busy
|
||||
}
|
||||
if (st_pre.buffer_state != PREP_BUFFER_OWNED_BY_LOADER) { // if there are no moves to load...
|
||||
|
||||
// ...start motor power timeouts
|
||||
// for (uint8_t motor = MOTOR_1; motor < MOTORS; motor++) {
|
||||
// Motors[motor]->motionStopped();
|
||||
// }
|
||||
// loop unrolled version
|
||||
|
||||
// If there are no moves to load start motor power timeouts
|
||||
if (st_pre.buffer_state != PREP_BUFFER_OWNED_BY_LOADER) {
|
||||
// for (uint8_t motor = MOTOR_1; motor < MOTORS; motor++) {
|
||||
// Motors[motor]->motionStopped();
|
||||
// }
|
||||
|
||||
// loop unrolled version
|
||||
motor_1.motionStopped(); // ...start motor power timeouts
|
||||
motor_2.motionStopped(); // ...start motor power timeouts
|
||||
motor_2.motionStopped();
|
||||
#if (MOTORS > 2)
|
||||
motor_3.motionStopped(); // ...start motor power timeouts
|
||||
motor_3.motionStopped();
|
||||
#endif
|
||||
#if (MOTORS > 3)
|
||||
motor_4.motionStopped(); // ...start motor power timeouts
|
||||
motor_4.motionStopped();
|
||||
#endif
|
||||
#if (MOTORS > 4)
|
||||
motor_5.motionStopped(); // ...start motor power timeouts
|
||||
motor_5.motionStopped();
|
||||
#endif
|
||||
#if (MOTORS > 5)
|
||||
motor_6.motionStopped(); // ...start motor power timeouts
|
||||
motor_6.motionStopped();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
+1
-1
@@ -515,7 +515,7 @@ struct Stepper {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
virtual void periodicCheck(bool have_actually_stopped) // can be overridden
|
||||
{
|
||||
if (have_actually_stopped && _power_state == MOTOR_RUNNING) {
|
||||
|
||||
Reference in New Issue
Block a user