Align AXIS control flow and fix pause and program rendering
Document source UI gates, explicit native live-plot clearing, and remaining parity boundaries. Fix pause/resume transport continuity, repeated stepping, coordinate previews, and spindle override state. Optimize large program snapshots and rendering, and cover the control flows with native Tcl, WASM, and browser checks. Validation: 22 native tests and source/browser checks pass. Worker/App regression: 113 of 123 pass; 10 pre-existing failures remain documented with no new failures.
This commit is contained in:
@@ -26,6 +26,7 @@ struct sim_linuxcnc_tp {
|
||||
uint32_t last_active_id;
|
||||
int just_completed;
|
||||
int initialized;
|
||||
int step_id;
|
||||
};
|
||||
|
||||
static sim_linuxcnc_tp *active_planner;
|
||||
@@ -211,11 +212,19 @@ int32_t sim_linuxcnc_tp_jog(sim_linuxcnc_tp *planner, int axis, int direction, d
|
||||
double *value;
|
||||
double velocity;
|
||||
struct state_tag_t state_tag = {0};
|
||||
if (planner == NULL || !planner->initialized || axis < 0 || axis >= 9 || (direction != -1 && direction != 1) || !isfinite(increment) || increment <= 0.0) return -1215;
|
||||
if (planner == NULL || !planner->initialized || axis < 0 || axis >= 9 || (direction != -1 && direction != 1) || !isfinite(increment) || increment < 0.0) return -1215;
|
||||
active_planner = planner;
|
||||
end = planner->tp.goalPos;
|
||||
value = axis == 0 ? &end.tran.x : axis == 1 ? &end.tran.y : axis == 2 ? &end.tran.z : axis == 3 ? &end.a : axis == 4 ? &end.b : axis == 5 ? &end.c : axis == 6 ? &end.u : axis == 7 ? &end.v : &end.w;
|
||||
*value += (double)direction * increment;
|
||||
// command.c::EMCMOT_JOG_CONT targets the directional jog limit until abort.
|
||||
// Zero is the continuous-mode encoding; positive increments retain their ABI.
|
||||
if (increment == 0.0) {
|
||||
double target = direction > 0 ? planner->axis_max[axis] : planner->axis_min[axis];
|
||||
if ((target - *value) * direction <= 0.0) return -1217;
|
||||
*value = target;
|
||||
} else {
|
||||
*value += (double)direction * increment;
|
||||
}
|
||||
if (!isfinite(*value) || *value < planner->axis_min[axis] || *value > planner->axis_max[axis]) return -1217;
|
||||
velocity = planner->axis_velocity[axis] * planner->jog_scale;
|
||||
state_tag.fields_float[GM_FIELD_FLOAT_LINE_NUMBER] = (float)tag;
|
||||
@@ -257,15 +266,36 @@ int32_t sim_linuxcnc_tp_set_dynamics(sim_linuxcnc_tp *planner, double accelerati
|
||||
int32_t sim_linuxcnc_tp_set_paused(sim_linuxcnc_tp *planner, int paused) {
|
||||
if (planner == NULL || !planner->initialized || (paused != 0 && paused != 1)) return -1219;
|
||||
active_planner = planner;
|
||||
planner->status.stepping = 0;
|
||||
if (paused) return tpPause(&planner->tp) == TP_ERR_OK ? 0 : -1220;
|
||||
return tpResume(&planner->tp) == TP_ERR_OK ? 0 : -1221;
|
||||
}
|
||||
|
||||
int32_t sim_linuxcnc_tp_step_line(sim_linuxcnc_tp *planner) {
|
||||
if (planner == NULL || !planner->initialized) return -1219;
|
||||
TC_STRUCT *active = tcqItem(&planner->tp.queue, 0);
|
||||
if (active == NULL) return -1219;
|
||||
active_planner = planner;
|
||||
planner->step_id = active->id;
|
||||
planner->status.stepping = 1;
|
||||
return tpResume(&planner->tp) == TP_ERR_OK ? 0 : -1221;
|
||||
}
|
||||
|
||||
int32_t sim_linuxcnc_tp_is_stepping(const sim_linuxcnc_tp *planner) {
|
||||
return planner != NULL && planner->initialized && planner->status.stepping;
|
||||
}
|
||||
|
||||
double sim_linuxcnc_tp_axis_limit(const sim_linuxcnc_tp *planner, int axis, int maximum) {
|
||||
if (planner == NULL || !planner->initialized || axis < 0 || axis > 8) return NAN;
|
||||
return maximum ? planner->axis_max[axis] : planner->axis_min[axis];
|
||||
}
|
||||
|
||||
int32_t sim_linuxcnc_tp_abort(sim_linuxcnc_tp *planner) {
|
||||
if (planner == NULL || !planner->initialized) return -1222;
|
||||
active_planner = planner;
|
||||
planner->last_active_id = 0;
|
||||
planner->just_completed = 0;
|
||||
planner->status.stepping = 0;
|
||||
if (tpAbort(&planner->tp) != TP_ERR_OK) return -1223;
|
||||
// A browser PROGRAM_ABORT has no background emcmot servo thread after
|
||||
// the command response. Complete the source TP abort transition here so
|
||||
@@ -316,9 +346,17 @@ int32_t sim_linuxcnc_tp_step(sim_linuxcnc_tp *planner) {
|
||||
planner->just_completed = 0;
|
||||
const int prior_id = tpGetExecId(&planner->tp);
|
||||
const int prior_depth = tcqLen(&planner->tp.queue);
|
||||
const int was_stepping = planner->status.stepping;
|
||||
const int result = tpRunCycle(&planner->tp, (long)llround(planner->tp.cycleTime * 1e9));
|
||||
// motion/control.c stops a step when the execution ID changes. Compare
|
||||
// the next queued ID too, before the following TC can start moving.
|
||||
TC_STRUCT *next = tcqItem(&planner->tp.queue, 0);
|
||||
if (planner->status.stepping && (next == NULL || next->id != planner->step_id)) {
|
||||
tpPause(&planner->tp);
|
||||
planner->status.stepping = 0;
|
||||
}
|
||||
planner->tick += 1u;
|
||||
if (prior_id > 0 && prior_depth > 0 && tcqLen(&planner->tp.queue) == 0) {
|
||||
if (!was_stepping && prior_id > 0 && prior_depth > 0 && tcqLen(&planner->tp.queue) == 0) {
|
||||
planner->last_active_id = (uint32_t)prior_id;
|
||||
planner->just_completed = 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user