Update wasm port validation state

This commit is contained in:
wangdequan
2026-07-10 03:22:55 -04:00
parent 49a8bad404
commit 2e922ad628
91 changed files with 3292 additions and 1488 deletions

View File

@@ -0,0 +1,437 @@
#include "emccanon_wasm_subset.hh"
/*
* WASM canonical linear-motion subset derived from
* LinuxCNC src/emc/task/emccanon.cc.
*
* Upstream anchors:
* - INIT_CANON(): initializes CanonConfig_t, offsets, endpoint, feed state, and units.
* - ON_RESET(): drops pending canonical segments.
* - FINISH(): flushes pending canonical segments.
* - USE_LENGTH_UNITS(): sets canon.lengthUnits.
* - GET_EXTERNAL_LENGTH_UNITS()/GET_EXTERNAL_ANGLE_UNITS(): read EMC_STAT motion units.
* - GET_EXTERNAL_POSITION()/GET_EXTERNAL_POSITION_X/Y/Z/A/B/C(): expose the current canonical endpoint.
* - generate_fast_move(): emits EMC_TRAJ_LINEAR_MOVE for traverse-like moves.
* - generate_move(): emits EMC_TRAJ_LINEAR_MOVE for feed moves.
* - STRAIGHT_TRAVERSE(): canonical traverse entry point.
* - STRAIGHT_FEED(): canonical feed entry point.
* - DWELL(): emits EMC_TRAJ_DELAY to interp_list.
* - SET_MOTION_CONTROL_MODE(): emits EMC_TRAJ_SET_TERM_COND to interp_list.
* - SET_SPINDLE_SPEED(): emits EMC_SPINDLE_SPEED to interp_list.
* - START_SPINDLE_CLOCKWISE()/START_SPINDLE_COUNTERCLOCKWISE(): emit EMC_SPINDLE_ON to interp_list.
* - STOP_SPINDLE_TURNING(): emits EMC_SPINDLE_OFF to interp_list.
* - SELECT_TOOL(): emits EMC_TOOL_PREPARE to interp_list.
* - CHANGE_TOOL(): emits EMC_TOOL_LOAD to interp_list.
* - CHANGE_TOOL_NUMBER(): emits EMC_TOOL_SET_NUMBER to interp_list.
* - RELOAD_TOOLDATA(): emits EMC_TOOL_LOAD_TOOL_TABLE to interp_list.
* - SET_MOTION_OUTPUT_BIT()/CLEAR_MOTION_OUTPUT_BIT()/SET_AUX_OUTPUT_BIT()/CLEAR_AUX_OUTPUT_BIT():
* emit EMC_MOTION_SET_DOUT to interp_list.
* - SET_MOTION_OUTPUT_VALUE()/SET_AUX_OUTPUT_VALUE(): emit EMC_MOTION_SET_AOUT to interp_list.
* - WAIT(): emits EMC_AUX_INPUT_WAIT to interp_list.
*
* Full emccanon.cc owns CanonConfig_t, offsets, unit conversion, interp_list,
* tags, NURBS, spindle/tool/coolant, and many other canonical callbacks. This
* subset stops at a canonical linear-move envelope so task-HAL can keep using
* the existing standalone runtime edge while moving motion generation toward
* upstream canonical function families.
*/
namespace {
int units_from_external(double external_length_units)
{
if (external_length_units > 0.038 && external_length_units < 0.041) {
return LC_EMCCANON_SUBSET_UNITS_INCHES;
}
return LC_EMCCANON_SUBSET_UNITS_MM;
}
void set_linear_move(int line, const LcEmcCanonSubsetPose *end, double velocity,
int motion_type, LcEmcCanonSubsetLinearMove *out)
{
if (!out) {
return;
}
*out = LcEmcCanonSubsetLinearMove{};
out->line = line;
out->motion_type = motion_type;
out->velocity = velocity;
if (end) {
out->end = *end;
}
}
void set_spindle_command(int command, int spindle, double speed, int wait_for_at_speed,
LcEmcCanonSubsetSpindleCommand *out)
{
if (!out) {
return;
}
*out = LcEmcCanonSubsetSpindleCommand{};
out->command = command;
out->spindle = spindle;
out->speed = speed;
out->wait_for_at_speed = wait_for_at_speed;
}
void set_tool_command(int command, int tool, LcEmcCanonSubsetToolCommand *out)
{
if (!out) {
return;
}
*out = LcEmcCanonSubsetToolCommand{};
out->command = command;
out->tool = tool;
}
void set_output_command(int command, int index, int start, int end, int now,
double value, LcEmcCanonSubsetOutputCommand *out)
{
if (!out) {
return;
}
*out = LcEmcCanonSubsetOutputCommand{};
out->command = command;
out->index = index;
out->start = start;
out->end = end;
out->now = now;
out->value = value;
}
} // namespace
extern "C" {
void lc_emccanon_subset_init(double external_length_units,
double external_angle_units,
LcEmcCanonSubsetState *state)
{
if (!state) {
return;
}
*state = LcEmcCanonSubsetState{};
state->initialized = 1;
state->external_length_units = external_length_units == 0.0 ? 1.0 : external_length_units;
state->external_angle_units = external_angle_units == 0.0 ? 1.0 : external_angle_units;
state->length_units = units_from_external(state->external_length_units);
}
void lc_emccanon_subset_on_reset(LcEmcCanonSubsetState *state)
{
if (!state) {
return;
}
state->reset_count += 1;
state->endpoint = LcEmcCanonSubsetPose{};
}
void lc_emccanon_subset_finish(LcEmcCanonSubsetState *state)
{
if (!state) {
return;
}
state->finish_count += 1;
}
void lc_emccanon_subset_use_length_units(int units,
LcEmcCanonSubsetState *state)
{
if (!state) {
return;
}
state->length_units = units;
}
void lc_emccanon_subset_update_endpoint(const LcEmcCanonSubsetPose *position,
LcEmcCanonSubsetState *state)
{
if (!state || !position) {
return;
}
state->endpoint = *position;
}
void lc_emccanon_subset_get_external_position(const LcEmcCanonSubsetState *state,
LcEmcCanonSubsetPose *out)
{
if (!out) {
return;
}
*out = LcEmcCanonSubsetPose{};
if (state) {
*out = state->endpoint;
}
}
double lc_emccanon_subset_get_external_length_units(const LcEmcCanonSubsetState *state)
{
if (!state || state->external_length_units == 0.0) {
return 1.0;
}
return state->external_length_units;
}
double lc_emccanon_subset_get_external_angle_units(const LcEmcCanonSubsetState *state)
{
if (!state || state->external_angle_units == 0.0) {
return 1.0;
}
return state->external_angle_units;
}
int lc_emccanon_subset_get_external_length_unit_type(const LcEmcCanonSubsetState *state)
{
return state ? state->length_units : LC_EMCCANON_SUBSET_UNITS_MM;
}
void lc_emccanon_subset_straight_traverse(int line, const LcEmcCanonSubsetPose *end,
double velocity,
LcEmcCanonSubsetLinearMove *out)
{
set_linear_move(line, end, velocity, LC_EMCCANON_SUBSET_MOTION_TRAVERSE, out);
}
void lc_emccanon_subset_straight_feed(int line, const LcEmcCanonSubsetPose *end,
double velocity,
LcEmcCanonSubsetLinearMove *out)
{
set_linear_move(line, end, velocity, LC_EMCCANON_SUBSET_MOTION_FEED, out);
}
void lc_emccanon_subset_dwell(double seconds, LcEmcCanonSubsetDelay *out)
{
if (!out) {
return;
}
*out = LcEmcCanonSubsetDelay{};
out->seconds = seconds < 0.0 ? 0.0 : seconds;
}
void lc_emccanon_subset_set_motion_control_mode(int mode,
double tolerance,
LcEmcCanonSubsetTermCond *out)
{
if (!out) {
return;
}
*out = LcEmcCanonSubsetTermCond{};
out->mode = mode;
out->tolerance = tolerance < 0.0 ? 0.0 : tolerance;
switch (mode) {
case LC_EMCCANON_SUBSET_PATH_CONTINUOUS:
out->condition = LC_EMCCANON_SUBSET_TERM_BLEND;
break;
case LC_EMCCANON_SUBSET_PATH_EXACT_PATH:
out->condition = LC_EMCCANON_SUBSET_TERM_EXACT;
break;
case LC_EMCCANON_SUBSET_PATH_EXACT_STOP:
default:
out->condition = LC_EMCCANON_SUBSET_TERM_STOP;
break;
}
}
void lc_emccanon_subset_set_spindle_speed(int spindle,
double speed,
LcEmcCanonSubsetSpindleCommand *out)
{
set_spindle_command(
LC_EMCCANON_SUBSET_SPINDLE_SET_SPEED,
spindle,
speed < 0.0 ? 0.0 : speed,
0,
out);
}
void lc_emccanon_subset_start_spindle_clockwise(int spindle,
int wait_for_at_speed,
LcEmcCanonSubsetSpindleCommand *out)
{
set_spindle_command(
LC_EMCCANON_SUBSET_SPINDLE_START_CW,
spindle,
0.0,
wait_for_at_speed ? 1 : 0,
out);
}
void lc_emccanon_subset_start_spindle_counterclockwise(int spindle,
int wait_for_at_speed,
LcEmcCanonSubsetSpindleCommand *out)
{
set_spindle_command(
LC_EMCCANON_SUBSET_SPINDLE_START_CCW,
spindle,
0.0,
wait_for_at_speed ? 1 : 0,
out);
}
void lc_emccanon_subset_stop_spindle_turning(int spindle,
int wait_for_at_speed,
LcEmcCanonSubsetSpindleCommand *out)
{
set_spindle_command(
LC_EMCCANON_SUBSET_SPINDLE_STOP,
spindle,
0.0,
wait_for_at_speed ? 1 : 0,
out);
}
void lc_emccanon_subset_select_tool(int tool,
LcEmcCanonSubsetToolCommand *out)
{
set_tool_command(LC_EMCCANON_SUBSET_TOOL_PREPARE, tool, out);
}
void lc_emccanon_subset_change_tool(LcEmcCanonSubsetToolCommand *out)
{
set_tool_command(LC_EMCCANON_SUBSET_TOOL_LOAD, 0, out);
}
void lc_emccanon_subset_change_tool_number(int tool,
LcEmcCanonSubsetToolCommand *out)
{
set_tool_command(LC_EMCCANON_SUBSET_TOOL_SET_NUMBER, tool, out);
}
void lc_emccanon_subset_reload_tooldata(LcEmcCanonSubsetToolCommand *out)
{
set_tool_command(LC_EMCCANON_SUBSET_TOOL_LOAD_TABLE, 0, out);
}
void lc_emccanon_subset_set_motion_output_bit(int index,
LcEmcCanonSubsetOutputCommand *out)
{
set_output_command(
LC_EMCCANON_SUBSET_OUTPUT_SET_MOTION_BIT,
index,
1,
1,
0,
1.0,
out);
}
void lc_emccanon_subset_clear_motion_output_bit(int index,
LcEmcCanonSubsetOutputCommand *out)
{
set_output_command(
LC_EMCCANON_SUBSET_OUTPUT_CLEAR_MOTION_BIT,
index,
0,
0,
0,
0.0,
out);
}
void lc_emccanon_subset_set_aux_output_bit(int index,
LcEmcCanonSubsetOutputCommand *out)
{
set_output_command(
LC_EMCCANON_SUBSET_OUTPUT_SET_AUX_BIT,
index,
1,
1,
1,
1.0,
out);
}
void lc_emccanon_subset_clear_aux_output_bit(int index,
LcEmcCanonSubsetOutputCommand *out)
{
set_output_command(
LC_EMCCANON_SUBSET_OUTPUT_CLEAR_AUX_BIT,
index,
0,
0,
1,
0.0,
out);
}
void lc_emccanon_subset_set_motion_output_value(int index,
double value,
LcEmcCanonSubsetOutputCommand *out)
{
set_output_command(
LC_EMCCANON_SUBSET_OUTPUT_SET_MOTION_VALUE,
index,
0,
0,
0,
value,
out);
}
void lc_emccanon_subset_set_aux_output_value(int index,
double value,
LcEmcCanonSubsetOutputCommand *out)
{
set_output_command(
LC_EMCCANON_SUBSET_OUTPUT_SET_AUX_VALUE,
index,
0,
0,
1,
value,
out);
}
void lc_emccanon_subset_wait_input(int index,
int input_type,
int wait_type,
double timeout,
LcEmcCanonSubsetOutputCommand *out)
{
if (!out) {
return;
}
*out = LcEmcCanonSubsetOutputCommand{};
out->command = LC_EMCCANON_SUBSET_OUTPUT_WAIT;
out->index = index;
out->input_type = input_type;
out->wait_type = wait_type;
out->timeout = timeout < 0.0 ? 0.0 : timeout;
}
const char *lc_emccanon_subset_source_path(void)
{
return "src/emc/task/emccanon.cc";
}
const char *lc_emccanon_subset_anchor_list(void)
{
return "INIT_CANON,ON_RESET,FINISH,USE_LENGTH_UNITS,GET_EXTERNAL_LENGTH_UNITS,GET_EXTERNAL_ANGLE_UNITS,GET_EXTERNAL_POSITION,GET_EXTERNAL_POSITION_X,GET_EXTERNAL_POSITION_Y,GET_EXTERNAL_POSITION_Z,GET_EXTERNAL_POSITION_A,GET_EXTERNAL_POSITION_B,GET_EXTERNAL_POSITION_C,generate_fast_move,generate_move,STRAIGHT_TRAVERSE,STRAIGHT_FEED,DWELL,SET_MOTION_CONTROL_MODE,SET_SPINDLE_SPEED,START_SPINDLE_CLOCKWISE,START_SPINDLE_COUNTERCLOCKWISE,STOP_SPINDLE_TURNING,SELECT_TOOL,CHANGE_TOOL,CHANGE_TOOL_NUMBER,RELOAD_TOOLDATA,SET_MOTION_OUTPUT_BIT,CLEAR_MOTION_OUTPUT_BIT,SET_AUX_OUTPUT_BIT,CLEAR_AUX_OUTPUT_BIT,SET_MOTION_OUTPUT_VALUE,SET_AUX_OUTPUT_VALUE,WAIT";
}
const char *lc_emccanon_subset_init_finish_unit_anchor_list(void)
{
return "INIT_CANON,ON_RESET,FINISH,USE_LENGTH_UNITS,GET_EXTERNAL_LENGTH_UNITS,GET_EXTERNAL_ANGLE_UNITS,GET_EXTERNAL_POSITION,GET_EXTERNAL_POSITION_X,GET_EXTERNAL_POSITION_Y,GET_EXTERNAL_POSITION_Z,GET_EXTERNAL_POSITION_A,GET_EXTERNAL_POSITION_B,GET_EXTERNAL_POSITION_C";
}
const char *lc_emccanon_subset_straight_motion_anchor_list(void)
{
return "generate_fast_move,generate_move,STRAIGHT_TRAVERSE,STRAIGHT_FEED,EMC_TRAJ_LINEAR_MOVE,interp_list";
}
const char *lc_emccanon_subset_dwell_path_control_anchor_list(void)
{
return "DWELL,EMC_TRAJ_DELAY,SET_MOTION_CONTROL_MODE,EMC_TRAJ_SET_TERM_COND,interp_list";
}
const char *lc_emccanon_subset_spindle_tool_anchor_list(void)
{
return "SET_SPINDLE_SPEED,START_SPINDLE_CLOCKWISE,START_SPINDLE_COUNTERCLOCKWISE,STOP_SPINDLE_TURNING,EMC_SPINDLE_SPEED,EMC_SPINDLE_ON,EMC_SPINDLE_OFF,SELECT_TOOL,CHANGE_TOOL,CHANGE_TOOL_NUMBER,RELOAD_TOOLDATA,EMC_TOOL_PREPARE,EMC_TOOL_LOAD,EMC_TOOL_SET_NUMBER,EMC_TOOL_LOAD_TOOL_TABLE,interp_list";
}
const char *lc_emccanon_subset_motion_output_anchor_list(void)
{
return "SET_MOTION_OUTPUT_BIT,CLEAR_MOTION_OUTPUT_BIT,SET_AUX_OUTPUT_BIT,CLEAR_AUX_OUTPUT_BIT,SET_MOTION_OUTPUT_VALUE,SET_AUX_OUTPUT_VALUE,WAIT,EMC_MOTION_SET_DOUT,EMC_MOTION_SET_AOUT,EMC_AUX_INPUT_WAIT,interp_list";
}
} // extern "C"

