More encapsulation, made some queue commands unsynchronized, final arc move to actual...
authorJoseph Coffland <joseph@cauldrondevelopment.com>
Sat, 10 Sep 2016 09:59:00 +0000 (02:59 -0700)
committerJoseph Coffland <joseph@cauldrondevelopment.com>
Sat, 10 Sep 2016 09:59:00 +0000 (02:59 -0700)
15 files changed:
src/machine.c
src/machine.h
src/plan/arc.c
src/plan/buffer.c
src/plan/buffer.h
src/plan/calibrate.c
src/plan/command.c
src/plan/dwell.c
src/plan/exec.c
src/plan/jog.c
src/plan/line.c
src/plan/planner.c
src/spindle.c
src/spindle.h
src/varcb.c

index 98b3fefa02994a9d10f170a4426b8fd496ac51ce..0ec4f9033a319f671bc7f8b9d6982d06e6d8843a 100644 (file)
@@ -44,7 +44,7 @@
  *   - Call the mach_xxx_xxx() function which will do any input validation and
  *     return an error if it detects one.
  *
- *   - The mach_ function calls mp_queue_command(). Arguments are a callback to
+ *   - The mach_ function calls mp_queue_command().  Arguments are a callback to
  *     the _exec_...() function, which is the runtime execution routine, and any
  *     arguments that are needed by the runtime. See typedef for *exec in
  *     planner.h for details
@@ -197,7 +197,6 @@ path_mode_t mach_get_path_control() {return mach.gm.path_control;}
 distance_mode_t mach_get_distance_mode() {return mach.gm.distance_mode;}
 feed_rate_mode_t mach_get_feed_rate_mode() {return mach.gm.feed_rate_mode;}
 uint8_t mach_get_tool() {return mach.gm.tool;}
-spindle_mode_t mach_get_spindle_mode() {return mach.gm.spindle_mode;}
 float mach_get_feed_rate() {return mach.gm.feed_rate;}
 
 
