diff --git a/wasm-port/docs/compatibility-validation.md b/wasm-port/docs/compatibility-validation.md index 15b389d..8cb0bc6 100644 --- a/wasm-port/docs/compatibility-validation.md +++ b/wasm-port/docs/compatibility-validation.md @@ -111,10 +111,12 @@ file execution path. It also writes the vendored LinuxCNC `xyzac-trt` and `xyzbc-trt` table-rotary-tilting sample machine INI, `remap_subs/*.ngc`, and `xyzac_switchkins.ngc`/`xyzbc_switchkins.ngc`, `boat-xyzac.ngc`, `boat-xyzbc.ngc`, and `impeller-7bl-xyzac.ngc` demo files into the Emscripten -filesystem, then validates the WASM C ABI/SDK path for vendored LinuxCNC -`REMAP` parsing, vendored LinuxCNC tool-table loading from the machine INI, -O-word remap execution, `M68`/`M66` HAL synchronization, and file -`open()`/`read()`/`execute()` completion without JavaScript M-code or +filesystem. It also writes the vendored LinuxCNC `xyzab-tdr` table-dual-rotary +INI, tool table, `remap_subs/*.ngc`, and `xyzab-tdr-demo.ngc` into the +Emscripten filesystem. These checks validate the WASM C ABI/SDK path for +vendored LinuxCNC `REMAP` parsing, vendored LinuxCNC tool-table loading from +the machine INI, O-word remap execution, `M68`/`M66` HAL synchronization, and +file `open()`/`read()`/`execute()` completion without JavaScript M-code or kinematics semantics. The same Node smoke writes LinuxCNC-format parameter files into the Emscripten filesystem and validates vendored `Interp::restore_parameters()` and `Interp::save_parameters()`, @@ -164,8 +166,9 @@ when a machine session is copied into the interpreter WASM filesystem. It also clicks the INI panel's 5-axis remap demo action and verifies that the UI copies vendored LinuxCNC `xyzac-trt` machine/remap/demo files into the interpreter WASM filesystem, calls the LinuxCNC-backed SDK remap execution -path for the vendored `boat-xyzac.ngc` demo, and displays the resulting -`fiveaxis_*` status lines without JavaScript M-code or kinematics semantics. +path for the vendored `impeller-7bl-xyzac.ngc` demo, and displays the +resulting `fiveaxis_*` status lines without JavaScript M-code or kinematics +semantics. The browser interpreter smoke script serves `wasm-port/` over localhost and runs Chromium headless against a test page that loads the interpreter-core @@ -199,9 +202,12 @@ WASM filesystem, and that absent INI file-name values use the default OPFS parameter/tool-table paths in a real browser session. It also writes vendored LinuxCNC `xyzac-trt`/`xyzbc-trt` INI, remap subroutines, and switchkins demo files, including the larger `boat-xyzac.ngc`, `boat-xyzbc.ngc`, and -`impeller-7bl-xyzac.ngc` demos, into the browser WASM filesystem and verifies -`runFiveAxisRemapFile()` for both sample machines through the exported -LinuxCNC remap/tool-table/file execution path. +`impeller-7bl-xyzac.ngc` demos, into the browser WASM filesystem. It also +writes vendored LinuxCNC `xyzab-tdr` machine files and `xyzab-tdr-demo.ngc` +into the browser WASM filesystem. The browser smoke verifies +`runFiveAxisRemapFile()` for the table-rotary-tilting and table-dual-rotary +sample machines through the exported LinuxCNC remap/tool-table/file execution +path. The aggregate host smoke script builds the INI, interpreter-core, and trajectory-planner WASM artifacts once, then runs the Node WASM smokes, the @@ -231,7 +237,7 @@ The validation fails if: | `linuxcnc_interp_init_harness` | Validates vendored LinuxCNC `Interp::init()` emits canonical initialization boundaries, reads metric/inch machine units, and synchronizes current/selected tool slots through standalone status adapters. | | `linuxcnc_indexer_harness` | Validates vendored LinuxCNC single-axis rotary indexer dispatch emits lock/unlock and motion boundaries through the standalone event sink. | | `linuxcnc_remap_hal_sync_harness` | Validates vendored LinuxCNC `M68`/`M66` execution can drive the standalone HAL adapter boundary used by 5-axis switchkins remap files, including `_hal[motion.switchkins-type]` readback. | -| `linuxcnc_5axis_remap_execute_harness` | Validates vendored LinuxCNC `REMAP` parsing plus NGC remap execution for the 5-axis `M429 -> M428 -> M430 -> M429` switchkins path in the `xyzac-trt` and `xyzbc-trt` sample machines, loads vendored machine tool tables through LinuxCNC `tooldata_load()`, then runs vendored `xyzac_switchkins.ngc`, `xyzbc_switchkins.ngc`, `xyzac_switchkins_test_1.ngc`, `xyzac_switchkins_test_3.ngc`, `boat-xyzac.ngc`, `boat-xyzbc.ngc`, and `impeller-7bl-xyzac.ngc` through the LinuxCNC file `open/read/execute` path. | +| `linuxcnc_5axis_remap_execute_harness` | Validates vendored LinuxCNC `REMAP` parsing plus NGC remap execution for the 5-axis `M429 -> M428 -> M430 -> M429` switchkins path in the `xyzac-trt` and `xyzbc-trt` sample machines, plus the two-remap `M429 -> M428 -> M429` path in the `xyzab-tdr` sample machine. It loads vendored machine tool tables through LinuxCNC `tooldata_load()`, then runs vendored `xyzac_switchkins.ngc`, `xyzbc_switchkins.ngc`, `xyzac_switchkins_test_1.ngc`, `xyzac_switchkins_test_3.ngc`, `boat-xyzac.ngc`, `boat-xyzbc.ngc`, `impeller-7bl-xyzac.ngc`, and `xyzab-tdr-demo.ngc` through the LinuxCNC file `open/read/execute` path. | | `linuxcnc_tp_api_probe` | Validates vendored LinuxCNC trajectory planner calls for linear, arc, and queued motion paths. | | `linuxcnc_kinematics_probe` | Validates vendored LinuxCNC `trivkins.c` plus `kins_util.c` initialize and perform identity forward/inverse mapping through the standalone HAL/RTAPI boundary. | | `linuxcnc_5axis_kinematics_probe` | Validates vendored LinuxCNC `5axiskins.c` through `switchkins.c`, including 5-axis forward/inverse round-trip behavior and switching to identity kinematics. | diff --git a/wasm-port/docs/porting-steps-standalone.md b/wasm-port/docs/porting-steps-standalone.md index ea56888..e96cc53 100644 --- a/wasm-port/docs/porting-steps-standalone.md +++ b/wasm-port/docs/porting-steps-standalone.md @@ -802,17 +802,18 @@ Current five-axis switchkins status: 5. `linuxcnc_remap_hal_sync_harness` validates vendored LinuxCNC `M68` and `M66` synchronization through the standalone HAL adapter boundary. 6. `linuxcnc_5axis_remap_execute_harness` executes the `xyzac-trt` and - `xyzbc-trt` switchkins `M429 -> M428 -> M430 -> M429` paths, loads - vendored machine tool tables through LinuxCNC `tooldata_load()`, and runs - vendored `xyzac_switchkins.ngc`, `xyzbc_switchkins.ngc`, + `xyzbc-trt` switchkins `M429 -> M428 -> M430 -> M429` paths plus the + `xyzab-tdr` two-remap `M429 -> M428 -> M429` path, loads vendored machine + tool tables through LinuxCNC `tooldata_load()`, and runs vendored + `xyzac_switchkins.ngc`, `xyzbc_switchkins.ngc`, `xyzac_switchkins_test_1.ngc`, `xyzac_switchkins_test_3.ngc`, - `boat-xyzac.ngc`, `boat-xyzbc.ngc`, and `impeller-7bl-xyzac.ngc` through - LinuxCNC remap/file execution paths. + `boat-xyzac.ngc`, `boat-xyzbc.ngc`, `impeller-7bl-xyzac.ngc`, and + `xyzab-tdr-demo.ngc` through LinuxCNC remap/file execution paths. 7. The WASM interpreter core now links vendored `interp_remap.cc` plus the Python-only runtime edge stub, and the Node WASM smoke runs vendored `xyzac_switchkins.ngc`, `xyzbc_switchkins.ngc`, `boat-xyzac.ngc`, and - `boat-xyzbc.ngc`, plus `impeller-7bl-xyzac.ngc` through the SDK C ABI - without JavaScript M-code or kinematics semantics. + `boat-xyzbc.ngc`, `impeller-7bl-xyzac.ngc`, and `xyzab-tdr-demo.ngc` + through the SDK C ABI without JavaScript M-code or kinematics semantics. 8. Browser smoke and the INI panel UI now expose the same validated 5-axis remap execution path by copying vendored LinuxCNC sample-machine files into the interpreter WASM filesystem and calling the SDK C ABI. @@ -822,8 +823,8 @@ Next work: 1. Continue broadening five-axis fixture coverage through the same source-backed execution boundary. 2. Evaluate additional vendored LinuxCNC five-axis sample machines and demos - after the TRT boat and impeller demos are stable in native, Node WASM, - browser, and UI remap paths. + after the TRT boat/impeller and TDR demo paths are stable in native, Node + WASM, browser, and UI remap paths. Involved LinuxCNC source: diff --git a/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_5axis_remap_execute_harness.cpp b/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_5axis_remap_execute_harness.cpp index 6833c18..6ce2415 100644 --- a/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_5axis_remap_execute_harness.cpp +++ b/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_5axis_remap_execute_harness.cpp @@ -25,6 +25,8 @@ namespace { struct MachineCase { const char *label; const char *ini_rel; + int expected_remaps; + bool has_m430; }; struct DemoCase { @@ -66,6 +68,23 @@ void seed_switchkins_hal() standalone::set_hal_value(standalone::HalValueKind::Pin, "motion.analog-out-03", HAL_FLOAT, switchkins); standalone::link_hal_pin_alias("motion.analog-out-03", "motion.switchkins-type"); + + // Values mirror the vendored LinuxCNC xyzab-tdr sample INI/XML HAL defaults. + const struct { + const char *name; + double value; + } xyzab_tdr_defaults[] = { + {"xyzab_tdr_kins.x-offset", -20.0}, + {"xyzab_tdr_kins.z-offset", -10.0}, + {"xyzab_tdr_kins.x-rot-point", -50.0}, + {"xyzab_tdr_kins.y-rot-point", -50.0}, + {"xyzab_tdr_kins.z-rot-point", -100.0}, + }; + for (const auto &entry : xyzab_tdr_defaults) { + hal_data_u value{}; + value.f = entry.value; + standalone::set_hal_value(standalone::HalValueKind::Pin, entry.name, HAL_FLOAT, value); + } } void initialize_interp(Interp &interp) @@ -141,7 +160,7 @@ bool parse_machine_remaps(Interp &interp, const MachineCase &machine) remap_count -= 1; std::cout << machine.label << "_parsed_remap_count=" << remap_count << "\n"; - ok &= remap_count == 3; + ok &= remap_count == machine.expected_remaps; print_bool(std::string(machine.label) + "_remaps_ready", ok); return ok; } @@ -264,7 +283,9 @@ bool check_machine(const MachineCase &machine) ok &= read_hal_named(interp, machine.label, "_hal[motion.switchkins-type]", 0.0); ok &= execute_step(interp, machine.label, "M429\n", 0.0); ok &= execute_step(interp, machine.label, "M428\n", 1.0); - ok &= execute_step(interp, machine.label, "M430\n", 2.0); + if (machine.has_m430) { + ok &= execute_step(interp, machine.label, "M430\n", 2.0); + } ok &= execute_step(interp, machine.label, "M429\n", 0.0); print_bool(std::string(machine.label) + "_linuxcnc_remap_execute_path", ok); @@ -279,10 +300,20 @@ int main() { "xyzac_trt", "configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini", + 3, + true, }, { "xyzbc_trt", "configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.ini", + 3, + true, + }, + { + "xyzab_tdr", + "configs/sim/axis/vismach/5axis/table-dual-rotary/xyzab-tdr.ini", + 2, + false, }, }; @@ -334,6 +365,12 @@ int main() "impeller-7bl-xyzac.ngc", 0.0, }, + { + "xyzab_tdr_demo", + "configs/sim/axis/vismach/5axis/table-dual-rotary/demos/" + "xyzab-tdr-demo.ngc", + 1.0, + }, }; ok &= execute_demo_file(cases[0], demos[0]); @@ -343,6 +380,7 @@ int main() ok &= execute_demo_file(cases[0], demos[4]); ok &= execute_demo_file(cases[1], demos[5]); ok &= execute_demo_file(cases[0], demos[6]); + ok &= execute_demo_file(cases[2], demos[7]); print_bool("fiveaxis_linuxcnc_remap_execute_path", ok); return ok ? 0 : 1; diff --git a/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_interp_wasm.cpp b/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_interp_wasm.cpp index dc5fe97..f0a54a1 100644 --- a/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_interp_wasm.cpp +++ b/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_interp_wasm.cpp @@ -70,6 +70,23 @@ void seed_switchkins_hal() standalone::set_hal_value(standalone::HalValueKind::Pin, "motion.analog-out-03", HAL_FLOAT, switchkins); standalone::link_hal_pin_alias("motion.analog-out-03", "motion.switchkins-type"); + + // Values mirror the vendored LinuxCNC xyzab-tdr sample INI/XML HAL defaults. + const struct { + const char *name; + double value; + } xyzab_tdr_defaults[] = { + {"xyzab_tdr_kins.x-offset", -20.0}, + {"xyzab_tdr_kins.z-offset", -10.0}, + {"xyzab_tdr_kins.x-rot-point", -50.0}, + {"xyzab_tdr_kins.y-rot-point", -50.0}, + {"xyzab_tdr_kins.z-rot-point", -100.0}, + }; + for (const auto &entry : xyzab_tdr_defaults) { + hal_data_u value{}; + value.f = entry.value; + standalone::set_hal_value(standalone::HalValueKind::Pin, entry.name, HAL_FLOAT, value); + } } void seed_tool_values() @@ -307,7 +324,7 @@ bool parse_machine_remaps(Interp &interp, std::ostringstream &output, const char remap_count -= 1; output << "fiveaxis_parsed_remap_count=" << remap_count << "\n"; - ok &= remap_count == 3; + ok &= remap_count == 2 || remap_count == 3; output << "fiveaxis_remaps_ready=" << (ok ? 1 : 0) << "\n"; return ok; } @@ -549,7 +566,7 @@ char *lcinterp_run_fiveaxis_remap_file(const char *path, const char *ini_path) ok &= file_execute_count > 0; ok &= file_read_count < max_file_steps; ok &= file_execute_count < max_file_steps; - ok &= hal_rc == INTERP_OK && hal_status == 1 && switchkins_type == 0.0; + ok &= hal_rc == INTERP_OK && hal_status == 1; output << "fiveaxis_linuxcnc_remap_file_execute=" << (ok ? 1 : 0) << "\n"; unsetenv("INI_FILE_NAME"); diff --git a/wasm-port/tests/browser/interp_smoke.html b/wasm-port/tests/browser/interp_smoke.html index 6f8fe69..7b0ed60 100644 --- a/wasm-port/tests/browser/interp_smoke.html +++ b/wasm-port/tests/browser/interp_smoke.html @@ -154,6 +154,30 @@ return wasmDir; } + async function writeFiveAxisTdrMachineFiles(interp) { + const sourceDir = + "../../vendor/linuxcnc/configs/sim/axis/vismach/5axis/table-dual-rotary"; + const wasmDir = "/work/browser-fiveaxis/table-dual-rotary"; + const remapFiles = ["428remap.ngc", "429remap.ngc"]; + + await writeFetchedTextFile(interp, `${sourceDir}/xyzab-tdr.ini`, `${wasmDir}/xyzab-tdr.ini`); + await writeFetchedTextFile(interp, `${sourceDir}/xyzab-tdr.tbl`, `${wasmDir}/xyzab-tdr.tbl`); + for (const filename of remapFiles) { + await writeFetchedTextFile( + interp, + `${sourceDir}/remap_subs/${filename}`, + `${wasmDir}/remap_subs/${filename}`, + ); + } + await writeFetchedTextFile( + interp, + `${sourceDir}/demos/xyzab-tdr-demo.ngc`, + `${wasmDir}/demos/xyzab-tdr-demo.ngc`, + ); + + return wasmDir; + } + async function verifyRejects(fixtureName, operation, expectedPattern) { try { await operation(); @@ -480,6 +504,30 @@ "fiveaxis_linuxcnc_remap_file_execute=1", ].join("\n"), ); + const fiveAxisTdrDir = await writeFiveAxisTdrMachineFiles(interp); + verifyExpectedOutput( + "browser_fiveaxis_xyzab_tdr_demo", + interp.runFiveAxisRemapFile( + `${fiveAxisTdrDir}/demos/xyzab-tdr-demo.ngc`, + `${fiveAxisTdrDir}/xyzab-tdr.ini`, + ), + [ + "fiveaxis_ini_open=1", + "fiveaxis_tool_table_load=0", + "fiveaxis_parse_remap_1=0", + "fiveaxis_parse_remap_2=0", + "fiveaxis_parsed_remap_count=2", + "fiveaxis_remaps_ready=1", + "fiveaxis_file_open=0", + "fiveaxis_file_read_count=97", + "fiveaxis_file_execute_count=97", + "fiveaxis_file_finish_count=3", + "fiveaxis_file_final_rc=1", + "fiveaxis_file_reached_exit=1", + "fiveaxis_hal_switchkins: rc=0 found=1 value=1", + "fiveaxis_linuxcnc_remap_file_execute=1", + ].join("\n"), + ); verifyExpectedOutput( "restore_parameters_missing_file", diff --git a/wasm-port/tests/native/verify_native_probes.sh b/wasm-port/tests/native/verify_native_probes.sh index 2415c4d..59f39ed 100755 --- a/wasm-port/tests/native/verify_native_probes.sh +++ b/wasm-port/tests/native/verify_native_probes.sh @@ -302,6 +302,14 @@ grep -Fq "xyzbc_trt_M428_execute_1=0" "$FIVEAXIS_REMAP_EXECUTE_STDOUT" grep -Fq "xyzbc_trt_M430_execute_0=2" "$FIVEAXIS_REMAP_EXECUTE_STDOUT" grep -Fq "xyzbc_trt_M430_execute_1=0" "$FIVEAXIS_REMAP_EXECUTE_STDOUT" grep -Fq "xyzbc_trt_linuxcnc_remap_execute_path=1" "$FIVEAXIS_REMAP_EXECUTE_STDOUT" +grep -Fq "xyzab_tdr_ini_open=1" "$FIVEAXIS_REMAP_EXECUTE_STDOUT" +grep -Fq "xyzab_tdr_parsed_remap_count=2" "$FIVEAXIS_REMAP_EXECUTE_STDOUT" +grep -Fq "xyzab_tdr_remaps_ready=1" "$FIVEAXIS_REMAP_EXECUTE_STDOUT" +grep -Fq "xyzab_tdr_M429_execute_0=2" "$FIVEAXIS_REMAP_EXECUTE_STDOUT" +grep -Fq "xyzab_tdr_M429_execute_1=0" "$FIVEAXIS_REMAP_EXECUTE_STDOUT" +grep -Fq "xyzab_tdr_M428_execute_0=2" "$FIVEAXIS_REMAP_EXECUTE_STDOUT" +grep -Fq "xyzab_tdr_M428_execute_1=0" "$FIVEAXIS_REMAP_EXECUTE_STDOUT" +grep -Fq "xyzab_tdr_linuxcnc_remap_execute_path=1" "$FIVEAXIS_REMAP_EXECUTE_STDOUT" grep -Fq "xyzac_trt_xyzac_switchkins_file_open=0" "$FIVEAXIS_REMAP_EXECUTE_STDOUT" grep -Fq "xyzac_trt_xyzac_switchkins_file_read_count=620" "$FIVEAXIS_REMAP_EXECUTE_STDOUT" grep -Fq "xyzac_trt_xyzac_switchkins_file_execute_count=620" "$FIVEAXIS_REMAP_EXECUTE_STDOUT" @@ -358,6 +366,14 @@ grep -Fq "xyzac_trt_impeller_7bl_xyzac_file_final_rc=1" "$FIVEAXIS_REMAP_EXECUTE grep -Fq "xyzac_trt_impeller_7bl_xyzac_file_reached_exit=1" "$FIVEAXIS_REMAP_EXECUTE_STDOUT" grep -Fq "xyzac_trt_impeller_7bl_xyzac__hal[motion.switchkins-type]: rc=0 found=1 value=0" "$FIVEAXIS_REMAP_EXECUTE_STDOUT" grep -Fq "xyzac_trt_impeller_7bl_xyzac_linuxcnc_demo_file_execute=1" "$FIVEAXIS_REMAP_EXECUTE_STDOUT" +grep -Fq "xyzab_tdr_xyzab_tdr_demo_file_open=0" "$FIVEAXIS_REMAP_EXECUTE_STDOUT" +grep -Fq "xyzab_tdr_xyzab_tdr_demo_file_read_count=97" "$FIVEAXIS_REMAP_EXECUTE_STDOUT" +grep -Fq "xyzab_tdr_xyzab_tdr_demo_file_execute_count=97" "$FIVEAXIS_REMAP_EXECUTE_STDOUT" +grep -Fq "xyzab_tdr_xyzab_tdr_demo_file_finish_count=3" "$FIVEAXIS_REMAP_EXECUTE_STDOUT" +grep -Fq "xyzab_tdr_xyzab_tdr_demo_file_final_rc=1" "$FIVEAXIS_REMAP_EXECUTE_STDOUT" +grep -Fq "xyzab_tdr_xyzab_tdr_demo_file_reached_exit=1" "$FIVEAXIS_REMAP_EXECUTE_STDOUT" +grep -Fq "xyzab_tdr_xyzab_tdr_demo__hal[motion.switchkins-type]: rc=0 found=1 value=1" "$FIVEAXIS_REMAP_EXECUTE_STDOUT" +grep -Fq "xyzab_tdr_xyzab_tdr_demo_linuxcnc_demo_file_execute=1" "$FIVEAXIS_REMAP_EXECUTE_STDOUT" grep -Fq "fiveaxis_linuxcnc_remap_execute_path=1" "$FIVEAXIS_REMAP_EXECUTE_STDOUT" NAMEDPARAM_STDOUT="$BUILD_DIR/linuxcnc_namedparam_harness.run.stdout.log" diff --git a/wasm-port/tests/wasm/node/verify_interp_wasm.mjs b/wasm-port/tests/wasm/node/verify_interp_wasm.mjs index 116c711..dc8430c 100644 --- a/wasm-port/tests/wasm/node/verify_interp_wasm.mjs +++ b/wasm-port/tests/wasm/node/verify_interp_wasm.mjs @@ -137,6 +137,31 @@ function writeFiveAxisTrtMachineFiles() { return wasmDir; } +function writeFiveAxisTdrMachineFiles() { + const sourceDir = resolve( + rootDir, + "vendor/linuxcnc/configs/sim/axis/vismach/5axis/table-dual-rotary", + ); + const wasmDir = "/work/fiveaxis/table-dual-rotary"; + + writeVendorTextFile(resolve(sourceDir, "xyzab-tdr.ini"), `${wasmDir}/xyzab-tdr.ini`); + writeVendorTextFile(resolve(sourceDir, "xyzab-tdr.tbl"), `${wasmDir}/xyzab-tdr.tbl`); + for (const filename of readdirSync(resolve(sourceDir, "remap_subs"))) { + if (filename.endsWith(".ngc")) { + writeVendorTextFile( + resolve(sourceDir, "remap_subs", filename), + `${wasmDir}/remap_subs/${filename}`, + ); + } + } + writeVendorTextFile( + resolve(sourceDir, "demos/xyzab-tdr-demo.ngc"), + `${wasmDir}/demos/xyzab-tdr-demo.ngc`, + ); + + return wasmDir; +} + const namedParamIniPath = "/work/namedparams.ini"; interp.writeTextFile( namedParamIniPath, @@ -469,6 +494,31 @@ verifyExpectedOutput( ].join("\n"), ); +const fiveAxisTdrDir = writeFiveAxisTdrMachineFiles(); +verifyExpectedOutput( + "fiveaxis_xyzab_tdr_demo_wasm", + interp.runFiveAxisRemapFile( + `${fiveAxisTdrDir}/demos/xyzab-tdr-demo.ngc`, + `${fiveAxisTdrDir}/xyzab-tdr.ini`, + ), + [ + "fiveaxis_ini_open=1", + "fiveaxis_tool_table_load=0", + "fiveaxis_parse_remap_1=0", + "fiveaxis_parse_remap_2=0", + "fiveaxis_parsed_remap_count=2", + "fiveaxis_remaps_ready=1", + "fiveaxis_file_open=0", + "fiveaxis_file_read_count=97", + "fiveaxis_file_execute_count=97", + "fiveaxis_file_finish_count=3", + "fiveaxis_file_final_rc=1", + "fiveaxis_file_reached_exit=1", + "fiveaxis_hal_switchkins: rc=0 found=1 value=1", + "fiveaxis_linuxcnc_remap_file_execute=1", + ].join("\n"), +); + const parameterFilePath = "/work/rs274ngc.var"; interp.writeTextFile( parameterFilePath,