diff --git a/g2core/canonical_machine.cpp b/g2core/canonical_machine.cpp
index 47b3bafc..e3f74621 100644
--- a/g2core/canonical_machine.cpp
+++ b/g2core/canonical_machine.cpp
@@ -113,11 +113,11 @@
**** CM GLOBALS & STRUCTURE ALLOCATIONS *******************************************
***********************************************************************************/
-cmMachineSelect cm_select;
-cmMachine_t *cm; // pointer to active canonical machine
-cmMachine_t cm1; // canonical machine primary machine
-cmMachine_t cm2; // canonical machine secondary machine
-cmToolTable_t tt; // global tool table
+cmMachineSelect cm_select; // CM_PRIMARY, CM_SECONDARY, CM_SECONDARY_RETURN
+cmMachine_t *cm; // pointer to active canonical machine
+cmMachine_t cm1; // canonical machine primary machine
+cmMachine_t cm2; // canonical machine secondary machine
+cmToolTable_t tt; // global tool table
/***********************************************************************************
**** GENERIC STATIC FUNCTIONS AND VARIABLES ***************************************
@@ -1766,52 +1766,81 @@ stat_t cm_mto_control(const float P_word, const bool P_flag) // M50.1
* to ensure that it either arrives on the data channel or that the data channel is
* empty before writing it to the control channel.
*/
+/* With the addition of the secondary CM, feedhold state management gets tricky.
+ What you see below is a temporary solution until we decide the general solution.
+
+ The general solution causes a feedhold from the primary context to switch
+ into the secondary context to perform feedhold actions. When in the secondary
+ context an additional feedhold will perform the usual STOP operation, but
+ will remain in the secondary context, and therefore not perform any feedhold
+ actions (lifts, spindle, etc.). This is needed to support homing and probing
+ operations from within the secondary context.
+
+ Oddities of the general solution:
+ - Should we allow a feedhold to be peformed if the tool is not moving?
+ Right now we don't, but with the secondary context this might be useful
+
+ What you see here is a Q&D to only allow feedholds from the primary context.
+ It has the following limitations:
+ - Feedhold requests are only honored form the primary context
+ - Queue flush requests are only honored form the primary context
+ - Machine alarm state is not (yet) taken into account in feedhold sequencing and restart
+ */
+
/*
* cm_request_feedhold()
- * cm_request_end_hold() - cycle restart
+ * cm_request_end_hold()
* cm_request_queue_flush()
+ * cm_feedhold_sequencing_callback() - sequence feedhold, queue_flush, and end_hold requests
*/
-void cm_request_feedhold(void) {
- // honor request if not already in a feedhold and you are moving
- if ((cm->hold_state == FEEDHOLD_OFF) && (cm->motion_state != MOTION_STOP)) {
- cm->hold_state = FEEDHOLD_REQUESTED;
+
+void cm_request_feedhold(void)
+{
+ // do not generate a feedhold request from the secondary context
+ if (cm_select != CM_PRIMARY) {
+ return;
+ }
+ // only generate request if not already in a feedhold and the machine is in motion
+ if ((cm1.hold_state == FEEDHOLD_OFF) && (cm1.motion_state != MOTION_STOP)) {
+ cm1.hold_state = FEEDHOLD_REQUESTED;
}
}
-void cm_request_end_hold(void)
+void cm_request_end_hold(void) // This is usually requested form the secondary context
{
- if (cm->hold_state != FEEDHOLD_OFF) {
- cm->end_hold_requested = true;
+ if (cm1.hold_state != FEEDHOLD_OFF) {
+ cm1.end_hold_requested = true;
}
}
void cm_request_queue_flush()
{
- if ((cm->hold_state != FEEDHOLD_OFF) && // don't honor request unless you are in a feedhold
- (cm->queue_flush_state == FLUSH_OFF)) { // ...and only once
- cm->queue_flush_state = FLUSH_REQUESTED; // request planner flush once motion has stopped
+ // do not generate a queue flush request from the secondary context
+ if (cm_select != CM_PRIMARY) {
+ return;
+ }
+ if ((cm1.hold_state != FEEDHOLD_OFF) && // don't honor request unless you are in a feedhold
+ (cm1.queue_flush_state == FLUSH_OFF)) { // ...and only once
+ cm1.queue_flush_state = FLUSH_REQUESTED; // request planner flush once motion has stopped
// NOTE: we used to flush the input buffers, but this is handled in xio *prior* to queue flush now
}
}
-/*
- * cm_feedhold_sequencing_callback() - sequence feedhold, queue_flush, and end_hold requests
- */
stat_t cm_feedhold_sequencing_callback()
{
- if (cm->hold_state == FEEDHOLD_REQUESTED) {
+ if (cm1.hold_state == FEEDHOLD_REQUESTED) {
cm_start_hold(); // feed won't run unless the machine is moving
}
- if (cm->hold_state == FEEDHOLD_FINALIZING) {
- cm->hold_state = FEEDHOLD_HOLD;
+ if (cm1.hold_state == FEEDHOLD_FINALIZING) {
+ cm1.hold_state = FEEDHOLD_HOLD;
cm_switch_to_hold(); // perform Z lift, spindle & coolant operations
}
- if (cm->queue_flush_state == FLUSH_REQUESTED) {
+ if (cm1.queue_flush_state == FLUSH_REQUESTED) {
cm_queue_flush(); // queue flush won't run until runtime is idle
}
- if (cm->end_hold_requested) {
- if (cm->queue_flush_state == FLUSH_OFF) { // either no flush or wait until it's done flushing
+ if (cm1.end_hold_requested) {
+ if (cm1.queue_flush_state == FLUSH_OFF) { // either no flush or wait until it's done flushing
cm_end_hold();
}
}
@@ -1822,18 +1851,17 @@ stat_t cm_feedhold_sequencing_callback()
* cm_has_hold() - return true if a hold condition exists (or a pending hold request)
* cm_start_hold() - start a feedhhold by signalling the exec
* cm_end_hold() - end a feedhold by returning the system to normal operation
- * cm_queue_flush() - Flush planner queue and correct model positions
*/
bool cm_has_hold()
{
- return (cm->hold_state != FEEDHOLD_OFF);
+ return (cm1.hold_state != FEEDHOLD_OFF);
}
void cm_start_hold()
{
if (mp_has_runnable_buffer(mp)) { //+++++ // meaning there's something running
- cm_spindle_optional_pause(spindle.pause_on_hold); // pause if this option is selected
- cm_coolant_optional_pause(coolant.pause_on_hold); // pause if this option is selected
+// cm_spindle_optional_pause(spindle.pause_on_hold); // pause if this option is selected
+// cm_coolant_optional_pause(coolant.pause_on_hold); // pause if this option is selected
cm_set_motion_state(MOTION_HOLD);
cm->hold_state = FEEDHOLD_SYNC; // invokes hold from aline execution
}
@@ -1841,43 +1869,9 @@ void cm_start_hold()
void cm_end_hold()
{
- if (cm->hold_state == FEEDHOLD_HOLD) {
- cm->end_hold_requested = false;
+ if (cm1.hold_state == FEEDHOLD_HOLD) {
+ cm1.end_hold_requested = false;
cm_return_from_hold();
-// mp_exit_hold_state();
-
- // State machine cases:
- if (cm->machine_state == MACHINE_ALARM) {
- cm_spindle_off_immediate();
- cm_coolant_off_immediate();
-
- } else if (cm->motion_state == MOTION_STOP) { // && (! MACHINE_ALARM)
- cm_spindle_off_immediate();
- cm_coolant_off_immediate();
- cm_cycle_end();
-
- } else { // (MOTION_RUN || MOTION_PLANNING) && (! MACHINE_ALARM)
- cm_cycle_start();
- cm_spindle_resume(spindle.dwell_seconds);
- cm_coolant_resume();
- st_request_exec_move();
- }
- }
-}
-
-void cm_queue_flush()
-{
- if (mp_runtime_is_idle()) { // can't flush planner during movement
- mp_flush_planner(mp); // +++++ Active planner. Potential cleanup
-
- for (uint8_t axis = AXIS_X; axis < AXES; axis++) { // set all positions
- cm_set_position(axis, mp_get_runtime_absolute_position(axis));
- }
- if(cm->hold_state == FEEDHOLD_HOLD) { // end feedhold if we're in one
- cm_end_hold();
- }
- cm->queue_flush_state = FLUSH_OFF;
- qr_request_queue_report(0); // request a queue report, since we've changed the number of buffers available
}
}
@@ -1976,13 +1970,17 @@ stat_t cm_return_from_hold() // LATER: if value == true return with offset c
return (STAT_COMMAND_NOT_ACCEPTED);
}
- // *** while still in secondary machine:
-
+ // *** While still in secondary machine:
+/*
+ if (cm->machine_state == MACHINE_ALARM) {
+ cm_spindle_off_immediate();
+ cm_coolant_off_immediate();
+*/
// restart spindle (with optional dwell)
// restart coolant
- // perform the G30 move and queue a wait
+ // perform the G30 move and queue a wait
float target[] = { 0,0,0,0,0,0 }; // LATER: Make this move return through XY, then Z
bool flags[] = { 0,0,0,0,0,0 };
cm_goto_g30_position(target, flags); // initiate a return move
@@ -2009,20 +2007,39 @@ stat_t cm_return_from_hold_callback()
mr = mp->mr;
cm_select = CM_PRIMARY;
-// cm_set_motion_state(MOTION_STOP); // sets active model to primary
-
-// mp_exit_hold_state();
-
cm->hold_state = FEEDHOLD_OFF;
- if (mp_has_runnable_buffer(mp)) { //+++++
+ if (mp_has_runnable_buffer(mp)) { //+++++ Should MP be passed or global?
cm_set_motion_state(MOTION_RUN);
+ cm_cycle_start();
+ st_request_exec_move();
sr_request_status_report(SR_REQUEST_IMMEDIATE);
} else {
cm_set_motion_state(MOTION_STOP);
+ cm_cycle_end();
}
return (STAT_OK);
}
+/*
+ * cm_queue_flush() - Flush planner queue and correct model positions
+ */
+
+void cm_queue_flush()
+{
+ if (mp_runtime_is_idle()) { // can't flush planner during movement
+ mp_flush_planner(mp); // +++++ Active planner. Potential cleanup
+
+ for (uint8_t axis = AXIS_X; axis < AXES; axis++) { // set all positions
+ cm_set_position(axis, mp_get_runtime_absolute_position(axis));
+ }
+ if(cm->hold_state == FEEDHOLD_HOLD) { // end feedhold if we're in one
+ cm_end_hold();
+ }
+ cm->queue_flush_state = FLUSH_OFF;
+ qr_request_queue_report(0); // request a queue report, since we've changed the number of buffers available
+ }
+}
+
/******************************
* Program Functions (4.3.10) *
******************************/
diff --git a/g2core/controller.h b/g2core/controller.h
index 6d290dc2..e17ca3a9 100644
--- a/g2core/controller.h
+++ b/g2core/controller.h
@@ -72,6 +72,9 @@ typedef struct controllerSingleton { // main TG controller struct
char out_buf[OUTPUT_BUFFER_LEN]; // output buffer
char saved_buf[SAVED_BUFFER_LEN]; // save the input buffer
+ // Exceptions - some exceptions cannot be notified by an ER because they are in interrupts
+ bool exec_aline_assertion_failure; // record an exception deep inside mp_exec_aline()
+
magic_t magic_end;
} controller_t;
diff --git a/g2core/error.h b/g2core/error.h
index 1a26756f..a6e346a5 100644
--- a/g2core/error.h
+++ b/g2core/error.h
@@ -164,10 +164,10 @@ char *get_status_message(stat_t status);
#define STAT_ERROR_84 84
#define STAT_ERROR_85 85
#define STAT_ERROR_86 86
-#define STAT_ERROR_87 87
// Assertion failures - build down from 99 until they meet the system internal errors
+#define STAT_EXEC_ALINE_ASSERTION_FAILURE 87
#define STAT_BUFFER_FREE_ASSERTION_FAILURE 88
#define STAT_STATE_MANAGEMENT_ASSERTION_FAILURE 89
#define STAT_CONFIG_ASSERTION_FAILURE 90
@@ -469,8 +469,8 @@ static const char stat_83[] = "83";
static const char stat_84[] = "84";
static const char stat_85[] = "85";
static const char stat_86[] = "86";
-static const char stat_87[] = "87";
+static const char stat_87[] = "mp_exec_aline() assertion failure";
static const char stat_88[] = "Buffer free assertion failure";
static const char stat_89[] = "State management assertion failure";
static const char stat_90[] = "Config assertion failure";
diff --git a/g2core/g2core.cppproj b/g2core/g2core.cppproj
index d57acc1f..c8cc86a8 100644
--- a/g2core/g2core.cppproj
+++ b/g2core/g2core.cppproj
@@ -73,7 +73,7 @@
SWD
com.atmel.avrdbg.tool.atmelice
- J41800036434
+ J41800030015
Atmel-ICE
True
@@ -100,7 +100,7 @@
True
true
- J41800036434
+ J41800030015
0x284E0A60
10000000
diff --git a/g2core/plan_exec.cpp b/g2core/plan_exec.cpp
index 589762c1..13ab102b 100644
--- a/g2core/plan_exec.cpp
+++ b/g2core/plan_exec.cpp
@@ -315,33 +315,33 @@ stat_t mp_exec_move()
/*************************************************************************
* ---> Everything here fires from interrupts and must be interrupt safe
*
- * _exec_aline() - acceleration line main routine
- * _exec_aline_head() - helper for acceleration section
- * _exec_aline_body() - helper for cruise section
- * _exec_aline_tail() - helper for deceleration section
+ * _exec_aline() - acceleration line main routine
+ * _exec_aline_head() - helper for acceleration section
+ * _exec_aline_body() - helper for cruise section
+ * _exec_aline_tail() - helper for deceleration section
* _exec_aline_segment() - helper for running a segment
*
* Returns:
* STAT_OK move is done
* STAT_EAGAIN move is not finished - has more segments to run
- * STAT_NOOP cause no operation from the steppers - do not load the move
+ * STAT_NOOP would cause no operation to the steppers - do not load the move
* STAT_xxxxx fatal error. Ends the move and frees the bf buffer
*
* This routine is called from the (LO) interrupt level. The interrupt sequencing
* relies on the behaviors of the routines being exactly correct. Each call to
- * _exec_aline() must execute and prep *one and only one* segment. If the segment
+ * _exec_aline() must execute and prep **one and only one** segment. If the segment
* is the not the last segment in the bf buffer the _aline() must return STAT_EAGAIN.
* If it's the last segment it must return STAT_OK. If it encounters a fatal error
* that would terminate the move it should return a valid error code. Failure to
* obey this will introduce subtle and very difficult to diagnose bugs (trust us on this).
*
* Note 1: Returning STAT_OK ends the move and frees the bf buffer.
- * Returning STAT_OK at this point does NOT advance position meaning any
- * position error will be compensated by the next move.
+ * Returning STAT_OK at this point does NOT advance the position vector,
+ * meaning any position error will be compensated by the next move.
*
- * Note 2: Solves a potential race condition where the current move ends but the
- * new move has not started because the previous move is still being run
- * by the steppers. Planning can overwrite the new move.
+ * Note 2: BF/MR sequencing solves a potential race condition where the current move
+ * ends but the new move has not started because the previous move is still
+ * being run by the steppers. Planning can overwrite the new move.
*/
/* --- State transitions - hierarchical state machine ---
*
@@ -357,7 +357,7 @@ stat_t mp_exec_move()
* _RUN2 - run the second part
*
* Important distinction to note:
- * - mp_plan move() is called for every type of move
+ * - mp_plan move() is called for every type of move (bf block)
* - mp_exec_move() is called for every type of move
* - mp_exec_aline() is only called for alines
*/
@@ -407,17 +407,17 @@ stat_t mp_exec_aline(mpBuf_t *bf)
// Initialize all new blocks, regardless of normal or feedhold operation
if (mr->block_state == BLOCK_INACTIVE) {
- // too short lines have already been removed...
- // so is the following code is no longer needed ++++ ash
+ // Zero length moves (and other too-short moves) should have already been removed...
+ // ...so the following code is no longer needed.
// But let's still alert the condition should it ever occur
if (fp_ZERO(bf->length)) { // ...looks for an actual zero here
rpt_exception(STAT_PLANNER_ASSERTION_FAILURE, "mp_exec_aline() zero length move");
}
// Start a new move by setting up the runtime singleton (mr)
- memcpy(&mr->gm, &(bf->gm), sizeof(GCodeState_t)); // copy in the gcode model state
- bf->block_state = BLOCK_ACTIVE; // note that this buffer is running
- // note the planner doesn't look at block_state
+ memcpy(&mr->gm, &(bf->gm), sizeof(GCodeState_t)); // copy in the gcode model state
+ bf->block_state = BLOCK_ACTIVE; // note that this buffer is running
+ // note the planner doesn't look at block_state
mr->block_state = BLOCK_INITIAL_ACTION;
mr->section = SECTION_HEAD;
mr->section_state = SECTION_NEW;
@@ -426,35 +426,35 @@ stat_t mp_exec_aline(mpBuf_t *bf)
mr->r = mr->p; // we are now going to run the planning block
mr->p = mr->p->nx; // re-use the old running block as the new planning block
- // Assumptions that are required for this to work:
- // entry velocity <= cruise velocity && cruise velocity >= exit velocity
+ // Equalities that must be true for this to work:
+ // entry velocity <= cruise velocity &&
+ // cruise velocity >= exit velocity
+ //
// Even if the move is head or tail only, cruise velocity needs to be valid.
// This is because a "head" is *always* entry->cruise, and a "tail" is *always* cruise->exit,
- // even if there are not other sections int he move. (This is a significant time savings.)
+ // even if there are not other sections in the move. (This is a significant time savings.)
// Here we will check to make sure that the sections are longer than MIN_SEGMENT_TIME
if ((!fp_ZERO(mr->r->head_length)) && (mr->r->head_time < MIN_SEGMENT_TIME)) {
- // head_time !== body_time
- // We have to compute the new body time addition.
- mr->r->body_length += mr->r->head_length;
- mr->r->body_time = mr->r->body_length/mr->r->cruise_velocity;
-
- mr->r->head_length = 0;
- mr->r->head_time = 0;
+ // head_time !== body_time
+ // We have to compute the new body time addition.
+ mr->r->body_length += mr->r->head_length;
+ mr->r->body_time = mr->r->body_length/mr->r->cruise_velocity;
+ mr->r->head_length = 0;
+ mr->r->head_time = 0;
}
if ((!fp_ZERO(mr->r->tail_length)) && (mr->r->tail_time < MIN_SEGMENT_TIME)) {
// tail_time !== body_time
// We have to compute the new body time addition.
mr->r->body_length += mr->r->tail_length;
mr->r->body_time = mr->r->body_length/mr->r->cruise_velocity;
-
mr->r->tail_length = 0;
mr->r->tail_time = 0;
}
// At this point, we've already possibly merged head and/or tail into the body.
- // If the body is too "short" (brief) still, we *might* be able to add it to a head or tail.
+ // If the body is still too "short" (brief) we *might* be able to add it to a head or tail.
// If there's still a head or a tail, we will add the body to whichever there is, maybe both.
// We saved it for last since it's the most expensive.
if ((!fp_ZERO(mr->r->body_length)) && (mr->r->body_time < MIN_SEGMENT_TIME)) {
@@ -466,10 +466,8 @@ stat_t mp_exec_aline(mpBuf_t *bf)
float body_split = mr->r->body_length/2.0;
mr->r->body_length = 0;
mr->r->body_time = 0;
-
mr->r->head_length += body_split;
mr->r->tail_length += body_split;
-
mr->r->head_time = (2.0 * mr->r->head_length)/(mr->entry_velocity + mr->r->cruise_velocity);
mr->r->tail_time = (2.0 * mr->r->tail_length)/(mr->r->cruise_velocity + mr->r->exit_velocity);
} else {
@@ -477,7 +475,6 @@ stat_t mp_exec_aline(mpBuf_t *bf)
mr->r->tail_length += mr->r->body_length;
mr->r->body_length = 0;
mr->r->body_time = 0;
-
mr->r->tail_time = (2.0 * mr->r->tail_length)/(mr->r->cruise_velocity + mr->r->exit_velocity);
}
}
@@ -486,13 +483,13 @@ stat_t mp_exec_aline(mpBuf_t *bf)
mr->r->head_length += mr->r->body_length;
mr->r->body_length = 0;
mr->r->body_time = 0;
-
mr->r->head_time = (2.0 * mr->r->head_length)/(mr->entry_velocity + mr->r->cruise_velocity);
}
else {
// Uh oh! We have a move that's all body, and is still too short!!
- // ++++ RG For now, we'll consider this impossible.
- while (1);
+ // while (1); // ++++ RG For now, we'll consider this impossible.
+ cs.exec_aline_assertion_failure = true;
+ return (STAT_EXEC_ALINE_ASSERTION_FAILURE);
}
}
@@ -523,27 +520,27 @@ stat_t mp_exec_aline(mpBuf_t *bf)
// (4) - We have decelerated a block to some velocity > zero (needs continuation in next block)
// (5) - We have decelerated a block to zero velocity
// (6) - We have finished all the runtime work now we have to wait for the steppers to stop
- // (7) - The steppers have stopped. No motion should occur
+ // (7) - The steppers have stopped. No motion should occur. ALlows hold finalization to commence
// (8) - We are removing the hold state and there is queued motion (handled outside this routine)
// (9) - We are removing the hold state and there is no queued motion (also handled outside this routine)
if (cm->motion_state == MOTION_HOLD) {
// Case (7) - all motion has ceased
- if (cm->hold_state >= FEEDHOLD_FINALIZING) { // FINALIZING or FEEDHOLD_HOLD
- return (STAT_NOOP); // VERY IMPORTANT to exit as a NOOP. No more movement
+ if (cm->hold_state >= FEEDHOLD_FINALIZING) { // FEEDHOLD_FINALIZING or FEEDHOLD_HOLD
+ return (STAT_NOOP); // VERY IMPORTANT to exit as a NOOP. No more movement
}
// Case (6) - wait for the steppers to stop
if (cm->hold_state == FEEDHOLD_PENDING) {
if (mp_runtime_is_idle()) { // wait for the steppers to actually clear out
if ((cm->cycle_state == CYCLE_HOMING) || (cm->cycle_state == CYCLE_PROBE)) {
- // when homing, we don't need to stay in HOLD
+ // when homing or probing we don't want to stay in HOLD or execute finalizations
cm->hold_state = FEEDHOLD_OFF;
} else {
cm->hold_state = FEEDHOLD_FINALIZING;
}
mp_zero_segment_velocity(); // for reporting purposes
- sr_request_status_report(SR_REQUEST_IMMEDIATE); // was SR_REQUEST_TIMED
+ sr_request_status_report(SR_REQUEST_IMMEDIATE);
cs.controller_state = CONTROLLER_READY; // remove controller readline() PAUSE
}
return (STAT_OK); // hold here. No more movement
@@ -552,28 +549,24 @@ stat_t mp_exec_aline(mpBuf_t *bf)
// Case (5) - decelerated to zero
// Update the run buffer then force a replan of the whole planner queue
if (cm->hold_state == FEEDHOLD_DECEL_END) {
- mr->block_state = BLOCK_INACTIVE; // invalidate mr buffer to reset the new move
+ mr->block_state = BLOCK_INACTIVE; // invalidate mr buffer to reset the new move
bf->block_state = BLOCK_INITIAL_ACTION; // tell _exec to re-use the bf buffer
bf->length = get_axis_vector_length(mr->target, mr->position);// reset length
- //bf->entry_vmax = 0; // set bp+0 as hold point
-
+ //bf->entry_vmax = 0; // set bp+0 as hold point
cm->hold_state = FEEDHOLD_PENDING;
// No point bothering with the rest of this move if homing or probing
if ((cm->cycle_state == CYCLE_HOMING) || (cm->cycle_state == CYCLE_PROBE)) {
mp_free_run_buffer();
}
-
mp_replan_queue(mp_get_r()); // make it replan all the blocks
-// mp_replan_queue(mb.r); // make it replan all the blocks
-
return (STAT_OK);
}
// Cases (1a, 1b), Case (2), Case (4)
// Build a tail-only move from here. Decelerate as fast as possible in the space we have.
if ((cm->hold_state == FEEDHOLD_SYNC) ||
- ((cm->hold_state == FEEDHOLD_DECEL_CONTINUE) && (mr->block_state == BLOCK_INITIAL_ACTION))) {
+ ((cm->hold_state == FEEDHOLD_DECEL_CONTINUE) && (mr->block_state == BLOCK_INITIAL_ACTION))) {
// Case (3a) - already decelerating, continue the deceleration.
if (mr->section == SECTION_TAIL) { // if already in a tail don't decelerate. You already are
@@ -587,13 +580,10 @@ stat_t mp_exec_aline(mpBuf_t *bf)
// Small exception, if we *just started* the head, then we're not actually accelerating yet.
} else if ((mr->section != SECTION_HEAD) || (mr->section_state == SECTION_NEW)) {
mr->entry_velocity = mr->segment_velocity;
-
mr->section = SECTION_TAIL;
mr->section_state = SECTION_NEW;
-
mr->r->head_length = 0;
mr->r->body_length = 0;
-
float available_length = get_axis_vector_length(mr->target, mr->position);
mr->r->tail_length = mp_get_target_length(0, mr->r->cruise_velocity, bf); // braking length
@@ -615,7 +605,8 @@ stat_t mp_exec_aline(mpBuf_t *bf)
}
}
}
-
+ // End Feedhold Processing
+
mr->block_state = BLOCK_ACTIVE;
// NB: from this point on the contents of the bf buffer do not affect execution
@@ -649,19 +640,18 @@ stat_t mp_exec_aline(mpBuf_t *bf)
// There is no fourth thing. Nobody expects the Spanish Inquisition
if (status == STAT_EAGAIN) {
- sr_request_status_report(SR_REQUEST_TIMED); // continue reporting mr buffer
- // Note that tha'll happen in a lower interrupt level.
+ sr_request_status_report(SR_REQUEST_TIMED); // continue reporting mr buffer
+ // Note that that'll happen in a lower interrupt level.
} else {
- mr->block_state = BLOCK_INACTIVE; // invalidate mr buffer (reset)
+ mr->block_state = BLOCK_INACTIVE; // invalidate mr buffer (reset)
mr->section_state = SECTION_OFF;
- mp->run_time_remaining = 0.0; // it's done, so time goes to zero
-
- mr->entry_velocity = mr->r->exit_velocity; // feed the old exit into the entry.
+ mp->run_time_remaining = 0.0; // it's done, so time goes to zero
+ mr->entry_velocity = mr->r->exit_velocity; // feed the old exit into the entry.
if (bf->block_state == BLOCK_ACTIVE) {
- if (mp_free_run_buffer()) { // returns true of the buffer is empty
+ if (mp_free_run_buffer()) { // returns true of the buffer is empty
if (cm->hold_state == FEEDHOLD_OFF) {
- cm_cycle_end(); // free buffer & end cycle if planner is empty
+ cm_cycle_end(); // free buffer & end cycle if planner is empty
}
} else {
st_request_forward_plan();
@@ -671,38 +661,6 @@ 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
- *
- * Feedhold is executed as cm->hold_state transitions executed inside _exec_aline()
- * Invoke a feedhold by calling cm_request_hold() or cm_start_hold() directly
- * Return from feedhold by calling cm_request_end_hold() or cm_end_hold directly.
- * See canonical_macine.c for a more detailed explanation of feedhold operation.
- */
-/*
-void mp_exit_hold_state()
-{
- cm->hold_state = FEEDHOLD_OFF;
- if (mp_has_runnable_buffer(mp)) { //+++++
- cm_set_motion_state(MOTION_RUN);
- sr_request_status_report(SR_REQUEST_IMMEDIATE);
- } else {
- cm_set_motion_state(MOTION_STOP);
- }
-}
-*/
-
/*
* Forward difference math explained:
*
@@ -836,7 +794,6 @@ static void _init_forward_diffs(const float v_0, const float v_1)
// E = 0
// F = Vi
-
const float h = 1/(mr->segments);
const float h_2 = h * h;
const float h_3 = h_2 * h;