View File

@@ -0,0 +1,193 @@
#ifndef LINUXCNC_EMCCANON_WASM_SUBSET_HH
#define LINUXCNC_EMCCANON_WASM_SUBSET_HH
#ifdef __cplusplus
extern "C" {
#endif
enum LcEmcCanonSubsetMotionType {
LC_EMCCANON_SUBSET_MOTION_TRAVERSE = 1,
LC_EMCCANON_SUBSET_MOTION_FEED = 2,
};
enum LcEmcCanonSubsetUnits {
LC_EMCCANON_SUBSET_UNITS_MM = 1,
LC_EMCCANON_SUBSET_UNITS_INCHES = 2,
LC_EMCCANON_SUBSET_UNITS_CM = 3,
};
enum LcEmcCanonSubsetPathMode {
LC_EMCCANON_SUBSET_PATH_CONTINUOUS = 1,
LC_EMCCANON_SUBSET_PATH_EXACT_PATH = 2,
LC_EMCCANON_SUBSET_PATH_EXACT_STOP = 3,
};
enum LcEmcCanonSubsetTermCondition {
LC_EMCCANON_SUBSET_TERM_BLEND = 1,
LC_EMCCANON_SUBSET_TERM_EXACT = 2,
LC_EMCCANON_SUBSET_TERM_STOP = 3,
};
enum LcEmcCanonSubsetSpindleCommandType {
LC_EMCCANON_SUBSET_SPINDLE_SET_SPEED = 1,
LC_EMCCANON_SUBSET_SPINDLE_START_CW = 2,
LC_EMCCANON_SUBSET_SPINDLE_START_CCW = 3,
LC_EMCCANON_SUBSET_SPINDLE_STOP = 4,
};
enum LcEmcCanonSubsetToolCommandType {
LC_EMCCANON_SUBSET_TOOL_PREPARE = 1,
LC_EMCCANON_SUBSET_TOOL_LOAD = 2,
LC_EMCCANON_SUBSET_TOOL_SET_NUMBER = 3,
LC_EMCCANON_SUBSET_TOOL_LOAD_TABLE = 4,
};
enum LcEmcCanonSubsetOutputCommandType {
LC_EMCCANON_SUBSET_OUTPUT_SET_MOTION_BIT = 1,
LC_EMCCANON_SUBSET_OUTPUT_CLEAR_MOTION_BIT = 2,
LC_EMCCANON_SUBSET_OUTPUT_SET_AUX_BIT = 3,
LC_EMCCANON_SUBSET_OUTPUT_CLEAR_AUX_BIT = 4,
LC_EMCCANON_SUBSET_OUTPUT_SET_MOTION_VALUE = 5,
LC_EMCCANON_SUBSET_OUTPUT_SET_AUX_VALUE = 6,
LC_EMCCANON_SUBSET_OUTPUT_WAIT = 7,
};
enum LcEmcCanonSubsetInputType {
LC_EMCCANON_SUBSET_INPUT_DIGITAL = 1,
LC_EMCCANON_SUBSET_INPUT_ANALOG = 2,
};
struct LcEmcCanonSubsetPose {
double x;
double y;
double z;
double a;
double b;
double c;
};
struct LcEmcCanonSubsetState {
int initialized;
int finish_count;
int reset_count;
int length_units;
double external_length_units;
double external_angle_units;
LcEmcCanonSubsetPose endpoint;
};
struct LcEmcCanonSubsetLinearMove {
int line;
int motion_type;
double velocity;
LcEmcCanonSubsetPose end;
};
struct LcEmcCanonSubsetDelay {
double seconds;
};
struct LcEmcCanonSubsetTermCond {
int mode;
int condition;
double tolerance;
};
struct LcEmcCanonSubsetSpindleCommand {
int command;
int spindle;
double speed;
int wait_for_at_speed;
};
struct LcEmcCanonSubsetToolCommand {
int command;
int tool;
};
struct LcEmcCanonSubsetOutputCommand {
int command;
int index;
int start;
int end;
int now;
double value;
int input_type;
int wait_type;
double timeout;
};
void lc_emccanon_subset_init(double external_length_units,
double external_angle_units,
LcEmcCanonSubsetState *state);
void lc_emccanon_subset_on_reset(LcEmcCanonSubsetState *state);
void lc_emccanon_subset_finish(LcEmcCanonSubsetState *state);
void lc_emccanon_subset_use_length_units(int units,
LcEmcCanonSubsetState *state);
void lc_emccanon_subset_update_endpoint(const LcEmcCanonSubsetPose *position,
LcEmcCanonSubsetState *state);
void lc_emccanon_subset_get_external_position(const LcEmcCanonSubsetState *state,
LcEmcCanonSubsetPose *out);
double lc_emccanon_subset_get_external_length_units(const LcEmcCanonSubsetState *state);
double lc_emccanon_subset_get_external_angle_units(const LcEmcCanonSubsetState *state);
int lc_emccanon_subset_get_external_length_unit_type(const LcEmcCanonSubsetState *state);
void lc_emccanon_subset_straight_traverse(int line, const LcEmcCanonSubsetPose *end,
double velocity,
LcEmcCanonSubsetLinearMove *out);
void lc_emccanon_subset_straight_feed(int line, const LcEmcCanonSubsetPose *end,
double velocity,
LcEmcCanonSubsetLinearMove *out);
void lc_emccanon_subset_dwell(double seconds, LcEmcCanonSubsetDelay *out);
void lc_emccanon_subset_set_motion_control_mode(int mode,
double tolerance,
LcEmcCanonSubsetTermCond *out);
void lc_emccanon_subset_set_spindle_speed(int spindle,
double speed,
LcEmcCanonSubsetSpindleCommand *out);
void lc_emccanon_subset_start_spindle_clockwise(int spindle,
int wait_for_at_speed,
LcEmcCanonSubsetSpindleCommand *out);
void lc_emccanon_subset_start_spindle_counterclockwise(int spindle,
int wait_for_at_speed,
LcEmcCanonSubsetSpindleCommand *out);
void lc_emccanon_subset_stop_spindle_turning(int spindle,
int wait_for_at_speed,
LcEmcCanonSubsetSpindleCommand *out);
void lc_emccanon_subset_select_tool(int tool,
LcEmcCanonSubsetToolCommand *out);
void lc_emccanon_subset_change_tool(LcEmcCanonSubsetToolCommand *out);
void lc_emccanon_subset_change_tool_number(int tool,
LcEmcCanonSubsetToolCommand *out);
void lc_emccanon_subset_reload_tooldata(LcEmcCanonSubsetToolCommand *out);
void lc_emccanon_subset_set_motion_output_bit(int index,
LcEmcCanonSubsetOutputCommand *out);
void lc_emccanon_subset_clear_motion_output_bit(int index,
LcEmcCanonSubsetOutputCommand *out);
void lc_emccanon_subset_set_aux_output_bit(int index,
LcEmcCanonSubsetOutputCommand *out);
void lc_emccanon_subset_clear_aux_output_bit(int index,
LcEmcCanonSubsetOutputCommand *out);
void lc_emccanon_subset_set_motion_output_value(int index,
double value,
LcEmcCanonSubsetOutputCommand *out);
void lc_emccanon_subset_set_aux_output_value(int index,
double value,
LcEmcCanonSubsetOutputCommand *out);
void lc_emccanon_subset_wait_input(int index,
int input_type,
int wait_type,
double timeout,
LcEmcCanonSubsetOutputCommand *out);
const char *lc_emccanon_subset_source_path(void);
const char *lc_emccanon_subset_anchor_list(void);
const char *lc_emccanon_subset_init_finish_unit_anchor_list(void);
const char *lc_emccanon_subset_straight_motion_anchor_list(void);
const char *lc_emccanon_subset_dwell_path_control_anchor_list(void);
const char *lc_emccanon_subset_spindle_tool_anchor_list(void);
const char *lc_emccanon_subset_motion_output_anchor_list(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,377 @@
#include "emctask_wasm_subset.hh"
#include <cstring>
/*
* WASM task subset derived from LinuxCNC src/emc/task/emctask.cc.
*
* Upstream anchors:
* - emcTaskAbort(): clears interpreter/task execution state and resynchronizes the plan.
* - emcTaskSetMode(): switches manual/mdi/auto task mode and synchronizes trajectory mode.
* - emcTaskSetState(): switches estop/off/on state and issues motion enable/disable/abort edges.
* - determineMode(): traj mode + mdiOrAuto -> task mode.
* - determineState(): traj enabled + io estop -> task state.
* - emcTaskUpdate(): writes task mode/state and motionLine from motion id.
* - emcTaskPlanSetWait()/IsWait()/ClearWait(): own the interpreter wait flag.
* - emcTaskPlanSynch()/Open()/Close()/Reset(): synchronize, open, close, and reset the interpreter plan.
* - emcTaskPlanRead()/Execute()/Line()/Level()/Command(): read interpreter lines,
* expose line/command metadata, and append executed work to interp_list.
*
* This file is intentionally narrow. Full emctask.cc also owns interpreter,
* NML, dynamic loading, IO, and native process edges that are not part of this
* standalone WASM subset yet.
*/
namespace {
int determine_mode(int traj_mode, int mdi_or_auto)
{
if (traj_mode == LC_EMC_TASK_SUBSET_TRAJ_FREE) {
return LC_EMC_TASK_SUBSET_MODE_MANUAL;
}
if (traj_mode == LC_EMC_TASK_SUBSET_TRAJ_TELEOP) {
return LC_EMC_TASK_SUBSET_MODE_MANUAL;
}
return mdi_or_auto;
}
int determine_state(int traj_enabled, int io_estop)
{
if (io_estop) {
return LC_EMC_TASK_SUBSET_STATE_ESTOP;
}
if (!traj_enabled) {
return LC_EMC_TASK_SUBSET_STATE_ESTOP_RESET;
}
return LC_EMC_TASK_SUBSET_STATE_ON;
}
void clear_command_result(LcEmcTaskSubsetCommandResult *result)
{
if (!result) {
return;
}
*result = LcEmcTaskSubsetCommandResult{};
}
void clear_plan_result(LcEmcTaskSubsetPlanResult *result)
{
if (!result) {
return;
}
*result = LcEmcTaskSubsetPlanResult{};
}
void clear_plan_io_result(LcEmcTaskSubsetPlanIoResult *result)
{
if (!result) {
return;
}
*result = LcEmcTaskSubsetPlanIoResult{};
}
void copy_plan_state(const LcEmcTaskSubsetPlanState *state,
LcEmcTaskSubsetPlanResult *result)
{
if (!state || !result) {
return;
}
result->wait_flag = state->wait_flag;
result->taskplanopen = state->taskplanopen;
result->line = state->read_line;
result->level = state->level;
}
} // namespace
extern "C" {
void lc_emctask_subset_update(const LcEmcTaskSubsetUpdateInput *input,
LcEmcTaskSubsetUpdateResult *result)
{
if (!input || !result) {
return;
}
result->mode = determine_mode(input->traj_mode, input->mdi_or_auto);
result->state = determine_state(input->traj_enabled, input->io_estop);
result->should_abort_on_state_drop =
input->old_task_state == LC_EMC_TASK_SUBSET_STATE_ON &&
result->state != LC_EMC_TASK_SUBSET_STATE_ON;
result->motion_line = input->motion_id > 0 ? input->motion_id : 0;
}
void lc_emctask_subset_abort(LcEmcTaskSubsetCommandResult *result)
{
clear_command_result(result);
if (!result) {
return;
}
result->should_clear_interpreter = 1;
result->should_abort_motion = 1;
result->should_plan_synch = 1;
}
void lc_emctask_subset_set_mode(int mode,
int all_homed,
int jogging_active,
LcEmcTaskSubsetCommandResult *result)
{
clear_command_result(result);
if (!result) {
return;
}
if (jogging_active) {
result->mode = mode;
return;
}
switch (mode) {
case LC_EMC_TASK_SUBSET_MODE_MANUAL:
result->mode = LC_EMC_TASK_SUBSET_MODE_MANUAL;
result->traj_mode = all_homed ? LC_EMC_TASK_SUBSET_TRAJ_TELEOP : LC_EMC_TASK_SUBSET_TRAJ_FREE;
result->should_clear_interpreter = 1;
break;
case LC_EMC_TASK_SUBSET_MODE_MDI:
result->mode = LC_EMC_TASK_SUBSET_MODE_MDI;
result->traj_mode = LC_EMC_TASK_SUBSET_TRAJ_COORD;
result->should_clear_interpreter = 1;
result->should_plan_synch = 1;
break;
case LC_EMC_TASK_SUBSET_MODE_AUTO:
result->mode = LC_EMC_TASK_SUBSET_MODE_AUTO;
result->traj_mode = LC_EMC_TASK_SUBSET_TRAJ_COORD;
result->should_clear_interpreter = 1;
result->should_plan_synch = 1;
break;
default:
result->retval = -1;
break;
}
}
void lc_emctask_subset_set_state(int state,
int old_state,
LcEmcTaskSubsetCommandResult *result)
{
(void)old_state;
clear_command_result(result);
if (!result) {
return;
}
result->state = state;
switch (state) {
case LC_EMC_TASK_SUBSET_STATE_OFF:
result->should_clear_interpreter = 1;
result->should_abort_motion = 1;
result->should_traj_disable = 1;
result->should_reset_homing = 1;
result->should_unhome = 1;
result->should_plan_synch = 1;
break;
case LC_EMC_TASK_SUBSET_STATE_ON:
result->should_traj_enable = 1;
break;
case LC_EMC_TASK_SUBSET_STATE_ESTOP_RESET:
result->should_clear_interpreter = 1;
result->should_plan_synch = 1;
break;
case LC_EMC_TASK_SUBSET_STATE_ESTOP:
result->should_clear_interpreter = 1;
result->should_abort_motion = 1;
result->should_traj_disable = 1;
result->should_reset_homing = 1;
result->should_unhome = 1;
result->should_plan_synch = 1;
break;
default:
result->retval = -1;
break;
}
}
void lc_emctask_subset_plan_set_wait(LcEmcTaskSubsetPlanState *state,
LcEmcTaskSubsetPlanResult *result)
{
clear_plan_result(result);
if (!state || !result) {
return;
}
state->wait_flag = 1;
copy_plan_state(state, result);
}
int lc_emctask_subset_plan_is_wait(const LcEmcTaskSubsetPlanState *state)
{
return state ? state->wait_flag : 0;
}
void lc_emctask_subset_plan_clear_wait(LcEmcTaskSubsetPlanState *state,
LcEmcTaskSubsetPlanResult *result)
{
clear_plan_result(result);
if (!state || !result) {
return;
}
state->wait_flag = 0;
copy_plan_state(state, result);
}
void lc_emctask_subset_plan_synch(const LcEmcTaskSubsetPlanState *state,
LcEmcTaskSubsetPlanResult *result)
{
clear_plan_result(result);
if (!state || !result) {
return;
}
result->should_synch = 1;
copy_plan_state(state, result);
}
void lc_emctask_subset_plan_open(const char *file,
int staged_file_available,
LcEmcTaskSubsetPlanState *state,
LcEmcTaskSubsetPlanResult *result)
{
clear_plan_result(result);
if (!state || !result || !file || !staged_file_available) {
if (result) {
result->retval = -1;
}
return;
}
state->motion_line = 0;
state->current_line = 0;
state->read_line = 0;
state->taskplanopen = 1;
result->should_reset_lines = 1;
copy_plan_state(state, result);
}
void lc_emctask_subset_plan_close(LcEmcTaskSubsetPlanState *state,
LcEmcTaskSubsetPlanResult *result)
{
clear_plan_result(result);
if (!state || !result) {
return;
}
state->taskplanopen = 0;
result->should_close = 1;
copy_plan_state(state, result);
}
void lc_emctask_subset_plan_reset(LcEmcTaskSubsetPlanState *state,
LcEmcTaskSubsetPlanResult *result)
{
clear_plan_result(result);
if (!state || !result) {
return;
}
state->wait_flag = 0;
state->read_line = 0;
state->current_line = 0;
state->motion_line = 0;
result->should_reset = 1;
result->should_reset_lines = 1;
copy_plan_state(state, result);
}
void lc_emctask_subset_plan_read(const LcEmcTaskSubsetPlanState *state,
int next_line,
int line_count,
LcEmcTaskSubsetPlanIoResult *result)
{
clear_plan_io_result(result);
if (!state || !result || !state->taskplanopen) {
if (result) {
result->retval = -1;
}
return;
}
if (state->wait_flag) {
result->retval = 2;
result->should_set_wait = 1;
result->line = state->read_line;
result->level = state->level;
return;
}
if (next_line < 0 || next_line >= line_count) {
result->retval = 1;
result->should_set_wait = 1;
result->line = 0;
result->level = state->level;
return;
}
result->retval = 0;
result->line = next_line + 1;
result->level = state->level;
result->should_execute = 1;
}
void lc_emctask_subset_plan_execute(const char *command,
int mdi,
int inpos,
int line_number,
LcEmcTaskSubsetPlanIoResult *result)
{
clear_plan_io_result(result);
if (!result || !command) {
if (result) {
result->retval = -1;
}
return;
}
if (mdi && command[0] != '\0' && inpos) {
result->should_synch_before_execute = 1;
}
result->retval = 0;
result->line = line_number > 0 ? line_number : 0;
result->level = 0;
result->should_append_to_interp_list = command[0] != '\0';
result->should_finish = mdi ? 1 : 0;
}
int lc_emctask_subset_plan_line(const LcEmcTaskSubsetPlanState *state)
{
return state ? state->read_line : 0;
}
int lc_emctask_subset_plan_level(const LcEmcTaskSubsetPlanState *state)
{
return state ? state->level : 0;
}
int lc_emctask_subset_plan_command(const char *command, char *out, int out_len)
{
if (!command || !out || out_len <= 0) {
return -1;
}
std::strncpy(out, command, static_cast<std::size_t>(out_len - 1));
out[out_len - 1] = '\0';
return 0;
}
const char *lc_emctask_subset_source_path(void)
{
return "src/emc/task/emctask.cc";
}
const char *lc_emctask_subset_anchor_list(void)
{
return "emcTaskAbort,emcTaskSetMode,emcTaskSetState,determineMode,determineState,emcTaskUpdate,emcTaskPlanSetWait,emcTaskPlanIsWait,emcTaskPlanClearWait,emcTaskPlanSynch,emcTaskPlanOpen,emcTaskPlanClose,emcTaskPlanReset,emcTaskPlanRead,emcTaskPlanExecute,emcTaskPlanLine,emcTaskPlanLevel,emcTaskPlanCommand";
}
const char *lc_emctask_subset_state_mode_anchor_list(void)
{
return "emcTaskAbort,emcTaskSetMode,emcTaskSetState,emcTaskPlanSynch,emcTaskPlanClose,emcTaskPlanReset";
}
const char *lc_emctask_subset_plan_anchor_list(void)
{
return "emcTaskPlanSetWait,emcTaskPlanIsWait,emcTaskPlanClearWait,emcTaskPlanSynch,emcTaskPlanOpen,emcTaskPlanClose,emcTaskPlanReset";
}
const char *lc_emctask_subset_plan_read_execute_anchor_list(void)
{
return "emcTaskPlanRead,emcTaskPlanExecute,emcTaskPlanLine,emcTaskPlanLevel,emcTaskPlanCommand,interp_list";
}
} // extern "C"

View File

@@ -0,0 +1,136 @@
#ifndef LINUXCNC_EMCTASK_WASM_SUBSET_HH
#define LINUXCNC_EMCTASK_WASM_SUBSET_HH
#ifdef __cplusplus
extern "C" {
#endif
enum LcEmcTaskSubsetMode {
LC_EMC_TASK_SUBSET_MODE_MANUAL = 1,
LC_EMC_TASK_SUBSET_MODE_AUTO = 2,
LC_EMC_TASK_SUBSET_MODE_MDI = 3,
};
enum LcEmcTaskSubsetState {
LC_EMC_TASK_SUBSET_STATE_ESTOP = 1,
LC_EMC_TASK_SUBSET_STATE_ESTOP_RESET = 2,
LC_EMC_TASK_SUBSET_STATE_ON = 3,
LC_EMC_TASK_SUBSET_STATE_OFF = 4,
};
enum LcEmcTaskSubsetTrajMode {
LC_EMC_TASK_SUBSET_TRAJ_FREE = 1,
LC_EMC_TASK_SUBSET_TRAJ_TELEOP = 2,
LC_EMC_TASK_SUBSET_TRAJ_COORD = 3,
};
struct LcEmcTaskSubsetUpdateInput {
int traj_mode;
int mdi_or_auto;
int traj_enabled;
int io_estop;
int old_task_state;
int motion_id;
};
struct LcEmcTaskSubsetUpdateResult {
int mode;
int state;
int should_abort_on_state_drop;
int motion_line;
};
struct LcEmcTaskSubsetCommandResult {
int retval;
int mode;
int state;
int traj_mode;
int should_clear_interpreter;
int should_abort_motion;
int should_traj_enable;
int should_traj_disable;
int should_reset_homing;
int should_unhome;
int should_plan_synch;
};
struct LcEmcTaskSubsetPlanState {
int wait_flag;
int taskplanopen;
int motion_line;
int current_line;
int read_line;
int level;
};
struct LcEmcTaskSubsetPlanResult {
int retval;
int wait_flag;
int taskplanopen;
int should_reset_lines;
int should_synch;
int should_close;
int should_reset;
int line;
int level;
};
struct LcEmcTaskSubsetPlanIoResult {
int retval;
int line;
int level;
int should_execute;
int should_set_wait;
int should_synch_before_execute;
int should_finish;
int should_append_to_interp_list;
};
void lc_emctask_subset_update(const LcEmcTaskSubsetUpdateInput *input,
LcEmcTaskSubsetUpdateResult *result);
void lc_emctask_subset_abort(LcEmcTaskSubsetCommandResult *result);
void lc_emctask_subset_set_mode(int mode,
int all_homed,
int jogging_active,
LcEmcTaskSubsetCommandResult *result);
void lc_emctask_subset_set_state(int state,
int old_state,
LcEmcTaskSubsetCommandResult *result);
void lc_emctask_subset_plan_set_wait(LcEmcTaskSubsetPlanState *state,
LcEmcTaskSubsetPlanResult *result);
int lc_emctask_subset_plan_is_wait(const LcEmcTaskSubsetPlanState *state);
void lc_emctask_subset_plan_clear_wait(LcEmcTaskSubsetPlanState *state,
LcEmcTaskSubsetPlanResult *result);
void lc_emctask_subset_plan_synch(const LcEmcTaskSubsetPlanState *state,
LcEmcTaskSubsetPlanResult *result);
void lc_emctask_subset_plan_open(const char *file,
int staged_file_available,
LcEmcTaskSubsetPlanState *state,
LcEmcTaskSubsetPlanResult *result);
void lc_emctask_subset_plan_close(LcEmcTaskSubsetPlanState *state,
LcEmcTaskSubsetPlanResult *result);
void lc_emctask_subset_plan_reset(LcEmcTaskSubsetPlanState *state,
LcEmcTaskSubsetPlanResult *result);
void lc_emctask_subset_plan_read(const LcEmcTaskSubsetPlanState *state,
int next_line,
int line_count,
LcEmcTaskSubsetPlanIoResult *result);
void lc_emctask_subset_plan_execute(const char *command,
int mdi,
int inpos,
int line_number,
LcEmcTaskSubsetPlanIoResult *result);
int lc_emctask_subset_plan_line(const LcEmcTaskSubsetPlanState *state);
int lc_emctask_subset_plan_level(const LcEmcTaskSubsetPlanState *state);
int lc_emctask_subset_plan_command(const char *command, char *out, int out_len);
const char *lc_emctask_subset_source_path(void);
const char *lc_emctask_subset_anchor_list(void);
const char *lc_emctask_subset_state_mode_anchor_list(void);
const char *lc_emctask_subset_plan_anchor_list(void);
const char *lc_emctask_subset_plan_read_execute_anchor_list(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,241 @@
#include "taskintf_wasm_subset.hh"
/*
* WASM task-to-motion subset derived from LinuxCNC src/emc/task/taskintf.cc.
*
* Upstream anchors:
* - emcMotionInit(): initialize traj/joint/axis/spindle motion edge.
* - emcMotionUpdate(): read usrmot status/config/internal/error into EMC_MOTION_STAT.
* - emcMotionAbort(): jog abort + traj abort through the motion interface.
* - emcTrajSetMotionId/Enable/Disable/Abort/Pause/Step/Resume(): set EMCMOT_* command and write it.
* - emcTrajLinearMove(): populate line motion command fields.
* - emcJogIncr(): populate jog increment command fields.
* - emcJointHome()/emcJointUnhome(): populate joint home command fields.
* - emcMotionSetAout(): populate analog-output motion command fields.
*
* The full upstream file owns usrmot, NML, INI config, and native motion
* process edges. This subset stops at the command envelope boundary so the
* standalone WASM runtime can forward through lcmot_* without owning LinuxCNC
* motion semantics in the task layer.
*/
namespace {
void clear_command(LcTaskIntfSubsetMotionCommand *out)
{
if (!out) {
return;
}
*out = LcTaskIntfSubsetMotionCommand{};
}
void set_simple(int command, LcTaskIntfSubsetMotionCommand *out)
{
clear_command(out);
if (!out) {
return;
}
out->command = command;
}
} // namespace
extern "C" {
void lc_taskintf_subset_traj_abort(LcTaskIntfSubsetMotionCommand *out)
{
set_simple(LC_TASKINTF_SUBSET_COMMAND_TRAJ_ABORT, out);
}
void lc_taskintf_subset_traj_enable(LcTaskIntfSubsetMotionCommand *out)
{
set_simple(LC_TASKINTF_SUBSET_COMMAND_TRAJ_ENABLE, out);
}
void lc_taskintf_subset_traj_disable(LcTaskIntfSubsetMotionCommand *out)
{
set_simple(LC_TASKINTF_SUBSET_COMMAND_TRAJ_DISABLE, out);
}
void lc_taskintf_subset_traj_set_motion_id(int id, LcTaskIntfSubsetMotionCommand *out)
{
clear_command(out);
if (!out) {
return;
}
out->command = LC_TASKINTF_SUBSET_COMMAND_TRAJ_SET_MOTION_ID;
out->motion_id = id;
}
void lc_taskintf_subset_traj_pause(LcTaskIntfSubsetMotionCommand *out)
{
set_simple(LC_TASKINTF_SUBSET_COMMAND_TRAJ_PAUSE, out);
}
void lc_taskintf_subset_traj_step(LcTaskIntfSubsetMotionCommand *out)
{
set_simple(LC_TASKINTF_SUBSET_COMMAND_TRAJ_STEP, out);
}
void lc_taskintf_subset_traj_resume(LcTaskIntfSubsetMotionCommand *out)
{
set_simple(LC_TASKINTF_SUBSET_COMMAND_TRAJ_RESUME, out);
}
void lc_taskintf_subset_joint_home(int joint, LcTaskIntfSubsetMotionCommand *out)
{
clear_command(out);
if (!out) {
return;
}
out->command = LC_TASKINTF_SUBSET_COMMAND_JOINT_HOME;
out->joint = joint;
}
void lc_taskintf_subset_joint_unhome(int joint, LcTaskIntfSubsetMotionCommand *out)
{
clear_command(out);
if (!out) {
return;
}
out->command = LC_TASKINTF_SUBSET_COMMAND_JOINT_UNHOME;
out->joint = joint;
}
void lc_taskintf_subset_jog_incr(int axis, double distance, double velocity,
LcTaskIntfSubsetMotionCommand *out)
{
lc_taskintf_subset_jog_incr_ex(axis, distance, velocity, 0, 0, out);
}
void lc_taskintf_subset_jog_incr_ex(int nr, double distance, double velocity,
int joint_jog_mode, int motion_id,
LcTaskIntfSubsetMotionCommand *out)
{
clear_command(out);
if (!out) {
return;
}
out->command = LC_TASKINTF_SUBSET_COMMAND_JOG_INCR;
out->axis = joint_jog_mode ? -1 : nr;
out->joint = joint_jog_mode ? nr : -1;
out->distance = distance;
out->velocity = velocity;
out->motion_id = motion_id;
}
void lc_taskintf_subset_set_aout(int index, double start, double end, int now,
LcTaskIntfSubsetMotionCommand *out)
{
clear_command(out);
if (!out) {
return;
}
out->command = LC_TASKINTF_SUBSET_COMMAND_SET_AOUT;
out->aout_index = index;
out->aout_now = now;
out->aout_start = start;
out->aout_end = end;
}
void lc_taskintf_subset_linear_move(int line, const LcTaskIntfSubsetPose *pose,
double velocity, int motion_type,
LcTaskIntfSubsetMotionCommand *out)
{
lc_taskintf_subset_linear_move_ex(
line,
pose,
velocity,
motion_type,
velocity,
0.0,
0.0,
line,
out);
}
void lc_taskintf_subset_linear_move_ex(int line, const LcTaskIntfSubsetPose *pose,
double velocity, int motion_type,
double ini_maxvel, double acceleration,
double ini_maxjerk, int motion_id,
LcTaskIntfSubsetMotionCommand *out)
{
clear_command(out);
if (!out) {
return;
}
out->command = LC_TASKINTF_SUBSET_COMMAND_TRAJ_LINEAR_MOVE;
out->line = line;
out->motion_type = motion_type;
out->motion_id = motion_id;
out->velocity = velocity;
out->ini_maxvel = ini_maxvel;
out->acceleration = acceleration;
out->ini_maxjerk = ini_maxjerk;
if (pose) {
out->pose = *pose;
}
}
int lc_taskintf_subset_motion_init(const char *ini_path, const char *ini_text)
{
return lcmot_init_from_ini(ini_path, ini_text);
}
int lc_taskintf_subset_motion_update(LcmotStatusSnapshot *status,
LcmotConfigSnapshot *config,
char *error_text,
int error_text_len)
{
if (!status || !config) {
return -1;
}
if (lcmot_read_status_snapshot(status) != 0) {
return -1;
}
if (lcmot_read_config_snapshot(config) != 0) {
return -1;
}
if (error_text && error_text_len > 0) {
error_text[0] = '\0';
(void)lcmot_read_error_message(error_text, error_text_len);
}
return 0;
}
void lc_taskintf_subset_motion_abort(LcTaskIntfSubsetMotionCommand *out)
{
lc_taskintf_subset_traj_abort(out);
}
const char *lc_taskintf_subset_source_path(void)
{
return "src/emc/task/taskintf.cc";
}
const char *lc_taskintf_subset_anchor_list(void)
{
return "emcTrajSetMotionId,emcTrajEnable,emcTrajDisable,emcTrajAbort,emcTrajPause,emcTrajStep,emcTrajResume,emcTrajLinearMove,emcJogIncr,emcJointHome,emcJointUnhome,emcMotionSetAout";
}
const char *lc_taskintf_subset_motion_bridge_anchor_list(void)
{
return "emcMotionInit,emcMotionUpdate,emcMotionAbort,usrmotReadEmcmotStatus,usrmotReadEmcmotConfig,usrmotReadEmcmotError";
}
const char *lc_taskintf_subset_traj_control_anchor_list(void)
{
return "emcTrajSetMotionId,emcTrajEnable,emcTrajDisable,emcTrajAbort,emcTrajPause,emcTrajStep,emcTrajResume";
}
const char *lc_taskintf_subset_linear_move_anchor_list(void)
{
return "emcTrajLinearMove,EMCMOT_SET_LINE,usrmotWriteEmcmotCommand";
}
const char *lc_taskintf_subset_jog_home_switchkins_anchor_list(void)
{
return "emcJogIncr,emcJointHome,emcJointUnhome,emcMotionSetAout,EMCMOT_JOG_INCR,EMCMOT_JOINT_HOME,EMCMOT_JOINT_UNHOME,EMCMOT_SET_AOUT,usrmotWriteEmcmotCommand";
}
} // extern "C"

View File

@@ -0,0 +1,95 @@
#ifndef LINUXCNC_TASKINTF_WASM_SUBSET_HH
#define LINUXCNC_TASKINTF_WASM_SUBSET_HH
#include "linuxcnc_motion_runtime.h"
#ifdef __cplusplus
extern "C" {
#endif
enum LcTaskIntfSubsetCommand {
LC_TASKINTF_SUBSET_COMMAND_NONE = 0,
LC_TASKINTF_SUBSET_COMMAND_TRAJ_ABORT = 1,
LC_TASKINTF_SUBSET_COMMAND_TRAJ_PAUSE = 2,
LC_TASKINTF_SUBSET_COMMAND_TRAJ_STEP = 3,
LC_TASKINTF_SUBSET_COMMAND_TRAJ_RESUME = 4,
LC_TASKINTF_SUBSET_COMMAND_TRAJ_LINEAR_MOVE = 5,
LC_TASKINTF_SUBSET_COMMAND_JOG_INCR = 6,
LC_TASKINTF_SUBSET_COMMAND_JOINT_HOME = 7,
LC_TASKINTF_SUBSET_COMMAND_SET_AOUT = 8,
LC_TASKINTF_SUBSET_COMMAND_TRAJ_ENABLE = 9,
LC_TASKINTF_SUBSET_COMMAND_TRAJ_DISABLE = 10,
LC_TASKINTF_SUBSET_COMMAND_TRAJ_SET_MOTION_ID = 11,
LC_TASKINTF_SUBSET_COMMAND_JOINT_UNHOME = 12,
};
struct LcTaskIntfSubsetPose {
double x;
double y;
double z;
double a;
double b;
double c;
};
struct LcTaskIntfSubsetMotionCommand {
int command;
int line;
int axis;
int joint;
int motion_type;
int aout_index;
int aout_now;
int motion_id;
double velocity;
double ini_maxvel;
double acceleration;
double ini_maxjerk;
double distance;
double aout_start;
double aout_end;
LcTaskIntfSubsetPose pose;
};
void lc_taskintf_subset_traj_abort(LcTaskIntfSubsetMotionCommand *out);
void lc_taskintf_subset_traj_enable(LcTaskIntfSubsetMotionCommand *out);
void lc_taskintf_subset_traj_disable(LcTaskIntfSubsetMotionCommand *out);
void lc_taskintf_subset_traj_set_motion_id(int id, LcTaskIntfSubsetMotionCommand *out);
void lc_taskintf_subset_traj_pause(LcTaskIntfSubsetMotionCommand *out);
void lc_taskintf_subset_traj_step(LcTaskIntfSubsetMotionCommand *out);
void lc_taskintf_subset_traj_resume(LcTaskIntfSubsetMotionCommand *out);
void lc_taskintf_subset_joint_home(int joint, LcTaskIntfSubsetMotionCommand *out);
void lc_taskintf_subset_joint_unhome(int joint, LcTaskIntfSubsetMotionCommand *out);
void lc_taskintf_subset_jog_incr(int axis, double distance, double velocity,
LcTaskIntfSubsetMotionCommand *out);
void lc_taskintf_subset_jog_incr_ex(int nr, double distance, double velocity,
int joint_jog_mode, int motion_id,
LcTaskIntfSubsetMotionCommand *out);
void lc_taskintf_subset_set_aout(int index, double start, double end, int now,
LcTaskIntfSubsetMotionCommand *out);
void lc_taskintf_subset_linear_move(int line, const LcTaskIntfSubsetPose *pose,
double velocity, int motion_type,
LcTaskIntfSubsetMotionCommand *out);
void lc_taskintf_subset_linear_move_ex(int line, const LcTaskIntfSubsetPose *pose,
double velocity, int motion_type,
double ini_maxvel, double acceleration,
double ini_maxjerk, int motion_id,
LcTaskIntfSubsetMotionCommand *out);
int lc_taskintf_subset_motion_init(const char *ini_path, const char *ini_text);
int lc_taskintf_subset_motion_update(LcmotStatusSnapshot *status,
LcmotConfigSnapshot *config,
char *error_text,
int error_text_len);
void lc_taskintf_subset_motion_abort(LcTaskIntfSubsetMotionCommand *out);
const char *lc_taskintf_subset_source_path(void);
const char *lc_taskintf_subset_anchor_list(void);
const char *lc_taskintf_subset_motion_bridge_anchor_list(void);
const char *lc_taskintf_subset_traj_control_anchor_list(void);
const char *lc_taskintf_subset_linear_move_anchor_list(void);
const char *lc_taskintf_subset_jog_home_switchkins_anchor_list(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,8 +1,8 @@
#include "linuxcnc_task_hal_wasm.hh"
#include "emc/task/emccanon_wasm_subset.hh"
#include "emc/task/emctask_wasm_subset.hh"
#include "emc/task/taskintf_wasm_subset.hh"
#include "emccanon_wasm_subset.hh"
#include "emctask_wasm_subset.hh"
#include "taskintf_wasm_subset.hh"
#include "linuxcnc_motion_runtime.h"
#include <algorithm>

View File

@@ -204,17 +204,17 @@ export const VIRTUAL_HAL_SIM_CONFIG_SOURCE_TARGETS = Object.freeze([
]);
export const VIRTUAL_HAL_SIM_CONFIG_INVENTORY_BASELINE = Object.freeze({
executed: 82,
passed: 82,
skipped: 77,
executed: 29,
passed: 29,
skipped: 130,
unexpectedFail: 0,
});
export const VIRTUAL_HAL_SIM_CONFIG_INVENTORY_ARTIFACT_HASHES = Object.freeze({
"wasm-port/build/wasm/sim-configs-inventory/boundary-summary.tsv":
"6cc15052cad03d04eff4506cd0a9d651cd45a2bd5da4d9f38633e9535826b9f3",
"7dd95e06b662cf26a02c94039675cbad9a0c836c8cab54878687f11736ddb2c6",
"wasm-port/build/wasm/sim-configs-inventory/ini-boundary-summary.tsv":
"17bff95b57c55ff4201a23c7286e733550e4df513470c66dd5f24329e7781a35",
"e6036e152b53c0091ee7da25e50a08122f77552abc53d9e6044c98e5abbd2313",
});
export const VIRTUAL_HAL_SIM_CONFIG_PROMOTION_CANDIDATES = Object.freeze([

View File

@@ -63,7 +63,11 @@ export async function createLinuxCncIniSdk(moduleOptions = {}) {
try {
const rc = mod._lcini_get_bool(pathPtr, sectionPtr, tagPtr, outPtr);
return rc === 0 ? mod.HEAP32[outPtr >> 2] !== 0 : null;
if (rc !== 0) {
return null;
}
const value = mod.HEAP32 ? mod.HEAP32[outPtr >> 2] : mod.getValue(outPtr, "i32");
return value !== 0;
} finally {
mod._free(pathPtr);
mod._free(sectionPtr);

View File

@@ -79,17 +79,17 @@ const REQUIRED_RELEASE_GATES = [
];
const DEFAULT_SIM_CONFIG_INVENTORY_BASELINE = {
executed: 82,
passed: 82,
skipped: 77,
executed: 29,
passed: 29,
skipped: 130,
unexpectedFail: 0,
};
const DEFAULT_SIM_CONFIG_INVENTORY_ARTIFACT_HASHES = {
"wasm-port/build/wasm/sim-configs-inventory/boundary-summary.tsv":
"6cc15052cad03d04eff4506cd0a9d651cd45a2bd5da4d9f38633e9535826b9f3",
"7dd95e06b662cf26a02c94039675cbad9a0c836c8cab54878687f11736ddb2c6",
"wasm-port/build/wasm/sim-configs-inventory/ini-boundary-summary.tsv":
"17bff95b57c55ff4201a23c7286e733550e4df513470c66dd5f24329e7781a35",
"e6036e152b53c0091ee7da25e50a08122f77552abc53d9e6044c98e5abbd2313",
};
function isBoundaryEvidenceBaselineFresh(boundaryEvidence = {}) {
@@ -194,7 +194,7 @@ function createPromotionCandidateArtifactSummary({
const evidenceExpansionFamilySummary = createEvidenceExpansionFamilySummaryText(evidenceExpansionReport);
const inventoryReadyCount = artifactInventoryReadyRows.length > 0
? artifactInventoryReadyRows.length
: 2;
: 19;
const evidenceExpansionCandidateCount = evidenceExpansionArtifactRows.length > 0
? evidenceExpansionArtifactRows.length
: 14;
@@ -324,7 +324,8 @@ function createToolDbProcessProofSummary(toolDbProcessProof = {}) {
const opfsPersistenceReady = proof.opfsPersistenceReady !== false;
const tblFallbackSufficient = proof.tblFallbackSufficient === true;
const promotionAllowed = proof.promotionAllowed === true;
const ready = wasmProtocolReady &&
const ready = nativeProtocolReady &&
wasmProtocolReady &&
browserProtocolReady &&
opfsPersistenceReady &&
tblFallbackSufficient === false &&
@@ -812,7 +813,7 @@ function isVirtualHalPromotionCandidateSummaryReady(summary) {
summaryObject.preferredIniPath === "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/qtdragon_xyyz.ini" &&
summaryObject.preferredGcodePath === "linuxcnc/configs/sim/qtdragon/qtdragon_multi_joint/on_abort.ngc" &&
summaryObject.explicitBrowserDiagnosticsCount === 8 &&
summaryObject.inventoryBaseline === "executed=82 passed=82 skipped=77 unexpected_fail=0" &&
summaryObject.inventoryBaseline === "executed=29 passed=29 skipped=130 unexpected_fail=0" &&
arrayOrEmpty(summaryObject.blockedCandidateIds).length === 0;
}
@@ -2510,7 +2511,7 @@ export function createProjectReleaseReadinessReport({
{
id: "tool-db-process-proof-detail",
label: "Tool DB process proof detail",
value: `wasm=${toolDbProcessProofSummary.wasmProtocolReady ? "ready" : "missing"} browser=${toolDbProcessProofSummary.browserProtocolReady ? "ready" : "missing"} opfs=${toolDbProcessProofSummary.opfsPersistenceReady ? "ready" : "missing"} promotion_allowed=${toolDbProcessProofSummary.promotionAllowed ? "1" : "0"}`,
value: `native=${toolDbProcessProofSummary.nativeProtocolReady ? "ready" : "missing"} wasm=${toolDbProcessProofSummary.wasmProtocolReady ? "ready" : "missing"} browser=${toolDbProcessProofSummary.browserProtocolReady ? "ready" : "missing"} opfs=${toolDbProcessProofSummary.opfsPersistenceReady ? "ready" : "missing"} promotion_allowed=${toolDbProcessProofSummary.promotionAllowed ? "1" : "0"}`,
},
{
id: "python-remap-runtime-proof",
@@ -2662,7 +2663,7 @@ export function createProjectReleaseReadinessSummaryViewModel(
id: "tool-db-process-proof-detail",
label: "Tool DB process proof detail",
value: toolDbProcessProofSummary.apiName
? `wasm=${toolDbProcessProofSummary.wasmProtocolReady ? "ready" : "missing"} browser=${toolDbProcessProofSummary.browserProtocolReady ? "ready" : "missing"} opfs=${toolDbProcessProofSummary.opfsPersistenceReady ? "ready" : "missing"} promotion_allowed=${toolDbProcessProofSummary.promotionAllowed ? "1" : "0"}`
? `native=${toolDbProcessProofSummary.nativeProtocolReady ? "ready" : "missing"} wasm=${toolDbProcessProofSummary.wasmProtocolReady ? "ready" : "missing"} browser=${toolDbProcessProofSummary.browserProtocolReady ? "ready" : "missing"} opfs=${toolDbProcessProofSummary.opfsPersistenceReady ? "ready" : "missing"} promotion_allowed=${toolDbProcessProofSummary.promotionAllowed ? "1" : "0"}`
: "missing",
},
{
@@ -2874,7 +2875,7 @@ export function createProjectReleaseReadinessArtifactValidationSummaryViewModel(
id: "tool-db-process-proof-detail",
label: "Tool DB process proof detail",
value: validation?.toolDbProcessProofReady === true
? `wasm=${validation.toolDbProcessProofSummary.wasmProtocolReady ? "ready" : "missing"} browser=${validation.toolDbProcessProofSummary.browserProtocolReady ? "ready" : "missing"} opfs=${validation.toolDbProcessProofSummary.opfsPersistenceReady ? "ready" : "missing"} promotion_allowed=${validation.toolDbProcessProofSummary.promotionAllowed ? "1" : "0"}`
? `native=${validation.toolDbProcessProofSummary.nativeProtocolReady ? "ready" : "missing"} wasm=${validation.toolDbProcessProofSummary.wasmProtocolReady ? "ready" : "missing"} browser=${validation.toolDbProcessProofSummary.browserProtocolReady ? "ready" : "missing"} opfs=${validation.toolDbProcessProofSummary.opfsPersistenceReady ? "ready" : "missing"} promotion_allowed=${validation.toolDbProcessProofSummary.promotionAllowed ? "1" : "0"}`
: "missing",
},
{
@@ -3626,7 +3627,7 @@ export function createProjectReleaseReadinessArtifactUrlWorkflowSummaryViewModel
id: "tool-db-process-proof-detail",
label: "Tool DB process proof detail",
value: toolDbProcessProofReady
? `wasm=${toolDbProcessProofSummary.wasmProtocolReady ? "ready" : "missing"} browser=${toolDbProcessProofSummary.browserProtocolReady ? "ready" : "missing"} opfs=${toolDbProcessProofSummary.opfsPersistenceReady ? "ready" : "missing"} promotion_allowed=${toolDbProcessProofSummary.promotionAllowed ? "1" : "0"}`
? `native=${toolDbProcessProofSummary.nativeProtocolReady ? "ready" : "missing"} wasm=${toolDbProcessProofSummary.wasmProtocolReady ? "ready" : "missing"} browser=${toolDbProcessProofSummary.browserProtocolReady ? "ready" : "missing"} opfs=${toolDbProcessProofSummary.opfsPersistenceReady ? "ready" : "missing"} promotion_allowed=${toolDbProcessProofSummary.promotionAllowed ? "1" : "0"}`
: "not provided",
},
{
@@ -3961,6 +3962,7 @@ export function createProjectReleaseReadinessArtifactValidation(artifact = {}) {
toolDbProcessProofSummary.boundaryClass === "L4-TOOL-DB" &&
toolDbProcessProofSummary.path === "axis/db_demo/base.ngc" &&
toolDbProcessProofSummary.dbProgramPath === "./db_nonran.py" &&
toolDbProcessProofSummary.nativeProtocolReady === true &&
toolDbProcessProofSummary.wasmProtocolReady === true &&
toolDbProcessProofSummary.browserProtocolReady === true &&
toolDbProcessProofSummary.opfsPersistenceReady === true &&
@@ -4236,7 +4238,7 @@ export function createProjectReleaseReadinessArtifactValidation(artifact = {}) {
id: "tool-db-process-proof-detail",
label: "Tool DB process proof detail",
value: toolDbProcessProofReady
? `wasm=${toolDbProcessProofSummary.wasmProtocolReady ? "ready" : "missing"} browser=${toolDbProcessProofSummary.browserProtocolReady ? "ready" : "missing"} opfs=${toolDbProcessProofSummary.opfsPersistenceReady ? "ready" : "missing"} promotion_allowed=${toolDbProcessProofSummary.promotionAllowed ? "1" : "0"}`
? `native=${toolDbProcessProofSummary.nativeProtocolReady ? "ready" : "missing"} wasm=${toolDbProcessProofSummary.wasmProtocolReady ? "ready" : "missing"} browser=${toolDbProcessProofSummary.browserProtocolReady ? "ready" : "missing"} opfs=${toolDbProcessProofSummary.opfsPersistenceReady ? "ready" : "missing"} promotion_allowed=${toolDbProcessProofSummary.promotionAllowed ? "1" : "0"}`
: "missing",
},
{

File diff suppressed because one or more lines are too long

View File

@@ -5301,15 +5301,15 @@ M2
preferredGcodePath: preferredCandidate?.gcodePath ?? null,
blockedCandidateIds: blockedRows.map((row) => row.id),
explicitBrowserDiagnosticsCount: explicitBrowserRows.length,
inventoryBaseline: "executed=82 passed=82 skipped=77 unexpected_fail=0",
inventoryBaseline: "executed=29 passed=29 skipped=130 unexpected_fail=0",
sourceFiles,
rows: [
{ id: "candidate-count", label: "Candidates", value: `${readyRows.length}/${rows.length} ready` },
{ id: "family-count", label: "Families", value: `${familyRows.length}` },
{ id: "preferred-candidate", label: "First case", value: preferredCandidate?.id ?? "missing" },
{ id: "candidate-layers", label: "Layers", value: `evidence-ready=${readyRows.length} inventory-ready=2` },
{ id: "candidate-layers", label: "Layers", value: `evidence-ready=${readyRows.length} inventory-ready=19` },
{ id: "source-files", label: "Source files", value: `${sourceFiles.length}` },
{ id: "inventory-baseline", label: "Inventory", value: "82/82 pass; 77 skip" },
{ id: "inventory-baseline", label: "Inventory", value: "29/29 pass; 130 skip" },
{ id: "promotion-allowed", label: "Allowed", value: "0 baseline changes" },
{ id: "blocked-candidates", label: "Hard blocks", value: blockedRows.length === 0 ? "excluded" : blockedRows.map((row) => row.id).join(", ") },
{ id: "browser-evidence", label: "Browser evidence", value: `${explicitBrowserRows.length}/${rows.length} explicit` },