* These functions are not part of the NIST defined functions
*/
-/* Perform final operations for a rapid or feed
- *
- * These routines set the point position in the gcode model.
- *
- * Note: As far as the machine is concerned the final
- * position of a Gcode block (move) is achieved as soon as the move is
- * planned and the move target becomes the new model position. In
- * reality the planner will (in all likelihood) have only just queued
- * the move for later execution, and the real tool position is still
- * close to the starting point.
- */
-void mach_finalize_move() {
- copy_vector(mach.position, mach.gm.target); // update model position
-
- // if in inverse time mode reset feed rate so next block requires an
- // explicit feed rate setting
- if (mach.gm.feed_rate_mode == INVERSE_TIME_MODE &&
- mach.gm.motion_mode == MOTION_MODE_FEED)
- mach.gm.feed_rate = 0;
-}
-
-
/* Compute optimal and minimum move times into the gcode_state
*
* "Minimum time" is the fastest the move can be performed given the velocity
// Compute times for feed motion
if (mach.gm.motion_mode != MOTION_MODE_RAPID) {
- if (mach.gm.feed_rate_mode == INVERSE_TIME_MODE) {
+ if (mach.gm.feed_rate_mode == INVERSE_TIME_MODE)
// Feed rate was un-inverted to minutes by mach_set_feed_rate()
max_time = mach.gm.feed_rate;
- mach.gm.feed_rate_mode = UNITS_PER_MINUTE_MODE;
- } else {
+ else {
// Compute length of linear move in millimeters. Feed rate in mm/min.
max_time = sqrt(axis_square[AXIS_X] + axis_square[AXIS_Y] +
axis_square[AXIS_Z]) / mach.gm.feed_rate;
// prep and plan the move
mach_update_work_offsets(); // update fully resolved offsets to state
status = mp_aline(mach.gm.target, mach.gm.line); // send the move to planner
- mach_finalize_move();
+ copy_vector(mach.position, mach.gm.target); // update model position
return status;
}
void mach_set_feed_rate(float feed_rate) {
if (mach.gm.feed_rate_mode == INVERSE_TIME_MODE)
// normalize to minutes (active for this gcode block only)
- mach.gm.feed_rate = 1 / feed_rate;
+ mach.gm.feed_rate = feed_rate ? 1 / feed_rate : 0; // Avoid div by zero
else mach.gm.feed_rate = TO_MILLIMETERS(feed_rate);
}
/// G93, G94
void mach_set_feed_rate_mode(feed_rate_mode_t mode) {
+ if (mach.gm.feed_rate_mode == mode) return;
+ mach.gm.feed_rate = 0; // Force setting feed rate after changing modes
mach.gm.feed_rate_mode = mode;
}
/// G1
stat_t mach_feed(float target[], float flags[]) {
// trap zero feed rate condition
- if (mach.gm.feed_rate_mode != INVERSE_TIME_MODE && fp_ZERO(mach.gm.feed_rate))
+ if (fp_ZERO(mach.gm.feed_rate) ||
+ (mach.gm.feed_rate_mode == INVERSE_TIME_MODE && !mach.gf.feed_rate))
return STAT_GCODE_FEEDRATE_NOT_SPECIFIED;
mach.gm.motion_mode = MOTION_MODE_FEED;
// prep and plan the move
mach_update_work_offsets(); // update fully resolved offsets to state
status = mp_aline(mach.gm.target, mach.gm.line); // send the move to planner
- mach_finalize_move();
+ copy_vector(mach.position, mach.gm.target); // update model position
return status;
}
*/
static float _estimate_arc_time(float length, float linear_travel,
float planar_travel) {
- float t;
-
// Determine move time at requested feed rate
- if (mach.gm.feed_rate_mode == INVERSE_TIME_MODE) {
- // Inverse feed rate has been normalized to minutes
- t = mach.gm.feed_rate;
-
- // Reset feed rate so next block requires an explicit feed rate setting
- mach.gm.feed_rate = 0;
- mach.gm.feed_rate_mode = UNITS_PER_MINUTE_MODE;
-
- } else t = length / mach.gm.feed_rate;
+ // Inverse feed rate is normalized to minutes
+ float time = mach.gm.feed_rate_mode == INVERSE_TIME_MODE ?
+ mach.gm.feed_rate : length / mach.gm.feed_rate;
// Downgrade the time if there is a rate-limiting axis
- t = max3(t, planar_travel / mach.a[arc.plane_axis_0].feedrate_max,
- planar_travel / mach.a[arc.plane_axis_1].feedrate_max);
-
- if (0 < fabs(linear_travel))
- t = max(t, fabs(linear_travel / mach.a[arc.linear_axis].feedrate_max));
-
- return t;
+ return max4(time, planar_travel / mach.a[arc.plane_axis_0].feedrate_max,
+ planar_travel / mach.a[arc.plane_axis_1].feedrate_max,
+ fabs(linear_travel) / mach.a[arc.linear_axis].feedrate_max);
}
}
-/*** machine entry point for arc
+/*** Machine entry point for arc
*
* Generates an arc by queuing line segments to the move buffer. The arc is
* approximated by generating a large number of tiny, linear segments.
float radius, // non-zero radius implies radius mode
uint8_t motion_mode) { // defined motion mode
// trap missing feed rate
- if (mach.gm.feed_rate_mode != INVERSE_TIME_MODE && fp_ZERO(mach.gm.feed_rate))
+ if (fp_ZERO(mach.gm.feed_rate) ||
+ (mach.gm.feed_rate_mode == INVERSE_TIME_MODE && !mach.gf.feed_rate))
return STAT_GCODE_FEEDRATE_NOT_SPECIFIED;
// set radius mode flag and do simple test(s)
// compute arc runtime values
RITORNO(_compute_arc(mach.position, offset, rotations, full_circle));
- arc.run_state = MOVE_RUN; // enable arc run from the callback
- mach_arc_callback(); // Queue initial arc moves
- mach_finalize_move();
+ arc.run_state = MOVE_RUN; // Enable arc run in callback
+ mach_arc_callback(); // Queue initial arc moves
+ copy_vector(mach.position, mach.gm.target); // update model position
return STAT_OK;
}
-/* Generate an arc
+/*** Generate an arc
*
* Called from the controller main loop. Each time it's called it queues
* as many arc segments (lines) as it can before it blocks, then returns.