@@ -393,7 +392,7 @@ float mach_get_active_coord_offset(uint8_t axis) {
 
 static stat_t _exec_update_work_offsets(mp_buffer_t *bf) {
   mp_runtime_set_work_offsets(bf->target);
-  return STAT_NOOP;
+  return STAT_NOOP; // No move queued
 }
 
 
@@ -413,10 +412,6 @@ void mach_update_work_offsets() {
 
   if (!same) {
     mp_buffer_t *bf = mp_get_write_buffer();
-
-    // never supposed to fail
-    if (!bf) {CM_ALARM(STAT_BUFFER_FULL_FATAL); return;}
-
     bf->bf_func = _exec_update_work_offsets;
     copy_vector(bf->target, work_offset);
 
@@ -425,29 +420,12 @@ void mach_update_work_offsets() {
 }
 
 
-/* Get position of axis in absolute coordinates
- *
- * NOTE: Machine position is always returned in mm mode. No units conversion
- * is performed
- */
-float mach_get_absolute_position(uint8_t axis) {
-  return mach.position[axis];
-}
-
-
-/* Return work position in prevailing units (mm/inch) and with all offsets
- * applied.
+/*** Get position of axis in absolute coordinates
  *
- * NOTE: This function only works after the gcode_state struct has had the
- * work_offsets setup by calling mach_get_model_coord_offset_vector() first.
+ * NOTE: Machine position is always returned in mm mode.  No units conversion
+ * is performed.
  */
-float mach_get_work_position(uint8_t axis) {
-  float position = mach.position[axis] - mach_get_active_coord_offset(axis);
-
-  if (mach.gm.units_mode == INCHES) position /= MM_PER_INCH;
-
-  return position;
-}
+float mach_get_absolute_position(uint8_t axis) {return mach.position[axis];}
 
 
 /* Critical helpers
@@ -618,7 +596,7 @@ void mach_set_model_target(float target[], float flag[]) {
 
 /* Return error code if soft limit is exceeded
  *
- * Must be called with target properly set in GM struct. Best done
+ * Must be called with target properly set in GM struct.  Best done
  * after mach_set_model_target().
  *
  * Tests for soft limit for any homed axis if min and max are
@@ -875,9 +853,6 @@ stat_t mach_goto_g28_position(float target[], float flags[]) {
   // move through intermediate point, or skip
   mach_rapid(target, flags);
 
-  // make sure you have an available buffer
-  mp_wait_for_buffer();
-
   // execute actual stored move
   float f[] = {1, 1, 1, 1, 1, 1};
   return mach_rapid(mach.g28_position, f);
@@ -895,9 +870,6 @@ stat_t mach_goto_g30_position(float target[], float flags[]) {
   // move through intermediate point, or skip
   mach_rapid(target, flags);
 
-  // make sure you have an available buffer
-  mp_wait_for_buffer();
-
   // execute actual stored move
   float f[] = {1, 1, 1, 1, 1, 1};
   return mach_rapid(mach.g30_position, f);
@@ -1065,17 +1037,21 @@ void mach_message(const char *message) {
  */
 
 
-static void _exec_program_stop(float *value, float *flag) {
+static stat_t _exec_program_stop(mp_buffer_t *bf) {
   // Machine should be stopped at this point.  Go into hold so that a start is
   // needed before executing further instructions.
   mp_state_holding();
+  return STAT_NOOP; // No move queued
 }
 
 
 /// M0 Queue a program stop
 void mach_program_stop() {
-  float value[AXES] = {0};
-  mp_queue_command(_exec_program_stop, value, value);
+  mp_buffer_t *bf = mp_get_write_buffer();
+  if (!bf) {CM_ALARM(STAT_BUFFER_FULL_FATAL); return;} // Should not fail
+
+  bf->bf_func = _exec_program_stop;
+  mp_commit_write_buffer(mach.gm.line);
 }
 
 
index 342d7bfb48901532ac0a270d94ba8c7d04c2f681..f41d11f78c176775a78eeb0a3e089e61e2f07a62 100644 (file)
@@ -317,8 +317,6 @@ path_mode_t mach_get_path_control();
 distance_mode_t mach_get_distance_mode();
 feed_rate_mode_t mach_get_feed_rate_mode();
 uint8_t mach_get_tool();
-spindle_mode_t mach_get_spindle_mode();
-inline float mach_get_spindle_speed() {return mach.gm.spindle_speed;}
 float mach_get_feed_rate();
 
 PGM_P mp_get_units_mode_pgmstr(units_mode_t mode);
@@ -342,7 +340,6 @@ void mach_set_axis_jerk(uint8_t axis, float jerk);
 float mach_get_active_coord_offset(uint8_t axis);
 void mach_update_work_offsets();
 float mach_get_absolute_position(uint8_t axis);
-float mach_get_work_position(uint8_t axis);
 
 // Critical helpers
 float mach_calc_move_time(const float axis_length[], const float axis_square[]);
index b8a346dd4e781bf8ca40619521c5be4f19297fd2..6578f73469c6aa2cd910608e41c46085531d7b40 100644 (file)
 
 
 typedef struct {
-  run_state_t run_state;            // runtime state machine sequence
+  bool running;
   int32_t line;                     // gcode block line number
 
   float target[AXES];               // XYZABC where the move should go
+  float position[AXES];             // end point of the current segment
 
   float theta;                      // total angle specified by arc
   float radius;                     // Raw R value, or computed via offsets
@@ -317,7 +318,7 @@ static stat_t _compute_arc(const float position[], float offset[],
   float segments = floor(min3(segments_for_chordal_accuracy,
                               segments_for_minimum_distance,
                               segments_for_minimum_time));
-  segments = max(segments, 1); // at least 1 segment
+  if (segments < 1) segments = 1; // at least 1 segment
 
   arc.segments = (uint32_t)segments;
   arc.segment_theta = angular_travel / segments;
@@ -325,8 +326,8 @@ static stat_t _compute_arc(const float position[], float offset[],
   arc.center_0 = position[arc.plane_axis_0] - sin(arc.theta) * arc.radius;
   arc.center_1 = position[arc.plane_axis_1] - cos(arc.theta) * arc.radius;
 
-  // initialize the linear target
-  arc.target[arc.linear_axis] = position[arc.linear_axis];
+  // initialize the linear position
+  arc.position[arc.linear_axis] = position[arc.linear_axis];
 
   return STAT_OK;
 }
@@ -432,7 +433,7 @@ stat_t mach_arc_feed(float target[], float flags[], // arc endpoints
   // compute arc runtime values
   RITORNO(_compute_arc(mach.position, offset, rotations, full_circle));
 
-  arc.run_state = MOVE_RUN;                   // Enable arc run in callback
+  arc.running = true;                         // Enable arc run in callback
   mach_arc_callback();                        // Queue initial arc moves
   copy_vector(mach.position, mach.gm.target); // update model position
 
@@ -446,23 +447,32 @@ stat_t mach_arc_feed(float target[], float flags[], // arc endpoints
  *  as many arc segments (lines) as it can before it blocks, then returns.
  */
 void mach_arc_callback() {
-  while (arc.run_state != MOVE_OFF && mp_get_planner_buffer_room()) {
-    arc.theta += arc.segment_theta;
-
-    arc.target[arc.plane_axis_0] = arc.center_0 + sin(arc.theta) * arc.radius;
-    arc.target[arc.plane_axis_1] = arc.center_1 + cos(arc.theta) * arc.radius;
-    arc.target[arc.linear_axis] += arc.segment_linear_travel;
+  while (arc.running && mp_get_planner_buffer_room()) {
+    if (arc.segments == 1) { // Final segment
+      arc.position[arc.plane_axis_0] = arc.target[arc.plane_axis_0];
+      arc.position[arc.plane_axis_1] = arc.target[arc.plane_axis_1];
+      arc.position[arc.linear_axis] = arc.target[arc.linear_axis];
+
+    } else {
+      arc.theta += arc.segment_theta;
+
+      arc.position[arc.plane_axis_0] =
+        arc.center_0 + sin(arc.theta) * arc.radius;
+      arc.position[arc.plane_axis_1] =
+        arc.center_1 + cos(arc.theta) * arc.radius;
+      arc.position[arc.linear_axis] += arc.segment_linear_travel;
+    }
 
-    mp_aline(arc.target, arc.line); // run the line
+    mp_aline(arc.position, arc.line); // run the line
 
-    if (!--arc.segments) arc.run_state = MOVE_OFF;
+    if (!--arc.segments) arc.running = false;
   }
 }
 
 
-bool mach_arc_active() {return arc.run_state != MOVE_OFF;}
+bool mach_arc_active() {return arc.running;}
 
 
 /// Stop arc movement without maintaining position
 /// OK to call if no arc is running
-void mach_abort_arc() {arc.run_state = MOVE_OFF;}
+void mach_abort_arc() {arc.running = false;}
index 6ff9d73f7cc20f43fcf33a2d64e88de702028c1f..b09cdfca35090f23e5a5ceab4048e91f526f1740 100644 (file)
@@ -109,26 +109,24 @@ void mp_wait_for_buffer() {while (!mb.buffers_available) continue;}
 bool mp_queue_empty() {return mb.w == mb.r;}
 
 
-/// Get pointer to next available write buffer
-/// Returns pointer or 0 if no buffer available.
+/// Get pointer to next available write buffer.  Wait until one is available.
 mp_buffer_t *mp_get_write_buffer() {
-  // get & clear a buffer
-  if (mb.w->buffer_state == MP_BUFFER_EMPTY) {
-    mp_buffer_t *w = mb.w;
-    mp_buffer_t *nx = mb.w->nx;               // save linked list pointers
-    mp_buffer_t *pv = mb.w->pv;
-    memset(mb.w, 0, sizeof(mp_buffer_t));     // clear all values
-    w->nx = nx;                               // restore pointers
-    w->pv = pv;
-    w->buffer_state = MP_BUFFER_LOADING;
-    mb.w = w->nx;
-
-    mb.buffers_available--;
-
-    return w;
-  }
-
-  return 0;
+  // Wait for a buffer
+  while (!mb.buffers_available) continue;
+
+  // Get & clear write buffer
+  mp_buffer_t *w = mb.w;
+  mp_buffer_t *nx = mb.w->nx;               // save linked list pointers
+  mp_buffer_t *pv = mb.w->pv;
+  memset(mb.w, 0, sizeof(mp_buffer_t));     // clear all values
+  w->nx = nx;                               // restore pointers
+  w->pv = pv;
+  w->buffer_state = MP_BUFFER_LOADING;
+  mb.w = w->nx;
+
+  mb.buffers_available--;
+
+  return w;
 }
 
 
@@ -183,7 +181,7 @@ mp_buffer_t *mp_get_last_buffer() {
   mp_buffer_t *bf = mp_get_run_buffer();
   mp_buffer_t *bp;
 
-  for (bp = bf; bp && bp->nx != bf; bp = mp_get_next_buffer(bp))
+  for (bp = bf; bp && bp->nx != bf; bp = mp_buffer_next(bp))
     if (bp->nx->run_state == MOVE_OFF) break;
 
   return bp;
index b19f16ca99b1aa1c3353935ed490894162309d6d..3108fb4fe744ba5cbec16b66ec7288f6b5291448 100644 (file)
@@ -108,7 +108,7 @@ void mp_commit_write_buffer(uint32_t line);
 mp_buffer_t *mp_get_run_buffer();
 void mp_free_run_buffer();
 mp_buffer_t *mp_get_last_buffer();
-#define mp_get_prev_buffer(b) (b->pv)
-#define mp_get_next_buffer(b) (b->nx)
+static inline mp_buffer_t *mp_buffer_prev(mp_buffer_t *bp) {return bp->pv;}
+static inline mp_buffer_t *mp_buffer_next(mp_buffer_t *bp) {return bp->nx;}
 void mp_clear_buffer(mp_buffer_t *bf);
 void mp_copy_buffer(mp_buffer_t *bf, const mp_buffer_t *bp);
index 23cb6fe1581ba157a90529819602053e627db316..696d8fdc0412464dc994e5613a0a51598fb1eeae 100644 (file)
@@ -164,17 +164,12 @@ uint8_t command_calibrate(int argc, char *argv[]) {
   if (mp_get_cycle() != CYCLE_MACHINING || mp_get_state() != STATE_READY)
     return 0;
 
-  mp_buffer_t *bf = mp_get_write_buffer();
-  if (!bf) {
-    CM_ALARM(STAT_BUFFER_FULL_FATAL);
-    return 0;
-  }
-
   // Start
   memset(&cal, 0, sizeof(cal));
   mp_set_cycle(CYCLE_CALIBRATING);
   cal.motor = 1;
 
+  mp_buffer_t *bf = mp_get_write_buffer();
   bf->bf_func = _exec_calibrate; // register callback
   mp_commit_write_buffer(-1);
 
index 80bb4c679797b86583dcfbec1f3d5860843cbcdc..7b2654ca5dd385421f632a17e63c7443dde751a2 100644 (file)
@@ -62,11 +62,6 @@ static stat_t _exec_command(mp_buffer_t *bf) {
 void mp_queue_command(mach_func_t mach_func, float values[], float flags[]) {
   mp_buffer_t *bf = mp_get_write_buffer();
 
-  if (!bf) {
-    CM_ALARM(STAT_BUFFER_FULL_FATAL);
-    return; // Shouldn't happen, buffer availability was checked upstream.
-  }
-
   bf->bf_func = _exec_command;    // callback to planner queue exec function
   bf->mach_func = mach_func;      // callback to machine exec function
 
index 1141bd479f76145ce47442e5470a4c77ffa9e9a6..c2dd079b6253fa4cfc3afecab4ffcd80db804b72 100644 (file)
@@ -47,10 +47,6 @@ static stat_t _exec_dwell(mp_buffer_t *bf) {
 /// Queue a dwell
 stat_t mp_dwell(float seconds, int32_t line) {
   mp_buffer_t *bf = mp_get_write_buffer();
-
-  // never supposed to fail
-  if (!bf) return CM_ALARM(STAT_BUFFER_FULL_FATAL);
-
   bf->bf_func = _exec_dwell; // register callback to dwell start
   bf->dwell = seconds;       // in seconds, not minutes
 
index 5d33bed73b47236baf5f871b00726126175bbdc7..2c3285386429878d8a76f5d2ea92053f85ae06f3 100644 (file)
@@ -457,10 +457,6 @@ static stat_t _exec_aline_init(mp_buffer_t *bf) {
  *     Returning STAT_OK at does NOT advance position meaning
  *     any position error will be compensated by the next move.
  *
- * [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.
- *
  * Operation:
  *
  * Aline generates jerk-controlled S-curves as per Ed Red's course notes:
@@ -498,16 +494,17 @@ stat_t mp_exec_aline(mp_buffer_t *bf) {
     if (status != STAT_OK) return status;
   }
 
+  // Plan holds
   if (mp_get_state() == STATE_STOPPING && !ex.hold_planned) _plan_hold();
 
-  // Main segment dispatch.  From this point on the contents of the bf buffer
-  // do not affect execution.
+  // Main segment dispatch
   switch (ex.section) {
   case SECTION_HEAD: status = _exec_aline_head(); break;
   case SECTION_BODY: status = _exec_aline_body(); break;
   case SECTION_TAIL: status = _exec_aline_tail(); break;
   }
 
+  // Set runtime velocity on exit
   if (status != STAT_EAGAIN) mp_runtime_set_velocity(ex.exit_velocity);
 
   return status;
@@ -552,8 +549,12 @@ stat_t mp_exec_move() {
     // Handle buffer run state
     if (bf->run_state == MOVE_RESTART) bf->run_state = MOVE_NEW;
     else {
-      bf->nx->replannable = false;   // Prevent overplanning (Note 2)
-      mp_free_run_buffer();          // Free buffer
+      // Solves a potential race condition where the current move ends but
+      // the new move has not started because the current move is still
+      // being run by the steppers.  Planning can overwrite the new move.
+      mp_buffer_next(bf)->replannable = false;
+
+      mp_free_run_buffer(); // Free buffer
 
       // Enter READY state
       if (mp_queue_empty()) {
index f5dcddb7fdfdf5669f7383d10d576d0d8605febf..06a6c7f832b7f55a1789e0bf09126e6a28d36865 100644 (file)
@@ -125,12 +125,9 @@ uint8_t command_jog(int argc, char *argv[]) {
   jr.writing = false;
 
   if (!mp_jog_busy()) {
-    // Should always be at least one free buffer
-    mp_buffer_t *bf = mp_get_write_buffer();
-    if (!bf) return STAT_BUFFER_FULL_FATAL;
-
-    // Start
     mp_set_cycle(CYCLE_JOGGING);
+
+    mp_buffer_t *bf = mp_get_write_buffer();
     bf->bf_func = _exec_jog; // register callback
     mp_commit_write_buffer(-1);
   }
index 9f6b8024e5432e2ea8454ef83876ee8f6da412d0..2b982bd89588e1ba08d7f6935d545ba804dd788a 100644 (file)
@@ -237,7 +237,8 @@ static void _calc_and_cache_jerk_values(mp_buffer_t *bf) {
 
 
 static void _calc_max_velocities(mp_buffer_t *bf, float move_time) {
-  float junction_velocity = _get_junction_vmax(bf->pv->unit, bf->unit);
+  float junction_velocity =
+    _get_junction_vmax(mp_buffer_prev(bf)->unit, bf->unit);
 
   bf->cruise_vmax = bf->length / move_time; // target velocity requested
   bf->entry_vmax = min(bf->cruise_vmax, junction_velocity);
@@ -285,7 +286,6 @@ stat_t mp_aline(const float target[], int32_t line) {
 
   // Get a buffer.  Note, new buffers are initialized to zero.
   mp_buffer_t *bf = mp_get_write_buffer(); // current move pointer
-  if (!bf) return CM_ALARM(STAT_BUFFER_FULL_FATAL); // should never fail
 
   // Set buffer values
   bf->bf_func = mp_exec_aline;
@@ -304,7 +304,7 @@ stat_t mp_aline(const float target[], int32_t line) {
   float time = mach_calc_move_time(axis_length, axis_square);
   _calc_max_velocities(bf, time);
 
-  // Note, next the following lines must remain in order.
+  // Note, the following lines must remain in order.
   mp_plan_block_list(bf);       // Plan block list
   mp_set_position(target);      // Set planner position before committing buffer
   mp_commit_write_buffer(line); // Commit current block after position update
index c98a070f4cca8ab351f747e6d9bf43db3df4a3fb..729de329bae83dedebffad2a362b9a6e1c1ab656 100644 (file)
@@ -262,7 +262,7 @@ void mp_calculate_trapezoid(mp_buffer_t *bf) {
 
   // B" case: Block is short, but fits into a single body segment
   if (naive_move_time <= NOM_SEGMENT_TIME) {
-    bf->entry_velocity = bf->pv->exit_velocity;
+    bf->entry_velocity = mp_buffer_prev(bf)->exit_velocity;
 
     if (fp_NOT_ZERO(bf->entry_velocity)) {
       bf->cruise_velocity = bf->entry_velocity;
@@ -444,20 +444,19 @@ void mp_calculate_trapezoid(mp_buffer_t *bf) {
 
 /*** Plans the entire block list
  *
- * The block list is the circular buffer of planner buffers
- * (bf's). The block currently being planned is the "bf" block.  The
- * "first block" is the next block to execute; queued immediately
- * behind the currently executing block, aka the "running" block.
- * In some cases, there is no first block because the list is empty
- * or there is only one block and it is already running.
+ * The block list is the circular buffer of planner buffers (bf's). The block
+ * currently being planned is the "bf" block.  The "first block" is the next
+ * block to execute; queued immediately behind the currently executing block,
+ * aka the "running" block.  In some cases, there is no first block because the
+ * list is empty or there is only one block and it is already running.
  *
- * If blocks following the first block are already optimally
- * planned (non replannable) the first block that is not optimally
- * planned becomes the effective first block.
+ * If blocks following the first block are already optimally planned (non
+ * replannable) the first block that is not optimally planned becomes the
+ * effective first block.
  *
- * mp_plan_block_list() plans all blocks between and including the
- * (effective) first block and the bf.  It sets entry, exit and
- * cruise v's from vmax's then calls trapezoid generation.
+ * mp_plan_block_list() plans all blocks between and including the (effective)
+ * first block and the bf.  It sets entry, exit and cruise v's from vmax's then
+ * calls trapezoid generation.
  *
  * Variables that must be provided in the mp_buffer_ts that will be processed:
  *
@@ -497,53 +496,54 @@ void mp_calculate_trapezoid(mp_buffer_t *bf) {
  *
  * Notes:
  *
- * [1] Whether or not a block is planned is controlled by the
- *     bf->replannable setting (set TRUE if it should be). Replan flags
- *     are checked during the backwards pass and prune the replan list
- *     to include only the the latest blocks that require planning
- *
- *     In normal operation the first block (currently running
- *     block) is not replanned, but may be for feedholds and feed
- *     overrides.  In these cases the prep routines modify the
- *     contents of the (ex) buffer and re-shuffle the block list,
- *     re-enlisting the current bf buffer with new parameters.
- *     These routines also set all blocks in the list to be
- *     replannable so the list can be recomputed regardless of
- *     exact stops and previous replanning optimizations.
+ * [1] Whether or not a block is planned is controlled by the bf->replannable
+ *     setting.  Replan flags are checked during the backwards pass.  They prune
+ *     the replan list to include only the the latest blocks that require
+ *     planning.
+ *
+ *     In normal operation, the first block (currently running block) is not
+ *     replanned, but may be for feedholds and feed overrides.  In these cases,
+ *     the prep routines modify the contents of the (ex) buffer and re-shuffle
+ *     the block list, re-enlisting the current bf buffer with new parameters.
+ *     These routines also set all blocks in the list to be replannable so the
+ *     list can be recomputed regardless of exact stops and previous replanning
+ *     optimizations.
  */
 void mp_plan_block_list(mp_buffer_t *bf) {
   mp_buffer_t *bp = bf;
 
   // Backward planning pass.  Find first block and update braking velocities.
   // By the end bp points to the buffer before the first block.
-  while ((bp = mp_get_prev_buffer(bp)) != bf) {
+  while ((bp = mp_buffer_prev(bp)) != bf) {
     if (!bp->replannable) break;
     bp->braking_velocity =
-      min(bp->nx->entry_vmax, bp->nx->braking_velocity) + bp->delta_vmax;
+      min(mp_buffer_next(bp)->entry_vmax,
+          mp_buffer_next(bp)->braking_velocity) + bp->delta_vmax;
   }
 
   // Forward planning pass.  Recompute trapezoids from the first block to bf.
-  while ((bp = mp_get_next_buffer(bp)) != bf) {
-    if (bp->pv == bf) bp->entry_velocity = bp->entry_vmax; // first block
-    else bp->entry_velocity = bp->pv->exit_velocity; // other blocks
+  while ((bp = mp_buffer_next(bp)) != bf) {
+    if (mp_buffer_prev(bp) == bf)
+      bp->entry_velocity = bp->entry_vmax; // first block
+    else bp->entry_velocity = mp_buffer_prev(bp)->exit_velocity; // other blocks
 
     bp->cruise_velocity = bp->cruise_vmax;
-    bp->exit_velocity = min4(bp->exit_vmax, bp->nx->entry_vmax,
-                             bp->nx->braking_velocity,
+    bp->exit_velocity = min4(bp->exit_vmax, mp_buffer_next(bp)->entry_vmax,
+                             mp_buffer_next(bp)->braking_velocity,
                              bp->entry_velocity + bp->delta_vmax);
 
     mp_calculate_trapezoid(bp);
 
     // Test for optimally planned trapezoids by checking exit conditions
     if  ((fp_EQ(bp->exit_velocity, bp->exit_vmax) ||
-          fp_EQ(bp->exit_velocity, bp->nx->entry_vmax)) ||
-         (!bp->pv->replannable &&
+          fp_EQ(bp->exit_velocity, mp_buffer_next(bp)->entry_vmax)) ||
+         (!mp_buffer_prev(bp)->replannable &&
           fp_EQ(bp->exit_velocity, (bp->entry_velocity + bp->delta_vmax))))
       bp->replannable = false;
   }
 
   // Finish last block
-  bp->entry_velocity = bp->pv->exit_velocity;
+  bp->entry_velocity = mp_buffer_prev(bp)->exit_velocity;
   bp->cruise_velocity = bp->cruise_vmax;
   bp->exit_velocity = 0;
 
@@ -560,8 +560,9 @@ void mp_replan_blocks() {
   // Mark all blocks replanable
   while (true) {
     bp->replannable = true;
-    if (bp->nx->run_state == MOVE_OFF || bp->nx == bf) break;
-    bp = mp_get_next_buffer(bp);
+    if (mp_buffer_next(bp)->run_state == MOVE_OFF || mp_buffer_next(bp) == bf)
+      break;
+    bp = mp_buffer_next(bp);
   }
 
   // Plan blocks
index 5cc12f5ab544caf356c0dd432950ec5ceaa9d335..c08f972fcbea1a3afec50c30d2486ffc386b97f0 100644 (file)
@@ -40,7 +40,15 @@ typedef enum {
   SPINDLE_TYPE_HUANYANG,
 } spindle_type_t;
 
-static spindle_type_t _type = SPINDLE_TYPE;
+
+typedef struct {
+  spindle_type_t type;
+  spindle_mode_t mode;
+  float speed;
+} spindle_t;
+
+
+static spindle_t spindle = {.type = SPINDLE_TYPE};
 
 
 void spindle_init() {
@@ -50,28 +58,38 @@ void spindle_init() {
 
 
 void spindle_set(spindle_mode_t mode, float speed) {
-  switch (_type) {
+  spindle.mode = mode;
+  spindle.speed = speed;
+
+  switch (spindle.type) {
   case SPINDLE_TYPE_PWM: pwm_spindle_set(mode, speed); break;
   case SPINDLE_TYPE_HUANYANG: huanyang_set(mode, speed); break;
   }
 }
 
 
+spindle_mode_t spindle_get_mode() {return spindle.mode;}
+float spindle_get_speed() {return spindle.speed;}
+
+
 void spindle_estop() {
-  switch (_type) {
+  switch (spindle.type) {
   case SPINDLE_TYPE_PWM: pwm_spindle_estop(); break;
   case SPINDLE_TYPE_HUANYANG: huanyang_estop(); break;
   }
 }
 
 
-uint8_t get_spindle_type(int index) {return _type;}
+uint8_t get_spindle_type(int index) {return spindle.type;}
 
 
 void set_spindle_type(int index, uint8_t value) {
-  if (value != _type) {
+  if (value != spindle.type) {
+    spindle_mode_t mode = spindle.mode;
+    float speed = spindle.speed;
+
     spindle_set(SPINDLE_OFF, 0);
-    _type = value;
-    spindle_set(mach.gm.spindle_mode, mach.gm.spindle_speed);
+    spindle.type = value;
+    spindle_set(mode, speed);
   }
 }
index c31ec85def2cf21abae5a3c7ac5a5505faf9c123..ef15e8682447be3278903754eb413771d679eade 100644 (file)
@@ -33,4 +33,6 @@
 
 void spindle_init();
 void spindle_set(spindle_mode_t spindle_mode, float speed);
+spindle_mode_t spindle_get_mode();
+float spindle_get_speed();
 void spindle_estop();
index 333ce1e91f9bc0fb055fe7c7daf83db6f6552295..4f48ebff36ac7fdeb703c00cc09d66ed0aa3cab6 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "usart.h"
 #include "machine.h"
+#include "spindle.h"
 #include "plan/runtime.h"
 #include "plan/state.h"
 
@@ -37,7 +38,7 @@ float get_position(int index) {return mp_runtime_get_axis_position(index);}
 // GCode
 int32_t get_line() {return mp_runtime_get_line();}
 PGM_P get_unit() {return mp_get_units_mode_pgmstr(mach_get_units_mode());}
-float get_speed() {return mach_get_spindle_speed();}
+float get_speed() {return spindle_get_speed();}
 float get_feed() {return mach_get_feed_rate();}
 uint8_t get_tool() {return mach_get_tool();}