继续把 interp_execute.cc、interp_queue.cc、interp_find.cc 等 LinuxCNC 源文件纳入直接编译/链接路径,逐步删除临时 convert_g() wrapper 行为
结论:已将核心 LinuxCNC interpreter 源接入 standalone native 编译链接路径,移除 minimal runtime 中的手写 convert_g 行为,并通过 native probe 验证。
This commit is contained in:
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
/.agents/
|
||||
/.codex/
|
||||
/git.txt
|
||||
/text.txt
|
||||
/linuxcnc/
|
||||
2
wasm-port/.gitignore
vendored
Normal file
2
wasm-port/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
build/
|
||||
dist/
|
||||
130
wasm-port/AGENTS.md
Normal file
130
wasm-port/AGENTS.md
Normal file
@@ -0,0 +1,130 @@
|
||||
# AGENTS.md
|
||||
|
||||
## Scope
|
||||
|
||||
This file defines agent operating rules for the standalone LinuxCNC WASM
|
||||
simulation port located under `wasm-port/`.
|
||||
|
||||
This workspace is separate from the upstream LinuxCNC tree in
|
||||
`../linuxcnc/`.
|
||||
|
||||
## Primary Objective
|
||||
|
||||
Build a standalone CNC simulation system that:
|
||||
|
||||
- reuses LinuxCNC source as the semantic source of truth;
|
||||
- compiles core CNC logic to WASM;
|
||||
- uses HTML + JavaScript for the frontend;
|
||||
- uses OPFS for browser persistence;
|
||||
- does not drive real hardware;
|
||||
- preserves LinuxCNC software behavior as closely as practical.
|
||||
|
||||
## Current Direction
|
||||
|
||||
The migration target is the LinuxCNC source program itself, adapted to run as
|
||||
the standalone WASM simulation program. The project must not evolve a
|
||||
project-authored interpreter, planner, or CNC semantics layer now that the
|
||||
porting harness is running.
|
||||
|
||||
Existing minimal runtime wrappers are migration probes only. They are allowed
|
||||
to expose, compile, and validate vendored LinuxCNC code, but they must not be
|
||||
expanded into a separate implementation of G-code behavior.
|
||||
|
||||
## Repository Boundaries
|
||||
|
||||
1. `../linuxcnc/` is upstream and must be treated as read-only input for the
|
||||
port effort.
|
||||
2. Port-specific code must live under `wasm-port/`.
|
||||
3. Vendored LinuxCNC source copies must live under
|
||||
`wasm-port/vendor/linuxcnc/`.
|
||||
4. Any source-level adaptation must be applied to vendored copies only.
|
||||
5. Never treat experimental files under `../linuxcnc/web/` as the official
|
||||
port target. The official port program is managed here.
|
||||
|
||||
## Engineering Rules
|
||||
|
||||
1. Reuse LinuxCNC source before reimplementing any CNC logic.
|
||||
2. Do not add new project-authored CNC semantics when LinuxCNC source exists.
|
||||
Replace temporary wrapper behavior with direct calls into vendored LinuxCNC
|
||||
source, or with the narrowest shims needed to make those calls compile.
|
||||
3. Prefer wrappers, shims, and extraction scripts over invasive source edits.
|
||||
4. Preserve LinuxCNC semantics for:
|
||||
- G-code execution;
|
||||
- modal state;
|
||||
- parameter and variable behavior;
|
||||
- kinematics;
|
||||
- planner behavior;
|
||||
- machine and controller state visible to software.
|
||||
5. Replace only the native runtime edges:
|
||||
- file IO;
|
||||
- process model;
|
||||
- HAL runtime;
|
||||
- IPC;
|
||||
- GUI.
|
||||
6. Frontend code must be implemented with web technology, not migrated from
|
||||
native GUI code.
|
||||
|
||||
## Required Layout
|
||||
|
||||
The standalone port should use these major areas:
|
||||
|
||||
- `docs/`
|
||||
- `vendor/`
|
||||
- `patches/`
|
||||
- `tools/`
|
||||
- `runtime/core/`
|
||||
- `runtime/sdk/`
|
||||
- `runtime/ui/`
|
||||
- `runtime/opfs/`
|
||||
- `tests/`
|
||||
|
||||
Do not collapse these concerns back into the upstream tree.
|
||||
|
||||
## File Ownership
|
||||
|
||||
- `docs/`: planning, architecture, drift tracking, validation
|
||||
- `vendor/`: copied upstream source
|
||||
- `patches/`: patches against vendored copies
|
||||
- `tools/`: extraction and sync scripts
|
||||
- `runtime/core/`: standalone native/WASM simulation runtime
|
||||
- `runtime/sdk/`: JS or TS SDK
|
||||
- `runtime/ui/`: HTML + JavaScript simulation frontend
|
||||
- `runtime/opfs/`: browser persistence layer
|
||||
- `tests/`: standalone native and browser regression coverage
|
||||
|
||||
## Validation Requirements
|
||||
|
||||
Every migrated feature should be validated against LinuxCNC-native behavior
|
||||
using one or more of:
|
||||
|
||||
- existing LinuxCNC tests;
|
||||
- extracted native harness tests;
|
||||
- WASM regression tests;
|
||||
- browser smoke tests.
|
||||
|
||||
Validation should cover:
|
||||
|
||||
- path output;
|
||||
- machine/controller state;
|
||||
- parameter and variable behavior;
|
||||
- kinematic transforms;
|
||||
- file/config loading.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
This project must not:
|
||||
|
||||
- attempt realtime hardware control;
|
||||
- port LinuxCNC drivers to the browser;
|
||||
- recreate LinuxCNC's native process topology;
|
||||
- rewrite major CNC semantics in JavaScript if LinuxCNC source can be reused;
|
||||
- depend on LinuxCNC native GUI code as implementation code.
|
||||
|
||||
## Working Style
|
||||
|
||||
When extending this workspace:
|
||||
|
||||
1. Update docs before or alongside structural changes.
|
||||
2. Keep extraction and patching reproducible.
|
||||
3. Keep adapters narrow and explicit.
|
||||
4. Keep LinuxCNC-derived logic traceable to its upstream file origin.
|
||||
128
wasm-port/README.md
Normal file
128
wasm-port/README.md
Normal file
@@ -0,0 +1,128 @@
|
||||
# LinuxCNC WASM Port Workspace
|
||||
|
||||
This directory is the standalone workspace for the WASM-based simulation port.
|
||||
|
||||
Rules:
|
||||
|
||||
1. `linuxcnc/` is treated as the upstream source tree.
|
||||
2. The porting work must not modify LinuxCNC source files in-place.
|
||||
3. Port-specific code, build scripts, adapters, tests, and documentation live here.
|
||||
4. LinuxCNC source is consumed by reference, copy, generated snapshot, or scripted extraction.
|
||||
5. The browser/WASM product is managed as a separate program.
|
||||
|
||||
Suggested layout:
|
||||
|
||||
- `docs/`
|
||||
Porting strategy and execution documents.
|
||||
- `vendor/`
|
||||
Controlled copies or generated snapshots of LinuxCNC source files selected for porting.
|
||||
- `patches/`
|
||||
Patch sets applied only to vendored copies, never directly to `linuxcnc/`.
|
||||
- `tools/`
|
||||
Extraction, sync, verification, and code generation scripts.
|
||||
- `runtime/`
|
||||
WASM core, JS SDK, HTML frontend, and OPFS adapters.
|
||||
- `tests/`
|
||||
Port-specific regression tests and browser harnesses.
|
||||
|
||||
Recommended target structure after the port takes shape:
|
||||
|
||||
```text
|
||||
wasm-port/
|
||||
├── README.md
|
||||
├── docs/
|
||||
│ ├── scope-and-baseline.md
|
||||
│ ├── source-reuse-map.md
|
||||
│ ├── state-porting-strategy.md
|
||||
│ ├── wasm-build-strategy.md
|
||||
│ ├── frontend-architecture.md
|
||||
│ ├── opfs-file-model.md
|
||||
│ ├── compatibility-validation.md
|
||||
│ └── drift-report.md
|
||||
├── vendor/
|
||||
│ └── linuxcnc/
|
||||
│ └── src/
|
||||
│ ├── emc/
|
||||
│ │ ├── ini/
|
||||
│ │ ├── kinematics/
|
||||
│ │ ├── rs274ngc/
|
||||
│ │ └── tp/
|
||||
│ ├── hal/
|
||||
│ │ └── components/
|
||||
│ └── libnml/
|
||||
│ └── posemath/
|
||||
├── patches/
|
||||
│ ├── vendor-linuxcnc-ini.patch
|
||||
│ ├── vendor-linuxcnc-rs274ngc.patch
|
||||
│ ├── vendor-linuxcnc-tp.patch
|
||||
│ └── vendor-linuxcnc-kinematics.patch
|
||||
├── tools/
|
||||
│ ├── extract_sources.sh
|
||||
│ ├── apply_vendor_patches.sh
|
||||
│ ├── verify_vendor_sync.sh
|
||||
│ ├── generate_source_manifest.py
|
||||
│ └── compare_with_upstream.sh
|
||||
├── runtime/
|
||||
│ ├── core/
|
||||
│ │ ├── include/
|
||||
│ │ ├── shims/
|
||||
│ │ ├── adapters/
|
||||
│ │ ├── canon/
|
||||
│ │ ├── session/
|
||||
│ │ ├── simulation/
|
||||
│ │ ├── linuxcnc_wrap/
|
||||
│ │ └── c_api/
|
||||
│ ├── sdk/
|
||||
│ │ ├── src/
|
||||
│ │ ├── package.json
|
||||
│ │ └── tsconfig.json
|
||||
│ ├── ui/
|
||||
│ │ ├── public/
|
||||
│ │ ├── src/
|
||||
│ │ │ ├── panels/
|
||||
│ │ │ ├── preview/
|
||||
│ │ │ ├── state/
|
||||
│ │ │ ├── machine/
|
||||
│ │ │ └── files/
|
||||
│ │ ├── package.json
|
||||
│ │ └── index.html
|
||||
│ └── opfs/
|
||||
│ ├── file-service.js
|
||||
│ ├── snapshot-store.js
|
||||
│ └── path-model.js
|
||||
├── tests/
|
||||
│ ├── native/
|
||||
│ │ ├── ini/
|
||||
│ │ ├── params/
|
||||
│ │ ├── interp/
|
||||
│ │ ├── tp/
|
||||
│ │ └── kinematics/
|
||||
│ ├── wasm/
|
||||
│ │ ├── node/
|
||||
│ │ └── browser/
|
||||
│ └── fixtures/
|
||||
│ ├── ini/
|
||||
│ ├── gcode/
|
||||
│ ├── tools/
|
||||
│ ├── params/
|
||||
│ └── machines/
|
||||
├── build/
|
||||
│ ├── native/
|
||||
│ └── wasm/
|
||||
└── dist/
|
||||
├── sdk/
|
||||
└── web/
|
||||
```
|
||||
|
||||
Directory intent:
|
||||
|
||||
- `vendor/linuxcnc/`: read-only copied LinuxCNC source selected for the port.
|
||||
- `runtime/core/`: the standalone simulation engine built around vendored LinuxCNC code.
|
||||
- `runtime/sdk/`: JavaScript/TypeScript API for calling the WASM engine.
|
||||
- `runtime/ui/`: HTML + JavaScript CNC simulation frontend.
|
||||
- `runtime/opfs/`: OPFS-backed persistence layer.
|
||||
- `tests/fixtures/`: stable simulation inputs shared by native and browser tests.
|
||||
- `build/` and `dist/`: generated outputs only; never hand-edited.
|
||||
|
||||
The presence of this directory means the port is managed independently of the
|
||||
native LinuxCNC tree even though LinuxCNC remains the semantic source of truth.
|
||||
155
wasm-port/SKILL.md
Normal file
155
wasm-port/SKILL.md
Normal file
@@ -0,0 +1,155 @@
|
||||
# SKILL.md
|
||||
|
||||
## Skill Name
|
||||
|
||||
LinuxCNC WASM Simulation Port
|
||||
|
||||
## Purpose
|
||||
|
||||
This skill guides work inside `wasm-port/` for building a standalone
|
||||
LinuxCNC-based CNC simulation program.
|
||||
|
||||
It is intended for tasks involving:
|
||||
|
||||
- source extraction from upstream LinuxCNC;
|
||||
- vendoring and patching selected LinuxCNC modules;
|
||||
- wrapping LinuxCNC compute code for native and WASM use;
|
||||
- preserving interpreter, planner, kinematics, HAL-visible, and INI-visible
|
||||
semantics;
|
||||
- building HTML + JavaScript + OPFS frontend integration.
|
||||
|
||||
## When To Use
|
||||
|
||||
Use this skill when the work involves any of the following:
|
||||
|
||||
- deciding whether to reuse or reimplement LinuxCNC code;
|
||||
- mapping CNC features to LinuxCNC source files;
|
||||
- creating or updating extraction scripts under `tools/`;
|
||||
- defining standalone runtime structure under `runtime/core/`;
|
||||
- building browser-facing WASM APIs;
|
||||
- integrating OPFS-backed configuration and session persistence;
|
||||
- validating LinuxCNC-equivalent simulation behavior.
|
||||
|
||||
## Core Principles
|
||||
|
||||
1. Upstream LinuxCNC is the semantic source of truth.
|
||||
2. The standalone port is a separate program and separate workspace.
|
||||
3. Reuse comes before rewrite.
|
||||
4. Native runtime dependencies are replaced at the edges, not copied whole.
|
||||
5. Machine state and controller-visible behavior are first-class compatibility
|
||||
targets, not optional nice-to-haves.
|
||||
6. Do not continue building a project-authored CNC program once the porting
|
||||
harness runs; move behavior back to vendored LinuxCNC source functions.
|
||||
|
||||
## Source Reuse Priorities
|
||||
|
||||
Highest-priority source reuse targets:
|
||||
|
||||
- `src/emc/rs274ngc`
|
||||
- `src/emc/tp`
|
||||
- `src/emc/kinematics`
|
||||
- `src/libnml/posemath`
|
||||
- `src/emc/ini`
|
||||
|
||||
Secondary semantic references:
|
||||
|
||||
- `src/hal/hal.h`
|
||||
- `src/hal/halmodule.cc`
|
||||
- `src/emc/ini/inihal.cc`
|
||||
|
||||
Reference-only UI sources:
|
||||
|
||||
- `src/emc/usr_intf/axis`
|
||||
- `src/hal/user_comps/vismach`
|
||||
- `configs/sim/axis/vismach/5axis`
|
||||
|
||||
## Required Port Boundaries
|
||||
|
||||
The port should preserve or expose these LinuxCNC behaviors:
|
||||
|
||||
- G-code parsing and execution
|
||||
- canonical motion generation
|
||||
- parameter file semantics
|
||||
- named variable lookup semantics
|
||||
- `_ini[...]` lookup semantics
|
||||
- `_hal[...]` lookup semantics through simulation adapter
|
||||
- planner behavior
|
||||
- 3-axis through 5-axis kinematics
|
||||
- machine/controller state visible to software
|
||||
|
||||
The port should replace these native dependencies:
|
||||
|
||||
- Linux process orchestration
|
||||
- NML transport implementation
|
||||
- HAL runtime internals
|
||||
- realtime scheduling
|
||||
- native GUI implementation
|
||||
- native filesystem assumptions
|
||||
|
||||
## Implementation Pattern
|
||||
|
||||
Preferred order of work:
|
||||
|
||||
1. Identify upstream file owners for the feature.
|
||||
2. Extract files into `vendor/linuxcnc/`.
|
||||
3. Add wrappers or shims in `runtime/core/`.
|
||||
4. Apply minimal patches only to vendored copies if needed.
|
||||
5. Build a native standalone harness first.
|
||||
6. Build the WASM export layer second.
|
||||
7. Build the JS SDK and HTML frontend last.
|
||||
|
||||
Current migration emphasis:
|
||||
|
||||
- Treat `linuxcnc_interp_minimal_runtime.cpp` as a temporary probe surface.
|
||||
- Retire hand-written `convert_g()` behavior by linking and calling vendored
|
||||
LinuxCNC interpreter conversion code.
|
||||
- Add shims only for host/runtime edges that prevent vendored LinuxCNC source
|
||||
from compiling.
|
||||
- Do not add new G-code behavior in JavaScript or in standalone C++ wrappers
|
||||
except as a short-lived adapter around LinuxCNC code.
|
||||
|
||||
## Filesystem And Browser Guidance
|
||||
|
||||
For browser use:
|
||||
|
||||
- WASM core should not directly own OPFS logic.
|
||||
- JavaScript host should own OPFS and file management.
|
||||
- WASM core should operate on abstract file services or explicit byte blobs.
|
||||
|
||||
Recommended browser storage targets:
|
||||
|
||||
- INI files
|
||||
- tool tables
|
||||
- parameter files
|
||||
- G-code programs
|
||||
- preview caches
|
||||
- session snapshots
|
||||
|
||||
## Validation Pattern
|
||||
|
||||
For each migrated feature, validate in this order:
|
||||
|
||||
1. Upstream LinuxCNC behavior
|
||||
2. Standalone native extracted-core behavior
|
||||
3. WASM behavior in Node or CLI harness
|
||||
4. Browser behavior through the frontend
|
||||
|
||||
Always record:
|
||||
|
||||
- source origin
|
||||
- any shim introduced
|
||||
- any vendored patch introduced
|
||||
- known deviations from upstream behavior
|
||||
|
||||
## Deliverable Bias
|
||||
|
||||
Prefer deliverables that directly improve execution readiness:
|
||||
|
||||
- source reuse maps
|
||||
- extraction scripts
|
||||
- standalone runtime wrappers
|
||||
- regression fixtures
|
||||
- drift reports
|
||||
|
||||
Prefer not to spend time on speculative abstractions unless they reduce
|
||||
real migration complexity.
|
||||
691
wasm-port/docs/porting-steps-standalone.md
Normal file
691
wasm-port/docs/porting-steps-standalone.md
Normal file
@@ -0,0 +1,691 @@
|
||||
# LinuxCNC WASM Porting Steps
|
||||
|
||||
## Goal
|
||||
|
||||
Build a separate WASM-based CNC simulation program that:
|
||||
|
||||
- uses LinuxCNC source as the semantic source of truth,
|
||||
- does not modify the original `linuxcnc/` source tree,
|
||||
- is managed independently from native LinuxCNC,
|
||||
- provides HTML + JavaScript frontend plus OPFS persistence,
|
||||
- matches LinuxCNC software behavior as closely as practical except for realtime hardware driving.
|
||||
|
||||
## Non-Negotiable Constraints
|
||||
|
||||
1. `linuxcnc/` is upstream and read-only for the port effort.
|
||||
2. Any source adaptation needed for WASM happens on copied or generated files under `wasm-port/`.
|
||||
3. No direct edits inside `linuxcnc/src`, `linuxcnc/lib`, `linuxcnc/tests`, or `linuxcnc/web` are part of the port workflow.
|
||||
4. LinuxCNC GUI code is reference-only. The migrated UI is rebuilt in HTML + JavaScript.
|
||||
5. LinuxCNC compute logic should be reused before any reimplementation is considered.
|
||||
|
||||
## Workspace Structure
|
||||
|
||||
Create and keep these directories under `wasm-port/`:
|
||||
|
||||
- `docs/`
|
||||
Planning, architecture, and validation documents.
|
||||
- `vendor/linuxcnc/`
|
||||
Copied source files selected for the port.
|
||||
- `patches/`
|
||||
Patch files against the vendored copies.
|
||||
- `tools/`
|
||||
Scripts that extract files from `../linuxcnc`, apply patches, and verify drift.
|
||||
- `runtime/core/`
|
||||
WASM-targeted C/C++ code and wrappers.
|
||||
- `runtime/sdk/`
|
||||
JavaScript/TypeScript wrapper over the WASM module.
|
||||
- `runtime/ui/`
|
||||
HTML + JavaScript frontend.
|
||||
- `runtime/opfs/`
|
||||
Browser file adapter.
|
||||
- `tests/native/`
|
||||
Native extracted-core regression tests.
|
||||
- `tests/browser/`
|
||||
Browser/WASM regression and smoke tests.
|
||||
|
||||
## Ported Program Directory Structure
|
||||
|
||||
The migrated program itself should be managed as a standalone product under
|
||||
`wasm-port/`, with LinuxCNC acting as an upstream source provider.
|
||||
|
||||
The recommended final structure is:
|
||||
|
||||
```text
|
||||
wasm-port/
|
||||
├── docs/
|
||||
├── vendor/
|
||||
│ └── linuxcnc/
|
||||
│ └── src/
|
||||
│ ├── emc/
|
||||
│ │ ├── ini/
|
||||
│ │ ├── kinematics/
|
||||
│ │ ├── rs274ngc/
|
||||
│ │ └── tp/
|
||||
│ ├── hal/
|
||||
│ │ └── components/
|
||||
│ └── libnml/
|
||||
│ └── posemath/
|
||||
├── patches/
|
||||
├── tools/
|
||||
├── runtime/
|
||||
│ ├── core/
|
||||
│ │ ├── include/
|
||||
│ │ ├── shims/
|
||||
│ │ ├── adapters/
|
||||
│ │ ├── canon/
|
||||
│ │ ├── session/
|
||||
│ │ ├── simulation/
|
||||
│ │ ├── linuxcnc_wrap/
|
||||
│ │ └── c_api/
|
||||
│ ├── sdk/
|
||||
│ │ └── src/
|
||||
│ ├── ui/
|
||||
│ │ ├── public/
|
||||
│ │ └── src/
|
||||
│ │ ├── panels/
|
||||
│ │ ├── preview/
|
||||
│ │ ├── state/
|
||||
│ │ ├── machine/
|
||||
│ │ └── files/
|
||||
│ └── opfs/
|
||||
├── tests/
|
||||
│ ├── native/
|
||||
│ ├── wasm/
|
||||
│ └── fixtures/
|
||||
├── build/
|
||||
│ ├── native/
|
||||
│ └── wasm/
|
||||
└── dist/
|
||||
├── sdk/
|
||||
└── web/
|
||||
```
|
||||
|
||||
### Directory Responsibilities
|
||||
|
||||
- `vendor/linuxcnc/`
|
||||
Holds extracted upstream LinuxCNC source files. These are copied or
|
||||
generated from `../linuxcnc` and are the only place where source-level
|
||||
port patches are applied.
|
||||
- `patches/`
|
||||
Stores every patch applied to vendored LinuxCNC files. Patches are tracked
|
||||
here instead of being mixed into the original source tree.
|
||||
- `tools/`
|
||||
Holds extraction, sync, verification, manifest generation, and
|
||||
compatibility-check scripts.
|
||||
- `runtime/core/`
|
||||
The standalone simulation runtime. This is where vendored LinuxCNC source
|
||||
is wrapped, adapted, and exposed to the rest of the ported program.
|
||||
- `runtime/core/include/`
|
||||
Public internal headers for the standalone runtime.
|
||||
- `runtime/core/shims/`
|
||||
Small compatibility headers and implementation stubs required to compile
|
||||
vendored LinuxCNC code outside the native runtime.
|
||||
- `runtime/core/adapters/`
|
||||
Host boundary adapters such as file IO, logging, simulation HAL, and
|
||||
runtime-state providers.
|
||||
- `runtime/core/canon/`
|
||||
Canonical motion event collection and serialization.
|
||||
- `runtime/core/session/`
|
||||
Per-simulation session ownership for interpreter state, planner state,
|
||||
machine state, and controller state.
|
||||
- `runtime/core/simulation/`
|
||||
Higher-level simulation orchestration built on top of reused LinuxCNC
|
||||
compute modules.
|
||||
- `runtime/core/linuxcnc_wrap/`
|
||||
Thin wrappers around vendored LinuxCNC entry points. Prefer wrappers here
|
||||
over editing vendored source directly.
|
||||
- `runtime/core/c_api/`
|
||||
Stable C ABI exported to the WASM layer.
|
||||
- `runtime/sdk/`
|
||||
JavaScript/TypeScript SDK that calls the WASM module and hides memory
|
||||
management and ABI details from the frontend.
|
||||
- `runtime/ui/`
|
||||
The actual CNC simulation web application built with HTML + JavaScript.
|
||||
- `runtime/ui/src/panels/`
|
||||
Operator panels, machine configuration panels, parameter editors, and
|
||||
controller-status panels.
|
||||
- `runtime/ui/src/preview/`
|
||||
2D/3D path preview, 5-axis visualization, joint/world overlays, and
|
||||
playback views.
|
||||
- `runtime/ui/src/state/`
|
||||
Browser-side state management for session lifecycle and UI coordination.
|
||||
- `runtime/ui/src/machine/`
|
||||
Machine-model-specific UI logic.
|
||||
- `runtime/ui/src/files/`
|
||||
File import/export and project/session handling UI logic.
|
||||
- `runtime/opfs/`
|
||||
OPFS-backed file services, snapshot persistence, and path mapping.
|
||||
- `tests/native/`
|
||||
Native extracted-core regression tests run before WASM build validation.
|
||||
- `tests/wasm/`
|
||||
WASM tests for Node and browser environments.
|
||||
- `tests/fixtures/`
|
||||
Shared INI, G-code, parameter, tool-table, and machine fixtures.
|
||||
- `build/`
|
||||
Intermediate build output. This is disposable.
|
||||
- `dist/`
|
||||
Deliverable artifacts such as generated web bundles and SDK packages.
|
||||
|
||||
### Source Ownership Rule
|
||||
|
||||
The ported program's own source code is expected to live under:
|
||||
|
||||
- `runtime/core/`
|
||||
- `runtime/sdk/`
|
||||
- `runtime/ui/`
|
||||
- `runtime/opfs/`
|
||||
- `tests/`
|
||||
- `tools/`
|
||||
- `docs/`
|
||||
|
||||
Vendored LinuxCNC code must live under:
|
||||
|
||||
- `vendor/linuxcnc/`
|
||||
|
||||
The original upstream tree must remain outside the ported program's source
|
||||
ownership boundary:
|
||||
|
||||
- `../linuxcnc/`
|
||||
|
||||
### Patch Placement Rule
|
||||
|
||||
If a LinuxCNC source file needs adaptation:
|
||||
|
||||
1. extract it into `vendor/linuxcnc/`;
|
||||
2. patch the vendored copy only;
|
||||
3. record the patch in `patches/`;
|
||||
4. document why the patch exists in `docs/` or in the patch header.
|
||||
|
||||
Do not place LinuxCNC source patches under `runtime/`.
|
||||
|
||||
### Build Graph Rule
|
||||
|
||||
The standalone build should flow like this:
|
||||
|
||||
1. `tools/` extracts upstream files into `vendor/`
|
||||
2. `patches/` are applied to vendored copies
|
||||
3. `runtime/core/` compiles vendored files plus wrappers
|
||||
4. `runtime/sdk/` consumes the generated WASM module
|
||||
5. `runtime/ui/` consumes the SDK
|
||||
6. `runtime/opfs/` provides browser persistence services
|
||||
7. `tests/` validate native and browser behavior
|
||||
|
||||
This ensures the ported program remains independently buildable while still
|
||||
tracking LinuxCNC as the semantic source of truth.
|
||||
|
||||
## Phase 0: Freeze Upstream Reference
|
||||
|
||||
Purpose:
|
||||
Make the LinuxCNC source baseline explicit before extraction starts.
|
||||
|
||||
Steps:
|
||||
|
||||
1. Record the exact upstream commit from `linuxcnc/.git`.
|
||||
2. Record local build assumptions:
|
||||
- compiler version
|
||||
- emscripten version
|
||||
- python version
|
||||
- node version
|
||||
3. Record the first supported LinuxCNC fixture set:
|
||||
- one 3-axis machine
|
||||
- one non-trivial kinematics case
|
||||
- one 5-axis machine
|
||||
4. Record the first G-code feature set:
|
||||
- linear motion
|
||||
- arc motion
|
||||
- canned cycles
|
||||
- offsets and coordinate systems
|
||||
- subroutines
|
||||
- numeric and named variables
|
||||
- representative 5-axis programs
|
||||
|
||||
Outputs:
|
||||
|
||||
- upstream revision note
|
||||
- supported feature baseline
|
||||
- supported machine baseline
|
||||
|
||||
## Phase 1: Build the Source Reuse Map
|
||||
|
||||
Purpose:
|
||||
Identify exactly which LinuxCNC source files are needed.
|
||||
|
||||
Steps:
|
||||
|
||||
1. Map each required capability to LinuxCNC files:
|
||||
- G-code interpreter:
|
||||
`../linuxcnc/src/emc/rs274ngc/*`
|
||||
- parameter tables and named variables:
|
||||
`../linuxcnc/src/emc/rs274ngc/interp_*`
|
||||
- INI parsing:
|
||||
`../linuxcnc/src/emc/ini/inifile.*`
|
||||
- planner:
|
||||
`../linuxcnc/src/emc/tp/*`
|
||||
- kinematics:
|
||||
`../linuxcnc/src/emc/kinematics/*`
|
||||
and selected files from `../linuxcnc/src/hal/components/*.comp`
|
||||
- posemath:
|
||||
`../linuxcnc/src/libnml/posemath/*`
|
||||
2. For each file, classify it:
|
||||
- copy unchanged
|
||||
- copy plus shim
|
||||
- copy plus light patch
|
||||
- not included in phase 1
|
||||
3. For each file, record dependencies:
|
||||
- HAL
|
||||
- RTAPI
|
||||
- NML
|
||||
- native file IO
|
||||
- Python
|
||||
- GUI
|
||||
4. Save the mapping as a table under `wasm-port/docs/`.
|
||||
|
||||
Outputs:
|
||||
|
||||
- file-level reuse matrix
|
||||
- dependency matrix
|
||||
|
||||
## Phase 2: Build the Extraction Pipeline
|
||||
|
||||
Purpose:
|
||||
Keep LinuxCNC source untouched while making port-specific copies available.
|
||||
|
||||
Steps:
|
||||
|
||||
1. Write extraction scripts in `wasm-port/tools/`.
|
||||
2. Copy selected upstream files into `wasm-port/vendor/linuxcnc/`.
|
||||
3. Preserve relative structure where useful, for example:
|
||||
- `vendor/linuxcnc/src/emc/rs274ngc/...`
|
||||
- `vendor/linuxcnc/src/emc/ini/...`
|
||||
4. Store every modification as:
|
||||
- a patch in `wasm-port/patches/`, or
|
||||
- a thin wrapper outside the vendored file
|
||||
5. Add a verification script that compares upstream file hashes against the vendored source list.
|
||||
|
||||
Rules:
|
||||
|
||||
- if upstream changes, re-run extraction;
|
||||
- reapply patches only in the standalone workspace;
|
||||
- never patch `../linuxcnc` directly.
|
||||
|
||||
Outputs:
|
||||
|
||||
- reproducible extraction pipeline
|
||||
- vendored source tree
|
||||
|
||||
## Phase 3: Build the Native Extracted Core
|
||||
|
||||
Purpose:
|
||||
Prove the reusable LinuxCNC compute code works outside the full runtime.
|
||||
|
||||
Steps:
|
||||
|
||||
1. Create `wasm-port/runtime/core/` as the portable core layer.
|
||||
2. Add wrapper translation units instead of editing vendored files where possible.
|
||||
3. Start with these subsystems in order:
|
||||
- INI parser
|
||||
- numeric parameter table
|
||||
- named parameter logic
|
||||
- interpreter core
|
||||
- planner
|
||||
- kinematics
|
||||
4. Build a native CLI harness first, before any WASM build.
|
||||
5. Replace host edges with abstractions:
|
||||
- file provider
|
||||
- HAL adapter
|
||||
- runtime state provider
|
||||
- logging adapter
|
||||
|
||||
Outputs:
|
||||
|
||||
- portable native core
|
||||
- native harness executable
|
||||
|
||||
Current verified progress:
|
||||
|
||||
- `tools/build_native_probes.sh` builds the INI parser probe, interpreter
|
||||
state probe, named-parameter harness, RS274 compile probe, and the minimal
|
||||
interpreter harness from the standalone `wasm-port/` workspace.
|
||||
- `tests/native/verify_native_probes.sh` validates that all native probe
|
||||
exit codes are zero and that the minimal interpreter harness emits a
|
||||
`STRAIGHT_TRAVERSE` canonical event for `G0 X1.0 Y2.0`, plus
|
||||
`SET_FEED_RATE` and `STRAIGHT_FEED` canonical events for
|
||||
`G1 X3.0 Y4.0 F120.0`.
|
||||
- The same validation is now fixture-driven through
|
||||
`tests/fixtures/gcode/minimal_linear.ngc` and
|
||||
`tests/fixtures/canon/minimal_linear.events`.
|
||||
- `tests/fixtures/gcode/modal_incremental.ngc` and
|
||||
`tests/fixtures/canon/modal_incremental.events` add `G90`/`G91`
|
||||
distance-mode switching plus modal `G1` carry-forward coverage. The
|
||||
temporary wrapper behavior is based on LinuxCNC
|
||||
`interp_convert.cc::convert_distance_mode()` and
|
||||
`interp_convert.cc::convert_straight()`.
|
||||
- `tests/fixtures/gcode/position_params.ngc` and
|
||||
`tests/fixtures/canon/position_params.events` cover Z-axis motion plus
|
||||
current-position parameter visibility for `#5420`, `#5421`, and `#5422`.
|
||||
The parameter source basis is LinuxCNC
|
||||
`interp_parameter_def.hh` and `interp_namedparams.cc`.
|
||||
- `tests/fixtures/gcode_errors/g1_zero_feed.ngc` and
|
||||
`tests/fixtures/canon_errors/g1_zero_feed.expected` pin the negative
|
||||
`G1` zero-feed case. The source basis is LinuxCNC
|
||||
`interp_convert.cc::convert_straight()` and
|
||||
`rs274ngc_return.hh::NCE_CANNOT_DO_G1_WITH_ZERO_FEED_RATE`.
|
||||
- This proves the current extracted interpreter slice can parse and execute a
|
||||
small fixture set through a standalone canonical event sink.
|
||||
- Important direction change: the minimal wrapper behavior is a migration
|
||||
probe, not the program body. Do not expand it into a separate CNC
|
||||
implementation. The next work must retire hand-written wrapper semantics and
|
||||
move execution through vendored LinuxCNC interpreter source such as
|
||||
`interp_convert.cc`, `interp_read.cc`, `interp_check.cc`, and
|
||||
`interp_execute.cc`.
|
||||
- `tools/build_native_probes.sh` now includes
|
||||
`linuxcnc_interp_convert_source_probe`, which directly compiles vendored
|
||||
`interp_convert.cc`. The required `emcStatus` shim is limited to the native
|
||||
status boundary used by `tag_arc()` for machine units; it is not a
|
||||
project-authored CNC behavior implementation.
|
||||
|
||||
## Phase 4: Port INI Parsing Without Editing Upstream
|
||||
|
||||
Purpose:
|
||||
Move LinuxCNC config parsing into the standalone runtime.
|
||||
|
||||
Steps:
|
||||
|
||||
1. Vendor:
|
||||
- `../linuxcnc/src/emc/ini/inifile.cc`
|
||||
- `../linuxcnc/src/emc/ini/inifile.hh`
|
||||
- `../linuxcnc/src/emc/ini/inifile.h`
|
||||
2. Add shim headers under `wasm-port/runtime/core/shims/` for small dependencies only.
|
||||
3. Replace file loading through:
|
||||
- wrapper-level adapter, preferred
|
||||
- minimal vendored patch only if unavoidable
|
||||
4. Preserve:
|
||||
- `#INCLUDE`
|
||||
- relative includes
|
||||
- recursion checks
|
||||
- line continuation
|
||||
- duplicate section merge behavior
|
||||
- typed query behavior
|
||||
5. Add tests for INI semantics under `tests/native/`.
|
||||
|
||||
Involved LinuxCNC source:
|
||||
|
||||
- `src/emc/ini/inifile.cc`
|
||||
- `src/emc/ini/inifile.hh`
|
||||
- `src/emc/ini/inifile.h`
|
||||
|
||||
## Phase 5: Port Parameter Tables and Variable Files
|
||||
|
||||
Purpose:
|
||||
Preserve LinuxCNC numeric parameter behavior exactly enough for simulation.
|
||||
|
||||
Steps:
|
||||
|
||||
1. Vendor:
|
||||
- `../linuxcnc/src/emc/rs274ngc/interp_parameter_def.hh`
|
||||
- `../linuxcnc/src/emc/rs274ngc/interp_array.cc`
|
||||
- `../linuxcnc/src/emc/rs274ngc/interp_internal.hh`
|
||||
- `../linuxcnc/src/emc/rs274ngc/rs274ngc_pre.cc`
|
||||
2. Extract:
|
||||
- `setup.parameters[]`
|
||||
- `required_parameters[]`
|
||||
- `readonly_parameters[]`
|
||||
- parameter file load/save logic
|
||||
3. Replace native file writes with a standalone file service abstraction.
|
||||
4. Keep LinuxCNC’s parameter text format in phase 1.
|
||||
5. Add regression tests for:
|
||||
- missing file
|
||||
- out-of-order parameters
|
||||
- zero-fill behavior
|
||||
- required parameter persistence
|
||||
- read-only protection
|
||||
|
||||
Involved LinuxCNC source:
|
||||
|
||||
- `src/emc/rs274ngc/interp_parameter_def.hh`
|
||||
- `src/emc/rs274ngc/interp_array.cc`
|
||||
- `src/emc/rs274ngc/interp_internal.hh`
|
||||
- `src/emc/rs274ngc/rs274ngc_pre.cc`
|
||||
|
||||
## Phase 6: Port Named Parameters and Interpreter State
|
||||
|
||||
Purpose:
|
||||
Preserve LinuxCNC variable semantics and controller-visible state.
|
||||
|
||||
Steps:
|
||||
|
||||
1. Vendor:
|
||||
- `../linuxcnc/src/emc/rs274ngc/interp_namedparams.cc`
|
||||
- `../linuxcnc/src/emc/rs274ngc/interp_internal.hh`
|
||||
- `../linuxcnc/src/emc/rs274ngc/interp_fwd.hh`
|
||||
- selected interpreter files needed by setup/state handling
|
||||
2. Preserve:
|
||||
- `context.named_params`
|
||||
- `PA_READONLY`
|
||||
- `PA_GLOBAL`
|
||||
- `PA_USE_LOOKUP`
|
||||
- `PA_FROM_INI`
|
||||
- built-in named parameters from `init_named_parameters()`
|
||||
3. Preserve lookup order:
|
||||
- local
|
||||
- global
|
||||
- `_ini[...]`
|
||||
- `_hal[...]`
|
||||
- optional Python providers later
|
||||
4. Export state outward rather than redesigning it in JS.
|
||||
5. Add regression cases for:
|
||||
- local/global scoping
|
||||
- built-in state variables
|
||||
- `_ini[...]`
|
||||
- `_hal[...]`
|
||||
- read-only errors
|
||||
|
||||
Involved LinuxCNC source:
|
||||
|
||||
- `src/emc/rs274ngc/interp_namedparams.cc`
|
||||
- `src/emc/rs274ngc/interp_internal.hh`
|
||||
- `src/emc/rs274ngc/interp_fwd.hh`
|
||||
- `src/emc/rs274ngc/interpmodule.cc`
|
||||
|
||||
## Phase 7: Replace HAL Runtime With a Simulation HAL Adapter
|
||||
|
||||
Purpose:
|
||||
Keep LinuxCNC interpreter-visible HAL behavior without migrating HAL itself.
|
||||
|
||||
Steps:
|
||||
|
||||
1. Do not vendor the whole HAL runtime as a target runtime dependency.
|
||||
2. Use LinuxCNC HAL source as reference only for interface semantics:
|
||||
- `../linuxcnc/src/hal/hal.h`
|
||||
- `../linuxcnc/src/hal/halmodule.cc`
|
||||
- `../linuxcnc/src/emc/ini/inihal.cc`
|
||||
3. Define a standalone HAL adapter interface:
|
||||
- lookup by name
|
||||
- typed numeric value
|
||||
- connection/existence status
|
||||
4. Make `_hal[...]` reads resolve through this adapter.
|
||||
5. Seed the adapter from simulation config and runtime state.
|
||||
6. Add tests for:
|
||||
- existing names
|
||||
- missing names
|
||||
- disconnected signals
|
||||
- type conversion
|
||||
|
||||
Involved LinuxCNC source:
|
||||
|
||||
- `src/hal/hal.h`
|
||||
- `src/hal/halmodule.cc`
|
||||
- `src/emc/rs274ngc/interp_namedparams.cc`
|
||||
- `src/emc/ini/inihal.cc`
|
||||
|
||||
## Phase 8: Port the Interpreter Core
|
||||
|
||||
Purpose:
|
||||
Build the standalone G-code execution engine without touching upstream files.
|
||||
|
||||
Steps:
|
||||
|
||||
1. Vendor selected files from `../linuxcnc/src/emc/rs274ngc/`.
|
||||
2. Keep original source as intact as possible in `vendor/`.
|
||||
3. Add wrappers or minimal patches only in the standalone area.
|
||||
4. Replace these external edges:
|
||||
- file open/read
|
||||
- world sync
|
||||
- HAL reads
|
||||
- logging
|
||||
- runtime callbacks
|
||||
5. Preserve:
|
||||
- modal state
|
||||
- subroutines
|
||||
- offsets
|
||||
- tool handling
|
||||
- parameter interactions
|
||||
- error semantics
|
||||
6. Add a canonical event sink interface in standalone code.
|
||||
|
||||
Involved LinuxCNC source:
|
||||
|
||||
- `src/emc/rs274ngc/interp_execute.cc`
|
||||
- `src/emc/rs274ngc/interp_read.cc`
|
||||
- `src/emc/rs274ngc/interp_check.cc`
|
||||
- `src/emc/rs274ngc/interp_convert.cc`
|
||||
- `src/emc/rs274ngc/interp_cycles.cc`
|
||||
- `src/emc/rs274ngc/interp_find.cc`
|
||||
- `src/emc/rs274ngc/interp_write.cc`
|
||||
- `src/emc/rs274ngc/interp_o_word.cc`
|
||||
- `src/emc/rs274ngc/rs274ngc_pre.cc`
|
||||
- `src/emc/rs274ngc/rs274ngc_interp.hh`
|
||||
|
||||
## Phase 9: Port Planner and Kinematics
|
||||
|
||||
Purpose:
|
||||
Preserve LinuxCNC motion planning and 5-axis simulation behavior.
|
||||
|
||||
Steps:
|
||||
|
||||
1. Vendor selected planner files from `../linuxcnc/src/emc/tp/`.
|
||||
2. Vendor selected kinematics files from:
|
||||
- `../linuxcnc/src/emc/kinematics/`
|
||||
- selected `.comp` sources mirrored into standalone code where needed
|
||||
3. Replace loadable-module assumptions with a registry in the standalone runtime.
|
||||
4. Keep original math and state logic intact as far as practical.
|
||||
5. Add tests for:
|
||||
- planner outputs
|
||||
- forward/inverse kinematics
|
||||
- 5-axis world/joint transforms
|
||||
|
||||
Involved LinuxCNC source:
|
||||
|
||||
- `src/emc/tp/tp.c`
|
||||
- `src/emc/tp/tc.c`
|
||||
- `src/emc/tp/tcq.c`
|
||||
- `src/emc/tp/blendmath.c`
|
||||
- `src/emc/tp/sp_scurve.c`
|
||||
- `src/emc/tp/ruckig_wrapper.c`
|
||||
- `src/emc/kinematics/*.c`
|
||||
- `src/hal/components/xyzab_tdr_kins.comp`
|
||||
- `src/hal/components/xyzacb_trsrn.comp`
|
||||
- `src/hal/components/xyzbca_trsrn.comp`
|
||||
|
||||
## Phase 10: Build the Standalone WASM Program
|
||||
|
||||
Purpose:
|
||||
Keep the migrated program completely outside native LinuxCNC management.
|
||||
|
||||
Steps:
|
||||
|
||||
1. Build the standalone native core first.
|
||||
2. Add a standalone WASM export layer under:
|
||||
- `wasm-port/runtime/core/`
|
||||
- `wasm-port/runtime/sdk/`
|
||||
3. Use `vendor/` sources plus standalone wrappers as build input.
|
||||
4. Do not compile from `../linuxcnc` directly in the final WASM product build.
|
||||
5. Emit:
|
||||
- `wasm` module
|
||||
- JS loader
|
||||
- standalone SDK
|
||||
|
||||
Outputs:
|
||||
|
||||
- independently managed WASM simulation core
|
||||
|
||||
## Phase 11: Build the Frontend and OPFS Layer
|
||||
|
||||
Purpose:
|
||||
Keep the standalone port program separate from LinuxCNC GUI code and storage.
|
||||
|
||||
Steps:
|
||||
|
||||
1. Build frontend files under:
|
||||
- `wasm-port/runtime/ui/`
|
||||
- `wasm-port/runtime/opfs/`
|
||||
2. Implement:
|
||||
- HTML shell
|
||||
- JavaScript control panel
|
||||
- OPFS persistence
|
||||
- file import/export
|
||||
- machine/controller state views
|
||||
3. Keep LinuxCNC GUI code reference-only.
|
||||
4. Ensure the frontend depends only on the standalone SDK, not on native LinuxCNC binaries.
|
||||
|
||||
Outputs:
|
||||
|
||||
- standalone browser program
|
||||
|
||||
## Phase 12: Validate Drift Against Upstream
|
||||
|
||||
Purpose:
|
||||
Prove the standalone port still tracks LinuxCNC behavior.
|
||||
|
||||
Steps:
|
||||
|
||||
1. Use native LinuxCNC tests and fixtures as semantic baselines.
|
||||
2. Compare:
|
||||
- LinuxCNC native behavior
|
||||
- standalone native extracted core
|
||||
- standalone WASM behavior
|
||||
3. Maintain a drift report.
|
||||
4. Re-run extraction if upstream source changes.
|
||||
5. Keep patches small and traceable.
|
||||
|
||||
Outputs:
|
||||
|
||||
- drift report
|
||||
- compatibility regression suite
|
||||
|
||||
## Management Rules For Daily Development
|
||||
|
||||
Use these rules continuously:
|
||||
|
||||
1. Never edit files under `linuxcnc/` as part of the port.
|
||||
2. Any needed modification to upstream logic must be applied to vendored copies only.
|
||||
3. Any upstream sync must be script-driven and repeatable.
|
||||
4. Every shim must be documented.
|
||||
5. Every local patch against vendored source must be stored as a patch file or clearly isolated wrapper.
|
||||
|
||||
## Recommended Document Set
|
||||
|
||||
Keep these documents under `wasm-port/docs/`:
|
||||
|
||||
- `scope-and-baseline.md`
|
||||
- `source-reuse-map.md`
|
||||
- `state-porting-strategy.md`
|
||||
- `wasm-build-strategy.md`
|
||||
- `frontend-architecture.md`
|
||||
- `opfs-file-model.md`
|
||||
- `compatibility-validation.md`
|
||||
- `drift-report.md`
|
||||
|
||||
## Immediate Next Step
|
||||
|
||||
Continue expanding the standalone interpreter core from the verified minimal
|
||||
traverse path:
|
||||
|
||||
1. replace the temporary minimal `convert_g()` implementation with calls into
|
||||
vendored LinuxCNC interpreter conversion code.
|
||||
2. identify and shim the native runtime symbols blocking direct compilation of
|
||||
`interp_convert.cc`, `interp_execute.cc`, and related interpreter files.
|
||||
3. keep fixture coverage as regression protection while deleting temporary
|
||||
hand-written semantics.
|
||||
4. keep all source changes inside `wasm-port/` and leave `../linuxcnc/`
|
||||
read-only.
|
||||
12
wasm-port/runtime/core/include/canon_event_sink.hh
Normal file
12
wasm-port/runtime/core/include/canon_event_sink.hh
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace standalone {
|
||||
|
||||
void reset_canon_events();
|
||||
void push_canon_event(const std::string &event);
|
||||
const std::vector<std::string> &canon_events();
|
||||
|
||||
} // namespace standalone
|
||||
@@ -0,0 +1,4 @@
|
||||
#include "nml_intf/emc.hh"
|
||||
|
||||
static EMC_STAT standalone_emc_status;
|
||||
EMC_STAT *emcStatus = &standalone_emc_status;
|
||||
32
wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_ini_probe.cpp
Normal file
32
wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_ini_probe.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "emc/ini/inifile.hh"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc != 2) {
|
||||
std::cerr << "usage: linuxcnc_ini_probe <ini-file>\n";
|
||||
return 2;
|
||||
}
|
||||
|
||||
const char *ini_path = argv[1];
|
||||
linuxcnc::IniFile ini(ini_path);
|
||||
if (!ini) {
|
||||
std::cerr << "failed to open ini file: " << ini_path << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
const auto machine = ini.findString("MACHINE", "EMC");
|
||||
const auto display = ini.findString("DISPLAY", "DISPLAY");
|
||||
const auto kins = ini.findString("KINEMATICS", "KINS");
|
||||
const auto coords = ini.findString("COORDINATES", "TRAJ");
|
||||
const auto parameter_file = ini.findString("PARAMETER_FILE", "RS274NGC");
|
||||
|
||||
std::cout << "EMC.MACHINE=" << (machine ? *machine : "<missing>") << "\n";
|
||||
std::cout << "DISPLAY.DISPLAY=" << (display ? *display : "<missing>") << "\n";
|
||||
std::cout << "KINS.KINEMATICS=" << (kins ? *kins : "<missing>") << "\n";
|
||||
std::cout << "TRAJ.COORDINATES=" << (coords ? *coords : "<missing>") << "\n";
|
||||
std::cout << "RS274NGC.PARAMETER_FILE=" << (parameter_file ? *parameter_file : "<missing>") << "\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
21
wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_ini_wasm.cpp
Normal file
21
wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_ini_wasm.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#include <emscripten/emscripten.h>
|
||||
|
||||
#include "emc/ini/inifile.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
int lcini_get_string(const char *inipath,
|
||||
const char *section,
|
||||
const char *tag,
|
||||
char *buf,
|
||||
int bufsize) {
|
||||
return iniFindString(inipath, tag, section, buf, static_cast<size_t>(bufsize));
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
int lcini_tilde_expand(const char *path, char *buf, int bufsize) {
|
||||
return TildeExpansion(path, buf, static_cast<size_t>(bufsize));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
#define private public
|
||||
#include "emc/rs274ngc/rs274ngc_interp.hh"
|
||||
#undef private
|
||||
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "canon_event_sink.hh"
|
||||
|
||||
namespace {
|
||||
|
||||
void initialize_minimal_interp(Interp &interp)
|
||||
{
|
||||
interp._setup.length_units = CANON_UNITS_MM;
|
||||
interp._setup.distance_mode = DISTANCE_MODE::ABSOLUTE;
|
||||
interp._setup.ijk_distance_mode = DISTANCE_MODE::ABSOLUTE;
|
||||
interp._setup.feed_mode = FEED_MODE::UNITS_PER_MINUTE;
|
||||
interp._setup.plane = CANON_PLANE::XY;
|
||||
interp._setup.motion_mode = G_0;
|
||||
interp._setup.percent_flag = false;
|
||||
interp._setup.sequence_number = 0;
|
||||
interp._setup.parameter_occurrence = 0;
|
||||
std::memcpy(interp._readers, Interp::default_readers, sizeof(Interp::default_readers));
|
||||
}
|
||||
|
||||
std::vector<std::string> load_program(int argc, char **argv)
|
||||
{
|
||||
if (argc <= 1) {
|
||||
return {
|
||||
"G0 X1.0 Y2.0 (Comment)\n",
|
||||
"G1 X3.0 Y4.0 F120.0\n",
|
||||
};
|
||||
}
|
||||
|
||||
std::ifstream input(argv[1]);
|
||||
if (!input) {
|
||||
std::cerr << "failed to open fixture: " << argv[1] << "\n";
|
||||
std::exit(2);
|
||||
}
|
||||
|
||||
std::vector<std::string> lines;
|
||||
std::string line;
|
||||
while (std::getline(input, line)) {
|
||||
if (!line.empty()) {
|
||||
lines.push_back(line + "\n");
|
||||
}
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
Interp interp;
|
||||
standalone::reset_canon_events();
|
||||
initialize_minimal_interp(interp);
|
||||
|
||||
const std::vector<std::string> program = load_program(argc, argv);
|
||||
if (program.empty()) {
|
||||
std::cerr << "empty fixture\n";
|
||||
return 2;
|
||||
}
|
||||
|
||||
char line[LINELEN] = {0};
|
||||
std::strncpy(line, program.front().c_str(), sizeof(line) - 1);
|
||||
char raw_line[LINELEN] = {0};
|
||||
char cooked_line[LINELEN] = {0};
|
||||
int length = -1;
|
||||
|
||||
const int read_text_rc = interp.read_text(line, nullptr, raw_line, cooked_line, &length);
|
||||
const int downcase_rc = interp.close_and_downcase(line);
|
||||
const int read_rc = interp.read(program.front().c_str());
|
||||
|
||||
initialize_minimal_interp(interp);
|
||||
for (std::size_t idx = 0; idx < program.size(); ++idx) {
|
||||
interp._setup.sequence_number = static_cast<int>(idx + 1);
|
||||
const int execute_rc = interp.execute(program[idx].c_str());
|
||||
std::cout << "execute_line_" << (idx + 1) << "=" << execute_rc << "\n";
|
||||
}
|
||||
|
||||
block block{};
|
||||
const int init_block_rc = interp.init_block(&block);
|
||||
int parse_line_rc = INTERP_ERROR;
|
||||
if (read_text_rc == INTERP_OK) {
|
||||
parse_line_rc = interp.parse_line(cooked_line, &block, &interp._setup);
|
||||
}
|
||||
|
||||
std::cout << "read_text=" << read_text_rc << "\n";
|
||||
std::cout << "raw_line=" << raw_line << "\n";
|
||||
std::cout << "cooked_line=" << cooked_line << "\n";
|
||||
std::cout << "line_length=" << length << "\n";
|
||||
std::cout << "read=" << read_rc << "\n";
|
||||
std::cout << "setup.linetext=" << interp._setup.linetext << "\n";
|
||||
std::cout << "setup.blocktext=" << interp._setup.blocktext << "\n";
|
||||
std::cout << "setup.line_length=" << interp._setup.line_length << "\n";
|
||||
std::cout << "setup.sequence_number=" << interp._setup.sequence_number << "\n";
|
||||
std::cout << "setup.current_x=" << interp._setup.current_x << "\n";
|
||||
std::cout << "setup.current_y=" << interp._setup.current_y << "\n";
|
||||
std::cout << "setup.current_z=" << interp._setup.current_z << "\n";
|
||||
std::cout << "setup.parameter_5420=" << interp._setup.parameters[5420] << "\n";
|
||||
std::cout << "setup.parameter_5421=" << interp._setup.parameters[5421] << "\n";
|
||||
std::cout << "setup.parameter_5422=" << interp._setup.parameters[5422] << "\n";
|
||||
std::cout << "setup.feed_rate=" << interp._setup.feed_rate << "\n";
|
||||
std::cout << "close_and_downcase=" << downcase_rc << "\n";
|
||||
std::cout << "normalized_line=" << line << "\n";
|
||||
std::cout << "init_block=" << init_block_rc << "\n";
|
||||
std::cout << "parse_line=" << parse_line_rc << "\n";
|
||||
std::cout << "block.motion_to_be=" << block.motion_to_be << "\n";
|
||||
std::cout << "block.g_modes[GM_MOTION]=" << block.g_modes[GM_MOTION] << "\n";
|
||||
std::cout << "block.x_flag=" << block.x_flag << " x=" << block.x_number << "\n";
|
||||
std::cout << "block.y_flag=" << block.y_flag << " y=" << block.y_number << "\n";
|
||||
std::cout << "executing_block.motion_to_be=" << EXECUTING_BLOCK(interp._setup).motion_to_be << "\n";
|
||||
std::cout << "executing_block.g_modes[GM_MOTION]=" << EXECUTING_BLOCK(interp._setup).g_modes[GM_MOTION] << "\n";
|
||||
std::cout << "executing_block.x_flag=" << EXECUTING_BLOCK(interp._setup).x_flag
|
||||
<< " x=" << EXECUTING_BLOCK(interp._setup).x_number << "\n";
|
||||
std::cout << "executing_block.y_flag=" << EXECUTING_BLOCK(interp._setup).y_flag
|
||||
<< " y=" << EXECUTING_BLOCK(interp._setup).y_number << "\n";
|
||||
std::cout << "executing_block.f_flag=" << EXECUTING_BLOCK(interp._setup).f_flag
|
||||
<< " f=" << EXECUTING_BLOCK(interp._setup).f_number << "\n";
|
||||
std::cout << "call_level=" << interp.call_level() << "\n";
|
||||
std::cout << "loggingLevel=" << interp._setup.loggingLevel << "\n";
|
||||
std::cout << "canon_event_count=" << standalone::canon_events().size() << "\n";
|
||||
for (const auto &event : standalone::canon_events()) {
|
||||
std::cout << "canon_event=" << event << "\n";
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,564 @@
|
||||
#include <cstdarg>
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#define private public
|
||||
#include "emc/rs274ngc/rs274ngc_interp.hh"
|
||||
#undef private
|
||||
|
||||
#include "emc/rs274ngc/rs274ngc_return.hh"
|
||||
#include "canon_event_sink.hh"
|
||||
|
||||
PythonPlugin *python_plugin = nullptr;
|
||||
|
||||
namespace standalone {
|
||||
|
||||
static std::vector<std::string> g_canon_events;
|
||||
|
||||
void reset_canon_events()
|
||||
{
|
||||
g_canon_events.clear();
|
||||
}
|
||||
|
||||
void push_canon_event(const std::string &event)
|
||||
{
|
||||
g_canon_events.push_back(event);
|
||||
}
|
||||
|
||||
const std::vector<std::string> &canon_events()
|
||||
{
|
||||
return g_canon_events;
|
||||
}
|
||||
|
||||
} // namespace standalone
|
||||
|
||||
bool GET_BLOCK_DELETE(void) { return false; }
|
||||
void FINISH(void) {}
|
||||
void ON_RESET(void) {}
|
||||
|
||||
USER_DEFINED_FUNCTION_TYPE USER_DEFINED_FUNCTION[USER_DEFINED_FUNCTION_NUM] = {};
|
||||
|
||||
int USER_DEFINED_FUNCTION_ADD(USER_DEFINED_FUNCTION_TYPE func, int num)
|
||||
{
|
||||
if ((num < 0) || (num >= USER_DEFINED_FUNCTION_NUM)) {
|
||||
return -1;
|
||||
}
|
||||
USER_DEFINED_FUNCTION[num] = func;
|
||||
return num;
|
||||
}
|
||||
|
||||
void INIT_CANON() {}
|
||||
void SET_G5X_OFFSET(int, double, double, double, double, double, double, double, double, double) {}
|
||||
void SET_G92_OFFSET(double, double, double, double, double, double, double, double, double) {}
|
||||
void SET_XY_ROTATION(double) {}
|
||||
void CANON_UPDATE_END_POINT(double, double, double, double, double, double, double, double, double) {}
|
||||
void USE_LENGTH_UNITS(CANON_UNITS) {}
|
||||
void SELECT_PLANE(CANON_PLANE) {}
|
||||
void SET_TRAVERSE_RATE(double) {}
|
||||
void SET_FEED_REFERENCE(CANON_FEED_REFERENCE) {}
|
||||
void SET_FEED_MODE(int, int) {}
|
||||
void SET_MOTION_CONTROL_MODE(CANON_MOTION_MODE, double) {}
|
||||
void SET_NAIVECAM_TOLERANCE(double) {}
|
||||
void SET_CUTTER_RADIUS_COMPENSATION(double) {}
|
||||
void START_CUTTER_RADIUS_COMPENSATION(int) {}
|
||||
void STOP_CUTTER_RADIUS_COMPENSATION() {}
|
||||
void START_SPEED_FEED_SYNCH(int, double, bool) {}
|
||||
void STOP_SPEED_FEED_SYNCH() {}
|
||||
void RIGID_TAP(int, double, double, double, double) {}
|
||||
void STRAIGHT_PROBE(int, double, double, double, double, double, double, double, double, double, unsigned char) {}
|
||||
void STOP() {}
|
||||
void DWELL(double) {}
|
||||
void SET_SPINDLE_MODE(int, double) {}
|
||||
void SPINDLE_RETRACT_TRAVERSE() {}
|
||||
void START_SPINDLE_CLOCKWISE(int, int) {}
|
||||
void START_SPINDLE_COUNTERCLOCKWISE(int, int) {}
|
||||
void SET_SPINDLE_SPEED(int, double) {}
|
||||
void STOP_SPINDLE_TURNING(int) {}
|
||||
void SPINDLE_RETRACT() {}
|
||||
void ORIENT_SPINDLE(int, double, int) {}
|
||||
void WAIT_SPINDLE_ORIENT_COMPLETE(int, double) {}
|
||||
void LOCK_SPINDLE_Z() {}
|
||||
void USE_SPINDLE_FORCE() {}
|
||||
void USE_NO_SPINDLE_FORCE() {}
|
||||
void SET_TOOL_TABLE_ENTRY(int, int, const EmcPose &, double, double, double, int) {}
|
||||
void USE_TOOL_LENGTH_OFFSET(const EmcPose &) {}
|
||||
void CHANGE_TOOL() {}
|
||||
void SELECT_TOOL(int) {}
|
||||
void CHANGE_TOOL_NUMBER(int) {}
|
||||
void RELOAD_TOOLDATA(void) {}
|
||||
void CLAMP_AXIS(CANON_AXIS) {}
|
||||
void DISABLE_ADAPTIVE_FEED() {}
|
||||
void ENABLE_ADAPTIVE_FEED() {}
|
||||
void DISABLE_FEED_OVERRIDE() {}
|
||||
void ENABLE_FEED_OVERRIDE() {}
|
||||
void DISABLE_SPEED_OVERRIDE(int) {}
|
||||
void ENABLE_SPEED_OVERRIDE(int) {}
|
||||
void DISABLE_FEED_HOLD() {}
|
||||
void ENABLE_FEED_HOLD() {}
|
||||
void FLOOD_OFF() {}
|
||||
void FLOOD_ON() {}
|
||||
void MIST_OFF() {}
|
||||
void MIST_ON() {}
|
||||
void PALLET_SHUTTLE() {}
|
||||
void TURN_PROBE_OFF() {}
|
||||
void TURN_PROBE_ON() {}
|
||||
void UNCLAMP_AXIS(CANON_AXIS) {}
|
||||
void NURB_KNOT_VECTOR() {}
|
||||
void NURB_CONTROL_POINT(int, double, double, double, double) {}
|
||||
void NURB_FEED(double, double) {}
|
||||
void SET_BLOCK_DELETE(bool) {}
|
||||
void OPTIONAL_PROGRAM_STOP() {}
|
||||
void SET_OPTIONAL_PROGRAM_STOP(bool) {}
|
||||
bool GET_OPTIONAL_PROGRAM_STOP() { return false; }
|
||||
void PROGRAM_END() {}
|
||||
void PROGRAM_STOP() {}
|
||||
void SET_MOTION_OUTPUT_BIT(int) {}
|
||||
void CLEAR_MOTION_OUTPUT_BIT(int) {}
|
||||
void SET_AUX_OUTPUT_BIT(int) {}
|
||||
void CLEAR_AUX_OUTPUT_BIT(int) {}
|
||||
void SET_MOTION_OUTPUT_VALUE(int, double) {}
|
||||
void SET_AUX_OUTPUT_VALUE(int, double) {}
|
||||
int WAIT(int, int, int, double) { return 0; }
|
||||
int UNLOCK_ROTARY(int, int) { return 0; }
|
||||
int LOCK_ROTARY(int, int) { return 0; }
|
||||
void UPDATE_TAG(const StateTag &) {}
|
||||
|
||||
void MESSAGE(char *s) { standalone::push_canon_event(std::string("MESSAGE: ") + (s ? s : "")); }
|
||||
void LOG(char *) {}
|
||||
void LOGOPEN(char *) {}
|
||||
void LOGAPPEND(char *) {}
|
||||
void LOGCLOSE() {}
|
||||
|
||||
void CANON_ERROR(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
fputc('\n', stderr);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
double GET_EXTERNAL_FEED_RATE() { return 0.0; }
|
||||
int GET_EXTERNAL_FLOOD() { return 0; }
|
||||
double GET_EXTERNAL_LENGTH_UNITS() { return CANON_UNITS_MM; }
|
||||
double GET_EXTERNAL_ANGLE_UNITS() { return 1.0; }
|
||||
int GET_EXTERNAL_MIST() { return 0; }
|
||||
CANON_MOTION_MODE GET_EXTERNAL_MOTION_CONTROL_MODE() { return CANON_EXACT_STOP; }
|
||||
double GET_EXTERNAL_MOTION_CONTROL_TOLERANCE() { return 0.0; }
|
||||
double GET_EXTERNAL_MOTION_CONTROL_NAIVECAM_TOLERANCE() { return 0.0; }
|
||||
double GET_EXTERNAL_ORIGIN_A() { return 0.0; }
|
||||
double GET_EXTERNAL_ORIGIN_B() { return 0.0; }
|
||||
double GET_EXTERNAL_ORIGIN_C() { return 0.0; }
|
||||
double GET_EXTERNAL_ORIGIN_X() { return 0.0; }
|
||||
double GET_EXTERNAL_ORIGIN_Y() { return 0.0; }
|
||||
double GET_EXTERNAL_ORIGIN_Z() { return 0.0; }
|
||||
void GET_EXTERNAL_PARAMETER_FILE_NAME(char *filename, int max_size)
|
||||
{
|
||||
if (max_size > 0) {
|
||||
filename[0] = '\0';
|
||||
}
|
||||
}
|
||||
void SET_PARAMETER_FILE_NAME(const char *) {}
|
||||
CANON_PLANE GET_EXTERNAL_PLANE() { return CANON_PLANE::XY; }
|
||||
double GET_EXTERNAL_POSITION_A() { return 0.0; }
|
||||
double GET_EXTERNAL_POSITION_B() { return 0.0; }
|
||||
double GET_EXTERNAL_POSITION_C() { return 0.0; }
|
||||
double GET_EXTERNAL_POSITION_X() { return 0.0; }
|
||||
double GET_EXTERNAL_POSITION_Y() { return 0.0; }
|
||||
double GET_EXTERNAL_POSITION_Z() { return 0.0; }
|
||||
double GET_EXTERNAL_POSITION_U() { return 0.0; }
|
||||
double GET_EXTERNAL_POSITION_V() { return 0.0; }
|
||||
double GET_EXTERNAL_POSITION_W() { return 0.0; }
|
||||
double GET_EXTERNAL_PROBE_POSITION_A() { return 0.0; }
|
||||
double GET_EXTERNAL_PROBE_POSITION_B() { return 0.0; }
|
||||
double GET_EXTERNAL_PROBE_POSITION_C() { return 0.0; }
|
||||
double GET_EXTERNAL_PROBE_POSITION_X() { return 0.0; }
|
||||
double GET_EXTERNAL_PROBE_POSITION_Y() { return 0.0; }
|
||||
double GET_EXTERNAL_PROBE_POSITION_Z() { return 0.0; }
|
||||
double GET_EXTERNAL_PROBE_POSITION_U() { return 0.0; }
|
||||
double GET_EXTERNAL_PROBE_POSITION_V() { return 0.0; }
|
||||
double GET_EXTERNAL_PROBE_POSITION_W() { return 0.0; }
|
||||
double GET_EXTERNAL_PROBE_VALUE() { return 0.0; }
|
||||
int GET_EXTERNAL_PROBE_TRIPPED_VALUE() { return 0; }
|
||||
int GET_EXTERNAL_QUEUE_EMPTY() { return 1; }
|
||||
double GET_EXTERNAL_SPEED(int) { return 0.0; }
|
||||
CANON_DIRECTION GET_EXTERNAL_SPINDLE(int) { return CANON_STOPPED; }
|
||||
double GET_EXTERNAL_TOOL_LENGTH_XOFFSET() { return 0.0; }
|
||||
double GET_EXTERNAL_TOOL_LENGTH_YOFFSET() { return 0.0; }
|
||||
double GET_EXTERNAL_TOOL_LENGTH_ZOFFSET() { return 0.0; }
|
||||
double GET_EXTERNAL_TOOL_LENGTH_AOFFSET() { return 0.0; }
|
||||
double GET_EXTERNAL_TOOL_LENGTH_BOFFSET() { return 0.0; }
|
||||
double GET_EXTERNAL_TOOL_LENGTH_COFFSET() { return 0.0; }
|
||||
double GET_EXTERNAL_TOOL_LENGTH_UOFFSET() { return 0.0; }
|
||||
double GET_EXTERNAL_TOOL_LENGTH_VOFFSET() { return 0.0; }
|
||||
double GET_EXTERNAL_TOOL_LENGTH_WOFFSET() { return 0.0; }
|
||||
int GET_EXTERNAL_TOOL_SLOT() { return 0; }
|
||||
int GET_EXTERNAL_SELECTED_TOOL_SLOT() { return -1; }
|
||||
CANON_TOOL_TABLE GET_EXTERNAL_TOOL_TABLE(int) { return tooldata_entry_init(); }
|
||||
int GET_EXTERNAL_TC_FAULT() { return 0; }
|
||||
int GET_EXTERNAL_TC_REASON() { return 0; }
|
||||
double GET_EXTERNAL_TRAVERSE_RATE() { return 0.0; }
|
||||
int GET_EXTERNAL_FEED_OVERRIDE_ENABLE() { return 1; }
|
||||
int GET_EXTERNAL_SPINDLE_OVERRIDE_ENABLE(int) { return 1; }
|
||||
int GET_EXTERNAL_ADAPTIVE_FEED_ENABLE() { return 1; }
|
||||
int GET_EXTERNAL_FEED_HOLD_ENABLE() { return 1; }
|
||||
int GET_EXTERNAL_DIGITAL_INPUT(int, int def) { return def; }
|
||||
double GET_EXTERNAL_ANALOG_INPUT(int, double def) { return def; }
|
||||
int GET_EXTERNAL_AXIS_MASK() { return 7; }
|
||||
int GET_EXTERNAL_OFFSET_APPLIED() { return 0; }
|
||||
EmcPose GET_EXTERNAL_OFFSETS() { return {{0, 0, 0}, 0, 0, 0, 0, 0, 0}; }
|
||||
|
||||
void NURBS_G5_FEED(int, const std::vector<NURBS_CONTROL_POINT> &, unsigned int, CANON_PLANE) {}
|
||||
void NURBS_G6_FEED(int, const std::vector<NURBS_G6_CONTROL_POINT> &, unsigned int, double, int, CANON_PLANE) {}
|
||||
|
||||
void COMMENT(const char *s)
|
||||
{
|
||||
standalone::push_canon_event(std::string("COMMENT: ") + (s ? s : ""));
|
||||
}
|
||||
|
||||
void STRAIGHT_TRAVERSE(int lineno,
|
||||
double x, double y, double z,
|
||||
double a, double b, double c,
|
||||
double u, double v, double w)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "STRAIGHT_TRAVERSE line=" << lineno
|
||||
<< " x=" << x
|
||||
<< " y=" << y
|
||||
<< " z=" << z
|
||||
<< " a=" << a
|
||||
<< " b=" << b
|
||||
<< " c=" << c
|
||||
<< " u=" << u
|
||||
<< " v=" << v
|
||||
<< " w=" << w;
|
||||
standalone::push_canon_event(oss.str());
|
||||
}
|
||||
|
||||
void STRAIGHT_FEED(int lineno,
|
||||
double x, double y, double z,
|
||||
double a, double b, double c,
|
||||
double u, double v, double w)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "STRAIGHT_FEED line=" << lineno
|
||||
<< " x=" << x
|
||||
<< " y=" << y
|
||||
<< " z=" << z
|
||||
<< " a=" << a
|
||||
<< " b=" << b
|
||||
<< " c=" << c
|
||||
<< " u=" << u
|
||||
<< " v=" << v
|
||||
<< " w=" << w;
|
||||
standalone::push_canon_event(oss.str());
|
||||
}
|
||||
|
||||
void ARC_FEED(int lineno,
|
||||
double first_end, double second_end,
|
||||
double first_axis, double second_axis, int rotation,
|
||||
double axis_end_point,
|
||||
double a, double b, double c,
|
||||
double u, double v, double w)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "ARC_FEED line=" << lineno
|
||||
<< " first_end=" << first_end
|
||||
<< " second_end=" << second_end
|
||||
<< " first_axis=" << first_axis
|
||||
<< " second_axis=" << second_axis
|
||||
<< " rotation=" << rotation
|
||||
<< " axis_end_point=" << axis_end_point
|
||||
<< " a=" << a
|
||||
<< " b=" << b
|
||||
<< " c=" << c
|
||||
<< " u=" << u
|
||||
<< " v=" << v
|
||||
<< " w=" << w;
|
||||
standalone::push_canon_event(oss.str());
|
||||
}
|
||||
|
||||
void SET_FEED_RATE(double rate)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "SET_FEED_RATE rate=" << rate;
|
||||
standalone::push_canon_event(oss.str());
|
||||
}
|
||||
|
||||
InterpBase::~InterpBase() {}
|
||||
|
||||
Interp::Interp()
|
||||
: log_file(stderr),
|
||||
_setup{}
|
||||
{
|
||||
_setup.init_once = 1;
|
||||
memset(_readers, 0, sizeof(_readers));
|
||||
}
|
||||
|
||||
Interp::~Interp() {
|
||||
if (log_file && log_file != stderr) {
|
||||
fclose(log_file);
|
||||
}
|
||||
log_file = nullptr;
|
||||
}
|
||||
|
||||
void Interp::doLog(unsigned int, const char *, int, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
const char *Interp::interp_status(int status)
|
||||
{
|
||||
static char statustext[64];
|
||||
snprintf(statustext, sizeof(statustext), "%d", status);
|
||||
return statustext;
|
||||
}
|
||||
|
||||
const char *Interp::getSavedError()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
int Interp::setSavedError(const char *)
|
||||
{
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
void Interp::setError(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
fputc('\n', stderr);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
int Interp::unwind_call(int status, const char *, int, const char *)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
int Interp::close() { return INTERP_OK; }
|
||||
int Interp::execute(const char *command)
|
||||
{
|
||||
int status = read(command);
|
||||
if (status != INTERP_OK) {
|
||||
if (status > INTERP_MIN_ERROR) {
|
||||
unwind_call(status, __FILE__, __LINE__, __FUNCTION__);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
if (_setup.line_length != 0) {
|
||||
status = execute_block(&EXECUTING_BLOCK(_setup), &_setup);
|
||||
if (status > INTERP_MIN_ERROR) {
|
||||
unwind_call(status, __FILE__, __LINE__, __FUNCTION__);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
int Interp::execute() { return execute(nullptr); }
|
||||
|
||||
int Interp::execute(const char *command, int line_number)
|
||||
{
|
||||
if (command && line_number) {
|
||||
_setup.sequence_number = line_number;
|
||||
}
|
||||
int status = execute(command);
|
||||
if ((_setup.call_level == 0) &&
|
||||
(status == INTERP_EXECUTE_FINISH) &&
|
||||
(_setup.mdi_interrupt)) {
|
||||
_setup.mdi_interrupt = false;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
int Interp::exit() { return INTERP_OK; }
|
||||
int Interp::init() { return INTERP_OK; }
|
||||
void Interp::set_loop_on_main_m99(bool state) { _setup.loop_on_main_m99 = state; }
|
||||
int Interp::open(const char *) { return INTERP_ERROR; }
|
||||
|
||||
int Interp::read_inputs(setup_pointer)
|
||||
{
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
int Interp::_read(const char *command)
|
||||
{
|
||||
int read_status = INTERP_OK;
|
||||
block_pointer eblock = &EXECUTING_BLOCK(_setup);
|
||||
|
||||
if ((_setup.call_state > CS_NORMAL) &&
|
||||
(eblock->call_type != CT_NGC_OWORD_SUB) &&
|
||||
(eblock->call_type != CT_NGC_M98_SUB) &&
|
||||
(eblock->call_type != CT_NONE) &&
|
||||
((eblock->o_type == O_call) ||
|
||||
(eblock->o_type == M_98) ||
|
||||
(eblock->o_type == O_return) ||
|
||||
(eblock->o_type == O_endsub) ||
|
||||
(eblock->o_type == M_99))) {
|
||||
_setup.line_length = 0;
|
||||
_setup.linetext[0] = 0;
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
_setup.call_state = CS_NORMAL;
|
||||
if (read_inputs(&_setup) != INTERP_OK) {
|
||||
return INTERP_ERROR;
|
||||
}
|
||||
|
||||
if ((command == nullptr) && (_setup.file_pointer == nullptr)) {
|
||||
return INTERP_FILE_NOT_OPEN;
|
||||
}
|
||||
|
||||
_setup.parameters[5420] = _setup.current_x;
|
||||
_setup.parameters[5421] = _setup.current_y;
|
||||
_setup.parameters[5422] = _setup.current_z;
|
||||
_setup.parameters[5423] = _setup.AA_current;
|
||||
_setup.parameters[5424] = _setup.BB_current;
|
||||
_setup.parameters[5425] = _setup.CC_current;
|
||||
_setup.parameters[5426] = _setup.u_current;
|
||||
_setup.parameters[5427] = _setup.v_current;
|
||||
_setup.parameters[5428] = _setup.w_current;
|
||||
|
||||
if (_setup.file_pointer) {
|
||||
EXECUTING_BLOCK(_setup).offset = ftell(_setup.file_pointer);
|
||||
}
|
||||
|
||||
read_status = read_text(command, _setup.file_pointer, _setup.linetext,
|
||||
_setup.blocktext, &_setup.line_length);
|
||||
|
||||
if ((read_status == INTERP_EXECUTE_FINISH) || (read_status == INTERP_OK)) {
|
||||
if (_setup.line_length != 0) {
|
||||
if (parse_line(_setup.blocktext, &(EXECUTING_BLOCK(_setup)), &_setup) != INTERP_OK) {
|
||||
return INTERP_ERROR;
|
||||
}
|
||||
} else {
|
||||
if (EXECUTING_BLOCK(_setup).o_type != O_none) {
|
||||
EXECUTING_BLOCK(_setup).o_type = 0;
|
||||
}
|
||||
}
|
||||
} else if (read_status == INTERP_ENDFILE) {
|
||||
if (_setup.skipping_o != nullptr) {
|
||||
return INTERP_ERROR;
|
||||
}
|
||||
} else {
|
||||
return read_status;
|
||||
}
|
||||
|
||||
return read_status;
|
||||
}
|
||||
|
||||
int Interp::read(const char *command)
|
||||
{
|
||||
int status = _read(command);
|
||||
if (status > INTERP_MIN_ERROR) {
|
||||
unwind_call(status, __FILE__, __LINE__, __FUNCTION__);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
int Interp::read()
|
||||
{
|
||||
return read(nullptr);
|
||||
}
|
||||
|
||||
int Interp::reset() { return INTERP_OK; }
|
||||
int Interp::synch() { return INTERP_OK; }
|
||||
void Interp::active_g_codes(int *codes) { std::memcpy(codes, _setup.active_g_codes, sizeof(_setup.active_g_codes)); }
|
||||
void Interp::active_m_codes(int *codes) { std::memcpy(codes, _setup.active_m_codes, sizeof(_setup.active_m_codes)); }
|
||||
void Interp::active_settings(double *settings) { std::memcpy(settings, _setup.active_settings, sizeof(_setup.active_settings)); }
|
||||
int Interp::active_modes(int *, int *, double *, StateTag const &) { return INTERP_ERROR; }
|
||||
void Interp::print_state_tag(StateTag const &) {}
|
||||
char *Interp::error_text(int, char *buf, size_t max_size)
|
||||
{
|
||||
if (max_size) buf[0] = '\0';
|
||||
return buf;
|
||||
}
|
||||
char *Interp::file_name(char *buf, size_t max_size)
|
||||
{
|
||||
if (max_size) {
|
||||
std::strncpy(buf, _setup.filename, max_size - 1);
|
||||
buf[max_size - 1] = '\0';
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
size_t Interp::line_length() { return static_cast<size_t>(_setup.line_length); }
|
||||
char *Interp::line_text(char *buf, size_t max_size)
|
||||
{
|
||||
if (max_size) {
|
||||
std::strncpy(buf, _setup.linetext, max_size - 1);
|
||||
buf[max_size - 1] = '\0';
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
int Interp::sequence_number() { return _setup.sequence_number; }
|
||||
char *Interp::stack_name(int idx, char *buf, size_t max_size)
|
||||
{
|
||||
if (!max_size) return buf;
|
||||
if (idx < 0 || idx >= STACK_LEN) {
|
||||
buf[0] = '\0';
|
||||
return buf;
|
||||
}
|
||||
std::strncpy(buf, _setup.stack[idx], max_size - 1);
|
||||
buf[max_size - 1] = '\0';
|
||||
return buf;
|
||||
}
|
||||
int Interp::ini_load(const char *) { return INTERP_OK; }
|
||||
int Interp::on_abort(int, const char *) { return INTERP_OK; }
|
||||
void Interp::set_loglevel(int level) { _setup.loggingLevel = level; }
|
||||
|
||||
int Interp::find_remappings(block_pointer, setup_pointer) { return 0; }
|
||||
|
||||
int Interp::load_tool_table() { return INTERP_OK; }
|
||||
int Interp::init_tool_parameters() { return INTERP_OK; }
|
||||
int Interp::default_tool_parameters() { return INTERP_OK; }
|
||||
int Interp::set_tool_parameters() { return INTERP_OK; }
|
||||
bool Interp::is_pycallable(setup_pointer, const char *, const char *) { return false; }
|
||||
bool Interp::is_user_defined_g_code(int) { return false; }
|
||||
bool Interp::is_any_m_code_remapped(block_pointer, setup_pointer) { return false; }
|
||||
bool Interp::is_user_defined_m_code(block_pointer, setup_pointer, int) { return false; }
|
||||
void Interp::loop_to_beginning(setup_pointer) {}
|
||||
int Interp::convert_control_functions(block_pointer, setup_pointer) { return INTERP_OK; }
|
||||
int Interp::convert_remapped_code(block_pointer, setup_pointer, int, char, int) { return INTERP_ERROR; }
|
||||
int Interp::py_execute(const char *, bool) { return INTERP_OK; }
|
||||
int Interp::py_reload() { return INTERP_OK; }
|
||||
|
||||
const char *o_ops[] = {
|
||||
"O_none", "O_sub", "O_endsub", "O_call", "O_do", "O_while", "O_if",
|
||||
"O_elseif", "O_else", "O_endif", "O_break", "O_continue",
|
||||
"O_endwhile", "O_return", "O_repeat", "O_endrepeat", "M_98", "M_99", "O_"
|
||||
};
|
||||
|
||||
int Interp::read_named_parameter(char *, int *, double *double_ptr, double *, bool check_exists)
|
||||
{
|
||||
if (check_exists) {
|
||||
*double_ptr = 0.0;
|
||||
}
|
||||
return INTERP_ERROR;
|
||||
}
|
||||
|
||||
int Interp::find_named_param(const char *, int *status, double *value)
|
||||
{
|
||||
*status = 0;
|
||||
*value = 0.0;
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
int Interp::store_named_param(setup_pointer, const char *, double, int)
|
||||
{
|
||||
return INTERP_ERROR;
|
||||
}
|
||||
|
||||
int Interp::add_named_param(const char *, int)
|
||||
{
|
||||
return INTERP_OK;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "emc/rs274ngc/interp_internal.hh"
|
||||
|
||||
int main() {
|
||||
std::cout << "RS274NGC_MAX_PARAMETERS="
|
||||
<< interp_param_global::RS274NGC_MAX_PARAMETERS << "\n";
|
||||
std::cout << "ACTIVE_G_CODES=" << ACTIVE_G_CODES << "\n";
|
||||
std::cout << "ACTIVE_M_CODES=" << ACTIVE_M_CODES << "\n";
|
||||
std::cout << "ACTIVE_SETTINGS=" << ACTIVE_SETTINGS << "\n";
|
||||
std::cout << "INTERP_SUB_ROUTINE_LEVELS=" << INTERP_SUB_ROUTINE_LEVELS << "\n";
|
||||
std::cout << "MAX_NAMED_PARAMETERS=" << MAX_NAMED_PARAMETERS << "\n";
|
||||
std::cout << "sizeof_setup=" << sizeof(setup) << "\n";
|
||||
std::cout << "sizeof_context=" << sizeof(context) << "\n";
|
||||
std::cout << "sizeof_parameter_value=" << sizeof(parameter_value) << "\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,341 @@
|
||||
#define private public
|
||||
#include "emc/rs274ngc/rs274ngc_interp.hh"
|
||||
#undef private
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "config.h"
|
||||
#include "emc/ini/inifile.hh"
|
||||
|
||||
namespace {
|
||||
|
||||
enum predefined_named_parameters {
|
||||
NP_LINE,
|
||||
NP_MOTION_MODE,
|
||||
NP_PLANE,
|
||||
NP_CCOMP,
|
||||
NP_METRIC,
|
||||
NP_IMPERIAL,
|
||||
NP_ABSOLUTE,
|
||||
NP_INCREMENTAL,
|
||||
NP_INVERSE_TIME,
|
||||
NP_UNITS_PER_MINUTE,
|
||||
NP_UNITS_PER_REV,
|
||||
NP_COORD_SYSTEM,
|
||||
NP_TOOL_OFFSET,
|
||||
NP_RETRACT_R_PLANE,
|
||||
NP_RETRACT_OLD_Z,
|
||||
NP_SPINDLE_RPM_MODE,
|
||||
NP_SPINDLE_CSS_MODE,
|
||||
NP_IJK_ABSOLUTE_MODE,
|
||||
NP_LATHE_DIAMETER_MODE,
|
||||
NP_LATHE_RADIUS_MODE,
|
||||
NP_SPINDLE_ON,
|
||||
NP_SPINDLE_CW,
|
||||
NP_MIST,
|
||||
NP_FLOOD,
|
||||
NP_SPEED_OVERRIDE,
|
||||
NP_FEED_OVERRIDE,
|
||||
NP_ADAPTIVE_FEED,
|
||||
NP_FEED_HOLD,
|
||||
NP_FEED,
|
||||
NP_RPM,
|
||||
NP_CURRENT_TOOL,
|
||||
NP_SELECTED_POCKET,
|
||||
NP_CURRENT_POCKET,
|
||||
NP_X,
|
||||
NP_Y,
|
||||
NP_Z,
|
||||
NP_A,
|
||||
NP_B,
|
||||
NP_C,
|
||||
NP_U,
|
||||
NP_V,
|
||||
NP_W,
|
||||
NP_ABS_X,
|
||||
NP_ABS_Y,
|
||||
NP_ABS_Z,
|
||||
NP_ABS_A,
|
||||
NP_ABS_B,
|
||||
NP_ABS_C,
|
||||
NP_VALUE,
|
||||
NP_CALL_LEVEL,
|
||||
NP_REMAP_LEVEL,
|
||||
NP_SELECTED_TOOL,
|
||||
NP_VALUE_RETURNED,
|
||||
NP_TASK,
|
||||
};
|
||||
|
||||
struct NamedParamRuntime {
|
||||
setup state;
|
||||
|
||||
int fetch_ini_param(const char *nameBuf, int *status, double *value) {
|
||||
*status = 0;
|
||||
const int n = static_cast<int>(strlen(nameBuf));
|
||||
if (n < 8) {
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
std::string sect = nameBuf + 5;
|
||||
for (auto &c : sect) {
|
||||
c = static_cast<char>(toupper(c));
|
||||
}
|
||||
const size_t i = sect.find(']');
|
||||
if (i == std::string::npos) {
|
||||
return INTERP_ERROR;
|
||||
}
|
||||
std::string var = sect.substr(i + 1);
|
||||
sect.erase(i);
|
||||
|
||||
const char *iniFileName = getenv("INI_FILE_NAME");
|
||||
if (!iniFileName) {
|
||||
return INTERP_OK;
|
||||
}
|
||||
linuxcnc::IniFile inifile(iniFileName);
|
||||
if (!inifile) {
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
if (auto inival = inifile.findReal(var, sect)) {
|
||||
*value = *inival;
|
||||
*status = 1;
|
||||
}
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
int lookup_named_param(const char *nameBuf, double index, double *value) {
|
||||
const int cmd = round_to_int(index);
|
||||
switch (cmd) {
|
||||
case NP_LINE:
|
||||
*value = state.sequence_number;
|
||||
break;
|
||||
case NP_MOTION_MODE:
|
||||
*value = state.motion_mode;
|
||||
break;
|
||||
case NP_METRIC:
|
||||
*value = (state.length_units == CANON_UNITS_MM);
|
||||
break;
|
||||
case NP_IMPERIAL:
|
||||
*value = (state.length_units == CANON_UNITS_INCHES);
|
||||
break;
|
||||
case NP_ABSOLUTE:
|
||||
*value = (state.distance_mode == DISTANCE_MODE::ABSOLUTE);
|
||||
break;
|
||||
case NP_INCREMENTAL:
|
||||
*value = (state.distance_mode == DISTANCE_MODE::INCREMENTAL);
|
||||
break;
|
||||
case NP_FEED:
|
||||
*value = state.feed_rate;
|
||||
break;
|
||||
case NP_RPM:
|
||||
*value = state.speed[0];
|
||||
break;
|
||||
case NP_X:
|
||||
*value = state.current_x;
|
||||
break;
|
||||
case NP_Y:
|
||||
*value = state.current_y;
|
||||
break;
|
||||
case NP_Z:
|
||||
*value = state.current_z;
|
||||
break;
|
||||
case NP_CURRENT_TOOL:
|
||||
*value = state.parameters[interp_param_global::TOOL_NUMBER];
|
||||
break;
|
||||
case NP_CALL_LEVEL:
|
||||
*value = state.call_level;
|
||||
break;
|
||||
default:
|
||||
return INTERP_ERROR;
|
||||
}
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
int find_named_param(const char *nameBuf, int *status, double *value) {
|
||||
const int level = (nameBuf[0] == '_') ? 0 : state.call_level;
|
||||
context_pointer frame = &state.sub_context[level];
|
||||
*status = 0;
|
||||
|
||||
auto pi = frame->named_params.find(nameBuf);
|
||||
if (pi == frame->named_params.end()) {
|
||||
int exists = 0;
|
||||
double inivalue = 0.0;
|
||||
if ((state.feature_set & FEATURE_INI_VARS) && (strncasecmp(nameBuf, "_ini[", 5) == 0)) {
|
||||
fetch_ini_param(nameBuf, &exists, &inivalue);
|
||||
if (exists) {
|
||||
*value = inivalue;
|
||||
*status = 1;
|
||||
parameter_value param;
|
||||
param.value = inivalue;
|
||||
param.attr = PA_GLOBAL | PA_READONLY | PA_FROM_INI;
|
||||
state.sub_context[0].named_params[strstore(nameBuf)] = param;
|
||||
return INTERP_OK;
|
||||
}
|
||||
}
|
||||
*value = 0.0;
|
||||
*status = 0;
|
||||
} else {
|
||||
parameter_pointer pv = &pi->second;
|
||||
if (pv->attr & PA_USE_LOOKUP) {
|
||||
if (lookup_named_param(nameBuf, pv->value, value) != INTERP_OK) {
|
||||
return INTERP_ERROR;
|
||||
}
|
||||
*status = 1;
|
||||
} else {
|
||||
*value = pv->value;
|
||||
*status = 1;
|
||||
}
|
||||
}
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
int store_named_param(const char *nameBuf, double value, bool override_readonly) {
|
||||
const int level = (nameBuf[0] == '_') ? 0 : state.call_level;
|
||||
context_pointer frame = &state.sub_context[level];
|
||||
auto pi = frame->named_params.find(nameBuf);
|
||||
if (pi == frame->named_params.end()) {
|
||||
return INTERP_ERROR;
|
||||
}
|
||||
parameter_pointer pv = &pi->second;
|
||||
if ((pv->attr & PA_READONLY) && !override_readonly) {
|
||||
return INTERP_ERROR;
|
||||
}
|
||||
pv->value = value;
|
||||
pv->attr &= ~PA_UNSET;
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
int add_named_param(const char *nameBuf, int attr) {
|
||||
int findStatus = 0;
|
||||
double value = 0.0;
|
||||
find_named_param(nameBuf, &findStatus, &value);
|
||||
if (findStatus) {
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
int level = 0;
|
||||
if (nameBuf[0] != '_') {
|
||||
level = state.call_level;
|
||||
} else {
|
||||
level = 0;
|
||||
attr |= PA_GLOBAL;
|
||||
}
|
||||
attr |= PA_UNSET;
|
||||
|
||||
parameter_value param;
|
||||
param.value = 0.0;
|
||||
param.attr = attr;
|
||||
state.sub_context[level].named_params[strstore(nameBuf)] = param;
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
int init_readonly_param(const char *nameBuf, double value, int attr) {
|
||||
if (add_named_param(nameBuf, PA_READONLY | attr) != INTERP_OK) {
|
||||
return INTERP_ERROR;
|
||||
}
|
||||
if (store_named_param(nameBuf, value, true) != INTERP_OK) {
|
||||
return INTERP_ERROR;
|
||||
}
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
double inicheck() {
|
||||
const char *filename = getenv("INI_FILE_NAME");
|
||||
if (!filename) {
|
||||
return -1.0;
|
||||
}
|
||||
linuxcnc::IniFile inifile(filename);
|
||||
if (!inifile) {
|
||||
return -1.0;
|
||||
}
|
||||
if (auto inistring = inifile.findString("LINEAR_UNITS", "TRAJ")) {
|
||||
if ((strcasecmp("mm", inistring->c_str()) == 0) ||
|
||||
(strcasecmp("metric", inistring->c_str()) == 0)) {
|
||||
return 1.0;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
int init_named_parameters() {
|
||||
const char *pkgversion = PACKAGE_VERSION;
|
||||
const char *version_major = "_vmajor";
|
||||
const char *version_minor = "_vminor";
|
||||
const char *metric_machine = "_metric_machine";
|
||||
double vmajor = 0.0;
|
||||
double vminor = 0.0;
|
||||
double munits = 1.0;
|
||||
sscanf(pkgversion, "%lf%lf", &vmajor, &vminor);
|
||||
|
||||
if (init_readonly_param(version_major, vmajor, 0) != INTERP_OK) return INTERP_ERROR;
|
||||
if (init_readonly_param(version_minor, vminor, 0) != INTERP_OK) return INTERP_ERROR;
|
||||
|
||||
munits = inicheck();
|
||||
if (init_readonly_param(metric_machine, munits, 0) != INTERP_OK) return INTERP_ERROR;
|
||||
|
||||
if (init_readonly_param("_line", NP_LINE, PA_USE_LOOKUP) != INTERP_OK) return INTERP_ERROR;
|
||||
if (init_readonly_param("_motion_mode", NP_MOTION_MODE, PA_USE_LOOKUP) != INTERP_OK) return INTERP_ERROR;
|
||||
if (init_readonly_param("_metric", NP_METRIC, PA_USE_LOOKUP) != INTERP_OK) return INTERP_ERROR;
|
||||
if (init_readonly_param("_imperial", NP_IMPERIAL, PA_USE_LOOKUP) != INTERP_OK) return INTERP_ERROR;
|
||||
if (init_readonly_param("_absolute", NP_ABSOLUTE, PA_USE_LOOKUP) != INTERP_OK) return INTERP_ERROR;
|
||||
if (init_readonly_param("_incremental", NP_INCREMENTAL, PA_USE_LOOKUP) != INTERP_OK) return INTERP_ERROR;
|
||||
if (init_readonly_param("_feed", NP_FEED, PA_USE_LOOKUP) != INTERP_OK) return INTERP_ERROR;
|
||||
if (init_readonly_param("_rpm", NP_RPM, PA_USE_LOOKUP) != INTERP_OK) return INTERP_ERROR;
|
||||
if (init_readonly_param("_x", NP_X, PA_USE_LOOKUP) != INTERP_OK) return INTERP_ERROR;
|
||||
if (init_readonly_param("_y", NP_Y, PA_USE_LOOKUP) != INTERP_OK) return INTERP_ERROR;
|
||||
if (init_readonly_param("_z", NP_Z, PA_USE_LOOKUP) != INTERP_OK) return INTERP_ERROR;
|
||||
if (init_readonly_param("_current_tool", NP_CURRENT_TOOL, PA_USE_LOOKUP) != INTERP_OK) return INTERP_ERROR;
|
||||
if (init_readonly_param("_call_level", NP_CALL_LEVEL, PA_USE_LOOKUP) != INTERP_OK) return INTERP_ERROR;
|
||||
|
||||
return INTERP_OK;
|
||||
}
|
||||
};
|
||||
|
||||
void print_named_value(NamedParamRuntime &runtime, const char *name) {
|
||||
int status = 0;
|
||||
double value = 0.0;
|
||||
const int rc = runtime.find_named_param(name, &status, &value);
|
||||
std::cout << name << ": rc=" << rc << " found=" << status << " value=" << value << "\n";
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc == 2) {
|
||||
setenv("INI_FILE_NAME", argv[1], 1);
|
||||
}
|
||||
|
||||
NamedParamRuntime runtime;
|
||||
runtime.state.feature_set = FEATURE_INI_VARS;
|
||||
runtime.state.length_units = CANON_UNITS_MM;
|
||||
runtime.state.distance_mode = DISTANCE_MODE::ABSOLUTE;
|
||||
runtime.state.motion_mode = G_1;
|
||||
runtime.state.feed_rate = 123.45;
|
||||
runtime.state.speed[0] = 678.9;
|
||||
runtime.state.current_x = 1.25;
|
||||
runtime.state.current_y = 2.5;
|
||||
runtime.state.current_z = 3.75;
|
||||
runtime.state.parameters[interp_param_global::TOOL_NUMBER] = 12.0;
|
||||
|
||||
const int rc = runtime.init_named_parameters();
|
||||
std::cout << "init_named_parameters=" << rc << "\n";
|
||||
std::cout << "global_named_count=" << runtime.state.sub_context[0].named_params.size() << "\n";
|
||||
std::cout << "required_parameter_first=" << interp_param_global::G28_X << "\n";
|
||||
std::cout << "readonly_tool_number_index=" << interp_param_global::TOOL_NUMBER << "\n";
|
||||
|
||||
print_named_value(runtime, "_vmajor");
|
||||
print_named_value(runtime, "_vminor");
|
||||
print_named_value(runtime, "_metric_machine");
|
||||
print_named_value(runtime, "_motion_mode");
|
||||
print_named_value(runtime, "_metric");
|
||||
print_named_value(runtime, "_feed");
|
||||
print_named_value(runtime, "_rpm");
|
||||
print_named_value(runtime, "_x");
|
||||
print_named_value(runtime, "_current_tool");
|
||||
print_named_value(runtime, "_ini[traj]max_linear_velocity");
|
||||
|
||||
return rc == INTERP_OK ? 0 : 1;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
#include "emc/rs274ngc/rs274ngc_interp.hh"
|
||||
|
||||
int main() {
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "emc/rs274ngc/interp_internal.hh"
|
||||
|
||||
struct pycontext_impl {};
|
||||
|
||||
pycontext::pycontext() : impl(new pycontext_impl) {}
|
||||
pycontext::~pycontext() { delete impl; }
|
||||
pycontext::pycontext(const pycontext &other) : impl(new pycontext_impl(*other.impl)) {}
|
||||
pycontext &pycontext::operator=(const pycontext &other) {
|
||||
if (this == &other) {
|
||||
return *this;
|
||||
}
|
||||
delete impl;
|
||||
impl = new pycontext_impl(*other.impl);
|
||||
return *this;
|
||||
}
|
||||
|
||||
const char *strstore(const char *s)
|
||||
{
|
||||
static std::unordered_set<std::string> stringtable;
|
||||
|
||||
if (s == nullptr) {
|
||||
throw std::invalid_argument("strstore(): NULL argument");
|
||||
}
|
||||
auto pair = stringtable.insert(s);
|
||||
return pair.first->c_str();
|
||||
}
|
||||
|
||||
context_struct::context_struct()
|
||||
: position(0), sequence_number(0), filename(""), subName(""),
|
||||
m98_loop_counter(-1), context_status(0), call_type(0)
|
||||
{
|
||||
memset(saved_params, 0, sizeof(saved_params));
|
||||
memset(saved_g_codes, 0, sizeof(saved_g_codes));
|
||||
memset(saved_m_codes, 0, sizeof(saved_m_codes));
|
||||
memset(saved_settings, 0, sizeof(saved_settings));
|
||||
}
|
||||
|
||||
void context_struct::clear()
|
||||
{
|
||||
new (this) context_struct();
|
||||
}
|
||||
|
||||
setup::setup()
|
||||
: AA_axis_offset(0.0),
|
||||
AA_current(0.0),
|
||||
AA_origin_offset(0.0),
|
||||
BB_axis_offset(0.0),
|
||||
BB_current(0.0),
|
||||
BB_origin_offset(0.0),
|
||||
CC_axis_offset(0.0),
|
||||
CC_current(0.0),
|
||||
CC_origin_offset(0.0),
|
||||
u_axis_offset(0.0),
|
||||
u_current(0.0),
|
||||
u_origin_offset(0.0),
|
||||
v_axis_offset(0.0),
|
||||
v_current(0.0),
|
||||
v_origin_offset(0.0),
|
||||
w_axis_offset(0.0),
|
||||
w_current(0.0),
|
||||
w_origin_offset(0.0),
|
||||
active_g_codes{},
|
||||
active_m_codes{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
active_settings{},
|
||||
arc_not_allowed(0),
|
||||
axis_offset_x(0.0),
|
||||
axis_offset_y(0.0),
|
||||
axis_offset_z(0.0),
|
||||
blocks{},
|
||||
remap_level(0),
|
||||
blocktext{},
|
||||
control_mode(CANON_EXACT_STOP),
|
||||
tolerance(0.0),
|
||||
naivecam_tolerance(0.0),
|
||||
tolerance_default(0.0),
|
||||
naivecam_tolerance_default(0.0),
|
||||
current_pocket(0),
|
||||
current_x(0.0),
|
||||
current_y(0.0),
|
||||
current_z(0.0),
|
||||
cutter_comp_radius(0.0),
|
||||
cutter_comp_orientation(0),
|
||||
cutter_comp_side(CUTTER_COMP::OFF),
|
||||
cycle_cc(0.0),
|
||||
cycle_i(0.0),
|
||||
cycle_j(0.0),
|
||||
cycle_k(0.0),
|
||||
cycle_l(0),
|
||||
cycle_p(0.0),
|
||||
cycle_q(0.0),
|
||||
cycle_r(0.0),
|
||||
cycle_il(0.0),
|
||||
cycle_il_flag(0),
|
||||
distance_mode(DISTANCE_MODE::ABSOLUTE),
|
||||
ijk_distance_mode(DISTANCE_MODE::ABSOLUTE),
|
||||
feed_mode(FEED_MODE::UNITS_PER_MINUTE),
|
||||
feed_override(0),
|
||||
feed_rate(0.0),
|
||||
filename{},
|
||||
file_pointer(nullptr),
|
||||
flood(0),
|
||||
length_units(CANON_UNITS_INCHES),
|
||||
center_arc_radius_tolerance_inch(CENTER_ARC_RADIUS_TOLERANCE_INCH),
|
||||
center_arc_radius_tolerance_mm(CENTER_ARC_RADIUS_TOLERANCE_MM),
|
||||
line_length(0),
|
||||
linetext{},
|
||||
mist(0),
|
||||
motion_mode(0),
|
||||
origin_index(0),
|
||||
origin_offset_x(0.0),
|
||||
origin_offset_y(0.0),
|
||||
origin_offset_z(0.0),
|
||||
rotation_xy(0.0),
|
||||
parameters{0},
|
||||
parameter_occurrence(0),
|
||||
parameter_numbers{0},
|
||||
parameter_values{0},
|
||||
named_parameter_occurrence(0),
|
||||
named_parameters{nullptr},
|
||||
named_parameter_values{0},
|
||||
percent_flag(0),
|
||||
plane(CANON_PLANE::XY),
|
||||
probe_flag(0),
|
||||
input_flag(0),
|
||||
toolchange_flag(0),
|
||||
input_index(0),
|
||||
input_digital(0),
|
||||
cutter_comp_firstmove(0),
|
||||
program_x(0.0),
|
||||
program_y(0.0),
|
||||
program_z(0.0),
|
||||
retract_mode(RETRACT_MODE::R_PLANE),
|
||||
random_toolchanger(0),
|
||||
selected_pocket(0),
|
||||
selected_tool(0),
|
||||
sequence_number(0),
|
||||
num_spindles(0),
|
||||
active_spindle(0),
|
||||
speed{0.0},
|
||||
spindle_mode{SPINDLE_MODE::CONSTANT_RPM},
|
||||
speed_feed_mode{CANON_INDEPENDENT},
|
||||
speed_override{false},
|
||||
spindle_turning{CANON_STOPPED},
|
||||
stack{},
|
||||
stack_index(0),
|
||||
tool_offset{{0,0,0},0,0,0,0,0,0},
|
||||
tool_table{},
|
||||
traverse_rate(0.0),
|
||||
orient_offset(0.0),
|
||||
g43_with_zero_offset(false),
|
||||
defining_sub(0),
|
||||
sub_name(nullptr),
|
||||
doing_continue(0),
|
||||
doing_break(0),
|
||||
executed_if(0),
|
||||
skipping_o(nullptr),
|
||||
skipping_to_sub(nullptr),
|
||||
skipping_start(0),
|
||||
test_value(0.0),
|
||||
return_value(0.0),
|
||||
value_returned(0),
|
||||
call_level(0),
|
||||
sub_context{},
|
||||
call_state(0),
|
||||
adaptive_feed(0),
|
||||
feed_hold(0),
|
||||
loggingLevel(0),
|
||||
debugmask(0),
|
||||
log_file{},
|
||||
program_prefix{},
|
||||
subroutines{},
|
||||
use_lazy_close(0),
|
||||
lazy_closing(0),
|
||||
wizard_root{},
|
||||
tool_change_at_g30(0),
|
||||
tool_change_quill_up(0),
|
||||
tool_change_with_spindle_on(0),
|
||||
parameter_g73_peck_clearance(0.0),
|
||||
parameter_g83_peck_clearance(0.0),
|
||||
a_axis_wrapped(0),
|
||||
b_axis_wrapped(0),
|
||||
c_axis_wrapped(0),
|
||||
a_indexer_jnum(0),
|
||||
b_indexer_jnum(0),
|
||||
c_indexer_jnum(0),
|
||||
lathe_diameter_mode(0),
|
||||
mdi_interrupt(0),
|
||||
feature_set(0),
|
||||
disable_fanuc_style_sub(false),
|
||||
loop_on_main_m99(false),
|
||||
disable_g92_persistence(0),
|
||||
pythis(nullptr),
|
||||
on_abort_command(nullptr),
|
||||
init_once(CANON_STOPPED)
|
||||
{
|
||||
std::fill(parameters, parameters + interp_param_global::RS274NGC_MAX_PARAMETERS, 0);
|
||||
}
|
||||
|
||||
setup::~setup() {
|
||||
if (pythis) {
|
||||
delete pythis;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
#pragma once
|
||||
@@ -0,0 +1 @@
|
||||
#pragma once
|
||||
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
struct _object;
|
||||
typedef _object PyObject;
|
||||
9
wasm-port/runtime/core/shims/boost/python/object_fwd.hpp
Normal file
9
wasm-port/runtime/core/shims/boost/python/object_fwd.hpp
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
namespace boost {
|
||||
namespace python {
|
||||
|
||||
class object {};
|
||||
|
||||
} // namespace python
|
||||
} // namespace boost
|
||||
3
wasm-port/runtime/core/shims/config.h
Normal file
3
wasm-port/runtime/core/shims/config.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#define PACKAGE_VERSION "2.10.0~pre1"
|
||||
7
wasm-port/runtime/core/shims/fmt/format.h
Normal file
7
wasm-port/runtime/core/shims/fmt/format.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <format>
|
||||
|
||||
namespace fmt {
|
||||
using std::format;
|
||||
}
|
||||
18
wasm-port/runtime/core/shims/nml_intf/emc.hh
Normal file
18
wasm-port/runtime/core/shims/nml_intf/emc.hh
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
// Minimal shim for standalone interpreter source probes.
|
||||
enum EmcJointType : int {
|
||||
EMC_LINEAR = 1,
|
||||
EMC_ANGULAR = 2,
|
||||
};
|
||||
|
||||
class EMC_STAT {
|
||||
public:
|
||||
struct Motion {
|
||||
struct Traj {
|
||||
double linearUnits = 1.0;
|
||||
} traj;
|
||||
} motion;
|
||||
};
|
||||
|
||||
extern EMC_STAT *emcStatus;
|
||||
13
wasm-port/runtime/core/shims/pythonplugin/python_plugin.hh
Normal file
13
wasm-port/runtime/core/shims/pythonplugin/python_plugin.hh
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
class PythonPlugin {
|
||||
public:
|
||||
bool usable() const { return false; }
|
||||
int plugin_status() const { return 0; }
|
||||
const std::string &last_exception() const {
|
||||
static std::string empty;
|
||||
return empty;
|
||||
}
|
||||
};
|
||||
67
wasm-port/runtime/core/shims/rtapi.h
Normal file
67
wasm-port/runtime/core/shims/rtapi.h
Normal file
@@ -0,0 +1,67 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <cstddef>
|
||||
|
||||
#ifndef RTAPI_BEGIN_DECLS
|
||||
#ifdef __cplusplus
|
||||
#define RTAPI_BEGIN_DECLS extern "C" {
|
||||
#define RTAPI_END_DECLS }
|
||||
#else
|
||||
#define RTAPI_BEGIN_DECLS
|
||||
#define RTAPI_END_DECLS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef RTAPI_NAME_LEN
|
||||
#define RTAPI_NAME_LEN 31
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
RTAPI_MSG_NONE = 0,
|
||||
RTAPI_MSG_ERR,
|
||||
RTAPI_MSG_WARN,
|
||||
RTAPI_MSG_INFO,
|
||||
RTAPI_MSG_DBG,
|
||||
RTAPI_MSG_ALL
|
||||
} msg_level_t;
|
||||
|
||||
RTAPI_BEGIN_DECLS
|
||||
|
||||
static inline int rtapi_snprintf(char *buf, unsigned long size, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
int rc = vsnprintf(buf, static_cast<size_t>(size), fmt, ap);
|
||||
va_end(ap);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline int rtapi_vsnprintf(char *buf, unsigned long size, const char *fmt, va_list ap) {
|
||||
return vsnprintf(buf, static_cast<size_t>(size), fmt, ap);
|
||||
}
|
||||
|
||||
static inline void rtapi_print(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static inline void rtapi_print_msg(msg_level_t, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static inline int rtapi_set_msg_level(int) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int rtapi_get_msg_level(void) {
|
||||
return RTAPI_MSG_ALL;
|
||||
}
|
||||
|
||||
RTAPI_END_DECLS
|
||||
29
wasm-port/runtime/core/shims/tooldata/tooldata.hh
Normal file
29
wasm-port/runtime/core/shims/tooldata/tooldata.hh
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "emc/nml_intf/emctool.h"
|
||||
|
||||
enum {
|
||||
IDX_OK = 0,
|
||||
};
|
||||
|
||||
inline CANON_TOOL_TABLE tooldata_entry_init()
|
||||
{
|
||||
CANON_TOOL_TABLE tool{};
|
||||
tool.toolno = 0;
|
||||
tool.pocketno = 0;
|
||||
return tool;
|
||||
}
|
||||
|
||||
inline int tooldata_find_index_for_tool(int toolno)
|
||||
{
|
||||
return toolno == 0 ? 0 : -1;
|
||||
}
|
||||
|
||||
inline int tooldata_get(CANON_TOOL_TABLE *tool, int index)
|
||||
{
|
||||
if ((tool == nullptr) || (index != 0)) {
|
||||
return -1;
|
||||
}
|
||||
*tool = tooldata_entry_init();
|
||||
return IDX_OK;
|
||||
}
|
||||
206
wasm-port/runtime/ui/ini-panel/app.js
Normal file
206
wasm-port/runtime/ui/ini-panel/app.js
Normal file
@@ -0,0 +1,206 @@
|
||||
import createLinuxCncIniModule from "./linuxcnc_ini.js";
|
||||
|
||||
const SAMPLE_PATH =
|
||||
"../../../linuxcnc/configs/sim/axis/vismach/5axis/table-dual-rotary/xyzab-tdr.ini";
|
||||
const OPFS_FILE = "linuxcnc/xyzab-tdr.ini";
|
||||
const WASM_FILE = "/work/xyzab-tdr.ini";
|
||||
|
||||
const editor = document.getElementById("ini-editor");
|
||||
const logNode = document.getElementById("log");
|
||||
const wasmBadge = document.getElementById("wasm-badge");
|
||||
const opfsBadge = document.getElementById("opfs-badge");
|
||||
|
||||
const fields = {
|
||||
machine: document.getElementById("field-machine"),
|
||||
display: document.getElementById("field-display"),
|
||||
kinematics: document.getElementById("field-kinematics"),
|
||||
joints: document.getElementById("field-joints"),
|
||||
coordinates: document.getElementById("field-coordinates"),
|
||||
parameterFile: document.getElementById("field-parameter-file"),
|
||||
};
|
||||
|
||||
let moduleInstance = null;
|
||||
|
||||
function setBadge(node, text, className = "badge") {
|
||||
node.className = className;
|
||||
node.textContent = text;
|
||||
}
|
||||
|
||||
function setLog(message, isError = false) {
|
||||
logNode.textContent = message;
|
||||
logNode.className = `log${isError ? " danger" : ""}`;
|
||||
}
|
||||
|
||||
function setField(name, value) {
|
||||
fields[name].textContent = value ?? "-";
|
||||
}
|
||||
|
||||
function requireModule() {
|
||||
if (!moduleInstance) {
|
||||
throw new Error("WASM module is not ready yet.");
|
||||
}
|
||||
return moduleInstance;
|
||||
}
|
||||
|
||||
function allocCString(mod, value) {
|
||||
const bytes = mod.lengthBytesUTF8(value) + 1;
|
||||
const ptr = mod._malloc(bytes);
|
||||
mod.stringToUTF8(value, ptr, bytes);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
function iniQuery(mod, wasmPath, section, tag) {
|
||||
const pathPtr = allocCString(mod, wasmPath);
|
||||
const sectionPtr = allocCString(mod, section);
|
||||
const tagPtr = allocCString(mod, tag);
|
||||
const outSize = 2048;
|
||||
const outPtr = mod._malloc(outSize);
|
||||
|
||||
try {
|
||||
const rc = mod._lcini_get_string(pathPtr, sectionPtr, tagPtr, outPtr, outSize);
|
||||
if (rc !== 0) {
|
||||
return null;
|
||||
}
|
||||
return mod.UTF8ToString(outPtr);
|
||||
} finally {
|
||||
mod._free(pathPtr);
|
||||
mod._free(sectionPtr);
|
||||
mod._free(tagPtr);
|
||||
mod._free(outPtr);
|
||||
}
|
||||
}
|
||||
|
||||
async function getOpfsRoot() {
|
||||
if (!navigator.storage?.getDirectory) {
|
||||
throw new Error("OPFS is not available in this browser.");
|
||||
}
|
||||
return navigator.storage.getDirectory();
|
||||
}
|
||||
|
||||
async function ensureParentDir(root, path) {
|
||||
const parts = path.split("/");
|
||||
let current = root;
|
||||
for (const part of parts.slice(0, -1)) {
|
||||
current = await current.getDirectoryHandle(part, { create: true });
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
async function saveToOpfs(path, text) {
|
||||
const root = await getOpfsRoot();
|
||||
const dir = await ensureParentDir(root, path);
|
||||
const filename = path.split("/").at(-1);
|
||||
const fileHandle = await dir.getFileHandle(filename, { create: true });
|
||||
const writable = await fileHandle.createWritable();
|
||||
await writable.write(text);
|
||||
await writable.close();
|
||||
}
|
||||
|
||||
async function loadFromOpfs(path) {
|
||||
const root = await getOpfsRoot();
|
||||
const parts = path.split("/");
|
||||
let current = root;
|
||||
for (const part of parts.slice(0, -1)) {
|
||||
current = await current.getDirectoryHandle(part);
|
||||
}
|
||||
const fileHandle = await current.getFileHandle(parts.at(-1));
|
||||
const file = await fileHandle.getFile();
|
||||
return file.text();
|
||||
}
|
||||
|
||||
function syncEditorToWasmFs() {
|
||||
const mod = requireModule();
|
||||
try {
|
||||
mod.FS.mkdir("/work");
|
||||
} catch {
|
||||
// already exists
|
||||
}
|
||||
mod.FS.writeFile(WASM_FILE, editor.value, { encoding: "utf8" });
|
||||
}
|
||||
|
||||
async function loadSample() {
|
||||
setLog(`Fetching ${SAMPLE_PATH}`);
|
||||
const response = await fetch(SAMPLE_PATH);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Cannot fetch sample INI (${response.status})`);
|
||||
}
|
||||
editor.value = await response.text();
|
||||
setLog("Loaded LinuxCNC sample INI into the standalone editor.");
|
||||
}
|
||||
|
||||
async function boot() {
|
||||
try {
|
||||
moduleInstance = await createLinuxCncIniModule();
|
||||
setBadge(wasmBadge, "WASM: ready");
|
||||
} catch (error) {
|
||||
setBadge(wasmBadge, "WASM: failed", "badge danger");
|
||||
setLog(`WASM init failed: ${error.message}`, true);
|
||||
throw error;
|
||||
}
|
||||
|
||||
try {
|
||||
await getOpfsRoot();
|
||||
setBadge(opfsBadge, "OPFS: ready");
|
||||
} catch (error) {
|
||||
setBadge(opfsBadge, "OPFS: unavailable", "badge danger");
|
||||
setLog(`OPFS check failed: ${error.message}`, true);
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById("load-sample").addEventListener("click", async () => {
|
||||
try {
|
||||
await loadSample();
|
||||
} catch (error) {
|
||||
setLog(error.message, true);
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById("save-opfs").addEventListener("click", async () => {
|
||||
try {
|
||||
await saveToOpfs(OPFS_FILE, editor.value);
|
||||
setLog(`Saved current INI text to OPFS at ${OPFS_FILE}`);
|
||||
} catch (error) {
|
||||
setLog(`OPFS save failed: ${error.message}`, true);
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById("load-opfs").addEventListener("click", async () => {
|
||||
try {
|
||||
editor.value = await loadFromOpfs(OPFS_FILE);
|
||||
setLog(`Loaded INI text from OPFS path ${OPFS_FILE}`);
|
||||
} catch (error) {
|
||||
setLog(`OPFS load failed: ${error.message}`, true);
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById("sync-wasm").addEventListener("click", () => {
|
||||
try {
|
||||
syncEditorToWasmFs();
|
||||
setLog(`Synced editor contents to WASM filesystem at ${WASM_FILE}`);
|
||||
} catch (error) {
|
||||
setLog(`WASM sync failed: ${error.message}`, true);
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById("query").addEventListener("click", async () => {
|
||||
try {
|
||||
syncEditorToWasmFs();
|
||||
const mod = requireModule();
|
||||
|
||||
setField("machine", iniQuery(mod, WASM_FILE, "EMC", "MACHINE"));
|
||||
setField("display", iniQuery(mod, WASM_FILE, "DISPLAY", "DISPLAY"));
|
||||
setField("kinematics", iniQuery(mod, WASM_FILE, "KINS", "KINEMATICS"));
|
||||
setField("joints", iniQuery(mod, WASM_FILE, "KINS", "JOINTS"));
|
||||
setField("coordinates", iniQuery(mod, WASM_FILE, "TRAJ", "COORDINATES"));
|
||||
setField(
|
||||
"parameterFile",
|
||||
iniQuery(mod, WASM_FILE, "RS274NGC", "PARAMETER_FILE"),
|
||||
);
|
||||
|
||||
setLog("Queried LinuxCNC INI fields through the standalone WASM parser.");
|
||||
} catch (error) {
|
||||
setLog(`Query failed: ${error.message}`, true);
|
||||
}
|
||||
});
|
||||
|
||||
boot().catch(() => {});
|
||||
189
wasm-port/runtime/ui/ini-panel/index.html
Normal file
189
wasm-port/runtime/ui/ini-panel/index.html
Normal file
@@ -0,0 +1,189 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>LinuxCNC WASM INI Panel</title>
|
||||
<style>
|
||||
:root {
|
||||
color-scheme: light;
|
||||
--bg: #eef3f7;
|
||||
--panel: #ffffff;
|
||||
--border: #c9d5df;
|
||||
--text: #182430;
|
||||
--muted: #566676;
|
||||
--accent: #1263a3;
|
||||
--accent-2: #0f8a70;
|
||||
--danger: #b04040;
|
||||
}
|
||||
* { box-sizing: border-box; }
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: "Segoe UI", "Noto Sans", sans-serif;
|
||||
background: linear-gradient(180deg, rgba(18, 99, 163, 0.08), transparent 24rem), var(--bg);
|
||||
color: var(--text);
|
||||
}
|
||||
main {
|
||||
max-width: 1180px;
|
||||
margin: 0 auto;
|
||||
padding: 24px;
|
||||
display: grid;
|
||||
gap: 16px;
|
||||
}
|
||||
.header, .panel {
|
||||
background: var(--panel);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 10px 30px rgba(17, 34, 51, 0.06);
|
||||
}
|
||||
.header { padding: 20px 24px; }
|
||||
h1, h2 { margin: 0; font-weight: 600; }
|
||||
p { margin: 0; color: var(--muted); line-height: 1.5; }
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1.2fr) minmax(320px, 0.8fr);
|
||||
gap: 16px;
|
||||
}
|
||||
.panel {
|
||||
padding: 16px;
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
}
|
||||
.controls {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
button {
|
||||
border: 1px solid var(--border);
|
||||
background: #f6f9fb;
|
||||
color: var(--text);
|
||||
padding: 10px 14px;
|
||||
border-radius: 6px;
|
||||
font: inherit;
|
||||
cursor: pointer;
|
||||
}
|
||||
button.primary {
|
||||
background: var(--accent);
|
||||
border-color: var(--accent);
|
||||
color: #fff;
|
||||
}
|
||||
button.secondary {
|
||||
background: var(--accent-2);
|
||||
border-color: var(--accent-2);
|
||||
color: #fff;
|
||||
}
|
||||
textarea {
|
||||
width: 100%;
|
||||
min-height: 420px;
|
||||
resize: vertical;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
padding: 12px;
|
||||
font: 13px/1.5 "SFMono-Regular", "Consolas", monospace;
|
||||
color: var(--text);
|
||||
background: #fbfdff;
|
||||
}
|
||||
.status { display: grid; gap: 8px; }
|
||||
.badge {
|
||||
display: inline-block;
|
||||
padding: 4px 8px;
|
||||
border-radius: 999px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
background: #dbe8f3;
|
||||
color: var(--accent);
|
||||
}
|
||||
.kv {
|
||||
display: grid;
|
||||
grid-template-columns: 132px 1fr;
|
||||
gap: 8px 12px;
|
||||
align-items: start;
|
||||
border-top: 1px solid #edf2f6;
|
||||
padding-top: 12px;
|
||||
}
|
||||
.kv dt {
|
||||
color: var(--muted);
|
||||
font-size: 12px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
.kv dd {
|
||||
margin: 0;
|
||||
font-family: "SFMono-Regular", "Consolas", monospace;
|
||||
font-size: 13px;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
.log {
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
background: #fbfdff;
|
||||
padding: 12px;
|
||||
min-height: 120px;
|
||||
font: 13px/1.5 "SFMono-Regular", "Consolas", monospace;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
.danger { color: var(--danger); }
|
||||
@media (max-width: 960px) {
|
||||
.grid { grid-template-columns: 1fr; }
|
||||
textarea { min-height: 320px; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<section class="header">
|
||||
<h1>LinuxCNC WASM INI Panel</h1>
|
||||
<p>
|
||||
This standalone panel uses LinuxCNC's native <code>IniFile</code> parser
|
||||
compiled to WASM. It is managed under <code>wasm-port/</code> and reads
|
||||
upstream LinuxCNC-style machine configs through the browser host.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="grid">
|
||||
<section class="panel">
|
||||
<h2>Configuration File</h2>
|
||||
<div class="controls">
|
||||
<button id="load-sample" class="primary">Load LinuxCNC Sample</button>
|
||||
<button id="save-opfs">Save To OPFS</button>
|
||||
<button id="load-opfs">Load From OPFS</button>
|
||||
<button id="sync-wasm">Sync To WASM FS</button>
|
||||
<button id="query" class="secondary">Query LinuxCNC Fields</button>
|
||||
</div>
|
||||
<textarea id="ini-editor" spellcheck="false"></textarea>
|
||||
</section>
|
||||
|
||||
<section class="panel">
|
||||
<h2>Control Panel</h2>
|
||||
<div class="status">
|
||||
<div><span id="wasm-badge" class="badge">WASM: loading</span></div>
|
||||
<div><span id="opfs-badge" class="badge">OPFS: checking</span></div>
|
||||
</div>
|
||||
|
||||
<dl class="kv">
|
||||
<dt>Machine</dt>
|
||||
<dd id="field-machine">-</dd>
|
||||
<dt>Display</dt>
|
||||
<dd id="field-display">-</dd>
|
||||
<dt>Kinematics</dt>
|
||||
<dd id="field-kinematics">-</dd>
|
||||
<dt>Joints</dt>
|
||||
<dd id="field-joints">-</dd>
|
||||
<dt>Coordinates</dt>
|
||||
<dd id="field-coordinates">-</dd>
|
||||
<dt>Parameter File</dt>
|
||||
<dd id="field-parameter-file">-</dd>
|
||||
<dt>OPFS Path</dt>
|
||||
<dd id="field-opfs-path">linuxcnc/xyzab-tdr.ini</dd>
|
||||
<dt>WASM Path</dt>
|
||||
<dd id="field-wasm-path">/work/xyzab-tdr.ini</dd>
|
||||
</dl>
|
||||
|
||||
<div class="log" id="log"></div>
|
||||
</section>
|
||||
</section>
|
||||
</main>
|
||||
<script type="module" src="./app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
16
wasm-port/runtime/ui/ini-panel/linuxcnc_ini.js
Normal file
16
wasm-port/runtime/ui/ini-panel/linuxcnc_ini.js
Normal file
File diff suppressed because one or more lines are too long
BIN
wasm-port/runtime/ui/ini-panel/linuxcnc_ini.wasm
Executable file
BIN
wasm-port/runtime/ui/ini-panel/linuxcnc_ini.wasm
Executable file
Binary file not shown.
4
wasm-port/tests/fixtures/canon/minimal_linear.events
vendored
Normal file
4
wasm-port/tests/fixtures/canon/minimal_linear.events
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
canon_event=COMMENT: Comment
|
||||
canon_event=STRAIGHT_TRAVERSE line=1 x=1 y=2 z=0 a=0 b=0 c=0 u=0 v=0 w=0
|
||||
canon_event=SET_FEED_RATE rate=120
|
||||
canon_event=STRAIGHT_FEED line=2 x=3 y=4 z=0 a=0 b=0 c=0 u=0 v=0 w=0
|
||||
5
wasm-port/tests/fixtures/canon/modal_incremental.events
vendored
Normal file
5
wasm-port/tests/fixtures/canon/modal_incremental.events
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
canon_event=STRAIGHT_TRAVERSE line=1 x=1 y=1 z=0 a=0 b=0 c=0 u=0 v=0 w=0
|
||||
canon_event=SET_FEED_RATE rate=60
|
||||
canon_event=STRAIGHT_FEED line=2 x=3 y=1 z=0 a=0 b=0 c=0 u=0 v=0 w=0
|
||||
canon_event=STRAIGHT_FEED line=3 x=3 y=4 z=0 a=0 b=0 c=0 u=0 v=0 w=0
|
||||
canon_event=STRAIGHT_TRAVERSE line=4 x=0 y=0 z=0 a=0 b=0 c=0 u=0 v=0 w=0
|
||||
10
wasm-port/tests/fixtures/canon/position_params.events
vendored
Normal file
10
wasm-port/tests/fixtures/canon/position_params.events
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
canon_event=STRAIGHT_TRAVERSE line=1 x=1 y=2 z=3 a=0 b=0 c=0 u=0 v=0 w=0
|
||||
canon_event=SET_FEED_RATE rate=80
|
||||
canon_event=COMMENT: interpreter: distance mode changed to incremental
|
||||
canon_event=STRAIGHT_FEED line=2 x=1.5 y=1 z=5 a=0 b=0 c=0 u=0 v=0 w=0
|
||||
setup.current_x=1.5
|
||||
setup.current_y=1
|
||||
setup.current_z=5
|
||||
setup.parameter_5420=1
|
||||
setup.parameter_5421=2
|
||||
setup.parameter_5422=3
|
||||
9
wasm-port/tests/fixtures/canon_errors/g1_zero_feed.expected
vendored
Normal file
9
wasm-port/tests/fixtures/canon_errors/g1_zero_feed.expected
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
execute_line_1=5
|
||||
error_text=Cannot do g1 with zero feed rate
|
||||
setup.current_x=0
|
||||
setup.current_y=0
|
||||
setup.current_z=0
|
||||
setup.parameter_5420=0
|
||||
setup.parameter_5421=0
|
||||
setup.parameter_5422=0
|
||||
absent=canon_event=STRAIGHT_FEED
|
||||
2
wasm-port/tests/fixtures/gcode/minimal_linear.ngc
vendored
Normal file
2
wasm-port/tests/fixtures/gcode/minimal_linear.ngc
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
G0 X1.0 Y2.0 (Comment)
|
||||
G1 X3.0 Y4.0 F120.0
|
||||
4
wasm-port/tests/fixtures/gcode/modal_incremental.ngc
vendored
Normal file
4
wasm-port/tests/fixtures/gcode/modal_incremental.ngc
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
G90 G0 X1.0 Y1.0
|
||||
G91 G1 X2.0 F60.0
|
||||
G1 Y3.0
|
||||
G90 G0 X0.0 Y0.0
|
||||
2
wasm-port/tests/fixtures/gcode/position_params.ngc
vendored
Normal file
2
wasm-port/tests/fixtures/gcode/position_params.ngc
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
G90 G0 X1.0 Y2.0 Z3.0
|
||||
G91 G1 X0.5 Y-1.0 Z2.0 F80.0
|
||||
1
wasm-port/tests/fixtures/gcode_errors/g1_zero_feed.ngc
vendored
Normal file
1
wasm-port/tests/fixtures/gcode_errors/g1_zero_feed.ngc
vendored
Normal file
@@ -0,0 +1 @@
|
||||
G1 X1.0
|
||||
113
wasm-port/tests/native/verify_native_probes.sh
Executable file
113
wasm-port/tests/native/verify_native_probes.sh
Executable file
@@ -0,0 +1,113 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
|
||||
BUILD_DIR="$ROOT_DIR/build/native"
|
||||
GCODE_FIXTURE_DIR="$ROOT_DIR/tests/fixtures/gcode"
|
||||
CANON_FIXTURE_DIR="$ROOT_DIR/tests/fixtures/canon"
|
||||
GCODE_ERROR_FIXTURE_DIR="$ROOT_DIR/tests/fixtures/gcode_errors"
|
||||
CANON_ERROR_FIXTURE_DIR="$ROOT_DIR/tests/fixtures/canon_errors"
|
||||
|
||||
"$ROOT_DIR/tools/build_native_probes.sh"
|
||||
|
||||
check_exitcode() {
|
||||
local name="$1"
|
||||
local file="$BUILD_DIR/$name.exitcode"
|
||||
|
||||
if [[ ! -f "$file" ]]; then
|
||||
echo "missing exitcode: $file" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local rc
|
||||
rc="$(tr -d '[:space:]' < "$file")"
|
||||
if [[ "$rc" != "0" ]]; then
|
||||
echo "$name failed with exit code $rc" >&2
|
||||
if [[ -f "$BUILD_DIR/$name.stderr.log" ]]; then
|
||||
sed -n '1,160p' "$BUILD_DIR/$name.stderr.log" >&2
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_exitcode linuxcnc_interp_state_probe
|
||||
check_exitcode linuxcnc_namedparam_harness
|
||||
check_exitcode linuxcnc_interp_minimal_harness
|
||||
check_exitcode linuxcnc_interp_minimal_harness.run
|
||||
check_exitcode linuxcnc_rs274_compile_probe
|
||||
check_exitcode linuxcnc_interp_convert_source_probe
|
||||
|
||||
check_fixture_output() {
|
||||
local fixture="$1"
|
||||
local expected="$2"
|
||||
local stdout_file="$3"
|
||||
|
||||
grep -Fq "read=0" "$stdout_file"
|
||||
grep -Fq "parse_line=0" "$stdout_file"
|
||||
|
||||
local line_count
|
||||
line_count="$(grep -cv '^[[:space:]]*$' "$fixture")"
|
||||
local line_number
|
||||
for ((line_number = 1; line_number <= line_count; line_number += 1)); do
|
||||
grep -Fq "execute_line_${line_number}=0" "$stdout_file"
|
||||
done
|
||||
|
||||
while IFS= read -r expected_event; do
|
||||
[[ -z "$expected_event" ]] && continue
|
||||
grep -Fq "$expected_event" "$stdout_file"
|
||||
done < "$expected"
|
||||
}
|
||||
|
||||
RUN_STDOUT="$BUILD_DIR/linuxcnc_interp_minimal_harness.run.stdout.log"
|
||||
check_fixture_output \
|
||||
"$GCODE_FIXTURE_DIR/minimal_linear.ngc" \
|
||||
"$CANON_FIXTURE_DIR/minimal_linear.events" \
|
||||
"$RUN_STDOUT"
|
||||
|
||||
for fixture in "$GCODE_FIXTURE_DIR"/*.ngc; do
|
||||
name="$(basename "$fixture" .ngc)"
|
||||
expected="$CANON_FIXTURE_DIR/$name.events"
|
||||
if [[ ! -f "$expected" ]]; then
|
||||
echo "missing expected canon fixture: $expected" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
stdout_file="$BUILD_DIR/linuxcnc_interp_minimal_harness.$name.stdout.log"
|
||||
stderr_file="$BUILD_DIR/linuxcnc_interp_minimal_harness.$name.stderr.log"
|
||||
"$BUILD_DIR/linuxcnc_interp_minimal_harness" "$fixture" \
|
||||
>"$stdout_file" \
|
||||
2>"$stderr_file"
|
||||
check_fixture_output "$fixture" "$expected" "$stdout_file"
|
||||
done
|
||||
|
||||
for fixture in "$GCODE_ERROR_FIXTURE_DIR"/*.ngc; do
|
||||
name="$(basename "$fixture" .ngc)"
|
||||
expected="$CANON_ERROR_FIXTURE_DIR/$name.expected"
|
||||
if [[ ! -f "$expected" ]]; then
|
||||
echo "missing expected error fixture: $expected" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
stdout_file="$BUILD_DIR/linuxcnc_interp_minimal_harness.$name.stdout.log"
|
||||
stderr_file="$BUILD_DIR/linuxcnc_interp_minimal_harness.$name.stderr.log"
|
||||
"$BUILD_DIR/linuxcnc_interp_minimal_harness" "$fixture" \
|
||||
>"$stdout_file" \
|
||||
2>"$stderr_file"
|
||||
|
||||
while IFS= read -r expected_line; do
|
||||
[[ -z "$expected_line" ]] && continue
|
||||
if [[ "$expected_line" == absent=* ]]; then
|
||||
forbidden="${expected_line#absent=}"
|
||||
if grep -Fq "$forbidden" "$stdout_file"; then
|
||||
echo "unexpected output in $stdout_file: $forbidden" >&2
|
||||
exit 1
|
||||
fi
|
||||
elif [[ "$expected_line" == error_text=* ]]; then
|
||||
grep -Fq "${expected_line#error_text=}" "$stderr_file"
|
||||
else
|
||||
grep -Fq "$expected_line" "$stdout_file"
|
||||
fi
|
||||
done < "$expected"
|
||||
done
|
||||
|
||||
echo "native probe validation complete"
|
||||
24
wasm-port/tools/build_ini_panel.sh
Executable file
24
wasm-port/tools/build_ini_panel.sh
Executable file
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
OUT_DIR="$ROOT_DIR/runtime/ui/ini-panel"
|
||||
|
||||
emcc \
|
||||
-std=c++20 \
|
||||
-O2 \
|
||||
-I"$ROOT_DIR/runtime/core/shims" \
|
||||
-I"$ROOT_DIR/vendor/linuxcnc/src" \
|
||||
-I"$ROOT_DIR/vendor/linuxcnc/src/rtapi" \
|
||||
-I"$ROOT_DIR/vendor/linuxcnc/src/emc" \
|
||||
"$ROOT_DIR/vendor/linuxcnc/src/emc/ini/inifile.cc" \
|
||||
"$ROOT_DIR/runtime/core/linuxcnc_wrap/linuxcnc_ini_wasm.cpp" \
|
||||
-o "$OUT_DIR/linuxcnc_ini.js" \
|
||||
-s MODULARIZE=1 \
|
||||
-s EXPORT_ES6=1 \
|
||||
-s ENVIRONMENT=web \
|
||||
-s ALLOW_MEMORY_GROWTH=1 \
|
||||
-s NO_EXIT_RUNTIME=1 \
|
||||
-s FORCE_FILESYSTEM=1 \
|
||||
-s EXPORTED_FUNCTIONS='["_malloc","_free","_lcini_get_string","_lcini_tilde_expand"]' \
|
||||
-s EXPORTED_RUNTIME_METHODS='["FS","UTF8ToString","stringToUTF8","lengthBytesUTF8"]'
|
||||
198
wasm-port/tools/build_native_probes.sh
Executable file
198
wasm-port/tools/build_native_probes.sh
Executable file
@@ -0,0 +1,198 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
VENDOR_DIR="$ROOT_DIR/vendor/linuxcnc"
|
||||
BUILD_DIR="$ROOT_DIR/build/native"
|
||||
WRAP_DIR="$ROOT_DIR/runtime/core/linuxcnc_wrap"
|
||||
SHIM_DIR="$ROOT_DIR/runtime/core/shims"
|
||||
INCLUDE_DIR="$ROOT_DIR/runtime/core/include"
|
||||
MINIMAL_GCODE_FIXTURE="$ROOT_DIR/tests/fixtures/gcode/minimal_linear.ngc"
|
||||
|
||||
mkdir -p "$BUILD_DIR"
|
||||
|
||||
rm -f \
|
||||
"$BUILD_DIR/linuxcnc_ini_probe" \
|
||||
"$BUILD_DIR/linuxcnc_interp_state_probe" \
|
||||
"$BUILD_DIR/linuxcnc_interp_state_probe.exitcode" \
|
||||
"$BUILD_DIR/linuxcnc_interp_state_probe.stdout.log" \
|
||||
"$BUILD_DIR/linuxcnc_interp_state_probe.stderr.log" \
|
||||
"$BUILD_DIR/linuxcnc_namedparam_harness" \
|
||||
"$BUILD_DIR/linuxcnc_namedparam_harness.exitcode" \
|
||||
"$BUILD_DIR/linuxcnc_namedparam_harness.stdout.log" \
|
||||
"$BUILD_DIR/linuxcnc_namedparam_harness.stderr.log" \
|
||||
"$BUILD_DIR/linuxcnc_interp_minimal_harness" \
|
||||
"$BUILD_DIR/linuxcnc_interp_minimal_harness.exitcode" \
|
||||
"$BUILD_DIR/linuxcnc_interp_minimal_harness.stdout.log" \
|
||||
"$BUILD_DIR/linuxcnc_interp_minimal_harness.stderr.log" \
|
||||
"$BUILD_DIR/linuxcnc_interp_minimal_harness.run.exitcode" \
|
||||
"$BUILD_DIR/linuxcnc_interp_minimal_harness.run.stdout.log" \
|
||||
"$BUILD_DIR/linuxcnc_interp_minimal_harness.run.stderr.log" \
|
||||
"$BUILD_DIR/linuxcnc_rs274_compile_probe.o" \
|
||||
"$BUILD_DIR/linuxcnc_rs274_compile_probe.exitcode" \
|
||||
"$BUILD_DIR/linuxcnc_rs274_compile_probe.stdout.log" \
|
||||
"$BUILD_DIR/linuxcnc_rs274_compile_probe.stderr.log" \
|
||||
"$BUILD_DIR/linuxcnc_interp_convert_source_probe.o" \
|
||||
"$BUILD_DIR/linuxcnc_interp_convert_source_probe.exitcode" \
|
||||
"$BUILD_DIR/linuxcnc_interp_convert_source_probe.stdout.log" \
|
||||
"$BUILD_DIR/linuxcnc_interp_convert_source_probe.stderr.log"
|
||||
|
||||
g++ -std=c++20 -O2 \
|
||||
-D_GNU_SOURCE \
|
||||
-DM_PI=3.14159265358979323846 \
|
||||
-DOBJECT_FWD_DWA2002724_HPP \
|
||||
-I"$SHIM_DIR" \
|
||||
-I"$INCLUDE_DIR" \
|
||||
-I"$VENDOR_DIR/src" \
|
||||
-I"$VENDOR_DIR/src/rtapi" \
|
||||
-I"$VENDOR_DIR/src/emc" \
|
||||
-I"$VENDOR_DIR/src/emc/nml_intf" \
|
||||
-I"$VENDOR_DIR/src/emc/motion" \
|
||||
-I"$VENDOR_DIR/src/libnml/posemath" \
|
||||
"$VENDOR_DIR/src/emc/ini/inifile.cc" \
|
||||
"$WRAP_DIR/linuxcnc_ini_probe.cpp" \
|
||||
-lfmt \
|
||||
-o "$BUILD_DIR/linuxcnc_ini_probe"
|
||||
|
||||
set +e
|
||||
g++ -std=c++20 -O2 \
|
||||
-D_GNU_SOURCE \
|
||||
-DM_PI=3.14159265358979323846 \
|
||||
-DOBJECT_FWD_DWA2002724_HPP \
|
||||
-I"$SHIM_DIR" \
|
||||
-I"$INCLUDE_DIR" \
|
||||
-I"$VENDOR_DIR/src" \
|
||||
-I"$VENDOR_DIR/src/rtapi" \
|
||||
-I"$VENDOR_DIR/src/emc" \
|
||||
-I"$VENDOR_DIR/src/emc/nml_intf" \
|
||||
-I"$VENDOR_DIR/src/emc/motion" \
|
||||
-I"$VENDOR_DIR/src/libnml/posemath" \
|
||||
"$WRAP_DIR/linuxcnc_interp_state_probe.cpp" \
|
||||
-o "$BUILD_DIR/linuxcnc_interp_state_probe" \
|
||||
>"$BUILD_DIR/linuxcnc_interp_state_probe.stdout.log" \
|
||||
2>"$BUILD_DIR/linuxcnc_interp_state_probe.stderr.log"
|
||||
STATE_RC=$?
|
||||
set -e
|
||||
|
||||
echo "$STATE_RC" > "$BUILD_DIR/linuxcnc_interp_state_probe.exitcode"
|
||||
|
||||
set +e
|
||||
g++ -std=c++20 -O2 \
|
||||
-D_GNU_SOURCE \
|
||||
-DM_PI=3.14159265358979323846 \
|
||||
-DOBJECT_FWD_DWA2002724_HPP \
|
||||
-I"$SHIM_DIR" \
|
||||
-I"$INCLUDE_DIR" \
|
||||
-I"$VENDOR_DIR/src" \
|
||||
-I"$VENDOR_DIR/src/rtapi" \
|
||||
-I"$VENDOR_DIR/src/emc" \
|
||||
-I"$VENDOR_DIR/src/emc/nml_intf" \
|
||||
-I"$VENDOR_DIR/src/emc/motion" \
|
||||
-I"$VENDOR_DIR/src/libnml/posemath" \
|
||||
"$VENDOR_DIR/src/emc/rs274ngc/modal_state.cc" \
|
||||
"$WRAP_DIR/linuxcnc_runtime_state_stubs.cpp" \
|
||||
"$WRAP_DIR/linuxcnc_namedparam_harness.cpp" \
|
||||
"$VENDOR_DIR/src/emc/ini/inifile.cc" \
|
||||
-lfmt \
|
||||
-o "$BUILD_DIR/linuxcnc_namedparam_harness" \
|
||||
>"$BUILD_DIR/linuxcnc_namedparam_harness.stdout.log" \
|
||||
2>"$BUILD_DIR/linuxcnc_namedparam_harness.stderr.log"
|
||||
NAMEDPARAM_RC=$?
|
||||
set -e
|
||||
|
||||
echo "$NAMEDPARAM_RC" > "$BUILD_DIR/linuxcnc_namedparam_harness.exitcode"
|
||||
|
||||
set +e
|
||||
g++ -std=c++20 -O2 -ffunction-sections -fdata-sections \
|
||||
-Wl,--gc-sections \
|
||||
-D_GNU_SOURCE \
|
||||
-DM_PI=3.14159265358979323846 \
|
||||
-DOBJECT_FWD_DWA2002724_HPP \
|
||||
-I"$SHIM_DIR" \
|
||||
-I"$INCLUDE_DIR" \
|
||||
-I"$VENDOR_DIR/src" \
|
||||
-I"$VENDOR_DIR/src/rtapi" \
|
||||
-I"$VENDOR_DIR/src/emc" \
|
||||
-I"$VENDOR_DIR/src/emc/nml_intf" \
|
||||
-I"$VENDOR_DIR/src/emc/motion" \
|
||||
-I"$VENDOR_DIR/src/libnml/posemath" \
|
||||
"$VENDOR_DIR/src/emc/rs274ngc/modal_state.cc" \
|
||||
"$VENDOR_DIR/src/emc/rs274ngc/interp_array.cc" \
|
||||
"$VENDOR_DIR/src/emc/rs274ngc/interp_internal.cc" \
|
||||
"$VENDOR_DIR/src/emc/rs274ngc/interp_read.cc" \
|
||||
"$VENDOR_DIR/src/emc/rs274ngc/interp_check.cc" \
|
||||
"$VENDOR_DIR/src/emc/rs274ngc/interp_arc.cc" \
|
||||
"$VENDOR_DIR/src/emc/rs274ngc/interp_inverse.cc" \
|
||||
"$VENDOR_DIR/src/emc/rs274ngc/interp_execute.cc" \
|
||||
"$VENDOR_DIR/src/emc/rs274ngc/interp_convert.cc" \
|
||||
"$VENDOR_DIR/src/emc/rs274ngc/interp_cycles.cc" \
|
||||
"$VENDOR_DIR/src/emc/rs274ngc/interp_g7x.cc" \
|
||||
"$VENDOR_DIR/src/emc/rs274ngc/interp_queue.cc" \
|
||||
"$VENDOR_DIR/src/emc/rs274ngc/interp_find.cc" \
|
||||
"$VENDOR_DIR/src/emc/rs274ngc/interp_write.cc" \
|
||||
"$WRAP_DIR/linuxcnc_runtime_state_stubs.cpp" \
|
||||
"$WRAP_DIR/linuxcnc_interp_minimal_runtime.cpp" \
|
||||
"$WRAP_DIR/linuxcnc_interp_minimal_harness.cpp" \
|
||||
-lfmt \
|
||||
-o "$BUILD_DIR/linuxcnc_interp_minimal_harness" \
|
||||
>"$BUILD_DIR/linuxcnc_interp_minimal_harness.stdout.log" \
|
||||
2>"$BUILD_DIR/linuxcnc_interp_minimal_harness.stderr.log"
|
||||
INTERP_MIN_RC=$?
|
||||
set -e
|
||||
|
||||
echo "$INTERP_MIN_RC" > "$BUILD_DIR/linuxcnc_interp_minimal_harness.exitcode"
|
||||
|
||||
if [[ "$INTERP_MIN_RC" -eq 0 ]]; then
|
||||
set +e
|
||||
"$BUILD_DIR/linuxcnc_interp_minimal_harness" "$MINIMAL_GCODE_FIXTURE" \
|
||||
>"$BUILD_DIR/linuxcnc_interp_minimal_harness.run.stdout.log" \
|
||||
2>"$BUILD_DIR/linuxcnc_interp_minimal_harness.run.stderr.log"
|
||||
INTERP_MIN_RUN_RC=$?
|
||||
set -e
|
||||
echo "$INTERP_MIN_RUN_RC" > "$BUILD_DIR/linuxcnc_interp_minimal_harness.run.exitcode"
|
||||
fi
|
||||
|
||||
set +e
|
||||
g++ -std=c++20 -O2 \
|
||||
-D_GNU_SOURCE \
|
||||
-DM_PI=3.14159265358979323846 \
|
||||
-DOBJECT_FWD_DWA2002724_HPP \
|
||||
-I"$SHIM_DIR" \
|
||||
-I"$INCLUDE_DIR" \
|
||||
-I"$VENDOR_DIR/src" \
|
||||
-I"$VENDOR_DIR/src/rtapi" \
|
||||
-I"$VENDOR_DIR/src/emc" \
|
||||
-I"$VENDOR_DIR/src/emc/nml_intf" \
|
||||
-I"$VENDOR_DIR/src/emc/motion" \
|
||||
-I"$VENDOR_DIR/src/libnml/posemath" \
|
||||
-c "$WRAP_DIR/linuxcnc_rs274_compile_probe.cpp" \
|
||||
-o "$BUILD_DIR/linuxcnc_rs274_compile_probe.o" \
|
||||
>"$BUILD_DIR/linuxcnc_rs274_compile_probe.stdout.log" \
|
||||
2>"$BUILD_DIR/linuxcnc_rs274_compile_probe.stderr.log"
|
||||
RS274_RC=$?
|
||||
set -e
|
||||
|
||||
echo "$RS274_RC" > "$BUILD_DIR/linuxcnc_rs274_compile_probe.exitcode"
|
||||
|
||||
set +e
|
||||
g++ -std=c++20 -O2 \
|
||||
-D_GNU_SOURCE \
|
||||
-DM_PI=3.14159265358979323846 \
|
||||
-DOBJECT_FWD_DWA2002724_HPP \
|
||||
-I"$SHIM_DIR" \
|
||||
-I"$INCLUDE_DIR" \
|
||||
-I"$VENDOR_DIR/src" \
|
||||
-I"$VENDOR_DIR/src/rtapi" \
|
||||
-I"$VENDOR_DIR/src/emc" \
|
||||
-I"$VENDOR_DIR/src/emc/nml_intf" \
|
||||
-I"$VENDOR_DIR/src/emc/motion" \
|
||||
-I"$VENDOR_DIR/src/libnml/posemath" \
|
||||
-c "$VENDOR_DIR/src/emc/rs274ngc/interp_convert.cc" \
|
||||
-o "$BUILD_DIR/linuxcnc_interp_convert_source_probe.o" \
|
||||
>"$BUILD_DIR/linuxcnc_interp_convert_source_probe.stdout.log" \
|
||||
2>"$BUILD_DIR/linuxcnc_interp_convert_source_probe.stderr.log"
|
||||
CONVERT_SOURCE_RC=$?
|
||||
set -e
|
||||
|
||||
echo "$CONVERT_SOURCE_RC" > "$BUILD_DIR/linuxcnc_interp_convert_source_probe.exitcode"
|
||||
echo "native probes complete"
|
||||
35
wasm-port/tools/extract_sources.sh
Executable file
35
wasm-port/tools/extract_sources.sh
Executable file
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
UPSTREAM_DIR="$ROOT_DIR/../linuxcnc"
|
||||
VENDOR_DIR="$ROOT_DIR/vendor/linuxcnc"
|
||||
MANIFEST_FILE="$ROOT_DIR/tools/source-manifest.txt"
|
||||
|
||||
copy_file() {
|
||||
local src_rel="$1"
|
||||
local src="$UPSTREAM_DIR/$src_rel"
|
||||
local dst="$VENDOR_DIR/$src_rel"
|
||||
|
||||
if [[ ! -f "$src" ]]; then
|
||||
echo "missing upstream file: $src" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$(dirname "$dst")"
|
||||
cp "$src" "$dst"
|
||||
echo "copied $src_rel"
|
||||
}
|
||||
|
||||
if [[ ! -f "$MANIFEST_FILE" ]]; then
|
||||
echo "missing manifest: $MANIFEST_FILE" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
while IFS= read -r src_rel; do
|
||||
[[ -z "$src_rel" ]] && continue
|
||||
[[ "${src_rel:0:1}" == "#" ]] && continue
|
||||
copy_file "$src_rel"
|
||||
done < "$MANIFEST_FILE"
|
||||
|
||||
echo "extraction complete"
|
||||
7
wasm-port/tools/serve_ini_panel.sh
Executable file
7
wasm-port/tools/serve_ini_panel.sh
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
PORT="${1:-8011}"
|
||||
|
||||
python3 -m http.server "$PORT" --directory "$ROOT_DIR"
|
||||
53
wasm-port/tools/source-manifest.txt
Normal file
53
wasm-port/tools/source-manifest.txt
Normal file
@@ -0,0 +1,53 @@
|
||||
src/emc/ini/inifile.cc
|
||||
src/emc/ini/inifile.h
|
||||
src/emc/ini/inifile.hh
|
||||
src/rtapi/rtapi_stdint.h
|
||||
src/rtapi/rtapi_string.h
|
||||
src/rtapi/rtapi_gfp.h
|
||||
src/rtapi/rtapi_math.h
|
||||
src/rtapi/rtapi_byteorder.h
|
||||
src/emc/nml_intf/emcpos.h
|
||||
src/emc/nml_intf/emcpose.h
|
||||
src/emc/linuxcnc.h
|
||||
src/emc/nml_intf/canon.hh
|
||||
src/emc/nml_intf/canon_position.hh
|
||||
src/emc/nml_intf/emc.hh
|
||||
src/emc/nml_intf/emctool.h
|
||||
src/emc/nml_intf/debugflags.h
|
||||
src/emc/nml_intf/interp_return.hh
|
||||
src/emc/motion/state_tag.h
|
||||
src/emc/motion/emcmotcfg.h
|
||||
src/emc/rs274ngc/modal_state.hh
|
||||
src/emc/rs274ngc/modal_state.cc
|
||||
src/libnml/posemath/posemath.h
|
||||
src/libnml/posemath/gomath.h
|
||||
src/libnml/posemath/gotypes.h
|
||||
src/libnml/posemath/sincos.h
|
||||
src/emc/rs274ngc/interp_parameter_def.hh
|
||||
src/emc/rs274ngc/interp_array.cc
|
||||
src/emc/rs274ngc/interp_namedparams.cc
|
||||
src/emc/rs274ngc/interp_internal.hh
|
||||
src/emc/rs274ngc/interp_fwd.hh
|
||||
src/emc/rs274ngc/interp_base.hh
|
||||
src/emc/rs274ngc/interp_base.cc
|
||||
src/emc/rs274ngc/rs274ngc.hh
|
||||
src/emc/rs274ngc/rs274ngc_interp.hh
|
||||
src/emc/rs274ngc/rs274ngc_return.hh
|
||||
src/emc/rs274ngc/rs274ngc_pre.cc
|
||||
src/emc/rs274ngc/interp_queue.hh
|
||||
src/emc/rs274ngc/interp_queue.cc
|
||||
src/emc/rs274ngc/units.h
|
||||
src/emc/rs274ngc/interp_arc.cc
|
||||
src/emc/rs274ngc/interp_internal.cc
|
||||
src/emc/rs274ngc/interp_write.cc
|
||||
src/emc/rs274ngc/interp_check.cc
|
||||
src/emc/rs274ngc/interp_read.cc
|
||||
src/emc/rs274ngc/interp_execute.cc
|
||||
src/emc/rs274ngc/interp_find.cc
|
||||
src/emc/rs274ngc/interp_inverse.cc
|
||||
src/emc/rs274ngc/interp_o_word.cc
|
||||
src/emc/rs274ngc/interp_convert.cc
|
||||
src/emc/rs274ngc/interp_cycles.cc
|
||||
src/emc/rs274ngc/interp_g7x.cc
|
||||
src/emc/rs274ngc/interp_check.cc
|
||||
src/emc/rs274ngc/interp_execute.cc
|
||||
1674
wasm-port/vendor/linuxcnc/src/emc/ini/inifile.cc
vendored
Normal file
1674
wasm-port/vendor/linuxcnc/src/emc/ini/inifile.cc
vendored
Normal file
File diff suppressed because it is too large
Load Diff
61
wasm-port/vendor/linuxcnc/src/emc/ini/inifile.h
vendored
Normal file
61
wasm-port/vendor/linuxcnc/src/emc/ini/inifile.h
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
//
|
||||
// IniFile - Ini-file reader and query class
|
||||
// Copyright (C) 2026 B.Stultiens
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
//
|
||||
#ifndef __LINUXCNC_INI_INIFILE_H
|
||||
#define __LINUXCNC_INI_INIFILE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
#warning "Including inifile.h in C++ code is inefficient. You should use the C++ API in inifile.hh instead."
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <rtapi_stdint.h>
|
||||
|
||||
//
|
||||
// C-API interface functions
|
||||
//
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// There is no real limit in the C++ version. This value is for compatibility.
|
||||
// It has been increased from the original 256 to PATH_MAX to allow for full
|
||||
// paths to be properly encapsulated.
|
||||
#define INI_MAX_LINELEN PATH_MAX
|
||||
|
||||
int TildeExpansion(const char *file, char *path, size_t size);
|
||||
|
||||
int iniFindString(const char *inipath, const char *tag, const char *section, char *buf, size_t bufsize);
|
||||
int iniFindBool(const char *inipath, const char *tag, const char *section, bool *result);
|
||||
int iniFindSInt(const char *inipath, const char *tag, const char *section, rtapi_s64 *result);
|
||||
int iniFindUInt(const char *inipath, const char *tag, const char *section, rtapi_u64 *result);
|
||||
int iniFindDouble(const char *inipath, const char *tag, const char *section, double *result);
|
||||
|
||||
// Compatibility with existing code
|
||||
// Maps to iniFindSInt() and truncates the result
|
||||
int iniFindInt(const char *inipath, const char *tag, const char *section, int *result);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
// vim: ts=4 sw=4
|
||||
504
wasm-port/vendor/linuxcnc/src/emc/ini/inifile.hh
vendored
Normal file
504
wasm-port/vendor/linuxcnc/src/emc/ini/inifile.hh
vendored
Normal file
@@ -0,0 +1,504 @@
|
||||
//
|
||||
// IniFile - Ini-file reader and query class
|
||||
// Copyright (C) 2026 B.Stultiens
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
//
|
||||
#ifndef __LINUXCNC_INI_INIFILE_HH
|
||||
#define __LINUXCNC_INI_INIFILE_HH
|
||||
|
||||
#ifndef __cplusplus
|
||||
#error "inifile.hh cannot be used in C. Please use the C-API in inifile.h"
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
#include <climits>
|
||||
|
||||
#include <float.h>
|
||||
#include <rtapi_stdint.h>
|
||||
|
||||
//
|
||||
// IniFile public methods for extraction of values from the ini-file:
|
||||
//
|
||||
// Note that selecting the num'th value is the first argument to prevent
|
||||
// accidents using wrong arguments for the bool/integer/real versions. This way
|
||||
// you have to select the num'th as the first argument if you really mean to
|
||||
// use it and cannot be mistaken as the default or min/max values. You can
|
||||
// just omit the num if you just want the first value as a convenience method.
|
||||
//
|
||||
// All find_X_All() methods, except findStringAll(), will perform conversion to
|
||||
// the requested type. That also means that mixed value content may result in
|
||||
// errors and dropped results. Use the find_X_All() methods only when you know
|
||||
// that the values are all supposed to be of the same type.
|
||||
//
|
||||
// Helper methods can be used to query the ini-file to get information about
|
||||
// sections, variables, paths and line numbers:
|
||||
// bool hasSection(section)
|
||||
// bool hasVariable(variable, section)
|
||||
// bool hasVariable(num, variable, section)
|
||||
// which all map to:
|
||||
// bool isSet(variable, section)
|
||||
// bool isSet(num, variable, section)
|
||||
//
|
||||
// Ini-file structural content methods:
|
||||
// std::vector<std::string> findSections()
|
||||
// std::vector<std::pair<std::string,std::string>> findVariables(section);
|
||||
// std::pair<std::string, int> lineOf(variable, section)
|
||||
// std::pair<std::string, int> lineOf(num, variable, section)
|
||||
//
|
||||
// General value extraction methods:
|
||||
// std::vector<std::string> findStringAll(tag, section)
|
||||
// std::optional<std::string> findString(tag, section)
|
||||
// std::optional<std::string> findString(num, tag, section)
|
||||
// std::string findStringV(tag, section, def)
|
||||
// std::string findStringV(num, tag, section, def)
|
||||
//
|
||||
// std::vector<bool> findBoolAll(tag, section)
|
||||
// std::optional<bool> findBool(tag, section)
|
||||
// std::optional<bool> findBool(num, tag, section)
|
||||
// bool findBoolV(tag, section, def)
|
||||
// bool findBoolV(num, tag, section, def)
|
||||
//
|
||||
// std::vector<rtapi_s64> findSIntAll(tag, section)
|
||||
// std::optional<rtapi_s64> findSInt(tag, section, mini = INT64_MIN, maxi = INT64_MAX)
|
||||
// std::optional<rtapi_s64> findSInt(num, tag, section, mini = INT64_MIN, maxi = INT64_MAX)
|
||||
// rtapi_s64 findSIntV(tag, section, def, mini = INT64_MIN, maxi = INT64_MAX)
|
||||
// rtapi_s64 findSIntV(num, tag, section, def, mini = INT64_MIN, maxi = INT64_MAX)
|
||||
//
|
||||
// std::vector<rtapi_u64> findUIntAll(tag, section)
|
||||
// std::optional<rtapi_u64> findUInt(tag, section, mini = 0, maxi = UINT64_MAX)
|
||||
// std::optional<rtapi_u64> findUInt(num, tag, section, mini = 0, maxi = UINT64_MAX)
|
||||
// rtapi_u64 findUIntV(tag, section, def, mini = 0, maxi = UINT64_MAX)
|
||||
// rtapi_u64 findUIntV(num, tag, section, def, mini = 0, maxi = UINT64_MAX)
|
||||
//
|
||||
// std::vector<double> findRealAll(tag, section)
|
||||
// std::optional<double> findReal(tag, section, mini = -DBL_MAX, maxi = +DBL_MAX)
|
||||
// std::optional<double> findReal(num, tag, section, mini = -DBL_MAX, maxi = +DBL_MAX)
|
||||
// double findRealV(tag, section, def, mini = -DBL_MAX, maxi = +DBL_MAX)
|
||||
// double findRealV(num, tag, section, def, mini = -DBL_MAX, maxi = +DBL_MAX)
|
||||
//
|
||||
// Convenience methods using the (usually 32-bit) integer type are provided and
|
||||
// map to findSInt:
|
||||
// std::optional<int> findInt(tag, section, mini = INT_MIN, maxi = INT_MAX)
|
||||
// std::optional<int> findInt(num, tag, section, mini = INT_MIN, maxi = INT_MAX)
|
||||
// int findIntV(tag, section, def, mini = INT_MIN, maxi = INT_MAX)
|
||||
// int findIntV(num, tag, section, def, mini = INT_MIN, maxi = INT_MAX)
|
||||
//
|
||||
// Implementing (case [in]sensitive) list type values can be done using the
|
||||
// IniFile::findMap() template function for case sensitive and case insensitive
|
||||
// compares. The map defined for type T mapping:
|
||||
// const std::map<const std::string, const T> = {...}
|
||||
// const std::map<const std::string, const T, IniFile::caseless> = {...}
|
||||
// for function:
|
||||
// T findCustom(const IniFile &ini, const std::string &tag, const std::string §ion, T def)
|
||||
//
|
||||
// Example:
|
||||
// double findUnits(const IniFile &ini, const std::string &tag, const std::string §ion, double def)
|
||||
// {
|
||||
// static const std::map<const std::string, const double> unitsMap = {
|
||||
// { "mm", 1.0 },
|
||||
// { "metric", 1.0 },
|
||||
// { "in", 1/25.4 },
|
||||
// { "inch", 1/25.4 },
|
||||
// { "imperial", 1/25.4 },
|
||||
// };
|
||||
//
|
||||
// if(auto c = ini.findMap(unitsMap, tag, section))
|
||||
// return *c;
|
||||
// return def;
|
||||
// }
|
||||
//
|
||||
|
||||
// Forward declaration (must be outside namespace)
|
||||
// This is found in emc/nml_intf/emc.hh
|
||||
enum EmcJointType : int;
|
||||
|
||||
namespace linuxcnc {
|
||||
|
||||
// Forward declaration of internal classes
|
||||
class IniFileContent;
|
||||
class IniFileTag;
|
||||
class IniFileSection;
|
||||
|
||||
//
|
||||
// Public facing IniFile operations
|
||||
//
|
||||
class IniFile
|
||||
{
|
||||
public:
|
||||
IniFile(const std::string &filePath);
|
||||
|
||||
operator bool() const { return isOpen(); }
|
||||
bool isOpen() const { return _inifilecontent != nullptr; }
|
||||
|
||||
bool hasSection(const std::string §ion) const {
|
||||
return isSet(1, "", section);
|
||||
}
|
||||
bool hasVariable(int num, const std::string &tag, const std::string §ion) const {
|
||||
return isSet(num, tag, section);
|
||||
}
|
||||
bool hasVariable(const std::string &tag, const std::string §ion) const {
|
||||
return hasVariable(1, tag, section);
|
||||
}
|
||||
|
||||
// Returns true if the specified [section]tag is present
|
||||
bool isSet(int num, const std::string &tag, const std::string §ion) const {
|
||||
if(tag.empty() && section.empty()) {
|
||||
// No, we don't have nothing
|
||||
return false;
|
||||
}
|
||||
if(tag.empty()) {
|
||||
// We can have a section that has no variables in it
|
||||
return (bool)findSection(section);
|
||||
}
|
||||
return (bool)findTag(tag, section, num);
|
||||
}
|
||||
bool isSet(const std::string &tag, const std::string §ion) const {
|
||||
return isSet(1, tag, section);
|
||||
}
|
||||
|
||||
// Returns the ini-file path and line number of the specified variable
|
||||
std::pair<std::string,int> lineOf(int num, const std::string &tag, const std::string §ion) const;
|
||||
std::pair<std::string,int> lineOf(const std::string &tag, const std::string §ion) const {
|
||||
return lineOf(1, tag, section);
|
||||
}
|
||||
|
||||
// Get all variables named 'tag' from (optional) section in a vector.
|
||||
// Returns an empty vector if none found.
|
||||
std::vector<std::string> findStringAll(const std::string &tag, const std::string §ion) const;
|
||||
std::vector<bool> findBoolAll(const std::string &tag, const std::string §ion) const;
|
||||
std::vector<rtapi_s64> findSIntAll(const std::string &tag, const std::string §ion) const;
|
||||
std::vector<rtapi_u64> findUIntAll(const std::string &tag, const std::string §ion) const;
|
||||
std::vector<double> findRealAll(const std::string &tag, const std::string §ion) const;
|
||||
|
||||
// Get the num'th variable named 'tag' from (optional) section.
|
||||
// Returns std::nullopt if not found
|
||||
std::optional<std::string> findString(int num, const std::string &tag, const std::string §ion) const;
|
||||
std::optional<bool> findBool(int num, const std::string &tag, const std::string §ion) const;
|
||||
|
||||
std::optional<std::string> findString(const std::string &tag, const std::string §ion) const {
|
||||
return findString(1, tag, section);
|
||||
}
|
||||
std::optional<bool> findBool(const std::string &tag, const std::string §ion) const {
|
||||
return findBool(1, tag, section);
|
||||
}
|
||||
|
||||
// Get numerical values with options bounded ranges.
|
||||
// Returns std::nullopt if not found or out-of-range.
|
||||
std::optional<rtapi_s64> findSInt(int num, const std::string &tag, const std::string §ion,
|
||||
rtapi_s64 mini = INT64_MIN, rtapi_s64 maxi = INT64_MAX) const;
|
||||
std::optional<rtapi_u64> findUInt(int num, const std::string &tag, const std::string §ion,
|
||||
rtapi_u64 mini = 0, rtapi_u64 maxi = UINT64_MAX) const;
|
||||
std::optional<double> findReal(int num, const std::string &tag, const std::string §ion,
|
||||
double mini = -DBL_MAX, double maxi = +DBL_MAX) const;
|
||||
|
||||
std::optional<rtapi_s64> findSInt(const std::string &tag, const std::string §ion,
|
||||
rtapi_s64 mini = INT64_MIN, rtapi_s64 maxi = INT64_MAX) const {
|
||||
return findSInt(1, tag, section, mini, maxi);
|
||||
}
|
||||
std::optional<rtapi_u64> findUInt(const std::string &tag, const std::string §ion,
|
||||
rtapi_u64 mini = 0, rtapi_u64 maxi = UINT64_MAX) const {
|
||||
return findUInt(1, tag, section, mini, maxi);
|
||||
}
|
||||
std::optional<double> findReal(const std::string &tag, const std::string §ion,
|
||||
double mini = -DBL_MAX, double maxi = +DBL_MAX) const {
|
||||
return findReal(1, tag, section, mini, maxi);
|
||||
}
|
||||
|
||||
// Get the num'th value with defaults if not found.
|
||||
std::string findStringV(int num, const std::string &tag, const std::string §ion, const std::string &def) const {
|
||||
if(auto v = findString(num, tag, section))
|
||||
return *v;
|
||||
return def;
|
||||
}
|
||||
bool findBoolV(int num, const std::string &tag, const std::string §ion, bool def) const {
|
||||
if(auto v = findBool(num, tag, section))
|
||||
return *v;
|
||||
return def;
|
||||
}
|
||||
|
||||
std::string findStringV(const std::string &tag, const std::string §ion, const std::string &def) const {
|
||||
return findStringV(1, tag, section, def);
|
||||
}
|
||||
bool findBoolV(const std::string &tag, const std::string §ion, bool def) const {
|
||||
return findBoolV(1, tag, section, def);
|
||||
}
|
||||
|
||||
// Find the num'th value within min/max range.
|
||||
// Returns default value if not found or out-of-range.
|
||||
// These have a suffix 'V' to counter the overloading ambiguity.
|
||||
rtapi_s64 findSIntV(int num, const std::string &tag, const std::string §ion, rtapi_s64 def,
|
||||
rtapi_s64 mini = INT64_MIN, rtapi_s64 maxi = INT64_MAX) const {
|
||||
if(auto v = findSInt(num, tag, section, mini, maxi))
|
||||
return *v;
|
||||
return def;
|
||||
}
|
||||
rtapi_u64 findUIntV(int num, const std::string &tag, const std::string §ion, rtapi_u64 def,
|
||||
rtapi_u64 mini = 0, rtapi_u64 maxi = UINT64_MAX) const {
|
||||
if(auto v = findUInt(num, tag, section, mini, maxi))
|
||||
return *v;
|
||||
return def;
|
||||
}
|
||||
double findRealV(int num, const std::string &tag, const std::string §ion, double def,
|
||||
double mini = -DBL_MAX, double maxi = +DBL_MAX) const {
|
||||
if(auto v = findReal(num, tag, section, mini, maxi))
|
||||
return *v;
|
||||
return def;
|
||||
}
|
||||
|
||||
rtapi_s64 findSIntV(const std::string &tag, const std::string §ion, rtapi_s64 def,
|
||||
rtapi_s64 mini = INT64_MIN, rtapi_s64 maxi = INT64_MAX) const {
|
||||
return findSIntV(1, tag, section, def, mini, maxi);
|
||||
}
|
||||
rtapi_u64 findUIntV(const std::string &tag, const std::string §ion, rtapi_u64 def,
|
||||
rtapi_u64 mini = 0, rtapi_u64 maxi = UINT64_MAX) const {
|
||||
return findUIntV(1, tag, section, def, mini, maxi);
|
||||
}
|
||||
double findRealV(const std::string &tag, const std::string §ion, double def,
|
||||
double mini = -DBL_MAX, double maxi = +DBL_MAX) const {
|
||||
return findRealV(1, tag, section, def, mini, maxi);
|
||||
}
|
||||
|
||||
// Convenience methods
|
||||
std::optional<int> findInt(int num, const std::string &tag, const std::string §ion,
|
||||
int mini = INT_MIN, int maxi = INT_MAX) const {
|
||||
if(auto v = findSInt(num, tag, section, mini, maxi))
|
||||
return (int)*v;
|
||||
return std::nullopt;
|
||||
}
|
||||
std::optional<int> findInt(const std::string &tag, const std::string §ion,
|
||||
int mini = INT_MIN, int maxi = INT_MAX) const {
|
||||
return findInt(1, tag, section, mini, maxi);
|
||||
}
|
||||
int findIntV(int num, const std::string &tag, const std::string §ion, int def,
|
||||
int mini = INT_MIN, int maxi = INT_MAX) const {
|
||||
return (int)findSIntV(num, tag, section, def, mini, maxi);
|
||||
}
|
||||
int findIntV(const std::string &tag, const std::string §ion, int def,
|
||||
int mini = INT_MIN, int maxi = INT_MAX) const {
|
||||
return findIntV(1, tag, section, def, mini, maxi);
|
||||
}
|
||||
|
||||
// Map-search matching of values returning the mapped value.
|
||||
// Search is case-sensitive.
|
||||
template<typename T>
|
||||
std::optional<T> findMap(int num, const std::map<const std::string, const T> &map,
|
||||
const std::string &tag, const std::string §ion = "") const {
|
||||
if(auto s = findString(num, tag, section)) {
|
||||
auto const m = map.find(*s);
|
||||
if(m != map.end()) {
|
||||
return m->second;
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::optional<T> findMap(const std::map<const std::string, const T> &map,
|
||||
const std::string &tag, const std::string §ion = "") const {
|
||||
return findMap(1, map, tag, section);
|
||||
}
|
||||
// Map compare function without case
|
||||
struct caseless {
|
||||
struct caseless_cmp {
|
||||
bool operator() (const char &a, const char &b) const {
|
||||
return std::tolower(a & 0xff) < std::tolower(b & 0xff);
|
||||
}
|
||||
};
|
||||
bool operator() (const std::string &a, const std::string &b) const {
|
||||
return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end(), caseless_cmp());
|
||||
}
|
||||
};
|
||||
|
||||
// Map-search matching of values returning the mapped value.
|
||||
// Search is case-insensitive.
|
||||
template<typename T>
|
||||
std::optional<T> findMap(int num, const std::map<const std::string, const T, caseless> &map,
|
||||
const std::string &tag, const std::string §ion = "") const {
|
||||
if(auto s = findString(num, tag, section)) {
|
||||
auto const m = map.find(*s);
|
||||
if(m != map.end()) {
|
||||
return m->second;
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::optional<T> findMap(const std::map<const std::string, const T, caseless> &map,
|
||||
const std::string &tag, const std::string §ion = "") const {
|
||||
return findMap(1, map, tag, section);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::optional<T> static mapMap(const std::map<const std::string, const T, caseless> &map,
|
||||
const std::string &str) {
|
||||
auto const m = map.find(str);
|
||||
if(m != map.end()) {
|
||||
return m->second;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
//
|
||||
// Mapping functions for enumerated types so they become consistent
|
||||
// throughout the code base. They take a string argument and match it to
|
||||
// the mapped values:
|
||||
// - mapLinearUnits() maps {mm, metric, in, inch, imperial}
|
||||
// - mapAngularUnits() maps {deg, degree, grad, gon, rad, radian}
|
||||
// - mapJointType() maps {LINEAR, ANGULAR}
|
||||
//
|
||||
static std::optional<double> mapLinearUnits(const std::string &str);
|
||||
static std::optional<double> mapAngularUnits(const std::string &str);
|
||||
static std::optional<EmcJointType> mapJointType(const std::string &str);
|
||||
|
||||
// The following find*() both lookup the ini variable and attempt to
|
||||
// convert to the associated numerical value.
|
||||
std::optional<double> findLinearUnits(int num, const std::string &var, const std::string &sec) const {
|
||||
if(auto c = findString(num, var, sec))
|
||||
return mapLinearUnits(*c);
|
||||
return std::nullopt;
|
||||
}
|
||||
std::optional<double> findAngularUnits(int num, const std::string &var, const std::string &sec) const {
|
||||
if(auto c = findString(num, var, sec))
|
||||
return mapAngularUnits(*c);
|
||||
return std::nullopt;
|
||||
}
|
||||
std::optional<EmcJointType> findJointType(int num, const std::string &var, const std::string &sec) const {
|
||||
if(auto c = findString(num, var, sec))
|
||||
return mapJointType(*c);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
double findLinearUnits(const std::string &var, const std::string &sec, double def) const {
|
||||
if(auto m = findLinearUnits(1, var, sec))
|
||||
return *m;
|
||||
return def;
|
||||
}
|
||||
double findAngularUnits(const std::string &var, const std::string &sec, double def) const {
|
||||
if(auto m = findAngularUnits(1, var, sec))
|
||||
return *m;
|
||||
return def;
|
||||
}
|
||||
EmcJointType findJointType(const std::string &var, const std::string &sec, EmcJointType def) const {
|
||||
if(auto m = findJointType(1, var, sec))
|
||||
return *m;
|
||||
return def;
|
||||
}
|
||||
|
||||
// Return a list of section names from the ini-file
|
||||
std::vector<std::string> findSections() const;
|
||||
// Return a list of variable name/value pairs from an optional section in the ini-file
|
||||
std::vector<std::pair<std::string,std::string>> findVariables(const std::string §ion) const;
|
||||
|
||||
// The fact that this is here is because of compatibility
|
||||
// Perform tilde expansion using HOME environment variable.
|
||||
// Returns the filePath "~/path" as "$HOME/path"
|
||||
// Zero is returned on success or a negative value (-errno) on failure.
|
||||
static int tildeExpand(const std::string &filePath, std::string &res);
|
||||
|
||||
// Compatibility method
|
||||
static int TildeExpansion(const std::string &filePath, std::string &res) {
|
||||
return IniFile::tildeExpand(filePath, res);
|
||||
}
|
||||
|
||||
static std::optional<bool> convertBool(const std::string &val);
|
||||
static std::optional<rtapi_s64> convertSInt(const std::string &val);
|
||||
static std::optional<rtapi_u64> convertUInt(const std::string &val);
|
||||
static std::optional<double> convertReal(const std::string &val);
|
||||
|
||||
// split() Tokenize 'str' based on 'delim'
|
||||
static std::vector<std::string> split(const std::string &delim, const std::string &str);
|
||||
|
||||
// Trim leading/trailing or both
|
||||
static void rtrim(std::string &str) {
|
||||
size_t n = str.find_last_not_of(IniFile::STR_WS);
|
||||
if(std::string::npos != n)
|
||||
str.erase(n+1);
|
||||
}
|
||||
static void ltrim(std::string &str) {
|
||||
if(str.empty())
|
||||
return;
|
||||
size_t n = str.find_first_not_of(IniFile::STR_WS);
|
||||
if(std::string::npos == n)
|
||||
str.clear(); // Only whitespace
|
||||
else
|
||||
str.erase(0, n);
|
||||
}
|
||||
|
||||
static void trim(std::string &str) {
|
||||
rtrim(str);
|
||||
ltrim(str);
|
||||
}
|
||||
|
||||
// Trim on a copy and return the trimmed copy
|
||||
static std::string rtrimcpy(const std::string &str) {
|
||||
std::string cpy = str;
|
||||
rtrim(cpy);
|
||||
return cpy;
|
||||
}
|
||||
|
||||
static std::string ltrimcpy(const std::string &str) {
|
||||
std::string cpy = str;
|
||||
ltrim(cpy);
|
||||
return cpy;
|
||||
}
|
||||
|
||||
static std::string trimcpy(const std::string &str) {
|
||||
std::string cpy = str;
|
||||
rtrim(cpy);
|
||||
ltrim(cpy);
|
||||
return cpy;
|
||||
}
|
||||
|
||||
// White-space characters for argument to find_first_of() and the like.
|
||||
// Using static constexpr std::string does not seem to work on Debian 11
|
||||
// with clang-19 and older than that. Gcc on debian 11 and before doesn't
|
||||
// support enough C++20 to build LinuxCNC at all.
|
||||
static constexpr char STR_WS[] =" \t\v\f\r\n";
|
||||
|
||||
// This isSpace is guaranteed not to depend on locale
|
||||
static bool isSpace(char c) {
|
||||
return std::string::npos != (std::string{STR_WS}).find(c);
|
||||
}
|
||||
private:
|
||||
bool Open(const std::string &filePath);
|
||||
bool Close() { _inifilecontent = nullptr; _filepath.clear(); return true; }
|
||||
|
||||
bool hasOpenError(const std::string &tag, const std::string §ion) const;
|
||||
std::string sectionFromTag(const IniFileTag *val) const;
|
||||
|
||||
std::optional<const IniFileSection *> findSection(const std::string §ion) const;
|
||||
std::optional<const IniFileTag *> findTag(const std::string &tag, const std::string §ion, int num) const;
|
||||
std::optional<std::vector<const IniFileTag *>> findTags(const std::string &tag, const std::string §ion) const;
|
||||
|
||||
std::optional<bool> convertBool(const IniFileTag *val) const;
|
||||
std::optional<rtapi_s64> convertSInt(const IniFileTag *val) const;
|
||||
std::optional<rtapi_u64> convertUInt(const IniFileTag *val) const;
|
||||
std::optional<double> convertReal(const IniFileTag *val) const;
|
||||
|
||||
const IniFileContent *_inifilecontent;
|
||||
std::string _filepath;
|
||||
};
|
||||
|
||||
} // namespace linuxcnc
|
||||
|
||||
#endif
|
||||
// vim: ts=4 sw=4
|
||||
27
wasm-port/vendor/linuxcnc/src/emc/linuxcnc.h
vendored
Normal file
27
wasm-port/vendor/linuxcnc/src/emc/linuxcnc.h
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
/********************************************************************
|
||||
* Description: linuxcnc.h
|
||||
* Common defines used in many emc2 source files.
|
||||
*
|
||||
*
|
||||
* Author: Petter Reinholdtsen
|
||||
* License: LGPL Version 2
|
||||
* System: Any
|
||||
*
|
||||
* Copyright (c) 2021 All rights reserved.
|
||||
********************************************************************/
|
||||
|
||||
#ifndef __LINUXCNC_LINUXCNC_H
|
||||
#define __LINUXCNC_LINUXCNC_H
|
||||
|
||||
/* LINELEN is used throughout for buffer sizes, length of file name strings,
|
||||
etc. Let's just have one instead of a multitude of defines all the same. */
|
||||
#define LINELEN 255
|
||||
|
||||
/* Used in a number of places for sprintf() buffers. */
|
||||
#define BUFFERLEN 80
|
||||
|
||||
/* Imperial/Metric conversion */
|
||||
#define MM_PER_INCH 25.4
|
||||
#define INCH_PER_MM (1.0/MM_PER_INCH)
|
||||
|
||||
#endif /* LINUXCNC_H */
|
||||
75
wasm-port/vendor/linuxcnc/src/emc/motion/emcmotcfg.h
vendored
Normal file
75
wasm-port/vendor/linuxcnc/src/emc/motion/emcmotcfg.h
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
/********************************************************************
|
||||
* Description: emcmotcfg.h
|
||||
* Default values for compile-time parameters.
|
||||
*
|
||||
* Derived from a work by Fred Proctor & Will Shackleford
|
||||
*
|
||||
* Author:
|
||||
* License: GPL Version 2
|
||||
* System: Linux
|
||||
*
|
||||
* Copyright (c) 2004 All rights reserved.
|
||||
********************************************************************/
|
||||
#ifndef __LINUXCNC_EMCMOTCFG_H
|
||||
#define __LINUXCNC_EMCMOTCFG_H
|
||||
|
||||
/* default name of EMCMOT INI file */
|
||||
#define DEFAULT_EMCMOT_INIFILE "emc.ini" /* same as for EMC-- we're in
|
||||
touch */
|
||||
|
||||
/* number of joints supported
|
||||
Note: this is not a global variable but a compile-time parameter
|
||||
since it sets array sizes, etc. */
|
||||
|
||||
// total number of joints available (kinematics_joints + extra_joints)
|
||||
#define EMCMOT_MAX_JOINTS 16
|
||||
|
||||
// number of extra joints (NOT used in kinematics calculations):
|
||||
#define EMCMOT_MAX_EXTRAJOINTS EMCMOT_MAX_JOINTS
|
||||
|
||||
/* number of axes defined by the interp */ //FIXME: shouldn't be here..
|
||||
#define EMCMOT_MAX_AXIS 9
|
||||
|
||||
#define EMCMOT_MAX_SPINDLES 8
|
||||
#define EMCMOT_MAX_DIO 64
|
||||
#define EMCMOT_MAX_AIO 64
|
||||
#define EMCMOT_MAX_MISC_ERROR 64
|
||||
|
||||
#if (EMCMOT_MAX_DIO > 64) || (EMCMOT_MAX_AIO > 64)
|
||||
#error A 64 bit bitmask is used in the planner. Don't increase these until that's fixed.
|
||||
#endif
|
||||
|
||||
#define EMCMOT_ERROR_NUM 32 /* how many errors we can queue */
|
||||
#define EMCMOT_ERROR_LEN 1024 /* how long error string can be */
|
||||
|
||||
/*
|
||||
Shared memory keys for simulated motion process. No base address
|
||||
values need to be computed, since operating system does this for us
|
||||
*/
|
||||
#define DEFAULT_SHMEM_KEY 100
|
||||
|
||||
/* default comm timeout, in seconds */
|
||||
#define DEFAULT_EMCMOT_COMM_TIMEOUT 1.0
|
||||
|
||||
/* initial velocity, accel used for coordinated moves */
|
||||
#define DEFAULT_VELOCITY 1.0
|
||||
#define DEFAULT_ACCELERATION 10.0
|
||||
|
||||
/* maximum and minimum limit defaults for all axes */
|
||||
#define DEFAULT_MAX_LIMIT 1000
|
||||
#define DEFAULT_MIN_LIMIT -1000
|
||||
|
||||
/* default number of motion io pins */
|
||||
#define DEFAULT_DIO 4
|
||||
#define DEFAULT_AIO 4
|
||||
#define DEFAULT_MISC_ERROR 0
|
||||
|
||||
/* size of motion queue
|
||||
* a TC_STRUCT is about 512 bytes so this queue is
|
||||
* about a megabyte. */
|
||||
#define DEFAULT_TC_QUEUE_SIZE 2000
|
||||
|
||||
/* max following error */
|
||||
#define DEFAULT_MAX_FERROR 100
|
||||
|
||||
#endif
|
||||
140
wasm-port/vendor/linuxcnc/src/emc/motion/state_tag.h
vendored
Normal file
140
wasm-port/vendor/linuxcnc/src/emc/motion/state_tag.h
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
/********************************************************************
|
||||
* Description: state_tag.h
|
||||
*
|
||||
* A "tag" struct that is used to add interpreter state information to
|
||||
* a given motion line. This state info isn't actually used by motion
|
||||
* directly, but indicates the motion state.
|
||||
*
|
||||
* Copyright © 2015 Robert W. Ellenberg
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
********************************************************************/
|
||||
|
||||
|
||||
#ifndef STATE_TAG_H
|
||||
#define STATE_TAG_H
|
||||
|
||||
|
||||
/**
|
||||
* Enum to define bit names for StateTag's flags register.
|
||||
* The actual position of the flag isn't important, so the actual index doesn't
|
||||
* matter. However, the bit field should be <=64 bits to fit within a long int.
|
||||
*/
|
||||
typedef enum {
|
||||
GM_FLAG_UNITS,
|
||||
GM_FLAG_DISTANCE_MODE,
|
||||
GM_FLAG_TOOL_OFFSETS_ON,
|
||||
GM_FLAG_RETRACT_OLDZ,
|
||||
GM_FLAG_BLEND,
|
||||
GM_FLAG_EXACT_STOP,
|
||||
GM_FLAG_FEED_INVERSE_TIME,
|
||||
GM_FLAG_FEED_UPM,
|
||||
GM_FLAG_CSS_MODE,
|
||||
GM_FLAG_IJK_ABS,
|
||||
GM_FLAG_DIAMETER_MODE,
|
||||
GM_FLAG_G92_IS_APPLIED,
|
||||
GM_FLAG_SPINDLE_ON,
|
||||
GM_FLAG_SPINDLE_CW,
|
||||
GM_FLAG_MIST,
|
||||
GM_FLAG_FLOOD,
|
||||
GM_FLAG_FEED_OVERRIDE,
|
||||
GM_FLAG_SPEED_OVERRIDE,
|
||||
GM_FLAG_ADAPTIVE_FEED,
|
||||
GM_FLAG_FEED_HOLD,
|
||||
GM_FLAG_RESTORABLE,
|
||||
GM_FLAG_IN_REMAP,
|
||||
GM_FLAG_IN_SUB,
|
||||
GM_FLAG_EXTERNAL_FILE,
|
||||
GM_FLAG_IS_CIRCLE,
|
||||
GM_FLAG_MAX_FLAGS
|
||||
} StateFlag;
|
||||
|
||||
|
||||
/**
|
||||
* Enum for various fields of state info that are int type.
|
||||
*
|
||||
* WARNING:
|
||||
*
|
||||
* 1) Since these are used as array indices, they have to start at 0,
|
||||
* be monotonic, and the GM_FIELD_MAX_FIELDS enum MUST be last in the list.
|
||||
*
|
||||
* 2) If your application needs to pass state tags through NML, then
|
||||
* you MUST update the corresponding cms->update function for state
|
||||
* tags.
|
||||
*
|
||||
* TODO: make that standalone function a method here for maintainability
|
||||
*/
|
||||
typedef enum {
|
||||
GM_FIELD_LINE_NUMBER,
|
||||
GM_FIELD_G_MODE_0,
|
||||
GM_FIELD_CUTTER_COMP,
|
||||
GM_FIELD_MOTION_MODE,
|
||||
GM_FIELD_PLANE,
|
||||
GM_FIELD_M_MODES_4,
|
||||
GM_FIELD_ORIGIN,
|
||||
GM_FIELD_TOOLCHANGE,
|
||||
GM_FIELD_MAX_FIELDS
|
||||
} StateField;
|
||||
|
||||
|
||||
/**
|
||||
* Enum for indexing state tag `fields_float`, machine state float
|
||||
* array: feed, speed, etc.
|
||||
*/
|
||||
typedef enum {
|
||||
GM_FIELD_FLOAT_LINE_NUMBER, // eww
|
||||
GM_FIELD_FLOAT_FEED,
|
||||
GM_FIELD_FLOAT_SPEED,
|
||||
GM_FIELD_FLOAT_PATH_TOLERANCE,
|
||||
GM_FIELD_FLOAT_NAIVE_CAM_TOLERANCE,
|
||||
GM_FIELD_FLOAT_ARC_RADIUS,
|
||||
GM_FIELD_FLOAT_ARC_CENTER_X,
|
||||
GM_FIELD_FLOAT_ARC_CENTER_Y,
|
||||
GM_FIELD_FLOAT_ARC_CENTER_Z,
|
||||
GM_FIELD_FLOAT_STRAIGHT_HEADING,
|
||||
GM_FIELD_FLOAT_NORMAL_HEADING,
|
||||
GM_FIELD_FLOAT_MAX_FIELDS
|
||||
} StateFieldFloat;
|
||||
|
||||
/**
|
||||
* Tag structure that is added to a motion segment so that motion has a copy of
|
||||
* the relevant interp state.
|
||||
*
|
||||
* Previously, this information was stored only in the interpreter, and as
|
||||
* vectors of g codes, m codes, and settings. Considering that the write_XXX
|
||||
* and gen_XXX functions had to jump through hoops to translate from a settings
|
||||
* struct, the extra packing here isn't much more complex to deal with, and
|
||||
* will cost much less space when copying back and forth.
|
||||
*/
|
||||
struct state_tag_t {
|
||||
|
||||
// Float-type machine settings: feed, speed, etc., indexed by the
|
||||
// StateFieldFloat enum above
|
||||
float fields_float[GM_FIELD_FLOAT_MAX_FIELDS];
|
||||
|
||||
// Any G / M code states that doesn't pack nicely into a single bit
|
||||
// These are an array mostly because it's easier to pass an
|
||||
// arbitrary-length array through NML than individual fields
|
||||
int fields[GM_FIELD_MAX_FIELDS];
|
||||
|
||||
/** G / M mode flags for simple states like inch / mm, feedhold enable, etc.
|
||||
* This stores packed bits in one field (since we can't use a bitset in a
|
||||
* pure C struct).
|
||||
*/
|
||||
unsigned long int packed_flags;
|
||||
char filename[256];
|
||||
};
|
||||
|
||||
#endif
|
||||
1069
wasm-port/vendor/linuxcnc/src/emc/nml_intf/canon.hh
vendored
Normal file
1069
wasm-port/vendor/linuxcnc/src/emc/nml_intf/canon.hh
vendored
Normal file
File diff suppressed because it is too large
Load Diff
77
wasm-port/vendor/linuxcnc/src/emc/nml_intf/canon_position.hh
vendored
Normal file
77
wasm-port/vendor/linuxcnc/src/emc/nml_intf/canon_position.hh
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
/********************************************************************
|
||||
* Description: canon_position.hh
|
||||
*
|
||||
* CANON position class with operators and common functions
|
||||
* Derived from a work by Thomas Kramer
|
||||
*
|
||||
* Author: Robert W. Ellenberg
|
||||
* License: GPL Version 2+
|
||||
* System: Linux
|
||||
*
|
||||
* Copyright (c) 2014 All rights reserved.
|
||||
********************************************************************/
|
||||
|
||||
#ifndef CANON_POSITION_HH
|
||||
#define CANON_POSITION_HH
|
||||
|
||||
#include <stdio.h> // FILE
|
||||
#include <vector>
|
||||
|
||||
#include <emcpos.h>
|
||||
#include "emctool.h"
|
||||
#include <posemath.h> // For PM_CARTESIAN type
|
||||
|
||||
struct CANON_POSITION {
|
||||
#ifndef JAVA_DIAG_APPLET
|
||||
CANON_POSITION() :
|
||||
x(0.0),
|
||||
y(0.0),
|
||||
z(0.0),
|
||||
a(0.0),
|
||||
b(0.0),
|
||||
c(0.0),
|
||||
u(0.0),
|
||||
v(0.0),
|
||||
w(0.0) {}
|
||||
|
||||
CANON_POSITION(double _x, double _y, double _z,
|
||||
double _a, double _b, double _c,
|
||||
double _u, double _v, double _w);
|
||||
CANON_POSITION(const EmcPose &_pos);
|
||||
CANON_POSITION(PM_CARTESIAN const &xyz);
|
||||
CANON_POSITION(PM_CARTESIAN const &xyz, PM_CARTESIAN const &abc);
|
||||
|
||||
bool operator==(const CANON_POSITION &o) const;
|
||||
bool operator!=(const CANON_POSITION &o) const;
|
||||
CANON_POSITION & operator+=(const CANON_POSITION &o);
|
||||
CANON_POSITION & operator+=(const EmcPose &o);
|
||||
|
||||
const CANON_POSITION operator+(const CANON_POSITION &o) const;
|
||||
const CANON_POSITION operator+(const EmcPose &o) const;
|
||||
CANON_POSITION & operator-=(const CANON_POSITION &o);
|
||||
CANON_POSITION & operator-=(const EmcPose &o);
|
||||
|
||||
const CANON_POSITION operator-(const CANON_POSITION &o) const;
|
||||
const CANON_POSITION operator-(const EmcPose &o) const;
|
||||
|
||||
double &operator[](const int ind);
|
||||
|
||||
const CANON_POSITION abs() const;
|
||||
const CANON_POSITION absdiff(const CANON_POSITION &o) const;
|
||||
double max() const;
|
||||
|
||||
const EmcPose toEmcPose() const;
|
||||
|
||||
const PM_CARTESIAN xyz() const;
|
||||
const PM_CARTESIAN abc() const;
|
||||
const PM_CARTESIAN uvw() const;
|
||||
|
||||
void set_xyz(const PM_CARTESIAN & xyz);
|
||||
|
||||
void print() const;
|
||||
#endif
|
||||
|
||||
double x, y, z, a, b, c, u, v, w;
|
||||
};
|
||||
|
||||
#endif /* ifndef CANON_POSITION_HH */
|
||||
50
wasm-port/vendor/linuxcnc/src/emc/nml_intf/debugflags.h
vendored
Normal file
50
wasm-port/vendor/linuxcnc/src/emc/nml_intf/debugflags.h
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
/* This is a component of LinuxCNC
|
||||
* Copyright 2011, 2012, 2013 Michael Haberler <git@mah.priv.at>,
|
||||
* Sebastian Kuzminsky <seb@highlab.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
// factored out from emcglb.h so subsystems not requiring the
|
||||
// emcglb.h defines may include them as well
|
||||
|
||||
|
||||
|
||||
#define EMC_DEBUG_CONFIG 0x00000002
|
||||
#define EMC_DEBUG_VERSIONS 0x00000008
|
||||
#define EMC_DEBUG_TASK_ISSUE 0x00000010
|
||||
#define EMC_DEBUG_NML 0x00000040
|
||||
#define EMC_DEBUG_MOTION_TIME 0x00000080
|
||||
#define EMC_DEBUG_INTERP 0x00000100
|
||||
#define EMC_DEBUG_RCS 0x00000200
|
||||
#define EMC_DEBUG_INTERP_LIST 0x00000800
|
||||
#define EMC_DEBUG_IOCONTROL 0x00001000
|
||||
#define EMC_DEBUG_OWORD 0x00002000
|
||||
#define EMC_DEBUG_REMAP 0x00004000
|
||||
#define EMC_DEBUG_PYTHON 0x00008000
|
||||
#define EMC_DEBUG_NAMEDPARAM 0x00010000
|
||||
#define EMC_DEBUG_GDBONSIGNAL 0x00020000
|
||||
#define EMC_DEBUG_STATE_TAGS 0x00080000
|
||||
|
||||
// not interpreted by EMC.
|
||||
#define EMC_DEBUG_USER1 0x10000000
|
||||
#define EMC_DEBUG_USER2 0x20000000
|
||||
|
||||
#define EMC_DEBUG_UNCONDITIONAL 0x40000000 // always logged
|
||||
#define EMC_DEBUG_ALL 0x7FFFFFFF /* it's an int for %i to work
|
||||
*/
|
||||
// debug prefix flags
|
||||
#define LOG_TIME 1
|
||||
#define LOG_PID 2
|
||||
#define LOG_FILENAME 4 // and line
|
||||
483
wasm-port/vendor/linuxcnc/src/emc/nml_intf/emc.hh
vendored
Normal file
483
wasm-port/vendor/linuxcnc/src/emc/nml_intf/emc.hh
vendored
Normal file
@@ -0,0 +1,483 @@
|
||||
/********************************************************************
|
||||
* Description: emc.hh
|
||||
* Declarations for EMC NML vocabulary
|
||||
*
|
||||
* Derived from a work by Fred Proctor & Will Shackleford
|
||||
*
|
||||
* Author:
|
||||
* License: GPL Version 2
|
||||
* System: Linux
|
||||
*
|
||||
* Copyright (c) 2004 All rights reserved.
|
||||
*
|
||||
* Last change:
|
||||
********************************************************************/
|
||||
#ifndef EMC_HH
|
||||
#define EMC_HH
|
||||
|
||||
#include <emcmotcfg.h> // EMC_JOINT_MAX, EMC_AXIS_MAX
|
||||
#include "libnml/nml/nml_type.hh"
|
||||
#include "motion_types.h"
|
||||
#include <stdint.h>
|
||||
#include "rs274ngc/modal_state.hh"
|
||||
|
||||
// Forward class declarations
|
||||
class EMC_JOINT_STAT;
|
||||
class EMC_AXIS_STAT;
|
||||
class EMC_TRAJ_STAT;
|
||||
class EMC_MOTION_STAT;
|
||||
class EMC_TASK_STAT;
|
||||
class EMC_TOOL_STAT;
|
||||
class EMC_AUX_STAT;
|
||||
class EMC_SPINDLE_STAT;
|
||||
class EMC_COOLANT_STAT;
|
||||
class EMC_IO_STAT;
|
||||
class EMC_STAT;
|
||||
class CMS;
|
||||
class RCS_CMD_CHANNEL;
|
||||
class RCS_STAT_CHANNEL;
|
||||
class NML;
|
||||
struct EmcPose;
|
||||
struct PM_CARTESIAN;
|
||||
|
||||
// ---------------------
|
||||
// EMC TYPE DECLARATIONS
|
||||
// ---------------------
|
||||
|
||||
// NML for base EMC
|
||||
|
||||
#define EMC_OPERATOR_ERROR_TYPE ((NMLTYPE) 11)
|
||||
#define EMC_OPERATOR_TEXT_TYPE ((NMLTYPE) 12)
|
||||
#define EMC_OPERATOR_DISPLAY_TYPE ((NMLTYPE) 13)
|
||||
|
||||
#define EMC_NULL_TYPE ((NMLTYPE) 21)
|
||||
|
||||
#define EMC_SET_DEBUG_TYPE ((NMLTYPE) 22)
|
||||
|
||||
#define EMC_SYSTEM_CMD_TYPE ((NMLTYPE) 30)
|
||||
|
||||
// NML for EMC_JOINT
|
||||
|
||||
#define EMC_JOINT_SET_MIN_POSITION_LIMIT_TYPE ((NMLTYPE) 107)
|
||||
#define EMC_JOINT_SET_MAX_POSITION_LIMIT_TYPE ((NMLTYPE) 108)
|
||||
#define EMC_JOINT_SET_FERROR_TYPE ((NMLTYPE) 111)
|
||||
#define EMC_JOINT_SET_HOMING_PARAMS_TYPE ((NMLTYPE) 112)
|
||||
#define EMC_JOINT_SET_MIN_FERROR_TYPE ((NMLTYPE) 115)
|
||||
#define EMC_JOINT_HALT_TYPE ((NMLTYPE) 119)
|
||||
#define EMC_JOINT_HOME_TYPE ((NMLTYPE) 123)
|
||||
#define EMC_JOG_CONT_TYPE ((NMLTYPE) 124)
|
||||
#define EMC_JOG_INCR_TYPE ((NMLTYPE) 125)
|
||||
#define EMC_JOG_ABS_TYPE ((NMLTYPE) 126)
|
||||
#define EMC_JOINT_OVERRIDE_LIMITS_TYPE ((NMLTYPE) 129)
|
||||
#define EMC_JOINT_LOAD_COMP_TYPE ((NMLTYPE) 131)
|
||||
#define EMC_JOINT_SET_BACKLASH_TYPE ((NMLTYPE) 134)
|
||||
#define EMC_JOINT_UNHOME_TYPE ((NMLTYPE) 135)
|
||||
#define EMC_JOG_STOP_TYPE ((NMLTYPE) 136)
|
||||
|
||||
#define EMC_JOINT_STAT_TYPE ((NMLTYPE) 198)
|
||||
#define EMC_AXIS_STAT_TYPE ((NMLTYPE) 199)
|
||||
|
||||
// NML for EMC_TRAJ
|
||||
|
||||
// defs for termination conditions
|
||||
#define EMC_TRAJ_TERM_COND_STOP 0
|
||||
#define EMC_TRAJ_TERM_COND_EXACT 1
|
||||
#define EMC_TRAJ_TERM_COND_BLEND 2
|
||||
|
||||
#define EMC_TRAJ_SET_MODE_TYPE ((NMLTYPE) 204)
|
||||
#define EMC_TRAJ_SET_VELOCITY_TYPE ((NMLTYPE) 205)
|
||||
#define EMC_TRAJ_SET_ACCELERATION_TYPE ((NMLTYPE) 206)
|
||||
#define EMC_TRAJ_SET_MAX_VELOCITY_TYPE ((NMLTYPE) 207)
|
||||
#define EMC_TRAJ_SET_SCALE_TYPE ((NMLTYPE) 209)
|
||||
#define EMC_TRAJ_SET_RAPID_SCALE_TYPE ((NMLTYPE) 238)
|
||||
|
||||
#define EMC_TRAJ_ABORT_TYPE ((NMLTYPE) 215)
|
||||
#define EMC_TRAJ_PAUSE_TYPE ((NMLTYPE) 216)
|
||||
#define EMC_TRAJ_RESUME_TYPE ((NMLTYPE) 218)
|
||||
#define EMC_TRAJ_DELAY_TYPE ((NMLTYPE) 219)
|
||||
#define EMC_TRAJ_LINEAR_MOVE_TYPE ((NMLTYPE) 220)
|
||||
#define EMC_TRAJ_CIRCULAR_MOVE_TYPE ((NMLTYPE) 221)
|
||||
#define EMC_TRAJ_SET_TERM_COND_TYPE ((NMLTYPE) 222)
|
||||
#define EMC_TRAJ_SET_OFFSET_TYPE ((NMLTYPE) 223)
|
||||
#define EMC_TRAJ_SET_G5X_TYPE ((NMLTYPE) 224)
|
||||
#define EMC_TRAJ_SET_ROTATION_TYPE ((NMLTYPE) 226)
|
||||
#define EMC_TRAJ_SET_G92_TYPE ((NMLTYPE) 227)
|
||||
#define EMC_TRAJ_CLEAR_PROBE_TRIPPED_FLAG_TYPE ((NMLTYPE) 228)
|
||||
#define EMC_TRAJ_PROBE_TYPE ((NMLTYPE) 229)
|
||||
#define EMC_TRAJ_SET_TELEOP_ENABLE_TYPE ((NMLTYPE) 230)
|
||||
#define EMC_TRAJ_SET_SPINDLESYNC_TYPE ((NMLTYPE) 232)
|
||||
#define EMC_TRAJ_SET_SPINDLE_SCALE_TYPE ((NMLTYPE) 233)
|
||||
#define EMC_TRAJ_SET_FO_ENABLE_TYPE ((NMLTYPE) 234)
|
||||
#define EMC_TRAJ_SET_SO_ENABLE_TYPE ((NMLTYPE) 235)
|
||||
#define EMC_TRAJ_SET_FH_ENABLE_TYPE ((NMLTYPE) 236)
|
||||
#define EMC_TRAJ_RIGID_TAP_TYPE ((NMLTYPE) 237)
|
||||
|
||||
#define EMC_TRAJ_STAT_TYPE ((NMLTYPE) 299)
|
||||
|
||||
// EMC_MOTION aggregate class type declaration
|
||||
|
||||
#define EMC_MOTION_SET_AOUT_TYPE ((NMLTYPE) 304)
|
||||
#define EMC_MOTION_SET_DOUT_TYPE ((NMLTYPE) 305)
|
||||
#define EMC_MOTION_ADAPTIVE_TYPE ((NMLTYPE) 306)
|
||||
|
||||
#define EMC_MOTION_STAT_TYPE ((NMLTYPE) 399)
|
||||
|
||||
// NML for EMC_TASK
|
||||
|
||||
#define EMC_TASK_ABORT_TYPE ((NMLTYPE) 503)
|
||||
#define EMC_TASK_SET_MODE_TYPE ((NMLTYPE) 504)
|
||||
#define EMC_TASK_SET_STATE_TYPE ((NMLTYPE) 505)
|
||||
#define EMC_TASK_PLAN_OPEN_TYPE ((NMLTYPE) 506)
|
||||
#define EMC_TASK_PLAN_RUN_TYPE ((NMLTYPE) 507)
|
||||
#define EMC_TASK_PLAN_EXECUTE_TYPE ((NMLTYPE) 509)
|
||||
#define EMC_TASK_PLAN_PAUSE_TYPE ((NMLTYPE) 510)
|
||||
#define EMC_TASK_PLAN_STEP_TYPE ((NMLTYPE) 511)
|
||||
#define EMC_TASK_PLAN_RESUME_TYPE ((NMLTYPE) 512)
|
||||
#define EMC_TASK_PLAN_END_TYPE ((NMLTYPE) 513)
|
||||
#define EMC_TASK_PLAN_CLOSE_TYPE ((NMLTYPE) 514)
|
||||
#define EMC_TASK_PLAN_INIT_TYPE ((NMLTYPE) 515)
|
||||
#define EMC_TASK_PLAN_SYNCH_TYPE ((NMLTYPE) 516)
|
||||
#define EMC_TASK_PLAN_SET_OPTIONAL_STOP_TYPE ((NMLTYPE) 517)
|
||||
#define EMC_TASK_PLAN_SET_BLOCK_DELETE_TYPE ((NMLTYPE) 518)
|
||||
#define EMC_TASK_PLAN_OPTIONAL_STOP_TYPE ((NMLTYPE) 519)
|
||||
#define EMC_TASK_PLAN_REVERSE_TYPE ((NMLTYPE) 520)
|
||||
#define EMC_TASK_PLAN_FORWARD_TYPE ((NMLTYPE) 521)
|
||||
|
||||
#define EMC_TASK_STAT_TYPE ((NMLTYPE) 599)
|
||||
|
||||
// EMC_TOOL type declarations
|
||||
|
||||
#define EMC_TOOL_HALT_TYPE ((NMLTYPE) 1102)
|
||||
#define EMC_TOOL_ABORT_TYPE ((NMLTYPE) 1103)
|
||||
#define EMC_TOOL_PREPARE_TYPE ((NMLTYPE) 1104)
|
||||
#define EMC_TOOL_LOAD_TYPE ((NMLTYPE) 1105)
|
||||
#define EMC_TOOL_UNLOAD_TYPE ((NMLTYPE) 1106)
|
||||
#define EMC_TOOL_LOAD_TOOL_TABLE_TYPE ((NMLTYPE) 1107)
|
||||
#define EMC_TOOL_SET_OFFSET_TYPE ((NMLTYPE) 1108)
|
||||
#define EMC_TOOL_SET_NUMBER_TYPE ((NMLTYPE) 1109)
|
||||
|
||||
#define EMC_TOOL_STAT_TYPE ((NMLTYPE) 1199)
|
||||
|
||||
// EMC_AUX type declarations
|
||||
#define EMC_AUX_INPUT_WAIT_TYPE ((NMLTYPE) 1209)
|
||||
|
||||
#define EMC_AUX_STAT_TYPE ((NMLTYPE) 1299)
|
||||
|
||||
// EMC_SPINDLE type declarations
|
||||
#define EMC_SPINDLE_ON_TYPE ((NMLTYPE) 1304)
|
||||
#define EMC_SPINDLE_OFF_TYPE ((NMLTYPE) 1305)
|
||||
#define EMC_SPINDLE_INCREASE_TYPE ((NMLTYPE) 1309)
|
||||
#define EMC_SPINDLE_DECREASE_TYPE ((NMLTYPE) 1310)
|
||||
#define EMC_SPINDLE_CONSTANT_TYPE ((NMLTYPE) 1311)
|
||||
#define EMC_SPINDLE_BRAKE_RELEASE_TYPE ((NMLTYPE) 1312)
|
||||
#define EMC_SPINDLE_BRAKE_ENGAGE_TYPE ((NMLTYPE) 1313)
|
||||
#define EMC_SPINDLE_SPEED_TYPE ((NMLTYPE) 1316)
|
||||
#define EMC_SPINDLE_ORIENT_TYPE ((NMLTYPE) 1317)
|
||||
#define EMC_SPINDLE_WAIT_ORIENT_COMPLETE_TYPE ((NMLTYPE) 1318)
|
||||
|
||||
#define EMC_SPINDLE_STAT_TYPE ((NMLTYPE) 1399)
|
||||
|
||||
// EMC_COOLANT type declarations
|
||||
#define EMC_COOLANT_MIST_ON_TYPE ((NMLTYPE) 1404)
|
||||
#define EMC_COOLANT_MIST_OFF_TYPE ((NMLTYPE) 1405)
|
||||
#define EMC_COOLANT_FLOOD_ON_TYPE ((NMLTYPE) 1406)
|
||||
#define EMC_COOLANT_FLOOD_OFF_TYPE ((NMLTYPE) 1407)
|
||||
|
||||
#define EMC_COOLANT_STAT_TYPE ((NMLTYPE) 1499)
|
||||
|
||||
#define EMC_IO_STAT_TYPE ((NMLTYPE) 1699)
|
||||
|
||||
#define EMC_STAT_TYPE ((NMLTYPE) 1999)
|
||||
|
||||
// types for EMC_TASK mode
|
||||
enum class EMC_TASK_MODE {
|
||||
MANUAL = 1,
|
||||
AUTO = 2,
|
||||
MDI = 3
|
||||
};
|
||||
|
||||
// types for EMC_TASK state
|
||||
enum class EMC_TASK_STATE {
|
||||
ESTOP = 1,
|
||||
ESTOP_RESET = 2,
|
||||
OFF = 3,
|
||||
ON = 4
|
||||
};
|
||||
|
||||
// types for EMC_TASK execState
|
||||
enum class EMC_TASK_EXEC {
|
||||
ERROR = 1,
|
||||
DONE = 2,
|
||||
WAITING_FOR_MOTION = 3,
|
||||
WAITING_FOR_MOTION_QUEUE = 4,
|
||||
WAITING_FOR_IO = 5,
|
||||
WAITING_FOR_MOTION_AND_IO = 7,
|
||||
WAITING_FOR_DELAY = 8,
|
||||
WAITING_FOR_SYSTEM_CMD = 9,
|
||||
WAITING_FOR_SPINDLE_ORIENTED = 10
|
||||
};
|
||||
|
||||
// types for EMC_TASK interpState
|
||||
enum class EMC_TASK_INTERP {
|
||||
IDLE = 1,
|
||||
READING = 2,
|
||||
PAUSED = 3,
|
||||
WAITING = 4
|
||||
};
|
||||
|
||||
// types for motion control
|
||||
enum class EMC_TRAJ_MODE {
|
||||
FREE = 1, // independent-axis motion,
|
||||
COORD = 2, // coordinated-axis motion,
|
||||
TELEOP = 3 // velocity based world coordinates motion,
|
||||
};
|
||||
|
||||
// types for emcIoAbort() reasons
|
||||
enum class EMC_ABORT {
|
||||
TASK_EXEC_ERROR = 1,
|
||||
AUX_ESTOP = 2,
|
||||
MOTION_OR_IO_RCS_ERROR = 3,
|
||||
TASK_STATE_OFF = 4,
|
||||
TASK_STATE_ESTOP_RESET = 5,
|
||||
TASK_STATE_ESTOP = 6,
|
||||
TASK_STATE_NOT_ON = 7,
|
||||
TASK_ABORT = 8,
|
||||
INTERPRETER_ERROR = 9, // interpreter failed during readahead
|
||||
INTERPRETER_ERROR_MDI = 10, // interpreter failed during MDI execution
|
||||
USER = 100 // user-defined abort codes start here
|
||||
};
|
||||
// --------------
|
||||
// EMC VOCABULARY
|
||||
// --------------
|
||||
|
||||
// NML formatting function
|
||||
extern int emcFormat(NMLTYPE type, void *buffer, CMS * cms);
|
||||
|
||||
// NML Symbol Lookup Function
|
||||
extern const char *emc_symbol_lookup(uint32_t type);
|
||||
#define emcSymbolLookup(a) emc_symbol_lookup(a)
|
||||
|
||||
// decls for command line args-- mains are responsible for setting these
|
||||
// so that other modules can get cmd line args for ad hoc processing
|
||||
extern int Argc;
|
||||
extern char **Argv;
|
||||
|
||||
// ------------------------
|
||||
// IMPLEMENTATION FUNCTIONS
|
||||
// ------------------------
|
||||
|
||||
// implementation functions for EMC error, message types
|
||||
// intended to be implemented in main() file, by writing to NML buffer
|
||||
|
||||
// print an error
|
||||
extern int emcOperatorError(const char *fmt, ...) __attribute__((format(printf,1,2)));
|
||||
|
||||
// print general text
|
||||
extern int emcOperatorText(const char *fmt, ...) __attribute__((format(printf,1,2)));
|
||||
|
||||
// print note to operator
|
||||
extern int emcOperatorDisplay(const char *fmt, ...) __attribute__((format(printf,1,2)));
|
||||
|
||||
// implementation functions for EMC_AXIS types
|
||||
|
||||
extern int emcAxisSetMinPositionLimit(int axis, double limit);
|
||||
extern int emcAxisSetMaxPositionLimit(int axis, double limit);
|
||||
extern int emcAxisSetMaxVelocity(int axis, double vel, double ext_offset_vel);
|
||||
extern int emcAxisSetMaxAcceleration(int axis, double acc, double ext_offset_acc);
|
||||
extern double emcAxisGetMaxVelocity(int axis);
|
||||
extern double emcAxisGetMaxAcceleration(int axis);
|
||||
extern int emcAxisSetLockingJoint(int axis,int joint);
|
||||
|
||||
extern int emcAxisUpdate(EMC_AXIS_STAT stat[], int numAxes);
|
||||
|
||||
extern int emcAxisSetMaxJerk(int axis,double jerk);
|
||||
extern int emcAxisHasMaxJerk(int axis);
|
||||
extern double emcAxisGetMaxJerk(int axis);
|
||||
// implementation functions for EMC_JOINT types
|
||||
|
||||
extern int emcJointSetType(int joint, unsigned char jointType);
|
||||
extern int emcJointSetUnits(int joint, double units);
|
||||
extern int emcJointSetBacklash(int joint, double backlash);
|
||||
extern int emcJointSetMinPositionLimit(int joint, double limit);
|
||||
extern int emcJointSetMaxPositionLimit(int joint, double limit);
|
||||
extern int emcJointSetMotorOffset(int joint, double offset);
|
||||
extern int emcJointSetFerror(int joint, double ferror);
|
||||
extern int emcJointSetMinFerror(int joint, double ferror);
|
||||
extern int emcJointSetHomingParams(int joint, double home, double offset, double home_vel,
|
||||
double search_vel, double latch_vel,
|
||||
int use_index, int encoder_does_not_reset, int ignore_limits,
|
||||
int is_shared, int home_sequence, int volatile_home, int locking_indexer,
|
||||
int absolute_encoder);
|
||||
extern int emcJointUpdateHomingParams(int joint, double home, double offset, int sequence);
|
||||
extern int emcJointSetMaxVelocity(int joint, double vel);
|
||||
extern int emcJointSetMaxAcceleration(int joint, double acc);
|
||||
|
||||
extern int emcJointInit(int joint);
|
||||
extern int emcJointHalt(int joint);
|
||||
extern int emcJointHome(int joint);
|
||||
extern int emcJointUnhome(int joint);
|
||||
extern int emcJointActivate(int joint);
|
||||
extern int emcJointDeactivate(int joint);
|
||||
extern int emcJointOverrideLimits(int joint);
|
||||
extern int emcJointLoadComp(int joint, const char *file, int type);
|
||||
extern int emcJogStop(int nr, int jjogmode);
|
||||
extern int emcJogCont(int nr, double vel, int jjogmode);
|
||||
extern int emcJogIncr(int nr, double incr, double vel, int jjogmode);
|
||||
extern int emcJogAbs(int nr, double pos, double vel, int jjogmode);
|
||||
|
||||
|
||||
extern int emcJointUpdate(EMC_JOINT_STAT stat[], int numJoints);
|
||||
|
||||
extern int emcJointSetMaxJerk(int joint, double jerk);
|
||||
|
||||
// implementation functions for EMC_SPINDLE types
|
||||
|
||||
extern int emcSpindleSetParams(int spindle, double max_pos, double min_pos, double max_neg,
|
||||
double min_neg, double search_vel, double home_angle, int sequence, double increment);
|
||||
|
||||
// implementation functions for EMC_TRAJ types
|
||||
|
||||
extern int emcTrajSetJoints(int joints);
|
||||
extern int emcTrajUpdateTag(StateTag const &tag);
|
||||
extern int emcTrajSetAxes(int axismask);
|
||||
extern int emcTrajSetSpindles(int spindles);
|
||||
extern int emcTrajSetUnits(double linearUnits, double angularUnits);
|
||||
extern int emcTrajSetMode(EMC_TRAJ_MODE traj_mode);
|
||||
extern int emcTrajSetVelocity(double vel, double ini_maxvel);
|
||||
extern int emcTrajSetAcceleration(double acc);
|
||||
extern int emcTrajSetMaxVelocity(double vel);
|
||||
extern int emcTrajSetMaxAcceleration(double acc);
|
||||
extern int emcTrajSetScale(double scale);
|
||||
extern int emcTrajSetRapidScale(double scale);
|
||||
extern int emcTrajSetFOEnable(unsigned char mode); //feed override enable
|
||||
extern int emcTrajSetFHEnable(unsigned char mode); //feed hold enable
|
||||
extern int emcTrajSetSpindleScale(int spindle, double scale);
|
||||
extern int emcTrajSetSOEnable(unsigned char mode); //spindle speed override enable
|
||||
extern int emcTrajSetAFEnable(unsigned char enable); //adaptive feed enable
|
||||
extern int emcTrajSetMotionId(int id);
|
||||
extern double emcTrajGetLinearUnits();
|
||||
extern double emcTrajGetAngularUnits();
|
||||
|
||||
extern int emcTrajInit();
|
||||
extern int emcTrajHalt();
|
||||
extern int emcTrajEnable();
|
||||
extern int emcTrajDisable();
|
||||
extern int emcTrajAbort();
|
||||
extern int emcTrajPause();
|
||||
extern int emcTrajReverse();
|
||||
extern int emcTrajForward();
|
||||
extern int emcTrajStep();
|
||||
extern int emcTrajResume();
|
||||
extern int emcTrajDelay(double delay);
|
||||
extern int emcTrajLinearMove(const EmcPose& end, int type, double vel,
|
||||
double ini_maxvel, double acc, double ini_maxjerk, int indexer_jnum);
|
||||
extern int emcTrajCircularMove(const EmcPose& end, const PM_CARTESIAN& center, const PM_CARTESIAN&
|
||||
normal, int turn, int type, double vel, double ini_maxvel, double acc, double ini_maxjerk);
|
||||
extern int emcTrajSetTermCond(int cond, double tolerance);
|
||||
extern int emcTrajSetSpindleSync(int spindle, double feed_per_revolution, bool wait_for_index);
|
||||
extern int emcTrajSetOffset(const EmcPose& tool_offset);
|
||||
extern int emcTrajSetHome(const EmcPose& home);
|
||||
extern int emcTrajClearProbeTrippedFlag();
|
||||
extern int emcTrajProbe(const EmcPose& pos, int type, double vel,
|
||||
double ini_maxvel, double acc, double ini_maxjerk, unsigned char probe_type);
|
||||
extern int emcTrajRigidTap(const EmcPose& pos, double vel, double ini_maxvel, double acc, double ini_maxjerk, double scale);
|
||||
|
||||
extern int emcTrajUpdate(EMC_TRAJ_STAT * stat);
|
||||
|
||||
extern int emcTrajSetJerk(double jerk);
|
||||
extern int emcTrajSetMaxJerk(double jerk);
|
||||
extern int emcTrajPlannerType(int type);
|
||||
// implementation functions for EMC_MOTION aggregate types
|
||||
|
||||
extern int emcMotionInit();
|
||||
extern int emcMotionHalt();
|
||||
extern int emcMotionAbort();
|
||||
extern int emcMotionSetDebug(int debug);
|
||||
extern int emcMotionSetAout(unsigned char index, double start, double end,
|
||||
unsigned char now);
|
||||
extern int emcMotionSetDout(unsigned char index, unsigned char start,
|
||||
unsigned char end, unsigned char now);
|
||||
|
||||
extern int emcMotionUpdate(EMC_MOTION_STAT * stat);
|
||||
|
||||
extern int emcAbortCleanup(EMC_ABORT reason,const char *message = "");
|
||||
|
||||
// implementation functions for EMC_TOOL types
|
||||
|
||||
extern int emcToolPrepare(int tool);
|
||||
extern int emcToolLoad();
|
||||
extern int emcToolUnload();
|
||||
extern int emcToolLoadToolTable(const char *file);
|
||||
extern int emcToolSetOffset(int pocket, int toolno, const EmcPose& offset, double diameter,
|
||||
double frontangle, double backangle, int orientation);
|
||||
extern int emcToolSetNumber(int number);
|
||||
|
||||
// implementation functions for EMC_AUX types
|
||||
|
||||
extern int emcAuxEstopOn();
|
||||
extern int emcAuxEstopOff();
|
||||
|
||||
// implementation functions for EMC_SPINDLE types
|
||||
|
||||
extern int emcSpindleAbort(int spindle);
|
||||
extern int emcSpindleSpeed(int spindle, double speed, double factor, double xoffset);
|
||||
extern int emcSpindleOn(int spindle, double speed, double factor, double xoffset,int wait_for_atspeed = 1);
|
||||
extern int emcSpindleOrient(int spindle, double orientation, int direction);
|
||||
extern int emcSpindleOff(int spindle);
|
||||
extern int emcSpindleIncrease(int spindle);
|
||||
extern int emcSpindleDecrease(int spindle);
|
||||
extern int emcSpindleConstant(int spindle);
|
||||
extern int emcSpindleBrakeRelease(int spindle);
|
||||
extern int emcSpindleBrakeEngage(int spindle);
|
||||
|
||||
extern int emcSpindleUpdate(EMC_SPINDLE_STAT stat[], int num_spindles);
|
||||
|
||||
// implementation functions for EMC_COOLANT types
|
||||
|
||||
extern int emcCoolantMistOn();
|
||||
extern int emcCoolantMistOff();
|
||||
extern int emcCoolantFloodOn();
|
||||
extern int emcCoolantFloodOff();
|
||||
|
||||
// implementation functions for EMC_IO types
|
||||
|
||||
extern int emcIoInit();
|
||||
extern int emcIoAbort(EMC_ABORT reason);
|
||||
|
||||
// implementation functions for EMC aggregate types
|
||||
|
||||
int emcSetMaxFeedOverride(double maxFeedScale);
|
||||
int emcSetupArcBlends(int arcBlendEnable,
|
||||
int arcBlendFallbackEnable,
|
||||
int arcBlendOptDepth,
|
||||
int arcBlendGapCycles,
|
||||
double arcBlendRampFreq,
|
||||
double arcBlendTangentKinkRatio);
|
||||
int emcSetProbeErrorInhibit(int j_inhibit, int h_inhibit);
|
||||
int emcGetExternalOffsetApplied(void);
|
||||
EmcPose emcGetExternalOffsets(void);
|
||||
|
||||
extern int emcUpdate(EMC_STAT * stat);
|
||||
// full EMC status
|
||||
extern EMC_STAT *emcStatus;
|
||||
|
||||
// EMC IO status
|
||||
extern EMC_IO_STAT *emcIoStatus;
|
||||
|
||||
// EMC MOTION status
|
||||
extern EMC_MOTION_STAT *emcMotionStatus;
|
||||
|
||||
// values for EMC_JOINT_SET_JOINT, jointType
|
||||
enum EmcJointType : int {
|
||||
EMC_LINEAR = 1,
|
||||
EMC_ANGULAR = 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the units conversion factor.
|
||||
* @see EMC_JOINT_SET_INPUT_SCALE
|
||||
*/
|
||||
using EmcLinearUnits = double;
|
||||
using EmcAngularUnits = double;
|
||||
|
||||
#endif // #ifndef EMC_HH
|
||||
36
wasm-port/vendor/linuxcnc/src/emc/nml_intf/emcpos.h
vendored
Normal file
36
wasm-port/vendor/linuxcnc/src/emc/nml_intf/emcpos.h
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/********************************************************************
|
||||
* Description: emcpos.h
|
||||
*
|
||||
* Derived from a work by Fred Proctor & Will Shackleford
|
||||
*
|
||||
* Author:
|
||||
* License: GPL Version 2
|
||||
* System: Linux
|
||||
*
|
||||
* Copyright (c) 2004 All rights reserved.
|
||||
*
|
||||
* Last change:
|
||||
********************************************************************/
|
||||
#ifndef __LINUXCNC_EMCPOS_H
|
||||
#define __LINUXCNC_EMCPOS_H
|
||||
|
||||
#include "posemath.h" /* PmCartesian */
|
||||
|
||||
typedef struct EmcPose {
|
||||
PmCartesian tran;
|
||||
double a, b, c;
|
||||
double u, v, w;
|
||||
} EmcPose;
|
||||
|
||||
#define ZERO_EMC_POSE(pos) do { \
|
||||
(pos).tran.x = 0.0; \
|
||||
(pos).tran.y = 0.0; \
|
||||
(pos).tran.z = 0.0; \
|
||||
(pos).a = 0.0; \
|
||||
(pos).b = 0.0; \
|
||||
(pos).c = 0.0; \
|
||||
(pos).u = 0.0; \
|
||||
(pos).v = 0.0; \
|
||||
(pos).w = 0.0; } while(0)
|
||||
|
||||
#endif
|
||||
51
wasm-port/vendor/linuxcnc/src/emc/nml_intf/emcpose.h
vendored
Normal file
51
wasm-port/vendor/linuxcnc/src/emc/nml_intf/emcpose.h
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
/********************************************************************
|
||||
* Description: emcpose.h
|
||||
*
|
||||
* Derived from a work by Fred Proctor & Will Shackleford
|
||||
*
|
||||
* Author: Robert W. Ellenberg
|
||||
* License: GPL Version 2
|
||||
* System: Linux
|
||||
*
|
||||
* Copyright (c) 2004 All rights reserved.
|
||||
*
|
||||
********************************************************************/
|
||||
#ifndef __LINUXCNC_EMCPOSE_H
|
||||
#define __LINUXCNC_EMCPOSE_H
|
||||
|
||||
#include "emcpos.h"
|
||||
|
||||
typedef enum {
|
||||
EMCPOSE_ERR_OK = 0,
|
||||
EMCPOSE_ERR_FAIL = -1,
|
||||
EMCPOSE_ERR_INPUT_MISSING = -2,
|
||||
EMCPOSE_ERR_OUTPUT_MISSING = -3,
|
||||
EMCPOSE_ERR_ALL
|
||||
} EmcPoseErr;
|
||||
|
||||
void emcPoseZero(EmcPose * const pos);
|
||||
|
||||
int emcPoseAdd(EmcPose const * const p1, EmcPose const * const p2, EmcPose * const out);
|
||||
int emcPoseSub(EmcPose const * const p1, EmcPose const * const p2, EmcPose * const out);
|
||||
|
||||
int emcPoseToPmCartesian(EmcPose const * const pose,
|
||||
PmCartesian * const xyz, PmCartesian * const abc, PmCartesian * const uvw);
|
||||
int pmCartesianToEmcPose(PmCartesian const * const xyz,
|
||||
PmCartesian const * const abc, PmCartesian const * const uvw, EmcPose * const pose);
|
||||
|
||||
int emcPoseSelfAdd(EmcPose * const self, EmcPose const * const p2);
|
||||
int emcPoseSelfSub(EmcPose * const self, EmcPose const * const p2);
|
||||
|
||||
int emcPoseSetXYZ(PmCartesian const * const xyz, EmcPose * const pose);
|
||||
int emcPoseSetABC(PmCartesian const * const abc, EmcPose * const pose);
|
||||
int emcPoseSetUVW(PmCartesian const * const uvw, EmcPose * const pose);
|
||||
|
||||
int emcPoseGetXYZ(EmcPose const * const pose, PmCartesian * const xyz);
|
||||
int emcPoseGetABC(EmcPose const * const pose, PmCartesian * const abc);
|
||||
int emcPoseGetUVW(EmcPose const * const pose, PmCartesian * const uvw);
|
||||
|
||||
int emcPoseMagnitude(EmcPose const * const pose, double * const out);
|
||||
|
||||
int emcPoseValid(EmcPose const * const pose);
|
||||
|
||||
#endif
|
||||
40
wasm-port/vendor/linuxcnc/src/emc/nml_intf/emctool.h
vendored
Normal file
40
wasm-port/vendor/linuxcnc/src/emc/nml_intf/emctool.h
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
// Copyright 2013 Jeff Epler <jepler@unpythonic.net>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
#ifndef EMCTOOL_H
|
||||
#define EMCTOOL_H
|
||||
|
||||
#include <emcpos.h>
|
||||
|
||||
/* pocketno: 0..(CANON_POCKETS_MAX-1) (0: spindle)
|
||||
** toolno: no restrictions (0: notool)
|
||||
*/
|
||||
#define CANON_POCKETS_MAX 1001 // max size of carousel handled
|
||||
#define CANON_TOOL_ENTRY_LEN 256 // how long each file line can be
|
||||
#define CANON_TOOL_COMMENT_SIZE 40 // max comment string (include trailing null)
|
||||
|
||||
struct CANON_TOOL_TABLE {
|
||||
int toolno;
|
||||
int pocketno;
|
||||
EmcPose offset;
|
||||
double diameter;
|
||||
double frontangle;
|
||||
double backangle;
|
||||
int orientation;
|
||||
char comment[CANON_TOOL_COMMENT_SIZE];
|
||||
};
|
||||
|
||||
#endif
|
||||
40
wasm-port/vendor/linuxcnc/src/emc/nml_intf/interp_return.hh
vendored
Normal file
40
wasm-port/vendor/linuxcnc/src/emc/nml_intf/interp_return.hh
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
/********************************************************************
|
||||
* Description: interp_return.hh
|
||||
*
|
||||
* Derived from a work by Thomas Kramer
|
||||
*
|
||||
* Author:
|
||||
* License: GPL Version 2
|
||||
* System: Linux
|
||||
*
|
||||
* Copyright (c) 2005 All rights reserved.
|
||||
*
|
||||
* Last change:
|
||||
*
|
||||
* This file declares the public interpreter return values. An
|
||||
* interpreter may extend this list with return values that are
|
||||
* used internally within the interpreters own code, but these
|
||||
* constitute the minimum set.
|
||||
********************************************************************/
|
||||
#ifndef INTERP_RETURN_H
|
||||
#define INTERP_RETURN_H
|
||||
|
||||
enum InterpReturn {
|
||||
INTERP_OK = 0,
|
||||
INTERP_EXIT = 1,
|
||||
INTERP_EXECUTE_FINISH = 2,
|
||||
INTERP_ENDFILE = 3,
|
||||
INTERP_FILE_NOT_OPEN = 4,
|
||||
INTERP_ERROR = 5,
|
||||
};
|
||||
|
||||
/*
|
||||
The return values OK, EXIT, EXECUTE_FINISH, and ENDFILE represent
|
||||
normal, non-error return conditions. FILE_NOT_OPEN is the first
|
||||
value that represents an error result. INTERP_MIN_ERROR
|
||||
is therefore the index of the last non-error return value.
|
||||
*/
|
||||
|
||||
static const InterpReturn INTERP_MIN_ERROR = INTERP_ENDFILE;
|
||||
|
||||
#endif /* INTERP_RETURN_H */
|
||||
393
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_arc.cc
vendored
Normal file
393
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_arc.cc
vendored
Normal file
@@ -0,0 +1,393 @@
|
||||
/********************************************************************
|
||||
* Description: interp_arc.cc
|
||||
*
|
||||
* Derived from a work by Thomas Kramer
|
||||
*
|
||||
* Author:
|
||||
* License: GPL Version 2
|
||||
* System: Linux
|
||||
*
|
||||
* Copyright (c) 2004 All rights reserved.
|
||||
*
|
||||
* Last change:
|
||||
********************************************************************/
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <libintl.h>
|
||||
#include <rtapi_math.h>
|
||||
#include "rs274ngc.hh"
|
||||
#include "rs274ngc_return.hh"
|
||||
#include "rs274ngc_interp.hh"
|
||||
#include "interp_internal.hh"
|
||||
|
||||
#define _(s) gettext(s)
|
||||
|
||||
char Interp::arc_axis1(CANON_PLANE plane) {
|
||||
switch(plane) {
|
||||
case CANON_PLANE::XY: return 'X';
|
||||
case CANON_PLANE::XZ: return 'Z';
|
||||
case CANON_PLANE::YZ: return 'Y';
|
||||
default: return '!';
|
||||
}
|
||||
}
|
||||
|
||||
char Interp::arc_axis2(CANON_PLANE plane) {
|
||||
switch(plane) {
|
||||
case CANON_PLANE::XY: return 'Y';
|
||||
case CANON_PLANE::XZ: return 'X';
|
||||
case CANON_PLANE::YZ: return 'Z';
|
||||
default: return '!';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
/*! arc_data_comp_ijk
|
||||
|
||||
Returned Value: int
|
||||
If any of the following errors occur, this returns the error code shown.
|
||||
Otherwise, it returns INTERP_OK.
|
||||
1. The two calculable values of the radius differ by more than
|
||||
tolerance: NCE_RADIUS_TO_END_OF_ARC_DIFFERS_FROM_RADIUS_TO_START
|
||||
2. move is not G_2 or G_3: NCE_BUG_CODE_NOT_G2_OR_G3
|
||||
|
||||
Side effects:
|
||||
This finds and sets the values of center_x, center_y, and turn.
|
||||
|
||||
Called by: convert_arc_comp1
|
||||
|
||||
This finds the center coordinates and number of full or partial turns
|
||||
counterclockwise of a helical or circular arc in ijk-format in the XY
|
||||
plane. The center is computed easily from the current point and center
|
||||
offsets, which are given. It is checked that the end point lies one
|
||||
tool radius from the arc.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
int Interp::arc_data_comp_ijk(int move, //!<either G_2 (cw arc) or G_3 (ccw arc)
|
||||
CANON_PLANE plane, //!<active plane
|
||||
CUTTER_COMP side, //!<either RIGHT or LEFT
|
||||
double tool_radius, //!<radius of the tool
|
||||
double current_x, //!<first coordinate of current point
|
||||
double current_y, //!<second coordinate of current point
|
||||
double end_x, //!<first coordinate of arc end point
|
||||
double end_y, //!<second coordinate of arc end point
|
||||
int ij_absolute, //!<how to interpret i/j numbers
|
||||
double i_number, //!<first coordinate of center (abs or incr)
|
||||
double j_number, //!<second coordinate of center (abs or incr)
|
||||
int p_number,
|
||||
double *center_x, //!<pointer to first coordinate of center of arc
|
||||
double *center_y, //!<pointer to second coordinate of center of arc
|
||||
int *turn, //!<pointer to number of full or partial circles CCW
|
||||
double radius_tolerance, //!<minimum radius tolerance
|
||||
double spiral_abs_tolerance, //!<tolerance of start and end radius difference
|
||||
double spiral_rel_tolerance)
|
||||
{
|
||||
double arc_radius;
|
||||
double radius2;
|
||||
char a = arc_axis1(plane), b = arc_axis2(plane);
|
||||
|
||||
if ( ij_absolute ) {
|
||||
*center_x = (i_number);
|
||||
*center_y = (j_number);
|
||||
} else {
|
||||
*center_x = (current_x + i_number);
|
||||
*center_y = (current_y + j_number);
|
||||
}
|
||||
arc_radius = hypot((*center_x - current_x), (*center_y - current_y));
|
||||
radius2 = hypot((*center_x - end_x), (*center_y - end_y));
|
||||
CHKS(((arc_radius < radius_tolerance) || (radius2 < radius_tolerance)),
|
||||
_("Zero-radius arc: "
|
||||
"start=(%c%.4f,%c%.4f) center=(%c%.4f,%c%.4f) end=(%c%.4f,%c%.4f) r1=%.4f r2=%.4f"),
|
||||
a, current_x, b, current_y,
|
||||
a, *center_x, b, *center_y,
|
||||
a, end_x, b, end_y, arc_radius, radius2);
|
||||
|
||||
double abs_err = fabs(arc_radius - radius2);
|
||||
double rel_err = abs_err / std::max(arc_radius, radius2);
|
||||
|
||||
CHKS((abs_err > spiral_abs_tolerance * 100.0) ||
|
||||
(rel_err > spiral_rel_tolerance && abs_err > spiral_abs_tolerance),
|
||||
_("Radius to end of arc differs from radius to start: "
|
||||
"start=(%c%.4f,%c%.4f) center=(%c%.4f,%c%.4f) end=(%c%.4f,%c%.4f) "
|
||||
"r1=%.4f r2=%.4f abs_err=%.4g rel_err=%.4f%%"),
|
||||
a, current_x, b, current_y,
|
||||
a, *center_x, b, *center_y,
|
||||
a, end_x, b, end_y, arc_radius, radius2,
|
||||
abs_err, rel_err*100);
|
||||
|
||||
CHKS(((arc_radius <= tool_radius) && (((side == CUTTER_COMP::LEFT) && (move == G_3)) ||
|
||||
((side == CUTTER_COMP::RIGHT) && (move == G_2)))),
|
||||
NCE_TOOL_RADIUS_NOT_LESS_THAN_ARC_RADIUS_WITH_COMP);
|
||||
|
||||
/* This catches an arc too small for the tool, also */
|
||||
if (move == G_2)
|
||||
*turn = -1 * p_number;
|
||||
else if (move == G_3)
|
||||
*turn = 1 * p_number;
|
||||
else
|
||||
ERS(NCE_BUG_CODE_NOT_G2_OR_G3);
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*! arc_data_comp_r
|
||||
|
||||
Returned Value: int
|
||||
If any of the following errors occur, this returns the error code shown.
|
||||
Otherwise, it returns INTERP_OK.
|
||||
1. The arc radius is too small to reach the end point:
|
||||
NCE_RADIUS_TOO_SMALL_TO_REACH_END_POINT
|
||||
2. The arc radius is not greater than the tool_radius, but should be:
|
||||
NCE_TOOL_RADIUS_NOT_LESS_THAN_ARC_RADIUS_WITH_COMP
|
||||
3. An imaginary value for offset would be found, which should never
|
||||
happen if the theory is correct: NCE_BUG_IN_TOOL_RADIUS_COMP
|
||||
|
||||
Side effects:
|
||||
This finds and sets the values of center_x, center_y, and turn.
|
||||
|
||||
Called by: convert_arc_comp1
|
||||
|
||||
This finds the center coordinates and number of full or partial turns
|
||||
counterclockwise of a helical or circular arc (call it arc1) in
|
||||
r-format in the XY plane. Arc2 is constructed so that it is tangent
|
||||
to a circle whose radius is tool_radius and whose center is at the
|
||||
point (current_x, current_y) and passes through the point (end_x,
|
||||
end_y). Arc1 has the same center as arc2. The radius of arc1 is one
|
||||
tool radius larger or smaller than the radius of arc2.
|
||||
|
||||
If the value of the big_radius argument is negative, that means [NCMS,
|
||||
page 21] that an arc larger than a semicircle is to be made.
|
||||
Otherwise, an arc of a semicircle or less is made.
|
||||
|
||||
The algorithm implemented here is to construct a line L from the
|
||||
current point to the end point, and a perpendicular to it from the
|
||||
center of the arc which intersects L at point P. Since the distance
|
||||
from the end point to the center and the distance from the current
|
||||
point to the center are known, two equations for the length of the
|
||||
perpendicular can be written. The right sides of the equations can be
|
||||
set equal to one another and the resulting equation solved for the
|
||||
length of the line from the current point to P. Then the location of
|
||||
P, the length of the perpendicular, the angle of the perpendicular,
|
||||
and the location of the center, can be found in turn.
|
||||
|
||||
This needs to be better documented, with figures. There are eight
|
||||
possible arcs, since there are three binary possibilities: (1) tool
|
||||
inside or outside arc, (2) clockwise or counterclockwise (3) two
|
||||
positions for each arc (of the given radius) tangent to the tool
|
||||
outline and through the end point. All eight are calculated below,
|
||||
since theta, radius2, and turn may each have two values.
|
||||
|
||||
To see two positions for each arc, imagine the arc is a hoop, the
|
||||
tool is a cylindrical pin, and the arc may rotate around the end point.
|
||||
The rotation covers all possible positions of the arc. It is easy to
|
||||
see the hoop is constrained by the pin at two different angles, whether
|
||||
the pin is inside or outside the hoop.
|
||||
|
||||
*/
|
||||
|
||||
int Interp::arc_data_comp_r(int move, //!< either G_2 (cw arc) or G_3 (ccw arc)
|
||||
CANON_PLANE plane,
|
||||
CUTTER_COMP side, //!< either RIGHT or LEFT
|
||||
double tool_radius, //!< radius of the tool
|
||||
double current_x, //!< first coordinate of current point
|
||||
double current_y, //!< second coordinate of current point
|
||||
double end_x, //!< first coordinate of arc end point
|
||||
double end_y, //!< second coordinate of arc end point
|
||||
double big_radius, //!< radius of arc
|
||||
int p_number,
|
||||
double *center_x, //!< pointer to first coordinate of center of arc
|
||||
double *center_y, //!< pointer to second coordinate of center of arc
|
||||
int *turn, //!< pointer to number of full or partial circles CCW
|
||||
double tolerance) //!< tolerance of differing radii
|
||||
{
|
||||
double abs_radius; // absolute value of big_radius
|
||||
|
||||
abs_radius = fabs(big_radius);
|
||||
CHKS(((abs_radius <= tool_radius) && (((side == CUTTER_COMP::LEFT) && (move == G_3)) ||
|
||||
((side == CUTTER_COMP::RIGHT) && (move == G_2)))),
|
||||
NCE_TOOL_RADIUS_NOT_LESS_THAN_ARC_RADIUS_WITH_COMP);
|
||||
|
||||
return arc_data_r(move, plane, current_x, current_y, end_x, end_y, big_radius, p_number,
|
||||
center_x, center_y, turn, tolerance);
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*! arc_data_ijk
|
||||
|
||||
Returned Value: int
|
||||
If any of the following errors occur, this returns the error code shown.
|
||||
Otherwise, it returns INTERP_OK.
|
||||
1. The two calculable values of the radius differ by more than
|
||||
tolerance: NCE_RADIUS_TO_END_OF_ARC_DIFFERS_FROM_RADIUS_TO_START
|
||||
2. The move code is not G_2 or G_3: NCE_BUG_CODE_NOT_G2_OR_G3
|
||||
3. Either of the two calculable values of the radius is zero:
|
||||
NCE_ZERO_RADIUS_ARC
|
||||
|
||||
Side effects:
|
||||
This finds and sets the values of center_x, center_y, and turn.
|
||||
|
||||
Called by:
|
||||
convert_arc2
|
||||
convert_arc_comp2
|
||||
|
||||
This finds the center coordinates and number of full or partial turns
|
||||
counterclockwise of a helical or circular arc in ijk-format. This
|
||||
function is used by convert_arc2 for all three planes, so "x" and
|
||||
"y" really mean "first_coordinate" and "second_coordinate" wherever
|
||||
they are used here as suffixes of variable names. The i and j prefixes
|
||||
are handled similarly.
|
||||
|
||||
*/
|
||||
|
||||
int Interp::arc_data_ijk(int move, //!< either G_2 (cw arc) or G_3 (ccw arc)
|
||||
CANON_PLANE plane,
|
||||
double current_x, //!< first coordinate of current point
|
||||
double current_y, //!< second coordinate of current point
|
||||
double end_x, //!< first coordinate of arc end point
|
||||
double end_y, //!< second coordinate of arc end point
|
||||
int ij_absolute, //!<how to interpret i/j numbers
|
||||
double i_number, //!<first coordinate of center (abs or incr)
|
||||
double j_number, //!<second coordinate of center (abs or incr)
|
||||
int p_number,
|
||||
double *center_x, //!< pointer to first coordinate of center of arc
|
||||
double *center_y, //!< pointer to second coordinate of center of arc
|
||||
int *turn, //!< pointer to no. of full or partial circles CCW
|
||||
double radius_tolerance, //!<minimum radius tolerance
|
||||
double spiral_abs_tolerance, //!<tolerance of start and end radius difference
|
||||
double spiral_rel_tolerance)
|
||||
{
|
||||
double radius; /* radius to current point */
|
||||
double radius2; /* radius to end point */
|
||||
char a = arc_axis1(plane), b = arc_axis2(plane);
|
||||
|
||||
if ( ij_absolute ) {
|
||||
*center_x = (i_number);
|
||||
*center_y = (j_number);
|
||||
} else {
|
||||
*center_x = (current_x + i_number);
|
||||
*center_y = (current_y + j_number);
|
||||
}
|
||||
radius = hypot((*center_x - current_x), (*center_y - current_y));
|
||||
radius2 = hypot((*center_x - end_x), (*center_y - end_y));
|
||||
CHKS(((radius < radius_tolerance) || (radius2 < radius_tolerance)),_("Zero-radius arc: "
|
||||
"start=(%c%.4f,%c%.4f) center=(%c%.4f,%c%.4f) end=(%c%.4f,%c%.4f) r1=%.4f r2=%.4f"),
|
||||
a, current_x, b, current_y,
|
||||
a, *center_x, b, *center_y,
|
||||
a, end_x, b, end_y, radius, radius2);
|
||||
double abs_err = fabs(radius - radius2);
|
||||
double rel_err = abs_err / std::max(radius, radius2);
|
||||
CHKS((abs_err > spiral_abs_tolerance * 100.0) ||
|
||||
(rel_err > spiral_rel_tolerance && abs_err > spiral_abs_tolerance),
|
||||
_("Radius to end of arc differs from radius to start: "
|
||||
"start=(%c%.4f,%c%.4f) center=(%c%.4f,%c%.4f) end=(%c%.4f,%c%.4f) "
|
||||
"r1=%.4f r2=%.4f abs_err=%.4g rel_err=%.4f%%"),
|
||||
a, current_x, b, current_y,
|
||||
a, *center_x, b, *center_y,
|
||||
a, end_x, b, end_y, radius, radius2,
|
||||
abs_err, rel_err*100);
|
||||
|
||||
if (move == G_2)
|
||||
*turn = -1 * p_number;
|
||||
else if (move == G_3)
|
||||
*turn = 1 * p_number;
|
||||
else
|
||||
ERS(NCE_BUG_CODE_NOT_G2_OR_G3);
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*! arc_data_r
|
||||
|
||||
Returned Value: int
|
||||
If any of the following errors occur, this returns the error shown.
|
||||
Otherwise, it returns INTERP_OK.
|
||||
1. The radius is too small to reach the end point:
|
||||
NCE_ARC_RADIUS_TOO_SMALL_TO_REACH_END_POINT
|
||||
2. The current point is the same as the end point of the arc
|
||||
(so that it is not possible to locate the center of the circle):
|
||||
NCE_CURRENT_POINT_SAME_AS_END_POINT_OF_ARC
|
||||
|
||||
Side effects:
|
||||
This finds and sets the values of center_x, center_y, and turn.
|
||||
|
||||
Called by:
|
||||
convert_arc2
|
||||
convert_arc_comp2
|
||||
|
||||
This finds the center coordinates and number of full or partial turns
|
||||
counterclockwise of a helical or circular arc in the r format. This
|
||||
function is used by convert_arc2 for all three planes, so "x" and
|
||||
"y" really mean "first_coordinate" and "second_coordinate" wherever
|
||||
they are used here as suffixes of variable names.
|
||||
|
||||
If the value of the radius argument is negative, that means [NCMS,
|
||||
page 21] that an arc larger than a semicircle is to be made.
|
||||
Otherwise, an arc of a semicircle or less is made.
|
||||
|
||||
The algorithm used here is based on finding the midpoint M of the line
|
||||
L between the current point and the end point of the arc. The center
|
||||
of the arc lies on a line through M perpendicular to L.
|
||||
|
||||
*/
|
||||
|
||||
int Interp::arc_data_r(int move, //!< either G_2 (cw arc) or G_3 (ccw arc)
|
||||
CANON_PLANE /*plane*/,
|
||||
double current_x, //!< first coordinate of current point
|
||||
double current_y, //!< second coordinate of current point
|
||||
double end_x, //!< first coordinate of arc end point
|
||||
double end_y, //!< second coordinate of arc end point
|
||||
double radius, //!< radius of arc
|
||||
int p_number,
|
||||
double *center_x, //!< pointer to first coordinate of center of arc
|
||||
double *center_y, //!< pointer to second coordinate of center of arc
|
||||
int *turn, //!< pointer to number of full or partial circles CCW
|
||||
double tolerance) //!< tolerance of differing radii
|
||||
{
|
||||
double abs_radius; /* absolute value of given radius */
|
||||
double half_length; /* distance from M to end point */
|
||||
double mid_x; /* first coordinate of M */
|
||||
double mid_y; /* second coordinate of M */
|
||||
double offset; /* distance from M to center */
|
||||
double theta; /* angle of line from M to center */
|
||||
double turn2; /* absolute value of half of turn */
|
||||
|
||||
CHKS(((end_x == current_x) && (end_y == current_y)),
|
||||
NCE_CURRENT_POINT_SAME_AS_END_POINT_OF_ARC);
|
||||
abs_radius = fabs(radius);
|
||||
mid_x = (end_x + current_x) / 2.0;
|
||||
mid_y = (end_y + current_y) / 2.0;
|
||||
half_length = hypot((mid_x - end_x), (mid_y - end_y));
|
||||
CHKS(((half_length - abs_radius) > tolerance),
|
||||
NCE_ARC_RADIUS_TOO_SMALL_TO_REACH_END_POINT);
|
||||
if ((half_length / abs_radius) > (1 - TINY))
|
||||
half_length = abs_radius; /* allow a small error for semicircle */
|
||||
/* check needed before calling asin */
|
||||
if (((move == G_2) && (radius > 0)) || ((move == G_3) && (radius < 0)))
|
||||
theta = atan2((end_y - current_y), (end_x - current_x)) - M_PI_2l;
|
||||
else
|
||||
theta = atan2((end_y - current_y), (end_x - current_x)) + M_PI_2l;
|
||||
|
||||
turn2 = asin(half_length / abs_radius);
|
||||
offset = abs_radius * cos(turn2);
|
||||
*center_x = mid_x + (offset * cos(theta));
|
||||
*center_y = mid_y + (offset * sin(theta));
|
||||
*turn = (move == G_2) ? -1 * p_number : 1 * p_number;
|
||||
|
||||
return INTERP_OK;
|
||||
}
|
||||
309
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_array.cc
vendored
Normal file
309
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_array.cc
vendored
Normal file
@@ -0,0 +1,309 @@
|
||||
/********************************************************************
|
||||
* Description: interp_array.cc
|
||||
*
|
||||
* This file just allocates space for the static arrays used by the
|
||||
* interpreter.
|
||||
*
|
||||
* Author:
|
||||
* License: GPL Version 2
|
||||
* System: Linux
|
||||
*
|
||||
* Copyright (c) 2004 All rights reserved.
|
||||
********************************************************************/
|
||||
|
||||
#include "rs274ngc_return.hh"
|
||||
#include "rs274ngc_interp.hh"
|
||||
|
||||
using namespace interp_param_global;
|
||||
|
||||
/* Interpreter arrays for g_codes and m_codes. The nth entry
|
||||
in each array is the modal group number corresponding to the nth
|
||||
code. Entries which are -1 represent illegal codes. Remember g_codes
|
||||
in this interpreter are multiplied by 10.
|
||||
|
||||
The modal g groups and group numbers defined in [NCMS, pages 71 - 73]
|
||||
(see also [Fanuc, pages 43 - 45]) are used here, except the canned
|
||||
cycles (g80 - g89), which comprise modal g group 9 in [Fanuc], are
|
||||
treated here as being in the same modal group (group 1) with the
|
||||
straight moves and arcs (g0, g1, g2,g3). [Fanuc, page 45] says only
|
||||
one g_code from any one group may appear on a line, and we are
|
||||
following that rule. The straight_probe move, g38.2, is in group 1; it
|
||||
is not defined in [NCMS].
|
||||
|
||||
Some g_codes are non-modal (g4, g10, g28, g30, g53, g92, g92.1, g92.2,
|
||||
and g92.3 here - many more in [NCMS]). [Fanuc] and [NCMS] put all
|
||||
these in the same group 0, so we do also. Logically, there are two
|
||||
subgroups, those which require coordinate values (g10, g28, g30, and
|
||||
g92) and those which do not (g4, g53, g92.1, g92.2, and g92.3).
|
||||
The subgroups are identified by itemization when necessary.
|
||||
|
||||
Those in group 0 which require coordinate values may not be on the
|
||||
same line as those in group 1 (except g80) because they would be
|
||||
competing for the coordinate values. Others in group 0 may be used on
|
||||
the same line as those in group 1.
|
||||
|
||||
A total of 52 G-codes are implemented.
|
||||
|
||||
The groups are:
|
||||
group 0 = {g4,g10,g28,g30,g52,g53,g92,g92.1,g92.2,g92.3} - NON-MODAL
|
||||
dwell, setup, return to ref1, return to ref2,
|
||||
local coordinate system, motion in machine coordinates,
|
||||
set and unset axis offsets
|
||||
group 1 = {g0,g1,g2,g3,g33,g33.1,g38.2,g38.3,g38.4,g38.5,
|
||||
g70,g71,g71.1,g71.2,g72,g72.1,g72.2,
|
||||
g73,g76,g80,
|
||||
g81,g82,g83,g84,g85,g86,g87,g88,g89} - motion
|
||||
group 2 = {g17,g17.1,g18,g18.1,g19,g19.1} - plane selection
|
||||
group 3 = {g90,g91} - distance mode
|
||||
group 4 = {g90.1,g91.1} - arc IJK distance mode
|
||||
group 5 = {g93,g94,g95} - feed rate mode
|
||||
group 6 = {g20,g21} - units
|
||||
group 7 = {g40,g41,g42} - cutter diameter compensation
|
||||
group 8 = {g43,g49} - tool length offset
|
||||
group 10 = {g98,g99} - return mode in canned cycles
|
||||
group 12 = {g54,g55,g56,g57,g58,g59,g59.1,g59.2,g59.3} - coordinate system
|
||||
group 13 = {g61,g61.1,g64} - control mode (path following)
|
||||
group 14 = {g96,g97} - spindle speed mode
|
||||
group 15 = {G07,G08} - lathe diameter mode
|
||||
group 16 = {g92.2,g92.3} - whether g92 offset is applied
|
||||
*/
|
||||
// This stops indent from reformatting the following code.
|
||||
// *INDENT-OFF*
|
||||
const int Interp::gees[] = {
|
||||
/* 0 */ 1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 20 */ 1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 40 */ //0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 40 */ 0,-1,-1,-1,-1,-1,-1,-1,-1,-1, 1, 1, 1, 0,-1,-1,-1,-1,-1,-1,
|
||||
/* 60 */ 1, 1, 1, 0,-1,-1,-1,-1,-1,-1,15,-1,-1,-1,-1,-1,-1,-1,-1,-1, // jjf added G6
|
||||
/* 80 */ 15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 100 */ 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 120 */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 140 */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 160 */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 2, 2,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 180 */ 2, 2,-1,-1,-1,-1,-1,-1,-1,-1, 2, 2,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 200 */ 6,-1,-1,-1,-1,-1,-1,-1,-1,-1, 6,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 220 */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 240 */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 260 */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 280 */ 0, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 300 */ 0, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 320 */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 1, 1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 340 */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 360 */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 380 */ -1,-1, 1, 1, 1, 1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 400 */ 7,-1,-1,-1,-1,-1,-1,-1,-1,-1, 7, 7,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 420 */ 7, 7,-1,-1,-1,-1,-1,-1,-1,-1, 8, 8, 8,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 440 */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 460 */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 480 */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 8,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 500 */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 520 */ 0,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 540 */ 12,-1,-1,-1,-1,-1,-1,-1,-1,-1,12,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 560 */ 12,-1,-1,-1,-1,-1,-1,-1,-1,-1,12,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 580 */ 12,-1,-1,-1,-1,-1,-1,-1,-1,-1,12,12,12,12,-1,-1,-1,-1,-1,-1,
|
||||
/* 600 */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,13,13,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 620 */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 640 */ 13,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 660 */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 680 */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 700 */ 1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 1, 1, 1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 720 */ 1, 1, 1,-1,-1,-1,-1,-1,-1,-1, 1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 740 */ 1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 760 */ 1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 780 */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 800 */ 1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 820 */ 1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 840 */ 1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 860 */ 1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 880 */ 1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 900 */ 3, 4,-1,-1,-1,-1,-1,-1,-1,-1, 3, 4,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 920 */ 0,16,16,16,-1,-1,-1,-1,-1,-1, 5,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 940 */ 5,-1,-1,-1,-1,-1,-1,-1,-1,-1, 5,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 960 */ 14,-1,-1,-1,-1,-1,-1,-1,-1,-1,14,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
/* 980 */ 10,-1,-1,-1,-1,-1,-1,-1,-1,-1,10,-1,-1,-1,-1,-1,-1,-1,-1,-1};
|
||||
|
||||
/*
|
||||
|
||||
Modal groups and modal group numbers for M codes are not described in
|
||||
[Fanuc]. We have used the groups from [NCMS] and added M60, as an
|
||||
extension of the language for pallet shuttle and stop. This version has
|
||||
no codes related to axis clamping.
|
||||
|
||||
The groups are:
|
||||
group 4 = {m0,m1,m2,m30,m60,
|
||||
m99} - stopping
|
||||
group 5 = {m62,m63,m64,m65, - turn I/O point on/off
|
||||
m66} - wait for Input
|
||||
group 6 = {m6,m61} - tool change
|
||||
group 7 = {m3,m4,m5,m19} - spindle turning, orient
|
||||
group 8 = {m7,m8,m9} - coolant
|
||||
group 9 = {m48,m49, - feed and speed override switch bypass
|
||||
m50, - feed override switch bypass P1 to turn on, P0 to turn off
|
||||
m51, - spindle speed override switch bypass P1 to turn on, P0 to turn off
|
||||
m52, - adaptive feed override switch bypass P1 to turn on, P0 to turn off
|
||||
m53} - feedstop override switch bypass P1 to turn on, P0 to turn off
|
||||
group 10 = {m100..m199} - user-defined
|
||||
*/
|
||||
|
||||
const int Interp::ems[] = {
|
||||
4, 4, 4, 7, 7, 7, 6, 8, 8, 8, // 9
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, 7, // 19
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 29
|
||||
4, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 39
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, 9, 9, // 49
|
||||
9, 9, 9, 9, -1, -1, -1, -1, -1, -1, // 59
|
||||
4, 6, 5, 5, 5, 5, 5, 5, 5, -1, // 69
|
||||
7, 7, 7, 7, -1, -1, -1, -1, -1, -1, // 79
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 89
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, 4, // 99
|
||||
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, //109
|
||||
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, //119
|
||||
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, //129
|
||||
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, //139
|
||||
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, //149
|
||||
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, //159
|
||||
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, //169
|
||||
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, //179
|
||||
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, //189
|
||||
10, 10, 10, 10, 10, 10, 10, 10, 10, 10};//199
|
||||
|
||||
/*
|
||||
|
||||
This is an array of the index numbers of system parameters that must
|
||||
be included in a file used with the Interp::restore_parameters
|
||||
function. The array is used by that function and by the
|
||||
Interp::save_parameters function.
|
||||
|
||||
*/
|
||||
|
||||
const int Interp::required_parameters[] = {
|
||||
5161, 5162, 5163, /* G28 home */
|
||||
5164, 5165, 5166, /* A, B, & C */
|
||||
5167, 5168, 5169, /* U, V, & W */
|
||||
5181, 5182, 5183, /* G30 home */
|
||||
5184, 5185, 5186, /* A, B, & C */
|
||||
5187, 5188, 5189, /* U, V, & W */
|
||||
5210, /* G92 is currently applied */
|
||||
5211, 5212, 5213, /* G92 offsets */
|
||||
5214, 5215, 5216, /* A, B, & C */
|
||||
5217, 5218, 5219, /* U, V, & W */
|
||||
5220, /* selected coordinate */
|
||||
5221, 5222, 5223, /* coordinate system 1 */
|
||||
5224, 5225, 5226, /* A, B, & C */
|
||||
5227, 5228, 5229, /* U, V, & W */
|
||||
5230,
|
||||
5241, 5242, 5243, /* coordinate system 2 */
|
||||
5244, 5245, 5246, /* A, B, & C */
|
||||
5247, 5248, 5249, /* U, V, & W */
|
||||
5250,
|
||||
5261, 5262, 5263, /* coordinate system 3 */
|
||||
5264, 5265, 5266, /* A, B, & C */
|
||||
5267, 5268, 5269, /* U, V, & W */
|
||||
5270,
|
||||
5281, 5282, 5283, /* coordinate system 4 */
|
||||
5284, 5285, 5286, /* A, B, & C */
|
||||
5287, 5288, 5289, /* U, V, & W */
|
||||
5290,
|
||||
5301, 5302, 5303, /* coordinate system 5 */
|
||||
5304, 5305, 5306, /* A, B, & C */
|
||||
5307, 5308, 5309, /* U, V, & W */
|
||||
5310,
|
||||
5321, 5322, 5323, /* coordinate system 6 */
|
||||
5324, 5325, 5326, /* A, B, & C */
|
||||
5327, 5328, 5329, /* U, V, & W */
|
||||
5330,
|
||||
5341, 5342, 5343, /* coordinate system 7 */
|
||||
5344, 5345, 5346, /* A, B, & C */
|
||||
5347, 5348, 5349, /* U, V, & W */
|
||||
5350,
|
||||
5361, 5362, 5363, /* coordinate system 8 */
|
||||
5364, 5365, 5366, /* A, B, & C */
|
||||
5367, 5368, 5369, /* U, V, & W */
|
||||
5370,
|
||||
5381, 5382, 5383, /* coordinate system 9 */
|
||||
5384, 5385, 5386, /* A, B, & C */
|
||||
5387, 5388, 5389, /* U, V, & W */
|
||||
5390,
|
||||
RS274NGC_MAX_PARAMETERS
|
||||
};
|
||||
|
||||
const int Interp::readonly_parameters[] = {
|
||||
5400, // tool toolno
|
||||
5401, // tool x offset
|
||||
5402, // tool y offset
|
||||
5403, // tool z offset
|
||||
5404, // tool a offset
|
||||
5405, // tool b offset
|
||||
5406, // tool c offset
|
||||
5407, // tool u offset
|
||||
5408, // tool v offset
|
||||
5409, // tool w offset
|
||||
5410, // tool diameter
|
||||
5411, // tool frontangle
|
||||
5412, // tool backangle
|
||||
5413, // tool orientation
|
||||
5420, 5421, 5422, 5423, 5424, 5425, 5426, 5427, 5428, // current X Y ... W
|
||||
};
|
||||
const int Interp::n_readonly_parameters = sizeof(readonly_parameters) / sizeof(int);
|
||||
|
||||
/* _readers is an array of pointers to functions that read.
|
||||
It is used by read_one_item.
|
||||
|
||||
Each read function is placed in the array according to the ASCII character it
|
||||
corresponds to. Whilst a switch statement could have been used in read_one_item,
|
||||
using an array of function pointers allows a new read_foo to be added quickly
|
||||
in this one table.
|
||||
|
||||
At some point, it may be advantageous to add a read_$ or read_n for perhaps
|
||||
macro or jump labels..
|
||||
*/
|
||||
const read_function_pointer Interp::default_readers[256] = {
|
||||
/* 00 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* 10 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* 20 */
|
||||
0, 0, 0,
|
||||
&Interp::read_parameter_setting, // reads # or ASCII 0x23
|
||||
&Interp::read_dollar, // reads $ or ASCII 0x24
|
||||
0, 0, 0,
|
||||
&Interp::read_comment, // reads ( or ASCII 0x28
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
/* 30 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
&Interp::read_semicolon,
|
||||
0, 0, 0, 0,
|
||||
/* 40 */
|
||||
&Interp::read_atsign, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* 50 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &Interp::read_carat, 0,
|
||||
/* 60 */
|
||||
0,
|
||||
&Interp::read_a, // reads a or ASCII 0x61
|
||||
&Interp::read_b, // reads b or ASCII 0x62
|
||||
&Interp::read_c, // reads c or ASCII 0x63
|
||||
&Interp::read_d, // reads d or ASCII 0x64
|
||||
&Interp::read_e, // reads d or ASCII 0x65
|
||||
&Interp::read_f, // reads f or ASCII 0x66
|
||||
&Interp::read_g, // reads g or ASCII 0x67
|
||||
&Interp::read_h, // reads h or ASCII 0x68
|
||||
&Interp::read_i, // reads i or ASCII 0x69
|
||||
&Interp::read_j, // reads j or ASCII 0x6A
|
||||
&Interp::read_k, // reads k or ASCII 0x6B
|
||||
&Interp::read_l, // reads l or ASCII 0x6C
|
||||
&Interp::read_m, // reads m or ASCII 0x6D
|
||||
0, 0,
|
||||
&Interp::read_p, // reads p or ASCII 0x70
|
||||
&Interp::read_q, // reads q or ASCII 0x71
|
||||
&Interp::read_r, // reads r or ASCII 0x72
|
||||
&Interp::read_s, // reads s or ASCII 0x73
|
||||
&Interp::read_t, // reads t or ASCII 0x74
|
||||
&Interp::read_u,
|
||||
&Interp::read_v,
|
||||
&Interp::read_w,
|
||||
&Interp::read_x, // reads x or ASCII 0x78
|
||||
&Interp::read_y, // reads y or ASCII 0x79
|
||||
&Interp::read_z}; // reads z or ASCII 0x7A
|
||||
// *INDENT-ON*
|
||||
// And now indent can continue.
|
||||
/****************************************************************************/
|
||||
62
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_base.cc
vendored
Normal file
62
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_base.cc
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Jeff Epler <jepler@unpythonic.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
#include "interp_base.hh"
|
||||
#include <dlfcn.h>
|
||||
#include <limits.h>
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
|
||||
InterpBase::~InterpBase() {}
|
||||
|
||||
InterpBase *interp_from_shlib(const char *shlib) {
|
||||
void * interp_lib;
|
||||
char relative_interp[PATH_MAX];
|
||||
char const * interp_path;
|
||||
|
||||
dlopen(NULL, RTLD_GLOBAL);
|
||||
|
||||
if (shlib[0] == '/') {
|
||||
// The passed-in .so name is an absolute path, use it directly.
|
||||
interp_path = shlib;
|
||||
} else {
|
||||
// The passed-in .so name is a relative path or just a bare
|
||||
// filename, look for it in `${EMC2_HOME}/lib/linuxcnc`.
|
||||
snprintf(relative_interp, sizeof(relative_interp), "%s/%s", EMC2_HOME "/lib/linuxcnc", shlib);
|
||||
interp_path = relative_interp;
|
||||
}
|
||||
|
||||
interp_lib = dlopen(interp_path, RTLD_NOW);
|
||||
if(!interp_lib) {
|
||||
fprintf(stderr, "emcTaskInit: could not open interpreter '%s': %s\n", interp_path, dlerror());
|
||||
return 0;
|
||||
}
|
||||
fprintf(stderr, "emcTaskInit: using custom interpreter '%s'\n", interp_path);
|
||||
|
||||
typedef InterpBase* (*Constructor)();
|
||||
Constructor constructor = (Constructor)dlsym(interp_lib, "makeInterp");
|
||||
if(!constructor) {
|
||||
fprintf(stderr, "emcTaskInit: could not get symbol makeInterp from interpreter '%s': %s\n", shlib, dlerror());
|
||||
return 0;
|
||||
}
|
||||
InterpBase *pinterp = constructor();
|
||||
if(!pinterp) {
|
||||
fprintf(stderr, "emcTaskInit: makeInterp() returned NULL from interpreter '%s'\n", shlib);
|
||||
return 0;
|
||||
}
|
||||
return pinterp;
|
||||
}
|
||||
76
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_base.hh
vendored
Normal file
76
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_base.hh
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Jeff Epler <jepler@unpythonic.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef INTERP_BASE_HH
|
||||
#define INTERP_BASE_HH
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <emcpos.h>
|
||||
#include "modal_state.hh"
|
||||
|
||||
/* Size of certain arrays */
|
||||
#define ACTIVE_G_CODES 17
|
||||
#define ACTIVE_M_CODES 10
|
||||
#define ACTIVE_SETTINGS 5
|
||||
|
||||
class InterpBase : boost::noncopyable {
|
||||
public:
|
||||
virtual ~InterpBase();
|
||||
virtual char *error_text(int errcode, char *buf, size_t buflen) = 0;
|
||||
virtual char *line_text(char *buf, size_t buflen) = 0;
|
||||
virtual char *file_name(char *buf, size_t buflen) = 0;
|
||||
virtual char *stack_name(int index, char *buf, size_t buflen) = 0;
|
||||
virtual size_t line_length() = 0;
|
||||
virtual int sequence_number() = 0;
|
||||
virtual int ini_load(const char *inifile) = 0;
|
||||
virtual int init() = 0;
|
||||
virtual int execute() = 0;
|
||||
virtual int execute(const char *line) = 0;
|
||||
virtual int execute(const char *line, int line_number) = 0;
|
||||
virtual int synch() = 0;
|
||||
virtual int exit() = 0;
|
||||
virtual int open(const char *filename) = 0;
|
||||
virtual int read() = 0;
|
||||
virtual int read(const char *line) = 0;
|
||||
virtual int close() = 0;
|
||||
virtual int reset() = 0;
|
||||
virtual int line() = 0;
|
||||
virtual int call_level() = 0;
|
||||
virtual char *command(char *buf, size_t buflen) = 0;
|
||||
virtual char *file(char *buf, size_t buflen) = 0;
|
||||
virtual int on_abort(int reason, const char *message) = 0;
|
||||
virtual void active_g_codes(int active_gcodes[ACTIVE_G_CODES]) = 0;
|
||||
virtual void active_m_codes(int active_mcodes[ACTIVE_M_CODES]) = 0;
|
||||
virtual void active_settings(double active_settings[ACTIVE_SETTINGS]) = 0;
|
||||
virtual int active_modes(int g_codes[ACTIVE_G_CODES],
|
||||
int m_codes[ACTIVE_M_CODES],
|
||||
double settings[ACTIVE_SETTINGS],
|
||||
StateTag const &tag) = 0;
|
||||
virtual int restore_from_tag(StateTag const &tag) = 0;
|
||||
virtual void print_state_tag(StateTag const &tag) = 0;
|
||||
virtual void set_loglevel(int level) = 0;
|
||||
virtual void set_loop_on_main_m99(bool state) = 0;
|
||||
virtual FILE* get_stdout() { return stdout; };
|
||||
};
|
||||
|
||||
InterpBase *interp_from_shlib(const char *shlib);
|
||||
extern "C" InterpBase *makeInterp();
|
||||
|
||||
#endif
|
||||
389
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_check.cc
vendored
Normal file
389
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_check.cc
vendored
Normal file
@@ -0,0 +1,389 @@
|
||||
/********************************************************************
|
||||
* Description: interp_check.cc
|
||||
*
|
||||
* Derived from a work by Thomas Kramer
|
||||
*
|
||||
* Author:
|
||||
* License: GPL Version 2
|
||||
* System: Linux
|
||||
*
|
||||
* Copyright (c) 2004 All rights reserved.
|
||||
*
|
||||
* Last change:
|
||||
********************************************************************/
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include "rs274ngc.hh"
|
||||
#include "rs274ngc_return.hh"
|
||||
#include "interp_internal.hh"
|
||||
#include "rs274ngc_interp.hh"
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*! check_g_codes
|
||||
|
||||
Returned Value: int
|
||||
If any of the following errors occur, this returns the error shown.
|
||||
Otherwise, it returns INTERP_OK.
|
||||
1. NCE_DWELL_TIME_MISSING_WITH_G4
|
||||
2. NCE_MUST_USE_G0_OR_G1_WITH_G53
|
||||
3. NCE_CANNOT_USE_G53_INCREMENTAL
|
||||
4. NCE_LINE_WITH_G10_DOES_NOT_HAVE_L2
|
||||
5. NCE_P_VALUE_NOT_AN_INTEGER_WITH_G10_L2
|
||||
6. NCE_P_VALUE_OUT_OF_RANGE_WITH_G10_L2
|
||||
7. NCE_BUG_BAD_G_CODE_MODAL_GROUP_0
|
||||
|
||||
Side effects: none
|
||||
|
||||
Called by: check_items
|
||||
|
||||
This runs checks on g_codes from a block of RS274/NGC instructions.
|
||||
Currently, all checks are on g_codes in modal group 0.
|
||||
|
||||
The read_g function checks for errors which would foul up the reading.
|
||||
The enhance_block function checks for logical errors in the use of
|
||||
axis values by G-codes in modal groups 0 and 1.
|
||||
This function checks for additional logical errors in g_codes.
|
||||
|
||||
[Fanuc, page 45, note 4] says there is no maximum for how many g_codes
|
||||
may be put on the same line, [NCMS] says nothing one way or the other,
|
||||
so the test for that is not used.
|
||||
|
||||
We are suspending any implicit motion g_code when a g_code from our
|
||||
group 0 is used. The implicit motion g_code takes effect again
|
||||
automatically after the line on which the group 0 g_code occurs. It
|
||||
is not clear what the intent of [Fanuc] is in this regard. The
|
||||
alternative is to require that any implicit motion be explicitly
|
||||
cancelled.
|
||||
|
||||
Not all checks on g_codes are included here. Those checks that are
|
||||
sensitive to whether other g_codes on the same line have been executed
|
||||
yet are made by the functions called by convert_g.
|
||||
|
||||
Our reference sources differ regarding what codes may be used for
|
||||
dwell time. [Fanuc, page 58] says use "p" or "x". [NCMS, page 23] says
|
||||
use "p", "x", or "u". We are allowing "p" only, since it is consistent
|
||||
with both sources and "x" would be confusing. However, "p" is also used
|
||||
with G10, where it must be an integer, so reading "p" values is a bit
|
||||
more trouble than would be nice.
|
||||
|
||||
*/
|
||||
|
||||
int Interp::check_g_codes(block_pointer block, //!< pointer to a block to be checked
|
||||
setup_pointer settings) //!< pointer to machine settings
|
||||
{
|
||||
int mode0, mode1;
|
||||
int p_int;
|
||||
|
||||
mode0 = block->g_modes[GM_MODAL_0];
|
||||
mode1 = block->g_modes[GM_MOTION];
|
||||
if (mode0 == -1) {
|
||||
} else if (mode0 == G_4) {
|
||||
CHKS((block->p_number == -1.0), NCE_DWELL_TIME_MISSING_WITH_G4);
|
||||
CHKS((mode1 == G_2 || mode1 == G_3), _("G4 not allowed with G2 or G3 because they both use P"));
|
||||
} else if (mode0 == G_10) {
|
||||
(block->p_number >= 0) ? p_int = (int) (block->p_number +0.5) :p_int = (int) (block->p_number -0.5);
|
||||
CHKS((block->l_number != 0 && block->l_number != 2 && block->l_number != 1 && block->l_number != 20 && block->l_number != 10 && block->l_number != 11), _("Line with G10 does not have L0, L1, L10, L11, L2, or L20"));
|
||||
CHKS((((block->p_number + 0.0001) - p_int) > 0.0002), _("P value not an integer with G10"));
|
||||
CHKS((((block->l_number == 2 || block->l_number == 20) && ((p_int < 0) || (p_int > 9)))), _("P value out of range (0-9) with G10 L%d"), block->l_number);
|
||||
CHKS((((block->l_number == 1 || block->l_number == 10 || block->l_number == 11) && p_int < 1)), _("P value out of range with G10 L%d"), block->l_number);
|
||||
} else if (mode0 == G_28) {
|
||||
} else if (mode0 == G_30) {
|
||||
} else if (mode0 == G_5_3) {
|
||||
CHKS(((mode1 != G_5_2) && (mode1 != -1)), _("Between G5.2 and G5.3 codes, only additional G5.2 codes are allowed."));
|
||||
} else if (mode1 == G_5_2){
|
||||
} else if (mode1 == G_6_2){
|
||||
} else if (mode0 == G_28_1 || mode0 == G_30_1) {
|
||||
} else if (mode0 == G_52) {
|
||||
} else if (mode0 == G_53) {
|
||||
CHKS(((block->motion_to_be != G_0) && (block->motion_to_be != G_1)),
|
||||
NCE_MUST_USE_G0_OR_G1_WITH_G53);
|
||||
CHKS(((block->g_modes[GM_DISTANCE_MODE] == G_91) ||
|
||||
((block->g_modes[GM_DISTANCE_MODE] != G_90) &&
|
||||
(settings->distance_mode == DISTANCE_MODE::INCREMENTAL))),
|
||||
NCE_CANNOT_USE_G53_INCREMENTAL);
|
||||
} else if (mode0 == G_92) {
|
||||
} else
|
||||
ERS(NCE_BUG_BAD_G_CODE_MODAL_GROUP_0);
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*! check_items
|
||||
|
||||
Returned Value: int
|
||||
If any one of check_g_codes, check_m_codes, and check_other_codes
|
||||
returns an error code, this returns that code.
|
||||
Otherwise, it returns INTERP_OK.
|
||||
|
||||
Side effects: none
|
||||
|
||||
Called by: parse_line
|
||||
|
||||
This runs checks on a block of RS274 code.
|
||||
|
||||
The functions named read_XXXX check for errors which would foul up the
|
||||
reading. This function checks for additional logical errors.
|
||||
|
||||
A block has an array of g_codes, which are initialized to -1
|
||||
(meaning no code). This calls check_g_codes to check the g_codes.
|
||||
|
||||
A block has an array of m_codes, which are initialized to -1
|
||||
(meaning no code). This calls check_m_codes to check the m_codes.
|
||||
|
||||
Items in the block which are not m or g codes are checked by
|
||||
check_other_codes.
|
||||
|
||||
*/
|
||||
|
||||
int Interp::check_items(block_pointer block, //!< pointer to a block to be checked
|
||||
setup_pointer settings) //!< pointer to machine settings
|
||||
{
|
||||
|
||||
CHP(check_g_codes(block, settings));
|
||||
CHP(check_m_codes(block));
|
||||
CHP(check_other_codes(block));
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*! check_m_codes
|
||||
|
||||
Returned Value: int
|
||||
If any of the following errors occur, this returns the error code shown.
|
||||
Otherwise, it returns INTERP_OK.
|
||||
1. There are too many m codes in the block: NCE_TOO_MANY_M_CODES_ON_LINE
|
||||
|
||||
Side effects: none
|
||||
|
||||
Called by: check_items
|
||||
|
||||
This runs checks on m_codes from a block of RS274/NGC instructions.
|
||||
|
||||
The read_m function checks for errors which would foul up the
|
||||
reading. This function checks for additional errors in m_codes.
|
||||
|
||||
*/
|
||||
|
||||
int Interp::check_m_codes(block_pointer block) //!< pointer to a block to be checked
|
||||
{
|
||||
|
||||
CHKS((block->m_count > MAX_EMS), NCE_TOO_MANY_M_CODES_ON_LINE);
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*! check_other_codes
|
||||
|
||||
Returned Value: int
|
||||
If any of the following errors occur, this returns the error code shown.
|
||||
Otherwise, it returns INTERP_OK.
|
||||
1. An A-axis value is given with a canned cycle (g80 to g89):
|
||||
NCE_CANNOT_PUT_AN_A_IN_CANNED_CYCLE
|
||||
2. A B-axis value is given with a canned cycle (g80 to g89):
|
||||
NCE_CANNOT_PUT_A_B_IN_CANNED_CYCLE
|
||||
3. A C-axis value is given with a canned cycle (g80 to g89):
|
||||
NCE_CANNOT_PUT_A_C_IN_CANNED_CYCLE
|
||||
4. A d word is in a block with no cutter_radius_compensation_on command:
|
||||
NCE_D_WORD_WITH_NO_G41_OR_G42
|
||||
5. An h_number is in a block with no tool length offset setting:
|
||||
NCE_H_WORD_WITH_NO_G43
|
||||
6. An i_number is in a block with no G-code that uses it:
|
||||
NCE_I_WORD_WITH_NO_G2_OR_G3_OR_G87_TO_USE_IT
|
||||
7. A j_number is in a block with no G-code that uses it:
|
||||
NCE_J_WORD_WITH_NO_G2_OR_G3_OR_G87_TO_USE_IT
|
||||
8. A k_number is in a block with no G-code that uses it:
|
||||
NCE_K_WORD_WITH_NO_G2_OR_G3_OR_G87_TO_USE_IT
|
||||
9. A l_number is in a block with no G-code that uses it:
|
||||
NCE_L_WORD_WITH_NO_CANNED_CYCLE_OR_G10
|
||||
10. A p_number is in a block with no G-code that uses it:
|
||||
NCE_P_WORD_WITH_NO_G4_G10_G64_G82_G86_G88_G89
|
||||
11. A q_number is in a block with no G-code that uses it:
|
||||
NCE_Q_WORD_WITH_NO_G83_OR_M66
|
||||
12. An r_number is in a block with no G-code that uses it:
|
||||
NCE_R_WORD_WITH_NO_G_CODE_THAT_USES_IT
|
||||
13. A k word is missing from a G33 block:
|
||||
NCE_K_WORD_MISSING_WITH_G33
|
||||
14. An e word is in a block with no G76 or M66 to use it:
|
||||
NCE_E_WORD_WITH_NO_G76_OR_M66_TO_USE_IT
|
||||
|
||||
Side effects: none
|
||||
|
||||
Called by: check_items
|
||||
|
||||
This runs checks on codes from a block of RS274/NGC code which are
|
||||
not m or g codes.
|
||||
|
||||
The functions named read_XXXX check for errors which would foul up the
|
||||
reading. This function checks for additional logical errors in codes.
|
||||
|
||||
*/
|
||||
|
||||
int Interp::check_other_codes(block_pointer block) //!< pointer to a block of RS274/NGC instructions
|
||||
{
|
||||
int motion;
|
||||
|
||||
motion = block->motion_to_be;
|
||||
|
||||
// bypass ALL checks, argspec takes care of that
|
||||
if (is_user_defined_g_code(motion)) {
|
||||
return INTERP_OK;
|
||||
}
|
||||
// bypass ALL checks, argspec takes care of that
|
||||
if (is_any_m_code_remapped(block, &(_setup))) {
|
||||
return INTERP_OK;
|
||||
}
|
||||
if (block->a_flag) {
|
||||
CHKS(is_a_cycle(motion), NCE_CANNOT_PUT_AN_A_IN_CANNED_CYCLE);
|
||||
}
|
||||
if (block->b_flag) {
|
||||
CHKS(is_a_cycle(motion), NCE_CANNOT_PUT_A_B_IN_CANNED_CYCLE);
|
||||
}
|
||||
if (block->c_flag) {
|
||||
CHKS(is_a_cycle(motion), NCE_CANNOT_PUT_A_C_IN_CANNED_CYCLE);
|
||||
}
|
||||
if (block->d_flag) {
|
||||
CHKS(((block->g_modes[7] != G_41) && (block->g_modes[7] != G_42) &&
|
||||
(block->g_modes[7] != G_41_1) && (block->g_modes[7] != G_42_1) &&
|
||||
(motion != G_70) && (motion != G_71) && (motion != G_71_1) &&
|
||||
(motion != G_71_2) && (motion != G_72) && (motion != G_72_1) &&
|
||||
(motion != G_72_2) && (motion != G_73) && (motion != G_83) &&
|
||||
(block->g_modes[14] != G_96)),
|
||||
_("D word with no G41, G41.1, G42, G42.1, G71, G71.1, G71.2 G73, G83 or G96 to use it"));
|
||||
}
|
||||
|
||||
if (block->dollar_flag) {
|
||||
CHKS(((motion != G_76) && (motion != G_33) && (motion != G_33_1) &&
|
||||
(block->g_modes[GM_FEED_MODE] != G_95) &&
|
||||
(block->g_modes[GM_SPINDLE_MODE] != G_96) &&
|
||||
(block->g_modes[GM_SPINDLE_MODE] != G_97) &&
|
||||
(block->m_modes[7] != 3) && (block->m_modes[7] != 4) &&
|
||||
(block->m_modes[7] != 5) && (block->m_modes[7] != 19) &&
|
||||
(block->m_modes[9] != 51) && (! block->s_flag)),
|
||||
_("$ (spindle selection) word with no M3, M4, M5, M19, M51, G33, G33.1, G76, G95, G96 or G97 to use it"));
|
||||
}
|
||||
|
||||
if (block->e_flag) {
|
||||
CHKS(((motion != G_76) && (motion != G_33) && (motion != G_33_1) &&
|
||||
(motion != G_70) && (block->m_modes[5] != 66) &&
|
||||
(block->m_modes[5] != 67) && (block->m_modes[5] != 68)),
|
||||
_("E word with no G70, G76, M66, M67 or M68 to use it"));
|
||||
}
|
||||
|
||||
if (block->h_flag) {
|
||||
CHKS((block->g_modes[GM_TOOL_LENGTH_OFFSET] != G_43 && motion != G_76 && block->g_modes[GM_TOOL_LENGTH_OFFSET] != G_43_2),
|
||||
_("H word with no G43 or G76 to use it"));
|
||||
}
|
||||
|
||||
if (block->i_flag) { /* could still be useless if yz_plane arc */
|
||||
CHKS(((motion != G_2) && (motion != G_3) && (motion != G_5) && (motion != G_5_1) &&
|
||||
(motion != G_6) && (motion != G_6_1) &&
|
||||
(motion != G_71) && (motion != G_71_1) && (motion != G_71_2) &&
|
||||
(motion != G_72) && (motion != G_72_1) && (motion != G_72_2) &&
|
||||
(motion != G_76) && (motion != G_87) && (motion != G_33_1) && (block->g_modes[GM_MODAL_0] != G_10)),
|
||||
_("I word with no G2, G3, G5, G5.1, G6, G6.1, G10, G33.1, G76, or G87 to use it"));
|
||||
}
|
||||
|
||||
if (block->j_flag) { /* could still be useless if xz_plane arc */
|
||||
CHKS(((motion != G_2) && (motion != G_3) && (motion != G_5) && (motion != G_5_1) &&
|
||||
(motion != G_6) && (motion != G_6_1) &&
|
||||
(motion != G_76) && (motion != G_87) && (block->g_modes[GM_MODAL_0] != G_10)),
|
||||
_("J word with no G2, G3, G5, G5.1, G6, G6.1, G10, G76 or G87 to use it"));
|
||||
}
|
||||
|
||||
if (block->k_flag) { /* could still be useless if xy_plane arc */
|
||||
CHKS(((motion != G_2) && (motion != G_3) && (motion != G_6_2) && (motion != G_33) && (motion != G_33_1) && (motion != G_76) && (motion != G_87)),
|
||||
_("K word with no G2, G3, G6.2, G33, G33.1, G76, or G87 to use it"));
|
||||
}
|
||||
|
||||
if (block->l_number != -1) {
|
||||
CHKS((((motion < G_81) || (motion > G_89)) && (motion != G_76) &&
|
||||
(motion != G_5_2) && (motion != G_6_2) && (motion != G_73) &&
|
||||
(block->g_modes[GM_MODAL_0] != G_10) &&
|
||||
(block->g_modes[GM_CUTTER_COMP] != G_41) && (block->g_modes[GM_CUTTER_COMP] != G_41_1) &&
|
||||
(block->g_modes[GM_CUTTER_COMP] != G_42) && (block->g_modes[GM_CUTTER_COMP] != G_42_1) &&
|
||||
(block->m_modes[5] != 66) &&
|
||||
(block->o_type != M_98) // m98 repeat
|
||||
),
|
||||
_("L word with no G10, cutter compensation, canned cycle, "
|
||||
"digital/analog input, M98 or NURBS code"));
|
||||
}
|
||||
|
||||
if (block->p_flag) {
|
||||
CHKS(((block->g_modes[GM_MODAL_0] != G_10) && (block->g_modes[GM_MODAL_0] != G_4) && (block->g_modes[GM_CONTROL_MODE] != G_64) &&
|
||||
(motion != G_76) && (motion != G_82) && (motion != G_86) && (motion != G_88) &&
|
||||
(motion != G_89) && (motion != G_5) && (motion != G_5_2) &&
|
||||
(motion != G_70) &&
|
||||
(motion != G_6) && (motion != G_6_2) &&
|
||||
(motion != G_2) && (motion != G_3) &&
|
||||
(motion != G_74) && (motion != G_84) &&
|
||||
(block->m_modes[9] != 50) && (block->m_modes[9] != 51) && (block->m_modes[9] != 52) &&
|
||||
(block->m_modes[9] != 53) && (block->m_modes[5] != 62) && (block->m_modes[5] != 63) &&
|
||||
(block->m_modes[5] != 64) && (block->m_modes[5] != 65) && (block->m_modes[5] != 66) &&
|
||||
(block->m_modes[7] != 19) && (block->user_m != 1) &&
|
||||
(block->o_type != M_98)),
|
||||
_("P word with no G2 G3 G4 G10 G64 G5 G5.2 G6, G6.2, G76 G82 G86 G88 G89"
|
||||
" or M50 M51 M52 M53 M62 M63 M64 M65 M66 M98 "
|
||||
"or user M code to use it"));
|
||||
int p_value = round_to_int(block->p_number);
|
||||
CHKS(((motion == G_2 || motion == G_3 || (block->m_modes[7] == 19)) &&
|
||||
fabs(p_value - block->p_number) > 0.001),
|
||||
_("P value not an integer with M19 G2 or G3"));
|
||||
CHKS((block->m_modes[7] == 19) && ((p_value > 2) || p_value < 0),
|
||||
_("P value must be 0,1,or 2 with M19"));
|
||||
CHKS(((motion == G_2 || motion == G_3) && round_to_int(block->p_number) < 1),
|
||||
_("P value should be 1 or greater with G2 or G3"));
|
||||
}
|
||||
|
||||
if (block->q_number != -1.0) {
|
||||
CHKS((motion != G_83) && (motion != G_73) && (motion != G_5) && (motion != G_6) && (motion != G_6_2) && (block->user_m != 1) && (motion != G_76) &&
|
||||
(block->m_modes[5] != 66) && (block->m_modes[5] != 67) && (block->m_modes[5] != 68) &&
|
||||
(block->g_modes[GM_MODAL_0] != G_10) && (block->m_modes[6] != 61) && (block->g_modes[GM_CONTROL_MODE] != G_64) &&
|
||||
(motion != G_70) &&
|
||||
(motion != G_71) && (motion != G_71_1) && (motion != G_71_2) &&
|
||||
(motion != G_72) && (motion != G_72_1) && (motion != G_72_2) &&
|
||||
(block->m_modes[7] != 19),
|
||||
_("Q word with no G5, G6, G10, G64, G73, G76, G83, M19, M66, M67, M68 or user M code that uses it"));
|
||||
}
|
||||
|
||||
if (block->r_flag) {
|
||||
CHKS(((motion != G_2) && (motion != G_3) && (motion != G_76) && (motion != G_6_2) &&
|
||||
(motion != G_71) && (motion != G_71_1) && (motion != G_71_2) &&
|
||||
(motion != G_72) && (motion != G_72_1) && (motion != G_72_2) &&
|
||||
((motion < G_81) || (motion > G_89)) && (motion != G_73) &&
|
||||
(motion != G_74) &&
|
||||
(block->g_modes[GM_CUTTER_COMP] != G_41_1) && (block->g_modes[GM_CUTTER_COMP] != G_42_1) &&
|
||||
(block->g_modes[GM_MODAL_0] != G_10) && (block->m_modes[7] != 19) ),
|
||||
NCE_R_WORD_WITH_NO_G_CODE_THAT_USES_IT);
|
||||
CHKS((block->m_modes[7] == 19) && ((block->r_number > 360.0) || (block->r_number < 0.0)),
|
||||
_("R value must be within 0..360 with M19"));
|
||||
}
|
||||
|
||||
if (!block->s_flag) {
|
||||
CHKS((block->g_modes[GM_SPINDLE_MODE] == G_96), NCE_S_WORD_MISSING_WITH_G96);
|
||||
}
|
||||
|
||||
if (motion == G_33 || motion == G_33_1) {
|
||||
CHKS((!block->k_flag), NCE_K_WORD_MISSING_WITH_G33);
|
||||
CHKS((block->f_flag), NCE_F_WORD_USED_WITH_G33);
|
||||
}
|
||||
|
||||
if (motion == G_76) {
|
||||
// pitch
|
||||
CHKS((block->p_number == -1), NCE_P_WORD_MISSING_WITH_G76);
|
||||
|
||||
CHKS((!block->i_flag || !block->j_flag || !block->k_flag),
|
||||
NCE_I_J_OR_K_WORDS_MISSING_WITH_G76);
|
||||
}
|
||||
|
||||
return INTERP_OK;
|
||||
}
|
||||
6550
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_convert.cc
vendored
Normal file
6550
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_convert.cc
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2272
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_cycles.cc
vendored
Normal file
2272
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_cycles.cc
vendored
Normal file
File diff suppressed because it is too large
Load Diff
422
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_execute.cc
vendored
Normal file
422
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_execute.cc
vendored
Normal file
@@ -0,0 +1,422 @@
|
||||
/********************************************************************
|
||||
* Description: interp_execute.cc
|
||||
*
|
||||
* Derived from a work by Thomas Kramer
|
||||
*
|
||||
* Author:
|
||||
* License: GPL Version 2
|
||||
* System: Linux
|
||||
*
|
||||
* Copyright (c) 2004 All rights reserved.
|
||||
*
|
||||
* Last change:
|
||||
********************************************************************/
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <rtapi_math.h>
|
||||
#include "rs274ngc.hh"
|
||||
#include "rs274ngc_return.hh"
|
||||
#include "interp_internal.hh"
|
||||
#include "rs274ngc_interp.hh"
|
||||
|
||||
#define RESULT_OK(x) ((x) == INTERP_OK || (x) == INTERP_EXECUTE_FINISH)
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*! execute binary
|
||||
|
||||
Returned value: int
|
||||
If execute_binary1 or execute_binary2 returns an error code, this
|
||||
returns that code.
|
||||
Otherwise, it returns INTERP_OK.
|
||||
|
||||
Side effects: The value of left is set to the result of applying
|
||||
the operation to left and right.
|
||||
|
||||
Called by: read_real_expression
|
||||
|
||||
This just calls either execute_binary1 or execute_binary2.
|
||||
|
||||
*/
|
||||
|
||||
int Interp::execute_binary(double *left, int operation, double *right)
|
||||
{
|
||||
if (operation < AND2)
|
||||
CHP(execute_binary1(left, operation, right));
|
||||
else
|
||||
CHP(execute_binary2(left, operation, right));
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*! execute_binary1
|
||||
|
||||
Returned Value: int
|
||||
If any of the following errors occur, this returns the error shown.
|
||||
Otherwise, it returns INTERP_OK.
|
||||
1. operation is unknown: NCE_BUG_UNKNOWN_OPERATION
|
||||
2. An attempt is made to divide by zero: NCE_ATTEMPT_TO_DIVIDE_BY_ZERO
|
||||
3. An attempt is made to raise a negative number to a non-integer power:
|
||||
NCE_ATTEMPT_TO_RAISE_NEGATIVE_TO_NON_INTEGER_POWER
|
||||
|
||||
Side effects:
|
||||
The result from performing the operation is put into what left points at.
|
||||
|
||||
Called by: read_real_expression.
|
||||
|
||||
This executes the operations: DIVIDED_BY, MODULO, POWER, TIMES.
|
||||
|
||||
*/
|
||||
|
||||
int Interp::execute_binary1(double *left, //!< pointer to the left operand
|
||||
int operation, //!< integer code for the operation
|
||||
double *right) //!< pointer to the right operand
|
||||
{
|
||||
switch (operation) {
|
||||
case DIVIDED_BY:
|
||||
CHKS((*right == 0.0), NCE_ATTEMPT_TO_DIVIDE_BY_ZERO);
|
||||
*left = (*left / *right);
|
||||
break;
|
||||
case MODULO: /* always calculates a positive answer */
|
||||
*left = fmod(*left, *right);
|
||||
if (*left < 0.0) {
|
||||
*left = (*left + fabs(*right));
|
||||
}
|
||||
break;
|
||||
case POWER:
|
||||
CHKS(((*left < 0.0) && (floor(*right) != *right)),
|
||||
NCE_ATTEMPT_TO_RAISE_NEGATIVE_TO_NON_INTEGER_POWER);
|
||||
*left = pow(*left, *right);
|
||||
break;
|
||||
case TIMES:
|
||||
*left = (*left * *right);
|
||||
break;
|
||||
default:
|
||||
ERS(NCE_BUG_UNKNOWN_OPERATION);
|
||||
}
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*! execute_binary2
|
||||
|
||||
Returned Value: int
|
||||
If any of the following errors occur, this returns the error code shown.
|
||||
Otherwise, it returns INTERP_OK.
|
||||
1. operation is unknown: NCE_BUG_UNKNOWN_OPERATION
|
||||
|
||||
Side effects:
|
||||
The result from performing the operation is put into what left points at.
|
||||
|
||||
Called by: read_real_expression.
|
||||
|
||||
This executes the operations: AND2, EXCLUSIVE_OR, MINUS,
|
||||
NON_EXCLUSIVE_OR, PLUS. The RS274/NGC manual [NCMS] does not say what
|
||||
the calculated value of the three logical operations should be. This
|
||||
function calculates either 1.0 (meaning true) or 0.0 (meaning false).
|
||||
Any non-zero input value is taken as meaning true, and only 0.0 means
|
||||
false.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
int Interp::execute_binary2(double *left, //!< pointer to the left operand
|
||||
int operation, //!< integer code for the operation
|
||||
double *right) //!< pointer to the right operand
|
||||
{
|
||||
double diff;
|
||||
switch (operation) {
|
||||
case AND2:
|
||||
*left = ((*left == 0.0) || (*right == 0.0)) ? 0.0 : 1.0;
|
||||
break;
|
||||
case EXCLUSIVE_OR:
|
||||
*left = (((*left == 0.0) && (*right != 0.0))
|
||||
|| ((*left != 0.0) && (*right == 0.0))) ? 1.0 : 0.0;
|
||||
break;
|
||||
case MINUS:
|
||||
*left = (*left - *right);
|
||||
break;
|
||||
case NON_EXCLUSIVE_OR:
|
||||
*left = ((*left != 0.0) || (*right != 0.0)) ? 1.0 : 0.0;
|
||||
break;
|
||||
case PLUS:
|
||||
*left = (*left + *right);
|
||||
break;
|
||||
|
||||
case LT:
|
||||
*left = (*left < *right) ? 1.0 : 0.0;
|
||||
break;
|
||||
case EQ:
|
||||
diff = fabs(*left - *right);
|
||||
*left = (diff < TOLERANCE_EQUAL) ? 1.0 : 0.0;
|
||||
break;
|
||||
case NE:
|
||||
diff = fabs(*left - *right);
|
||||
*left = (diff >= TOLERANCE_EQUAL) ? 1.0 : 0.0;
|
||||
break;
|
||||
case LE:
|
||||
diff = fabs(*left - *right);
|
||||
*left = ((diff < TOLERANCE_EQUAL) || (*left <= *right)) ? 1.0 : 0.0;
|
||||
break;
|
||||
case GE:
|
||||
diff = fabs(*left - *right);
|
||||
*left = ((diff < TOLERANCE_EQUAL) || (*left >= *right)) ? 1.0 : 0.0;
|
||||
break;
|
||||
case GT:
|
||||
*left = (*left > *right) ? 1.0 : 0.0;
|
||||
break;
|
||||
|
||||
default:
|
||||
ERS(NCE_BUG_UNKNOWN_OPERATION);
|
||||
}
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*! execute_block
|
||||
|
||||
Returned Value: int
|
||||
If convert_stop returns INTERP_EXIT, this returns INTERP_EXIT.
|
||||
If any of the following functions is called and returns an error code,
|
||||
this returns that code.
|
||||
convert_comment
|
||||
convert_feed_mode
|
||||
convert_feed_rate
|
||||
convert_g
|
||||
convert_m
|
||||
convert_speed
|
||||
convert_stop
|
||||
convert_tool_select
|
||||
Otherwise, if the probe_flag in the settings is true,
|
||||
or the input_flag is set to true this returns
|
||||
INTERP_EXECUTE_FINISH.
|
||||
Otherwise, it returns INTERP_OK.
|
||||
|
||||
Side effects:
|
||||
One block of RS274/NGC instructions is executed.
|
||||
|
||||
Called by:
|
||||
Interp::execute
|
||||
|
||||
This converts a block to zero to many actions. The order of execution
|
||||
of items in a block is critical to safe and effective machine operation,
|
||||
but is not specified clearly in the RS274/NGC documentation.
|
||||
|
||||
Actions are executed in the following order:
|
||||
1. any comment.
|
||||
2. a feed mode setting (g93, g94, g95)
|
||||
3. a feed rate (f) setting if in units_per_minute feed mode.
|
||||
4. a spindle speed (s) setting.
|
||||
5. a tool selection (t).
|
||||
6. "m" commands as described in convert_m (includes tool change).
|
||||
7. any g_codes (except g93, g94) as described in convert_g.
|
||||
8. stopping commands (m0, m1, m2, m30, or m60).
|
||||
|
||||
In inverse time feed mode, the explicit and implicit g code executions
|
||||
include feed rate setting with g1, g2, and g3. Also in inverse time
|
||||
feed mode, attempting a canned cycle cycle (g81 to g89) or setting a
|
||||
feed rate with g0 is illegal and will be detected and result in an
|
||||
error message.
|
||||
|
||||
*/
|
||||
|
||||
int Interp::execute_block(block_pointer block, //!< pointer to a block of RS274/NGC instructions
|
||||
setup_pointer settings) //!< pointer to machine settings
|
||||
{
|
||||
int status = INTERP_EXIT;
|
||||
|
||||
block->line_number = settings->sequence_number;
|
||||
if ((block->comment[0] != 0) && ONCE(STEP_COMMENT)) {
|
||||
status = convert_comment(block->comment);
|
||||
CHP(status);
|
||||
}
|
||||
if ((block->g_modes[GM_SPINDLE_MODE] != -1) && ONCE(STEP_SPINDLE_MODE)) {
|
||||
settings->active_spindle = 0; //must be single-spindle, default to 0
|
||||
if (block->dollar_flag){
|
||||
CHKS((block->dollar_number < 0 || block->dollar_number >= settings->num_spindles),
|
||||
(_("Invalid spindle ($) number in Spindle Mode command")));
|
||||
settings->active_spindle = (int)block->dollar_number;
|
||||
}
|
||||
status = convert_spindle_mode(settings->active_spindle, block, settings);
|
||||
CHP(status);
|
||||
}
|
||||
if ((block->g_modes[GM_FEED_MODE] != -1) && ONCE(STEP_FEED_MODE)) {
|
||||
settings->active_spindle = 0; //must be single-spindle, default to 0
|
||||
if (block->dollar_flag){
|
||||
CHKS((block->dollar_number < 0 || block->dollar_number >= settings->num_spindles),
|
||||
(_("Invalid spindle ($) number in Spindle Feed command")));
|
||||
settings->active_spindle = (int)block->dollar_number;
|
||||
}
|
||||
status = convert_feed_mode(block->g_modes[GM_FEED_MODE], settings);
|
||||
CHP(status);
|
||||
|
||||
}
|
||||
if (block->f_flag){
|
||||
if ((settings->feed_mode != FEED_MODE::INVERSE_TIME) && ONCE(STEP_SET_FEED_RATE)) {
|
||||
if (STEP_REMAPPED_IN_BLOCK(block, STEP_SET_FEED_RATE)) {
|
||||
return (convert_remapped_code(block, settings, STEP_SET_FEED_RATE, 'F'));
|
||||
} else {
|
||||
status = convert_feed_rate(block, settings);
|
||||
CHP(status);
|
||||
}
|
||||
}
|
||||
/* INVERSE_TIME is handled elsewhere */
|
||||
}
|
||||
if ((block->s_flag) && ONCE(STEP_SET_SPINDLE_SPEED)){
|
||||
if (STEP_REMAPPED_IN_BLOCK(block, STEP_SET_SPINDLE_SPEED)) {
|
||||
return (convert_remapped_code(block,settings,STEP_SET_SPINDLE_SPEED,'S'));
|
||||
} else {
|
||||
if (block->dollar_flag){
|
||||
CHKS((block->dollar_number < -1 || block->dollar_number >= settings->num_spindles),
|
||||
(_("Invalid spindle ($) number in Spindle speed command")));
|
||||
if (block->dollar_number == -1 ){
|
||||
for (int i = 0; i < settings->num_spindles; status = convert_speed(i++, block, settings));
|
||||
} else {
|
||||
status = convert_speed(block->dollar_number, block, settings);
|
||||
}
|
||||
} else {
|
||||
status = convert_speed(0, block, settings);
|
||||
}
|
||||
CHP(status);
|
||||
}
|
||||
}
|
||||
if ((block->t_flag) && ONCE(STEP_PREPARE)) {
|
||||
if (STEP_REMAPPED_IN_BLOCK(block, STEP_PREPARE)) {
|
||||
return (convert_remapped_code(block,settings,STEP_PREPARE,'T'));
|
||||
} else {
|
||||
CHP(convert_tool_select(block, settings));
|
||||
}
|
||||
}
|
||||
CHP(convert_m(block, settings));
|
||||
CHP(convert_g(block, settings));
|
||||
/* convert m0, m1, m2, m30, m60, or (when main program loops disabled) m99 */
|
||||
if ((block->m_modes[4] != -1) && ONCE(STEP_MGROUP4)) {
|
||||
if (STEP_REMAPPED_IN_BLOCK(block, STEP_MGROUP4)) {
|
||||
status = convert_remapped_code(block,settings,STEP_MGROUP4,'M',block->m_modes[4]);
|
||||
} else {
|
||||
status = convert_stop(block, settings);
|
||||
}
|
||||
if (status == INTERP_EXIT) {
|
||||
return(INTERP_EXIT);
|
||||
}
|
||||
else if (status != INTERP_OK) {
|
||||
ERP(status);
|
||||
}
|
||||
}
|
||||
if (settings->probe_flag)
|
||||
return (INTERP_EXECUTE_FINISH);
|
||||
|
||||
if (settings->input_flag)
|
||||
return (INTERP_EXECUTE_FINISH);
|
||||
|
||||
if (settings->toolchange_flag)
|
||||
return (INTERP_EXECUTE_FINISH);
|
||||
|
||||
// All changes to settings are complete
|
||||
write_canon_state_tag(block, settings);
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*! execute_unary
|
||||
|
||||
Returned Value: int
|
||||
If any of the following errors occur, this returns the error code shown.
|
||||
Otherwise, it returns INTERP_OK.
|
||||
1. the operation is unknown: NCE_BUG_UNKNOWN_OPERATION
|
||||
2. the argument to acos is not between minus and plus one:
|
||||
NCE_ARGUMENT_TO_ACOS_OUT_RANGE
|
||||
3. the argument to asin is not between minus and plus one:
|
||||
NCE_ARGUMENT_TO_ASIN_OUT_RANGE
|
||||
4. the argument to the natural logarithm is not positive:
|
||||
NCE_ZERO_OR_NEGATIVE_ARGUMENT_TO_LN
|
||||
5. the argument to square root is negative:
|
||||
NCE_NEGATIVE_ARGUMENT_TO_SQRT
|
||||
|
||||
Side effects:
|
||||
The result from performing the operation on the value in double_ptr
|
||||
is put into what double_ptr points at.
|
||||
|
||||
Called by: read_unary.
|
||||
|
||||
This executes the operations: ABS, ACOS, ASIN, COS, EXP, FIX, FUP, LN
|
||||
ROUND, SIN, SQRT, TAN
|
||||
|
||||
All angle measures in the input or output are in degrees.
|
||||
|
||||
*/
|
||||
|
||||
int Interp::execute_unary(double *double_ptr, //!< pointer to the operand
|
||||
int operation) //!< integer code for the operation
|
||||
{
|
||||
switch (operation) {
|
||||
case ABS:
|
||||
if (*double_ptr < 0.0)
|
||||
*double_ptr = (-1.0 * *double_ptr);
|
||||
break;
|
||||
case ACOS:
|
||||
CHKS(((*double_ptr < -1.0) || (*double_ptr > 1.0)),
|
||||
NCE_ARGUMENT_TO_ACOS_OUT_OF_RANGE);
|
||||
*double_ptr = acos(*double_ptr);
|
||||
*double_ptr = ((*double_ptr * 180.0) / M_PIl);
|
||||
break;
|
||||
case ASIN:
|
||||
CHKS(((*double_ptr < -1.0) || (*double_ptr > 1.0)),
|
||||
NCE_ARGUMENT_TO_ASIN_OUT_OF_RANGE);
|
||||
*double_ptr = asin(*double_ptr);
|
||||
*double_ptr = ((*double_ptr * 180.0) / M_PIl);
|
||||
break;
|
||||
case COS:
|
||||
*double_ptr = cos((*double_ptr * M_PIl) / 180.0);
|
||||
break;
|
||||
case EXISTS:
|
||||
// do nothing here
|
||||
// result for the EXISTS function is set by Interp:read_unary()
|
||||
break;
|
||||
case EXP:
|
||||
*double_ptr = exp(*double_ptr);
|
||||
break;
|
||||
case FIX:
|
||||
*double_ptr = floor(*double_ptr);
|
||||
break;
|
||||
case FUP:
|
||||
*double_ptr = ceil(*double_ptr);
|
||||
break;
|
||||
case LN:
|
||||
CHKS((*double_ptr <= 0.0), NCE_ZERO_OR_NEGATIVE_ARGUMENT_TO_LN);
|
||||
*double_ptr = log(*double_ptr);
|
||||
break;
|
||||
case ROUND:
|
||||
*double_ptr = (double)
|
||||
((int) (*double_ptr + ((*double_ptr < 0.0) ? -0.5 : 0.5)));
|
||||
break;
|
||||
case SIN:
|
||||
*double_ptr = sin((*double_ptr * M_PIl) / 180.0);
|
||||
break;
|
||||
case SQRT:
|
||||
CHKS((*double_ptr < 0.0), NCE_NEGATIVE_ARGUMENT_TO_SQRT);
|
||||
*double_ptr = sqrt(*double_ptr);
|
||||
break;
|
||||
case TAN:
|
||||
*double_ptr = tan((*double_ptr * M_PIl) / 180.0);
|
||||
break;
|
||||
default:
|
||||
ERS(NCE_BUG_UNKNOWN_OPERATION);
|
||||
}
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
758
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_find.cc
vendored
Normal file
758
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_find.cc
vendored
Normal file
@@ -0,0 +1,758 @@
|
||||
/********************************************************************
|
||||
* Description: interp_find.cc
|
||||
*
|
||||
* Derived from a work by Thomas Kramer
|
||||
*
|
||||
* Author:
|
||||
* License: GPL Version 2
|
||||
* System: Linux
|
||||
*
|
||||
* Copyright (c) 2004 All rights reserved.
|
||||
*
|
||||
* Last change:
|
||||
********************************************************************/
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <rtapi_math.h>
|
||||
#include "rs274ngc.hh"
|
||||
#include "nml_intf/interp_return.hh"
|
||||
#include "interp_internal.hh"
|
||||
#include "rs274ngc_interp.hh"
|
||||
#include "units.h"
|
||||
#include "tooldata/tooldata.hh"
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*! find_arc_length
|
||||
|
||||
Returned Value: double (length of path between start and end points)
|
||||
|
||||
Side effects: none
|
||||
|
||||
Called by:
|
||||
inverse_time_rate_arc
|
||||
inverse_time_rate_arc2
|
||||
inverse_time_rate_as
|
||||
|
||||
This calculates the length of the path that will be made relative to
|
||||
the XYZ axes for a motion in which the X,Y,Z, motion is a circular or
|
||||
helical arc with its axis parallel to the Z-axis. If tool length
|
||||
compensation is on, this is the path of the tool tip; if off, the
|
||||
length of the path of the spindle tip. Any rotary axis motion is
|
||||
ignored.
|
||||
|
||||
If the arc is helical, it is coincident with the hypotenuse of a right
|
||||
triangle wrapped around a cylinder. If the triangle is unwrapped, its
|
||||
base is [the radius of the cylinder times the number of radians in the
|
||||
helix] and its height is [z2 - z1], and the path length can be found
|
||||
by the Pythagorean theorem.
|
||||
|
||||
This is written as though it is only for arcs whose axis is parallel to
|
||||
the Z-axis, but it will serve also for arcs whose axis is parallel
|
||||
to the X-axis or Y-axis, with suitable permutation of the arguments.
|
||||
|
||||
This works correctly when turn is zero (find_turn returns 0 in that
|
||||
case).
|
||||
|
||||
*/
|
||||
|
||||
double Interp::find_arc_length(double x1, //!< X-coordinate of start point
|
||||
double y1, //!< Y-coordinate of start point
|
||||
double z1, //!< Z-coordinate of start point
|
||||
double center_x, //!< X-coordinate of arc center
|
||||
double center_y, //!< Y-coordinate of arc center
|
||||
int turn, //!< no. of full or partial circles CCW
|
||||
double x2, //!< X-coordinate of end point
|
||||
double y2, //!< Y-coordinate of end point
|
||||
double z2) //!< Z-coordinate of end point
|
||||
{
|
||||
double radius;
|
||||
double theta; /* amount of turn of arc in radians */
|
||||
|
||||
radius = hypot((center_x - x1), (center_y - y1));
|
||||
theta = find_turn(x1, y1, center_x, center_y, turn, x2, y2);
|
||||
if (z2 == z1)
|
||||
return (radius * fabs(theta));
|
||||
else
|
||||
return hypot((radius * theta), (z2 - z1));
|
||||
}
|
||||
|
||||
|
||||
/* Find the real destination, given the axis's current position, the
|
||||
commanded destination, and the direction to turn (which comes from
|
||||
the sign of the commanded value in the gcode). Modulo 360 positions
|
||||
of the axis are considered equivalent and we just need to find the
|
||||
nearest one. */
|
||||
|
||||
int Interp::unwrap_rotary(double *r, double sign_of, double commanded, double current, char axis) {
|
||||
double result;
|
||||
int neg = copysign(1.0, sign_of) < 0.0;
|
||||
CHKS((sign_of <= -360.0 || sign_of >= 360.0), (_("Invalid absolute position %5.2f for wrapped rotary axis %c")), sign_of, axis);
|
||||
|
||||
double d = floor(current/360.0);
|
||||
result = fabs(commanded) + (d*360.0);
|
||||
if(!neg && result < current) result += 360.0;
|
||||
if(neg && result > current) result -= 360.0;
|
||||
*r = result;
|
||||
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*! find_ends
|
||||
|
||||
Returned Value: int (INTERP_OK)
|
||||
|
||||
Side effects:
|
||||
The values of px, py, pz, aa_p, bb_p, and cc_p are set
|
||||
|
||||
Called by:
|
||||
convert_arc
|
||||
convert_home
|
||||
convert_probe
|
||||
convert_straight
|
||||
|
||||
This finds the coordinates of a point, "end", in the currently
|
||||
active coordinate system, and sets the values of the pointers to the
|
||||
coordinates (which are the arguments to the function).
|
||||
|
||||
In all cases, if no value for the coordinate is given in the block, the
|
||||
current value for the coordinate is used. When cutter radius
|
||||
compensation is on, this function is called before compensation
|
||||
calculations are performed, so the current value of the programmed
|
||||
point is used, not the current value of the actual current_point.
|
||||
|
||||
There are three cases for when the coordinate is included in the block:
|
||||
|
||||
1. G_53 is active. This means to interpret the coordinates as machine
|
||||
coordinates. That is accomplished by adding the three offsets to the
|
||||
coordinates given in the block. The x,y block coordinates are also
|
||||
rotated. The end result is the machine coordinates in the block are
|
||||
converted to coordinates in the current system.
|
||||
|
||||
2. Absolute coordinate mode is in effect. The coordinate in the block
|
||||
is used.
|
||||
|
||||
3. Incremental coordinate mode is in effect. The coordinate in the
|
||||
block plus either (i) the programmed current position - when cutter
|
||||
radius compensation is in progress, or (2) the actual current position.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
int Interp::find_ends(block_pointer block, //!< pointer to a block of RS274/NGC instructions
|
||||
setup_pointer s, //!< pointer to machine settings
|
||||
double *px, //!< pointer to end_x
|
||||
double *py, //!< pointer to end_y
|
||||
double *pz, //!< pointer to end_z
|
||||
double *AA_p, //!< pointer to end_a
|
||||
double *BB_p, //!< pointer to end_b
|
||||
double *CC_p, //!< pointer to end_c
|
||||
double *u_p, double *v_p, double *w_p)
|
||||
{
|
||||
bool middle;
|
||||
CUTTER_COMP comp;
|
||||
|
||||
middle = !s->cutter_comp_firstmove;
|
||||
comp = s->cutter_comp_side;
|
||||
|
||||
if (block->g_modes[GM_MODAL_0] == G_53) { /* distance mode is absolute in this case */
|
||||
#ifdef DEBUG_EMC
|
||||
COMMENT("interpreter: offsets temporarily suspended");
|
||||
#endif
|
||||
CHKS((block->radius_flag || block->theta_flag), _("Cannot use polar coordinates with G53"));
|
||||
|
||||
double cx = s->current_x + s->axis_offset_x;
|
||||
double cy = s->current_y + s->axis_offset_y;
|
||||
rotate(&cx, &cy, s->rotation_xy);
|
||||
|
||||
if(block->x_flag) {
|
||||
*px = block->x_number - s->origin_offset_x - s->tool_offset.tran.x;
|
||||
} else {
|
||||
*px = cx;
|
||||
}
|
||||
|
||||
if(block->y_flag) {
|
||||
*py = block->y_number - s->origin_offset_y - s->tool_offset.tran.y;
|
||||
} else {
|
||||
*py = cy;
|
||||
}
|
||||
|
||||
rotate(px, py, -s->rotation_xy);
|
||||
*px -= s->axis_offset_x;
|
||||
*py -= s->axis_offset_y;
|
||||
|
||||
if(block->z_flag) {
|
||||
*pz = block->z_number - s->origin_offset_z - s->axis_offset_z - s->tool_offset.tran.z;
|
||||
} else {
|
||||
*pz = s->current_z;
|
||||
}
|
||||
|
||||
if(block->a_flag) {
|
||||
if(s->a_axis_wrapped) {
|
||||
CHP(unwrap_rotary(AA_p, block->a_number,
|
||||
block->a_number - s->AA_origin_offset - s->AA_axis_offset - s->tool_offset.a,
|
||||
s->AA_current, 'A'));
|
||||
} else {
|
||||
*AA_p = block->a_number - s->AA_origin_offset - s->AA_axis_offset;
|
||||
}
|
||||
} else {
|
||||
*AA_p = s->AA_current;
|
||||
}
|
||||
|
||||
if(block->b_flag) {
|
||||
if(s->b_axis_wrapped) {
|
||||
CHP(unwrap_rotary(BB_p, block->b_number,
|
||||
block->b_number - s->BB_origin_offset - s->BB_axis_offset - s->tool_offset.b,
|
||||
s->BB_current, 'B'));
|
||||
} else {
|
||||
*BB_p = block->b_number - s->BB_origin_offset - s->BB_axis_offset;
|
||||
}
|
||||
} else {
|
||||
*BB_p = s->BB_current;
|
||||
}
|
||||
|
||||
if(block->c_flag) {
|
||||
if(s->c_axis_wrapped) {
|
||||
CHP(unwrap_rotary(CC_p, block->c_number,
|
||||
block->c_number - s->CC_origin_offset - s->CC_axis_offset - s->tool_offset.c,
|
||||
s->CC_current, 'C'));
|
||||
} else {
|
||||
*CC_p = block->c_number - s->CC_origin_offset - s->CC_axis_offset;
|
||||
}
|
||||
} else {
|
||||
*CC_p = s->CC_current;
|
||||
}
|
||||
|
||||
if(block->u_flag) {
|
||||
*u_p = block->u_number - s->u_origin_offset - s->u_axis_offset - s->tool_offset.u;
|
||||
} else {
|
||||
*u_p = s->u_current;
|
||||
}
|
||||
|
||||
if(block->v_flag) {
|
||||
*v_p = block->v_number - s->v_origin_offset - s->v_axis_offset - s->tool_offset.v;
|
||||
} else {
|
||||
*v_p = s->v_current;
|
||||
}
|
||||
|
||||
if(block->w_flag) {
|
||||
*w_p = block->w_number - s->w_origin_offset - s->w_axis_offset - s->tool_offset.w;
|
||||
} else {
|
||||
*w_p = s->w_current;
|
||||
}
|
||||
} else if (s->distance_mode == DISTANCE_MODE::ABSOLUTE) {
|
||||
|
||||
if(block->x_flag) {
|
||||
*px = block->x_number;
|
||||
} else {
|
||||
// both cutter comp planes affect X ...
|
||||
*px = (comp != CUTTER_COMP::OFF && middle) ? s->program_x : s->current_x;
|
||||
}
|
||||
|
||||
if(block->y_flag) {
|
||||
*py = block->y_number;
|
||||
} else {
|
||||
// but only XY affects Y ...
|
||||
*py = (comp != CUTTER_COMP::OFF && middle && s->plane == CANON_PLANE::XY) ? s->program_y : s->current_y;
|
||||
}
|
||||
|
||||
if(block->radius_flag && block->theta_flag) {
|
||||
CHKS((block->x_flag || block->y_flag), _("Cannot specify X or Y words with polar coordinate"));
|
||||
*px = block->radius * cos(D2R(block->theta));
|
||||
*py = block->radius * sin(D2R(block->theta));
|
||||
} else if(block->radius_flag) {
|
||||
double theta;
|
||||
CHKS((block->x_flag || block->y_flag), _("Cannot specify X or Y words with polar coordinate"));
|
||||
CHKS((*py == 0 && *px == 0), _("Must specify angle in polar coordinate if at the origin"));
|
||||
theta = atan2(*py, *px);
|
||||
*px = block->radius * cos(theta);
|
||||
*py = block->radius * sin(theta);
|
||||
} else if(block->theta_flag) {
|
||||
double radius;
|
||||
CHKS((block->x_flag || block->y_flag), _("Cannot specify X or Y words with polar coordinate"));
|
||||
radius = hypot(*py, *px);
|
||||
*px = radius * cos(D2R(block->theta));
|
||||
*py = radius * sin(D2R(block->theta));
|
||||
}
|
||||
|
||||
if(block->z_flag) {
|
||||
*pz = block->z_number;
|
||||
} else {
|
||||
// and only XZ affects Z.
|
||||
*pz = (comp != CUTTER_COMP::OFF && middle && s->plane == CANON_PLANE::XZ) ? s->program_z : s->current_z;
|
||||
}
|
||||
|
||||
if(block->a_flag) {
|
||||
if(s->a_axis_wrapped) {
|
||||
CHP(unwrap_rotary(AA_p, block->a_number, block->a_number, s->AA_current, 'A'));
|
||||
} else {
|
||||
*AA_p = block->a_number;
|
||||
}
|
||||
} else {
|
||||
*AA_p = s->AA_current;
|
||||
}
|
||||
|
||||
if(block->b_flag) {
|
||||
if(s->b_axis_wrapped) {
|
||||
CHP(unwrap_rotary(BB_p, block->b_number, block->b_number, s->BB_current, 'B'));
|
||||
} else {
|
||||
*BB_p = block->b_number;
|
||||
}
|
||||
} else {
|
||||
*BB_p = s->BB_current;
|
||||
}
|
||||
|
||||
if(block->c_flag) {
|
||||
if(s->c_axis_wrapped) {
|
||||
CHP(unwrap_rotary(CC_p, block->c_number, block->c_number, s->CC_current, 'C'));
|
||||
} else {
|
||||
*CC_p = block->c_number;
|
||||
}
|
||||
} else {
|
||||
*CC_p = s->CC_current;
|
||||
}
|
||||
|
||||
*u_p = (block->u_flag) ? block->u_number : s->u_current;
|
||||
*v_p = (block->v_flag) ? block->v_number : s->v_current;
|
||||
*w_p = (block->w_flag) ? block->w_number : s->w_current;
|
||||
|
||||
} else { /* mode is DISTANCE_MODE::INCREMENTAL */
|
||||
|
||||
// both cutter comp planes affect X ...
|
||||
*px = (comp != CUTTER_COMP::OFF && middle) ? s->program_x: s->current_x;
|
||||
if(block->x_flag) *px += block->x_number;
|
||||
|
||||
// but only XY affects Y ...
|
||||
*py = (comp != CUTTER_COMP::OFF && middle && s->plane == CANON_PLANE::XY) ? s->program_y: s->current_y;
|
||||
if(block->y_flag) *py += block->y_number;
|
||||
|
||||
if(block->radius_flag) {
|
||||
double radius, theta;
|
||||
CHKS((block->x_flag || block->y_flag), _("Cannot specify X or Y words with polar coordinate"));
|
||||
CHKS((*py == 0 && *px == 0), _("Incremental motion with polar coordinates is indeterminate when at the origin"));
|
||||
theta = atan2(*py, *px);
|
||||
radius = hypot(*py, *px) + block->radius;
|
||||
*px = radius * cos(theta);
|
||||
*py = radius * sin(theta);
|
||||
}
|
||||
|
||||
if(block->theta_flag) {
|
||||
double radius, theta;
|
||||
CHKS((block->x_flag || block->y_flag), _("Cannot specify X or Y words with polar coordinate"));
|
||||
CHKS((*py == 0 && *px == 0), _("G91 motion with polar coordinates is indeterminate when at the origin"));
|
||||
theta = atan2(*py, *px) + D2R(block->theta);
|
||||
radius = hypot(*py, *px);
|
||||
*px = radius * cos(theta);
|
||||
*py = radius * sin(theta);
|
||||
}
|
||||
|
||||
// and only XZ affects Z.
|
||||
*pz = (comp != CUTTER_COMP::OFF && middle && s->plane == CANON_PLANE::XZ) ? s->program_z: s->current_z;
|
||||
if(block->z_flag) *pz += block->z_number;
|
||||
|
||||
*AA_p = s->AA_current;
|
||||
if(block->a_flag) *AA_p += block->a_number;
|
||||
|
||||
*BB_p = s->BB_current;
|
||||
if(block->b_flag) *BB_p += block->b_number;
|
||||
|
||||
*CC_p = s->CC_current;
|
||||
if(block->c_flag) *CC_p += block->c_number;
|
||||
|
||||
*u_p = s->u_current;
|
||||
if(block->u_flag) *u_p += block->u_number;
|
||||
|
||||
*v_p = s->v_current;
|
||||
if(block->v_flag) *v_p += block->v_number;
|
||||
|
||||
*w_p = s->w_current;
|
||||
if(block->w_flag) *w_p += block->w_number;
|
||||
}
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*! find_relative
|
||||
|
||||
Returned Value: int (INTERP_OK)
|
||||
|
||||
Side effects:
|
||||
The values of x2, y2, z2, aa_2, bb_2, and cc_2 are set.
|
||||
(NOTE: aa_2 etc. are written with lower case letters in this
|
||||
documentation because upper case would confuse the pre-preprocessor.)
|
||||
|
||||
Called by:
|
||||
convert_home
|
||||
|
||||
This finds the coordinates in the current system, under the current
|
||||
tool length offset, of a point (x1, y1, z1, aa_1, bb_1, cc_1) whose absolute
|
||||
coordinates are known.
|
||||
|
||||
Don't confuse this with the inverse operation.
|
||||
|
||||
*/
|
||||
|
||||
int Interp::find_relative(double x1, //!< absolute x position
|
||||
double y1, //!< absolute y position
|
||||
double z1, //!< absolute z position
|
||||
double AA_1, //!< absolute a position
|
||||
double BB_1, //!< absolute b position
|
||||
double CC_1, //!< absolute c position
|
||||
double u_1,
|
||||
double v_1,
|
||||
double w_1,
|
||||
double *x2, //!< pointer to relative x
|
||||
double *y2, //!< pointer to relative y
|
||||
double *z2, //!< pointer to relative z
|
||||
double *AA_2, //!< pointer to relative a
|
||||
double *BB_2, //!< pointer to relative b
|
||||
double *CC_2, //!< pointer to relative c
|
||||
double *u_2,
|
||||
double *v_2,
|
||||
double *w_2,
|
||||
setup_pointer settings) //!< pointer to machine settings
|
||||
{
|
||||
*x2 = x1 - settings->origin_offset_x - settings->tool_offset.tran.x;
|
||||
*y2 = y1 - settings->origin_offset_y - settings->tool_offset.tran.y;
|
||||
rotate(x2, y2, -settings->rotation_xy);
|
||||
*x2 -= settings->axis_offset_x;
|
||||
*y2 -= settings->axis_offset_y;
|
||||
*z2 = z1 - settings->origin_offset_z - settings->axis_offset_z - settings->tool_offset.tran.z;
|
||||
|
||||
if(settings->a_axis_wrapped) {
|
||||
CHP(unwrap_rotary(AA_2, AA_1,
|
||||
AA_1 - settings->AA_origin_offset - settings->AA_axis_offset - settings->tool_offset.a,
|
||||
settings->AA_current, 'A'));
|
||||
} else {
|
||||
*AA_2 = AA_1 - settings->AA_origin_offset - settings->AA_axis_offset;
|
||||
}
|
||||
|
||||
if(settings->b_axis_wrapped) {
|
||||
CHP(unwrap_rotary(BB_2, BB_1,
|
||||
BB_1 - settings->BB_origin_offset - settings->BB_axis_offset - settings->tool_offset.b,
|
||||
settings->BB_current, 'B'));
|
||||
} else {
|
||||
*BB_2 = BB_1 - settings->BB_origin_offset - settings->BB_axis_offset;
|
||||
}
|
||||
|
||||
if(settings->c_axis_wrapped) {
|
||||
CHP(unwrap_rotary(CC_2, CC_1,
|
||||
CC_1 - settings->CC_origin_offset - settings->CC_axis_offset - settings->tool_offset.c,
|
||||
settings->CC_current, 'C'));
|
||||
} else {
|
||||
*CC_2 = CC_1 - settings->CC_origin_offset - settings->CC_axis_offset;
|
||||
}
|
||||
|
||||
*u_2 = u_1 - settings->u_origin_offset - settings->u_axis_offset - settings->tool_offset.u;
|
||||
*v_2 = v_1 - settings->v_origin_offset - settings->v_axis_offset - settings->tool_offset.v;
|
||||
*w_2 = w_1 - settings->w_origin_offset - settings->w_axis_offset - settings->tool_offset.w;
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
// find what the current coordinates would be if we were in a different system
|
||||
|
||||
int Interp::find_current_in_system(setup_pointer s, int system,
|
||||
double *x, double *y, double *z,
|
||||
double *a, double *b, double *c,
|
||||
double *u, double *v, double *w) {
|
||||
double *p = s->parameters;
|
||||
|
||||
*x = s->current_x;
|
||||
*y = s->current_y;
|
||||
*z = s->current_z;
|
||||
*a = s->AA_current;
|
||||
*b = s->BB_current;
|
||||
*c = s->CC_current;
|
||||
*u = s->u_current;
|
||||
*v = s->v_current;
|
||||
*w = s->w_current;
|
||||
|
||||
*x += s->axis_offset_x;
|
||||
*y += s->axis_offset_y;
|
||||
*z += s->axis_offset_z;
|
||||
*a += s->AA_axis_offset;
|
||||
*b += s->BB_axis_offset;
|
||||
*c += s->CC_axis_offset;
|
||||
*u += s->u_axis_offset;
|
||||
*v += s->v_axis_offset;
|
||||
*w += s->w_axis_offset;
|
||||
|
||||
rotate(x, y, s->rotation_xy);
|
||||
|
||||
*x += s->origin_offset_x;
|
||||
*y += s->origin_offset_y;
|
||||
*z += s->origin_offset_z;
|
||||
*a += s->AA_origin_offset;
|
||||
*b += s->BB_origin_offset;
|
||||
*c += s->CC_origin_offset;
|
||||
*u += s->u_origin_offset;
|
||||
*v += s->v_origin_offset;
|
||||
*w += s->w_origin_offset;
|
||||
|
||||
*x -= USER_TO_PROGRAM_LEN(p[5201 + system * 20]);
|
||||
*y -= USER_TO_PROGRAM_LEN(p[5202 + system * 20]);
|
||||
*z -= USER_TO_PROGRAM_LEN(p[5203 + system * 20]);
|
||||
*a -= USER_TO_PROGRAM_ANG(p[5204 + system * 20]);
|
||||
*b -= USER_TO_PROGRAM_ANG(p[5205 + system * 20]);
|
||||
*c -= USER_TO_PROGRAM_ANG(p[5206 + system * 20]);
|
||||
*u -= USER_TO_PROGRAM_LEN(p[5207 + system * 20]);
|
||||
*v -= USER_TO_PROGRAM_LEN(p[5208 + system * 20]);
|
||||
*w -= USER_TO_PROGRAM_LEN(p[5209 + system * 20]);
|
||||
|
||||
rotate(x, y, -p[5210 + system * 20]);
|
||||
|
||||
if (p[5210]) {
|
||||
*x -= USER_TO_PROGRAM_LEN(p[5211]);
|
||||
*y -= USER_TO_PROGRAM_LEN(p[5212]);
|
||||
*z -= USER_TO_PROGRAM_LEN(p[5213]);
|
||||
*a -= USER_TO_PROGRAM_ANG(p[5214]);
|
||||
*b -= USER_TO_PROGRAM_ANG(p[5215]);
|
||||
*c -= USER_TO_PROGRAM_ANG(p[5216]);
|
||||
*u -= USER_TO_PROGRAM_LEN(p[5217]);
|
||||
*v -= USER_TO_PROGRAM_LEN(p[5218]);
|
||||
*w -= USER_TO_PROGRAM_LEN(p[5219]);
|
||||
}
|
||||
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
|
||||
// find what the current coordinates would be if we were in a different system,
|
||||
// if TLO were unapplied
|
||||
|
||||
int Interp::find_current_in_system_without_tlo(setup_pointer s, int system,
|
||||
double *x, double *y, double *z,
|
||||
double *a, double *b, double *c,
|
||||
double *u, double *v, double *w) {
|
||||
double *p = s->parameters;
|
||||
|
||||
*x = s->current_x;
|
||||
*y = s->current_y;
|
||||
*z = s->current_z;
|
||||
*a = s->AA_current;
|
||||
*b = s->BB_current;
|
||||
*c = s->CC_current;
|
||||
*u = s->u_current;
|
||||
*v = s->v_current;
|
||||
*w = s->w_current;
|
||||
|
||||
*x += s->axis_offset_x;
|
||||
*y += s->axis_offset_y;
|
||||
*z += s->axis_offset_z;
|
||||
*a += s->AA_axis_offset;
|
||||
*b += s->BB_axis_offset;
|
||||
*c += s->CC_axis_offset;
|
||||
*u += s->u_axis_offset;
|
||||
*v += s->v_axis_offset;
|
||||
*w += s->w_axis_offset;
|
||||
|
||||
rotate(x, y, s->rotation_xy);
|
||||
|
||||
*x += s->origin_offset_x;
|
||||
*y += s->origin_offset_y;
|
||||
*z += s->origin_offset_z;
|
||||
*a += s->AA_origin_offset;
|
||||
*b += s->BB_origin_offset;
|
||||
*c += s->CC_origin_offset;
|
||||
*u += s->u_origin_offset;
|
||||
*v += s->v_origin_offset;
|
||||
*w += s->w_origin_offset;
|
||||
|
||||
*x += s->tool_offset.tran.x;
|
||||
*y += s->tool_offset.tran.y;
|
||||
*z += s->tool_offset.tran.z;
|
||||
*a += s->tool_offset.a;
|
||||
*b += s->tool_offset.b;
|
||||
*c += s->tool_offset.c;
|
||||
*u += s->tool_offset.u;
|
||||
*v += s->tool_offset.v;
|
||||
*w += s->tool_offset.w;
|
||||
|
||||
*x -= USER_TO_PROGRAM_LEN(p[5201 + system * 20]);
|
||||
*y -= USER_TO_PROGRAM_LEN(p[5202 + system * 20]);
|
||||
*z -= USER_TO_PROGRAM_LEN(p[5203 + system * 20]);
|
||||
*a -= USER_TO_PROGRAM_ANG(p[5204 + system * 20]);
|
||||
*b -= USER_TO_PROGRAM_ANG(p[5205 + system * 20]);
|
||||
*c -= USER_TO_PROGRAM_ANG(p[5206 + system * 20]);
|
||||
*u -= USER_TO_PROGRAM_LEN(p[5207 + system * 20]);
|
||||
*v -= USER_TO_PROGRAM_LEN(p[5208 + system * 20]);
|
||||
*w -= USER_TO_PROGRAM_LEN(p[5209 + system * 20]);
|
||||
|
||||
rotate(x, y, -p[5210 + system * 20]);
|
||||
|
||||
if (p[5210]) {
|
||||
*x -= USER_TO_PROGRAM_LEN(p[5211]);
|
||||
*y -= USER_TO_PROGRAM_LEN(p[5212]);
|
||||
*z -= USER_TO_PROGRAM_LEN(p[5213]);
|
||||
*a -= USER_TO_PROGRAM_ANG(p[5214]);
|
||||
*b -= USER_TO_PROGRAM_ANG(p[5215]);
|
||||
*c -= USER_TO_PROGRAM_ANG(p[5216]);
|
||||
*u -= USER_TO_PROGRAM_LEN(p[5217]);
|
||||
*v -= USER_TO_PROGRAM_LEN(p[5218]);
|
||||
*w -= USER_TO_PROGRAM_LEN(p[5219]);
|
||||
}
|
||||
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*! find_straight_length
|
||||
|
||||
Returned Value: double (length of path between start and end points)
|
||||
|
||||
Side effects: none
|
||||
|
||||
Called by:
|
||||
inverse_time_rate_straight
|
||||
inverse_time_rate_as
|
||||
|
||||
This calculates a number to use in feed rate calculations when inverse
|
||||
time feed mode is used, for a motion in which X,Y,Z,A,B, and C each change
|
||||
linearly or not at all from their initial value to their end value.
|
||||
|
||||
This is used when the feed_reference mode is CANON_XYZ, which is
|
||||
always in rs274NGC.
|
||||
|
||||
If any of the X, Y, or Z axes move or the A-axis, B-axis, and C-axis
|
||||
do not move, this is the length of the path relative to the XYZ axes
|
||||
from the first point to the second, and any rotary axis motion is
|
||||
ignored. The length is the simple Euclidean distance.
|
||||
|
||||
The formula for the Euclidean distance "length" of a move involving
|
||||
only the A, B and C axes is based on a conversation with Jim Frohardt at
|
||||
Boeing, who says that the Fanuc controller on their 5-axis machine
|
||||
interprets the feed rate this way. Note that if only one rotary axis
|
||||
moves, this formula returns the absolute value of that axis move,
|
||||
which is what is desired.
|
||||
|
||||
*/
|
||||
|
||||
double Interp::find_straight_length(double x2, //!< X-coordinate of end point
|
||||
double y2, //!< Y-coordinate of end point
|
||||
double z2, //!< Z-coordinate of end point
|
||||
double AA_2, //!< A-coordinate of end point
|
||||
double BB_2, //!< B-coordinate of end point
|
||||
double CC_2, //!< C-coordinate of end point
|
||||
double u_2,
|
||||
double v_2,
|
||||
double w_2,
|
||||
double x1, //!< X-coordinate of start point
|
||||
double y1, //!< Y-coordinate of start point
|
||||
double z1, //!< Z-coordinate of start point
|
||||
double AA_1, //!< A-coordinate of start point
|
||||
double BB_1, //!< B-coordinate of start point
|
||||
double CC_1, //!< C-coordinate of start point
|
||||
double u_1,
|
||||
double v_1,
|
||||
double w_1
|
||||
)
|
||||
{
|
||||
#define tiny 1e-7
|
||||
if ( (fabs(x1-x2) > tiny) || (fabs(y1-y2) > tiny) || (fabs(z1-z2) > tiny) )
|
||||
return sqrt(pow((x2 - x1), 2) + pow((y2 - y1), 2) + pow((z2 - z1), 2));
|
||||
else if ( (fabs(u_1-u_2) > tiny) || (fabs(v_1-v_2) > tiny) || (fabs(w_1-w_2) > tiny) )
|
||||
return sqrt(pow((u_2 - u_1), 2) + pow((v_2 - v_1), 2) + pow((w_2 - w_1), 2));
|
||||
else
|
||||
return sqrt(pow((AA_2 - AA_1), 2) + pow((BB_2 - BB_1), 2) + pow((CC_2 - CC_1), 2));
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*! find_turn
|
||||
|
||||
Returned Value: double (angle in radians between two radii of a circle)
|
||||
|
||||
Side effects: none
|
||||
|
||||
Called by: find_arc_length
|
||||
|
||||
All angles are in radians.
|
||||
|
||||
*/
|
||||
|
||||
double Interp::find_turn(double x1, //!< X-coordinate of start point
|
||||
double y1, //!< Y-coordinate of start point
|
||||
double center_x, //!< X-coordinate of arc center
|
||||
double center_y, //!< Y-coordinate of arc center
|
||||
int turn, //!< no. of full or partial circles CCW
|
||||
double x2, //!< X-coordinate of end point
|
||||
double y2) //!< Y-coordinate of end point
|
||||
{
|
||||
double alpha; /* angle of first radius */
|
||||
double beta; /* angle of second radius */
|
||||
double theta; /* amount of turn of arc CCW - negative if CW */
|
||||
|
||||
if (turn == 0)
|
||||
return 0.0;
|
||||
alpha = atan2((y1 - center_y), (x1 - center_x));
|
||||
beta = atan2((y2 - center_y), (x2 - center_x));
|
||||
if (turn > 0) {
|
||||
if (beta <= alpha)
|
||||
beta = (beta + (2 * M_PIl));
|
||||
theta = ((beta - alpha) + ((turn - 1) * (2 * M_PIl)));
|
||||
} else { /* turn < 0 */
|
||||
|
||||
if (alpha <= beta)
|
||||
alpha = (alpha + (2 * M_PIl));
|
||||
theta = ((beta - alpha) + ((turn + 1) * (2 * M_PIl)));
|
||||
}
|
||||
return (theta);
|
||||
}
|
||||
|
||||
int Interp::find_tool_index(setup_pointer settings, int toolno, int *index)
|
||||
{
|
||||
|
||||
#ifdef TOOL_NML //{
|
||||
if(!settings->random_toolchanger && toolno == 0) {
|
||||
*index = 0;
|
||||
return INTERP_OK;
|
||||
}
|
||||
#else //}{
|
||||
(void)settings;
|
||||
// special case is included in tooldata_find_index_for_tool()
|
||||
#endif //}
|
||||
|
||||
*index = tooldata_find_index_for_tool(toolno);
|
||||
|
||||
CHKS((*index == -1), (_("Requested tool %d not found in the tool table")), toolno);
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
int Interp::find_tool_pocket(setup_pointer settings, int toolno, int *pocket)
|
||||
{
|
||||
#ifdef TOOL_NML //{
|
||||
if(!settings->random_toolchanger && toolno == 0) {
|
||||
*pocket = 0;
|
||||
return INTERP_OK;
|
||||
}
|
||||
#else //}{
|
||||
(void)settings;
|
||||
// special case is included in tooldata_find_index_for_tool()
|
||||
#endif //}
|
||||
int idx = tooldata_find_index_for_tool(toolno);
|
||||
*pocket = 0; //not found
|
||||
CHKS((idx == -1), (_("Requested tool %d not found in the tool table")), toolno);
|
||||
|
||||
CANON_TOOL_TABLE tdata = tooldata_entry_init();
|
||||
if (tooldata_get(&tdata,idx) != IDX_OK) {
|
||||
fprintf(stderr,"UNEXPECTED idx %s %d\n",__FILE__,__LINE__);
|
||||
}
|
||||
*pocket = tdata.pocketno;
|
||||
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
42
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_fwd.hh
vendored
Normal file
42
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_fwd.hh
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* @file interp_fwd.hh
|
||||
*
|
||||
* Forward declarations for interp_internal.hh.
|
||||
*
|
||||
* @author Robert W. Ellenberg <rwe24g@gmail.com>
|
||||
*
|
||||
* Copyright (c) 2019, Robert W. Ellenberg
|
||||
*
|
||||
* This source code is released for free distribution under the terms of the
|
||||
* GNU General Public License (V2) as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef INTERP_FWD_HH
|
||||
#define INTERP_FWD_HH
|
||||
|
||||
class Interp;
|
||||
|
||||
struct block_struct;
|
||||
typedef struct block_struct *block_pointer;
|
||||
typedef struct block_struct block;
|
||||
|
||||
struct setup;
|
||||
typedef struct setup *setup_pointer;
|
||||
|
||||
struct remap_struct;
|
||||
typedef struct remap_struct *remap_pointer;
|
||||
typedef struct remap_struct remap;
|
||||
|
||||
struct context_struct;
|
||||
typedef struct context_struct *context_pointer;
|
||||
typedef struct context_struct context;
|
||||
|
||||
struct parameter_value_struct;
|
||||
typedef parameter_value_struct *parameter_pointer;
|
||||
typedef parameter_value_struct parameter_value;
|
||||
|
||||
struct offset_struct;
|
||||
typedef offset_struct *offset_pointer;
|
||||
typedef offset_struct offset;
|
||||
|
||||
#endif // INTERP_FWD_HH
|
||||
1244
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_g7x.cc
vendored
Normal file
1244
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_g7x.cc
vendored
Normal file
File diff suppressed because it is too large
Load Diff
494
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_internal.cc
vendored
Normal file
494
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_internal.cc
vendored
Normal file
@@ -0,0 +1,494 @@
|
||||
/********************************************************************
|
||||
* Description: interp_internal.cc
|
||||
*
|
||||
* Derived from a work by Thomas Kramer
|
||||
*
|
||||
* Author:
|
||||
* License: GPL Version 2
|
||||
* System: Linux
|
||||
*
|
||||
* Copyright (c) 2004 All rights reserved.
|
||||
*
|
||||
* Last change:
|
||||
********************************************************************/
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include "rs274ngc.hh"
|
||||
#include "rs274ngc_return.hh"
|
||||
#include "interp_internal.hh" // interpreter private definitions
|
||||
#include "rs274ngc_interp.hh"
|
||||
#include <string.h>
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*! close_and_downcase
|
||||
|
||||
Returned Value: int
|
||||
If any of the following errors occur, this returns the error code shown.
|
||||
Otherwise, it returns INTERP_OK.
|
||||
1. A left parenthesis is found inside a comment:
|
||||
NCE_NESTED_COMMENT_FOUND
|
||||
2. The line ends before an open comment is closed:
|
||||
NCE_UNCLOSED_COMMENT_FOUND
|
||||
3. A newline character is found that is not followed by null:
|
||||
NCE_NULL_MISSING_AFTER_NEWLINE
|
||||
|
||||
Side effects: See below
|
||||
|
||||
Called by: read_text
|
||||
|
||||
To simplify handling upper case letters, spaces, and tabs, this
|
||||
function removes spaces and tabs and downcases everything on a
|
||||
line which is not part of a comment.
|
||||
|
||||
Comments are left unchanged in place. Comments are anything
|
||||
enclosed in parentheses. Nested comments, indicated by a left
|
||||
parenthesis inside a comment, are illegal.
|
||||
|
||||
The line must have a null character at the end when it comes in.
|
||||
The line may have one newline character just before the end. If
|
||||
there is a newline, it will be removed.
|
||||
|
||||
Although this software system detects and rejects all illegal characters
|
||||
and illegal syntax, this particular function does not detect problems
|
||||
with anything but comments.
|
||||
|
||||
We are treating RS274 code here as case-insensitive and spaces and
|
||||
tabs as if they have no meaning. [RS274D, page 6] says spaces and tabs
|
||||
are to be ignored by control.
|
||||
|
||||
The KT and NGC manuals say nothing about case or spaces and tabs.
|
||||
|
||||
*/
|
||||
|
||||
int Interp::close_and_downcase(char *line) //!< string: one line of NC code
|
||||
{
|
||||
int m;
|
||||
int n;
|
||||
int comment, semicomment;
|
||||
char item;
|
||||
comment = semicomment = 0;
|
||||
for (n = 0, m = 0; (item = line[m]) != '\0'; m++) {
|
||||
if ((item == ';') && !comment)
|
||||
semicomment = 1;
|
||||
|
||||
if (semicomment) {
|
||||
line[n++] = item; // pass literally
|
||||
continue;
|
||||
}
|
||||
if (comment) {
|
||||
line[n++] = item;
|
||||
if (item == ')') {
|
||||
comment = 0;
|
||||
} else if (item == '(')
|
||||
ERS(NCE_NESTED_COMMENT_FOUND);
|
||||
} else if ((item == ' ') || (item == '\t') || (item == '\r'));
|
||||
/* don't copy blank or tab or CR */
|
||||
else if (item == '\n') { /* don't copy newline *//* but check null follows */
|
||||
CHKS((line[m + 1] != 0), NCE_NULL_MISSING_AFTER_NEWLINE);
|
||||
} else if ((64 < item) && (item < 91)) { /* downcase upper case letters */
|
||||
line[n++] = (32 + item);
|
||||
} else if ((item == '(') && !semicomment) { /* (comment is starting */
|
||||
comment = 1;
|
||||
line[n++] = item;
|
||||
} else {
|
||||
line[n++] = item; /* copy anything else */
|
||||
}
|
||||
}
|
||||
CHKS((comment), NCE_UNCLOSED_COMMENT_FOUND);
|
||||
line[n] = 0;
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*! enhance_block
|
||||
|
||||
Returned Value:
|
||||
If any of the following errors occur, this returns the error shown.
|
||||
Otherwise, it returns INTERP_OK.
|
||||
1. A g80 is in the block, no modal group 0 code that uses axes
|
||||
is in the block, and one or more axis values is given:
|
||||
NCE_CANNOT_USE_AXIS_VALUES_WITH_G80
|
||||
2. A g52 g92 is in the block and no axis value is given:
|
||||
NCE_ALL_AXES_MISSING_WITH_G52_OR_G92
|
||||
3. One G-code from group 1 and one from group 0, both of which can use
|
||||
axis values, are in the block:
|
||||
NCE_CANNOT_USE_TWO_G_CODES_THAT_BOTH_USE_AXIS_VALUES
|
||||
4. A G-code (other than 0 or 1, for which we are allowing all axes
|
||||
missing) from group 1 which can use axis values is in the block,
|
||||
but no axis value is given: NCE_ALL_AXES_MISSING_WITH_MOTION_CODE
|
||||
5. Axis values are given, but there is neither a G-code in the block
|
||||
nor an active previously given modal G-code that uses axis values:
|
||||
NCE_CANNOT_USE_AXIS_VALUES_WITHOUT_A_G_CODE_THAT_USES_THEM
|
||||
|
||||
Side effects:
|
||||
The value of motion_to_be in the block is set.
|
||||
|
||||
Called by: parse_line
|
||||
|
||||
If there is a G-code for motion in the block (in g_modes[1]),
|
||||
set motion_to_be to that. Otherwise, if there is an axis value in the
|
||||
block and no G-code to use it (any such would be from group 0 in
|
||||
g_modes[0]), set motion_to_be to be the last motion saved (in
|
||||
settings->motion mode).
|
||||
|
||||
This also make the checks described above.
|
||||
|
||||
*/
|
||||
|
||||
int Interp::enhance_block(block_pointer block, //!< pointer to a block to be checked
|
||||
setup_pointer settings) //!< pointer to machine settings
|
||||
{
|
||||
int axis_flag;
|
||||
int ijk_flag;
|
||||
int polar_flag;
|
||||
int mode_zero_covets_axes;
|
||||
int mode0;
|
||||
int mode1;
|
||||
|
||||
if(block->radius_flag || block->theta_flag) {
|
||||
// someday, tediously add polar support for other planes here:
|
||||
CHKS((!_readers[(int)'x'] || !_readers[(int)'y']), _("Cannot use polar coordinate on a machine lacking X or Y axes"));
|
||||
CHKS(((settings->plane != CANON_PLANE::XY)), _("Cannot use polar coordinate except in G17 plane"));
|
||||
CHKS(((block->x_flag)), _("Cannot specify both polar coordinate and X word"));
|
||||
CHKS(((block->y_flag)), _("Cannot specify both polar coordinate and Y word"));
|
||||
}
|
||||
|
||||
axis_flag = ((block->x_flag) || (block->y_flag) ||
|
||||
(block->z_flag) || (block->a_flag) ||
|
||||
(block->b_flag) || (block->c_flag) ||
|
||||
(block->u_flag) || (block->v_flag) ||
|
||||
(block->w_flag));
|
||||
polar_flag = (block->radius_flag) || (block->theta_flag);
|
||||
ijk_flag = ((block->i_flag) || (block->j_flag) ||
|
||||
(block->k_flag));
|
||||
mode0 = block->g_modes[GM_MODAL_0];
|
||||
mode1 = block->g_modes[GM_MOTION];
|
||||
mode_zero_covets_axes =
|
||||
((mode0 == G_10) || (mode0 == G_28) || (mode0 == G_30)
|
||||
|| (mode0 == G_52) || (mode0 == G_92));
|
||||
|
||||
if (mode1 != -1) {
|
||||
if (mode1 == G_80) {
|
||||
CHKS(((polar_flag || axis_flag) && (!mode_zero_covets_axes)),
|
||||
NCE_CANNOT_USE_AXIS_VALUES_WITH_G80);
|
||||
CHKS((polar_flag && mode0 == G_92), _("Polar coordinates can only be used for motion"));
|
||||
CHKS(((!axis_flag) && (mode0 == G_52 || mode0 == G_92)),
|
||||
NCE_ALL_AXES_MISSING_WITH_G52_OR_G92);
|
||||
} else {
|
||||
CHKS(mode_zero_covets_axes, NCE_CANNOT_USE_TWO_G_CODES_THAT_BOTH_USE_AXIS_VALUES);
|
||||
CHKS(((!axis_flag && !polar_flag) &&
|
||||
mode1 != G_0 && mode1 != G_1 &&
|
||||
mode1 != G_2 && mode1 != G_3 &&
|
||||
mode1 != G_5_2 &&
|
||||
mode1 != G_6_2 &&
|
||||
mode1 != G_70 &&
|
||||
mode1 != G_71 && mode1 != G_71_1 && mode1 != G_71_2 &&
|
||||
mode1 != G_72 && mode1 != G_72_1 && mode1 != G_72_2 &&
|
||||
!is_user_defined_g_code(mode1)),
|
||||
NCE_ALL_AXES_MISSING_WITH_MOTION_CODE);
|
||||
}
|
||||
block->motion_to_be = mode1;
|
||||
} else if (mode_zero_covets_axes) { /* other 3 can get by without axes but not G92 */
|
||||
CHKS((polar_flag && mode0 == G_92), _("Polar coordinates can only be used for motion"));
|
||||
CHKS(((!axis_flag) &&
|
||||
(block->g_modes[GM_MODAL_0] == G_52 || block->g_modes[GM_MODAL_0] == G_92)),
|
||||
NCE_ALL_AXES_MISSING_WITH_G52_OR_G92);
|
||||
} else if (axis_flag || polar_flag) {
|
||||
CHKS(((settings->motion_mode == -1)
|
||||
|| (settings->motion_mode == G_80)) && (block->g_modes[GM_TOOL_LENGTH_OFFSET] != G_43_1)
|
||||
&& (block->g_modes[GM_TOOL_LENGTH_OFFSET] != G_43_2),
|
||||
NCE_CANNOT_USE_AXIS_VALUES_WITHOUT_A_G_CODE_THAT_USES_THEM);
|
||||
if (block->g_modes[GM_TOOL_LENGTH_OFFSET] != G_43_1) {
|
||||
block->motion_to_be = settings->motion_mode;
|
||||
}
|
||||
} else if (!axis_flag && !polar_flag && ijk_flag && (settings->motion_mode == G_2 || settings->motion_mode == G_3)) {
|
||||
// this is a block like simply "i1" which should be accepted if we're in arc mode
|
||||
block->motion_to_be = settings->motion_mode;
|
||||
}
|
||||
CHKS((polar_flag && block->motion_to_be == -1), _("Polar coordinates can only be used for motion"));
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*! init_block
|
||||
|
||||
Returned Value: int (INTERP_OK)
|
||||
|
||||
Side effects:
|
||||
Values in the block are reset as described below.
|
||||
|
||||
Called by: parse_line
|
||||
|
||||
This system reuses the same block over and over, rather than building
|
||||
a new one for each line of NC code. The block is re-initialized before
|
||||
each new line of NC code is read.
|
||||
|
||||
The block contains many slots for values which may or may not be present
|
||||
on a line of NC code. For some of these slots, there is a flag which
|
||||
is turned on (at the time time value of the slot is read) if the item
|
||||
is present. For slots whose values are to be read which do not have a
|
||||
flag, there is always some excluded range of values. Setting the
|
||||
initial value of these slot to some number in the excluded range
|
||||
serves to show that a value for that slot has not been read.
|
||||
|
||||
The rules for the indicators for slots whose values may be read are:
|
||||
1. If the value may be an arbitrary real number (which is always stored
|
||||
internally as a double), a flag is needed to indicate if a value has
|
||||
been read. All such flags are initialized to false.
|
||||
Note that the value itself is not initialized; there is no point in it.
|
||||
2. If the value must be a non-negative real number (which is always stored
|
||||
internally as a double), a value of -1.0 indicates the item is not present.
|
||||
3. If the value must be an unsigned integer (which is always stored
|
||||
internally as an int), a value of -1 indicates the item is not present.
|
||||
(RS274/NGC does not use any negative integers.)
|
||||
4. If the value is a character string (only the comment slot is one), the
|
||||
first character is set to 0 (NULL).
|
||||
|
||||
*/
|
||||
|
||||
int Interp::init_block(block_pointer block) //!< pointer to a block to be initialized or reset
|
||||
{
|
||||
int n;
|
||||
block->breadcrumbs = 0; // clear execution trail
|
||||
block->executing_remap = NULL;
|
||||
block->param_cnt = 0;
|
||||
block->remappings.clear();
|
||||
block->builtin_used = false;
|
||||
|
||||
block->a_flag = false;
|
||||
block->b_flag = false;
|
||||
block->c_flag = false;
|
||||
block->comment[0] = 0;
|
||||
block->d_flag = false;
|
||||
block->dollar_flag = false;
|
||||
block->e_flag = false;
|
||||
block->f_flag = false;
|
||||
for (n = 0; n < GM_MAX_MODAL_GROUPS; n++) {
|
||||
block->g_modes[n] = -1;
|
||||
}
|
||||
block->h_flag = false;
|
||||
block->h_number = -1;
|
||||
block->i_flag = false;
|
||||
block->j_flag = false;
|
||||
block->k_flag = false;
|
||||
block->l_number = -1;
|
||||
block->l_flag = false;
|
||||
block->line_number = -1;
|
||||
block->n_number = -1;
|
||||
block->motion_to_be = -1;
|
||||
block->m_count = 0;
|
||||
for (n = 0; n < 11; n++) {
|
||||
block->m_modes[n] = -1;
|
||||
}
|
||||
block->user_m = 0;
|
||||
block->p_number = -1.0;
|
||||
block->p_flag = false;
|
||||
block->q_flag = false;
|
||||
block->q_number = -1.0;
|
||||
block->r_flag = false;
|
||||
block->s_flag = false;
|
||||
block->t_flag = false;
|
||||
block->u_flag = false;
|
||||
block->v_flag = false;
|
||||
block->w_flag = false;
|
||||
block->x_flag = false;
|
||||
block->y_flag = false;
|
||||
block->z_flag = false;
|
||||
|
||||
block->theta_flag = false;
|
||||
block->radius_flag = false;
|
||||
|
||||
block->o_type = O_none;
|
||||
block->o_name = 0;
|
||||
block->call_type = -1;
|
||||
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*! parse_line
|
||||
|
||||
Returned Value: int
|
||||
If any of the following functions returns an error code,
|
||||
this returns that code.
|
||||
init_block
|
||||
read_items
|
||||
enhance_block
|
||||
check_items
|
||||
Otherwise, it returns INTERP_OK.
|
||||
|
||||
Side effects:
|
||||
One RS274 line is read into a block and the block is checked for
|
||||
errors. System parameters may be reset.
|
||||
|
||||
Called by: Interp::read
|
||||
|
||||
*/
|
||||
|
||||
int Interp::parse_line(char *line, //!< array holding a line of RS274 code
|
||||
block_pointer block, //!< pointer to a block to be filled
|
||||
setup_pointer settings) //!< pointer to machine settings
|
||||
{
|
||||
CHP(init_block(block));
|
||||
CHP(read_items(block, line, settings->parameters));
|
||||
|
||||
if(settings->skipping_o == 0)
|
||||
{
|
||||
CHP(enhance_block(block, settings));
|
||||
CHP(check_items(block, settings));
|
||||
int n = find_remappings(block,settings);
|
||||
if (n) logRemap("parse_line: found %d remappings",n);
|
||||
}
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*! precedence
|
||||
|
||||
Returned Value: int
|
||||
This returns an integer representing the precedence level of an_operator
|
||||
|
||||
Side Effects: None
|
||||
|
||||
Called by: read_real_expression
|
||||
|
||||
To add additional levels of operator precedence, edit this function.
|
||||
|
||||
*/
|
||||
|
||||
int Interp::precedence(int an_operator)
|
||||
{
|
||||
switch(an_operator)
|
||||
{
|
||||
case RIGHT_BRACKET:
|
||||
return 1;
|
||||
|
||||
case AND2:
|
||||
case EXCLUSIVE_OR:
|
||||
case NON_EXCLUSIVE_OR:
|
||||
return 2;
|
||||
|
||||
case LT:
|
||||
case EQ:
|
||||
case NE:
|
||||
case LE:
|
||||
case GE:
|
||||
case GT:
|
||||
return 3;
|
||||
|
||||
case MINUS:
|
||||
case PLUS:
|
||||
return 4;
|
||||
|
||||
case NO_OPERATION:
|
||||
case DIVIDED_BY:
|
||||
case MODULO:
|
||||
case TIMES:
|
||||
return 5;
|
||||
|
||||
case POWER:
|
||||
return 6;
|
||||
}
|
||||
// should never happen
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Interp::refresh_actual_position(setup_pointer settings)
|
||||
{
|
||||
settings->current_x = GET_EXTERNAL_POSITION_X();
|
||||
settings->current_y = GET_EXTERNAL_POSITION_Y();
|
||||
settings->current_z = GET_EXTERNAL_POSITION_Z();
|
||||
settings->AA_current = GET_EXTERNAL_POSITION_A();
|
||||
settings->BB_current = GET_EXTERNAL_POSITION_B();
|
||||
settings->CC_current = GET_EXTERNAL_POSITION_C();
|
||||
settings->u_current = GET_EXTERNAL_POSITION_U();
|
||||
settings->v_current = GET_EXTERNAL_POSITION_V();
|
||||
settings->w_current = GET_EXTERNAL_POSITION_W();
|
||||
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*! set_probe_data
|
||||
|
||||
Returned Value: int (INTERP_OK)
|
||||
|
||||
Side effects:
|
||||
The current position is set.
|
||||
System parameters for probe position are set.
|
||||
|
||||
Called by: Interp::read
|
||||
|
||||
*/
|
||||
|
||||
int Interp::set_probe_data(setup_pointer settings) //!< pointer to machine settings
|
||||
{
|
||||
double a, b, c;
|
||||
refresh_actual_position(settings);
|
||||
settings->parameters[5061] = GET_EXTERNAL_PROBE_POSITION_X();
|
||||
settings->parameters[5062] = GET_EXTERNAL_PROBE_POSITION_Y();
|
||||
settings->parameters[5063] = GET_EXTERNAL_PROBE_POSITION_Z();
|
||||
|
||||
a = GET_EXTERNAL_PROBE_POSITION_A();
|
||||
if(settings->a_axis_wrapped) {
|
||||
a = fmod(a, 360.0);
|
||||
if(a<0) a += 360.0;
|
||||
}
|
||||
settings->parameters[5064] = a;
|
||||
|
||||
b = GET_EXTERNAL_PROBE_POSITION_B();
|
||||
if(settings->b_axis_wrapped) {
|
||||
b = fmod(b, 360.0);
|
||||
if(b<0) b += 360.0;
|
||||
}
|
||||
settings->parameters[5065] = b;
|
||||
|
||||
c = GET_EXTERNAL_PROBE_POSITION_C();
|
||||
if(settings->c_axis_wrapped) {
|
||||
c = fmod(c, 360.0);
|
||||
if(c<0) c += 360.0;
|
||||
}
|
||||
settings->parameters[5066] = c;
|
||||
|
||||
settings->parameters[5067] = GET_EXTERNAL_PROBE_POSITION_U();
|
||||
settings->parameters[5068] = GET_EXTERNAL_PROBE_POSITION_V();
|
||||
settings->parameters[5069] = GET_EXTERNAL_PROBE_POSITION_W();
|
||||
settings->parameters[5070] = (double) GET_EXTERNAL_PROBE_TRIPPED_VALUE();
|
||||
|
||||
// was an undocumented feature?: settings->parameters[5067] = GET_EXTERNAL_PROBE_VALUE();
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
int Interp::call_level(void) { return _setup.call_level; }
|
||||
|
||||
std::string toString(GCodes g)
|
||||
{
|
||||
char buf[15]={};
|
||||
int dec_value = g%10;
|
||||
if (dec_value)
|
||||
{
|
||||
// Has a decimal
|
||||
snprintf(buf, sizeof(buf), "G%d.%d", g/10, dec_value);
|
||||
} else {
|
||||
snprintf(buf, sizeof(buf), "G%d", g/10);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
1029
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_internal.hh
vendored
Normal file
1029
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_internal.hh
vendored
Normal file
File diff suppressed because it is too large
Load Diff
136
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_inverse.cc
vendored
Normal file
136
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_inverse.cc
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
/********************************************************************
|
||||
* Description: interp_inverse.cc
|
||||
*
|
||||
* Derived from a work by Thomas Kramer
|
||||
*
|
||||
* Author:
|
||||
* License: GPL Version 2
|
||||
* System: Linux
|
||||
*
|
||||
* Copyright (c) 2004 All rights reserved.
|
||||
*
|
||||
* Last change:
|
||||
********************************************************************/
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include "rs274ngc.hh"
|
||||
#include "nml_intf/interp_return.hh"
|
||||
#include "interp_internal.hh"
|
||||
#include "interp_queue.hh"
|
||||
#include "rs274ngc_interp.hh"
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*! inverse_time_rate_arc
|
||||
|
||||
Returned Value: int (INTERP_OK)
|
||||
|
||||
Side effects: a call is made to SET_FEED_RATE and _setup.feed_rate is set.
|
||||
|
||||
Called by:
|
||||
convert_arc2
|
||||
convert_arc_comp1
|
||||
convert_arc_comp2
|
||||
|
||||
This finds the feed rate needed by an inverse time move. The move
|
||||
consists of an a single arc. Most of the work here is in finding the
|
||||
length of the arc.
|
||||
|
||||
*/
|
||||
|
||||
int Interp::inverse_time_rate_arc(double x1, //!< x coord of start point of arc
|
||||
double y1, //!< y coord of start point of arc
|
||||
double z1, //!< z coord of start point of arc
|
||||
double cx, //!< x coord of center of arc
|
||||
double cy, //!< y coord of center of arc
|
||||
int turn, //!< turn of arc
|
||||
double x2, //!< x coord of end point of arc
|
||||
double y2, //!< y coord of end point of arc
|
||||
double z2, //!< z coord of end point of arc
|
||||
block_pointer block, //!< pointer to a block of RS274 instructions
|
||||
setup_pointer settings) //!< pointer to machine settings
|
||||
{
|
||||
double length;
|
||||
double rate;
|
||||
|
||||
if (settings->feed_mode != FEED_MODE::INVERSE_TIME) return -1;
|
||||
|
||||
length = find_arc_length(x1, y1, z1, cx, cy, turn, x2, y2, z2);
|
||||
if (length == 0){
|
||||
rate = 0.1; // See https://github.com/LinuxCNC/linuxcnc/issues/2410
|
||||
} else {
|
||||
rate = length * block->f_number;
|
||||
}
|
||||
enqueue_SET_FEED_RATE(rate);
|
||||
settings->feed_rate = rate;
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*! inverse_time_rate_straight
|
||||
|
||||
Returned Value: int (INTERP_OK)
|
||||
|
||||
Side effects: a call is made to SET_FEED_RATE and _setup.feed_rate is set.
|
||||
|
||||
Called by:
|
||||
convert_straight
|
||||
convert_straight_comp1
|
||||
convert_straight_comp2
|
||||
|
||||
This finds the feed rate needed by an inverse time straight move. Most
|
||||
of the work here is in finding the length of the line.
|
||||
|
||||
*/
|
||||
|
||||
int Interp::inverse_time_rate_straight(double end_x, //!< x coordinate of end point of straight line
|
||||
double end_y, //!< y coordinate of end point of straight line
|
||||
double end_z, //!< z coordinate of end point of straight line
|
||||
double AA_end, //!< A coordinate of end point of straight line/*AA*/
|
||||
double BB_end, //!< B coordinate of end point of straight line/*BB*/
|
||||
double CC_end, //!< C coordinate of end point of straight line/*CC*/
|
||||
double u_end, double v_end, double w_end,
|
||||
block_pointer block, //!< pointer to a block of RS274 instructions
|
||||
setup_pointer settings) //!< pointer to machine settings
|
||||
{
|
||||
double length;
|
||||
double rate;
|
||||
double cx, cy, cz;
|
||||
|
||||
if (settings->feed_mode != FEED_MODE::INVERSE_TIME) return -1;
|
||||
|
||||
if (settings->cutter_comp_side != CUTTER_COMP::OFF && settings->cutter_comp_radius > 0.0 &&
|
||||
!settings->cutter_comp_firstmove) {
|
||||
cx = settings->program_x;
|
||||
cy = settings->program_y;
|
||||
cz = settings->program_z;
|
||||
} else {
|
||||
cx = settings->current_x;
|
||||
cy = settings->current_y;
|
||||
cz = settings->current_z;
|
||||
}
|
||||
|
||||
length = find_straight_length(end_x, end_y, end_z,
|
||||
AA_end, BB_end, CC_end,
|
||||
u_end, v_end, w_end,
|
||||
cx, cy, cz,
|
||||
settings->AA_current, settings->BB_current, settings->CC_current,
|
||||
settings->u_current, settings->v_current, settings->w_current);
|
||||
if (length == 0){
|
||||
rate = 0.1; // See https://github.com/LinuxCNC/linuxcnc/issues/2410
|
||||
} else {
|
||||
rate = length * block->f_number;
|
||||
}
|
||||
|
||||
enqueue_SET_FEED_RATE(rate);
|
||||
settings->feed_rate = rate;
|
||||
|
||||
return INTERP_OK;
|
||||
}
|
||||
989
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_namedparams.cc
vendored
Normal file
989
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_namedparams.cc
vendored
Normal file
@@ -0,0 +1,989 @@
|
||||
/*misnomer: _setup.current_pocket,selected_pocket
|
||||
** These are indexes to sequential tooldata entries
|
||||
** but the names are not changed due to frequent
|
||||
** legacy usage in py files used for remapping
|
||||
*/
|
||||
/********************************************************************
|
||||
* Description: interp_namedparams.cc
|
||||
*
|
||||
* collect all code related to named parameter handling
|
||||
*
|
||||
* Author: mostly K. Lerman
|
||||
* rewrite by Michael Haberler to use STL containers
|
||||
* License: GPL Version 2
|
||||
* System: Linux
|
||||
*
|
||||
* Copyright (c) 2004 All rights reserved.
|
||||
*
|
||||
* Last change: Juli 2011
|
||||
********************************************************************/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#define BOOST_PYTHON_MAX_ARITY 4
|
||||
#include "pythonplugin/python_plugin.hh"
|
||||
#include <boost/python/dict.hpp>
|
||||
#include <boost/python/extract.hpp>
|
||||
#include <boost/python/list.hpp>
|
||||
#include <boost/python/tuple.hpp>
|
||||
namespace bp = boost::python;
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include "rs274ngc.hh"
|
||||
#include "rs274ngc_return.hh"
|
||||
#include "interp_internal.hh"
|
||||
#include "rs274ngc_interp.hh"
|
||||
#include <inifile.hh>
|
||||
|
||||
// for HAL pin variables
|
||||
#include <hal.h>
|
||||
|
||||
using namespace linuxcnc;
|
||||
|
||||
enum predefined_named_parameters {
|
||||
NP_LINE,
|
||||
NP_MOTION_MODE,
|
||||
NP_PLANE,
|
||||
NP_CCOMP,
|
||||
NP_METRIC,
|
||||
NP_IMPERIAL,
|
||||
NP_ABSOLUTE,
|
||||
NP_INCREMENTAL,
|
||||
NP_INVERSE_TIME,
|
||||
NP_UNITS_PER_MINUTE,
|
||||
NP_UNITS_PER_REV,
|
||||
NP_COORD_SYSTEM,
|
||||
NP_TOOL_OFFSET,
|
||||
NP_RETRACT_R_PLANE,
|
||||
NP_RETRACT_OLD_Z,
|
||||
NP_SPINDLE_RPM_MODE,
|
||||
NP_SPINDLE_CSS_MODE,
|
||||
NP_IJK_ABSOLUTE_MODE,
|
||||
NP_LATHE_DIAMETER_MODE,
|
||||
NP_LATHE_RADIUS_MODE,
|
||||
NP_SPINDLE_ON,
|
||||
NP_SPINDLE_CW,
|
||||
NP_MIST,
|
||||
NP_FLOOD,
|
||||
NP_SPEED_OVERRIDE,
|
||||
NP_FEED_OVERRIDE,
|
||||
NP_ADAPTIVE_FEED,
|
||||
NP_FEED_HOLD,
|
||||
NP_FEED,
|
||||
NP_RPM,
|
||||
NP_CURRENT_TOOL,
|
||||
NP_SELECTED_POCKET,
|
||||
NP_CURRENT_POCKET,
|
||||
NP_X,
|
||||
NP_Y,
|
||||
NP_Z,
|
||||
NP_A,
|
||||
NP_B,
|
||||
NP_C,
|
||||
NP_U,
|
||||
NP_V,
|
||||
NP_W,
|
||||
NP_ABS_X,
|
||||
NP_ABS_Y,
|
||||
NP_ABS_Z,
|
||||
NP_ABS_A,
|
||||
NP_ABS_B,
|
||||
NP_ABS_C,
|
||||
NP_VALUE,
|
||||
NP_CALL_LEVEL,
|
||||
NP_REMAP_LEVEL,
|
||||
NP_SELECTED_TOOL,
|
||||
NP_VALUE_RETURNED,
|
||||
NP_TASK,
|
||||
};
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*! read_named_parameter
|
||||
|
||||
Returned Value: int
|
||||
If read_integer_value returns an error code, this returns that code.
|
||||
If any of the following errors occur, this returns the error code shown.
|
||||
Otherwise, this returns INTERP_OK.
|
||||
1. The first character read is not a <:
|
||||
NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED
|
||||
2. The named parameter string is not terminated by >:
|
||||
NCE_NAMED_PARAMETER_NOT_TERSINATED
|
||||
3. The named parameter has not been defined before use:
|
||||
NCE_NAMED_PARAMETER_NOT_DEFINED
|
||||
|
||||
Side effects:
|
||||
The value of the given parameter is put into what double_ptr points at.
|
||||
The counter is reset to point to the first character after the
|
||||
characters which make up the value.
|
||||
|
||||
Called by: read_parameter
|
||||
|
||||
This attempts to read the value of a parameter out of the line,
|
||||
starting at the index given by the counter.
|
||||
|
||||
According to the RS274/NGC manual [NCMS, p. 62], the characters following
|
||||
# may be any "parameter expression". Thus, the following are legal
|
||||
and mean the same thing (the value of the parameter whose number is
|
||||
stored in parameter 2):
|
||||
##2
|
||||
#[#2]
|
||||
|
||||
|
||||
ADDED by K. Lerman
|
||||
Named parameters are now supported.
|
||||
#<_abcd> is a parameter with name "abcd" of global scope
|
||||
#<abce> is a named parameter of local scope.
|
||||
|
||||
*/
|
||||
|
||||
int Interp::read_named_parameter(
|
||||
char *line, //!< string: line of RS274/NGC code being processed
|
||||
int *counter, //!< pointer to a counter for position on the line
|
||||
double *double_ptr, //!< pointer to double to be read
|
||||
double * /*parameters*/, //!< array of system parameters
|
||||
bool check_exists) //!< test for existence, not value
|
||||
{
|
||||
static char name[] = "read_named_parameter";
|
||||
char paramNameBuf[LINELEN+1];
|
||||
int exists;
|
||||
double value;
|
||||
parameter_map_iterator pi;
|
||||
|
||||
CHKS((line[*counter] != '<'),
|
||||
NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
|
||||
CHP(read_name(line, counter, paramNameBuf));
|
||||
|
||||
CHP(find_named_param(paramNameBuf, &exists, &value));
|
||||
if (check_exists) {
|
||||
*double_ptr = exists ? 1.0 : 0.0;
|
||||
return INTERP_OK;
|
||||
}
|
||||
if (exists) {
|
||||
*double_ptr = value;
|
||||
return INTERP_OK;
|
||||
} else {
|
||||
// do not require named parameters to be defined during a
|
||||
// subroutine definition:
|
||||
if (_setup.defining_sub)
|
||||
return INTERP_OK;
|
||||
|
||||
logNP("%s: referencing undefined named parameter '%s' level=%d",
|
||||
name, paramNameBuf, (paramNameBuf[0] == '_') ? 0 : _setup.call_level);
|
||||
ERS(_("Named parameter #<%s> not defined"), paramNameBuf);
|
||||
}
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
// if the variable is of the form '_ini[section]name', then treat it as
|
||||
// an inifile variable. Lookup section/name and cache the value
|
||||
// as global and read-only.
|
||||
// the shortest possible INI variable is '_ini[s]n' or 8 chars long .
|
||||
int Interp::fetch_ini_param( const char *nameBuf, int *status, double *value)
|
||||
{
|
||||
*status = 0;
|
||||
int n = strlen(nameBuf);
|
||||
|
||||
if(n < 8) {
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
std::string sect = nameBuf + 5; // skip the '_ini[' part
|
||||
// Make it all upper case
|
||||
for(auto &c : sect) {
|
||||
c = toupper(c);
|
||||
}
|
||||
size_t i = sect.find(']');
|
||||
if(std::string::npos == i) {
|
||||
ERS(_("_ini expansion missing ']'"));
|
||||
return INTERP_OK;
|
||||
}
|
||||
std::string var = sect.substr(i+1);
|
||||
sect.erase(i); // Remove everything from ']'and after
|
||||
|
||||
const char *iniFileName;
|
||||
if ((iniFileName = getenv("INI_FILE_NAME")) == NULL) {
|
||||
logNP("warning: referencing INI parameter '%s': no INI file", nameBuf);
|
||||
return INTERP_OK;
|
||||
}
|
||||
IniFile inifile(iniFileName);
|
||||
if (!inifile) {
|
||||
ERS(_("can\'t open INI file '%s'"), iniFileName);
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
if (auto inival = inifile.findReal(var, sect)) {
|
||||
*value = *inival;
|
||||
*status = 1;
|
||||
} else {
|
||||
ERS(_("Named INI parameter #<%s> not found in INI file '%s'"), nameBuf, iniFileName);
|
||||
}
|
||||
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
// if the variable is of the form '_hal[hal_name]', then treat it as
|
||||
// a HAL pin, signal or param. Lookup value, convert to float, and export as global and read-only.
|
||||
// do not cache.
|
||||
// the shortest possible INI variable is '_hal[x]' or 7 chars long .
|
||||
int Interp::fetch_hal_param( const char *nameBuf, int *status, double *value)
|
||||
{
|
||||
static int comp_id;
|
||||
int retval;
|
||||
hal_type_t type = HAL_TYPE_UNINITIALIZED;
|
||||
hal_data_u* ptr;
|
||||
bool conn;
|
||||
char hal_name[HAL_NAME_LEN];
|
||||
|
||||
*status = 0;
|
||||
if (!comp_id) {
|
||||
char hal_comp[HAL_NAME_LEN];
|
||||
snprintf(hal_comp, sizeof(hal_comp),"interp%d",getpid());
|
||||
comp_id = hal_init(hal_comp); // manpage says: NULL ok - which fails miserably
|
||||
CHKS(comp_id < 0,_("fetch_hal_param: hal_init(%s): %d"), hal_comp,comp_id);
|
||||
CHKS((retval = hal_ready(comp_id)), _("fetch_hal_param: hal_ready(): %d"),retval);
|
||||
}
|
||||
char *s;
|
||||
int n = strlen(nameBuf);
|
||||
if ((n > 6) &&
|
||||
((s = (char *) strchr(&nameBuf[5],']')) != NULL)) {
|
||||
|
||||
int closeBracket = s - nameBuf;
|
||||
|
||||
strncpy(hal_name, &nameBuf[5], closeBracket);
|
||||
hal_name[closeBracket - 5] = '\0';
|
||||
if (nameBuf[closeBracket + 1]) {
|
||||
logOword("%s: trailing garbage after closing bracket", hal_name);
|
||||
*status = 0;
|
||||
ERS("%s: trailing garbage after closing bracket", nameBuf);
|
||||
}
|
||||
// the result of these lookups could be cached in the parameter struct, but I'm not sure
|
||||
// this is a good idea - a removed pin/signal will not be noticed
|
||||
|
||||
// I dont think that's needed - no change in pins/sigs/params
|
||||
// rtapi_mutex_get(&(hal_data->mutex));
|
||||
// rtapi_mutex_give(&(hal_data->mutex));
|
||||
|
||||
if (hal_get_pin_value_by_name(hal_name, &type, &ptr, &conn) == 0) {
|
||||
if (!conn)
|
||||
logOword("%s: no signal connected", hal_name);
|
||||
goto assign;
|
||||
}
|
||||
if (hal_get_signal_value_by_name(hal_name, &type, &ptr, &conn) == 0) {
|
||||
if (!conn)
|
||||
logOword("%s: signal has no writer", hal_name);
|
||||
goto assign;
|
||||
}
|
||||
if (hal_get_param_value_by_name(hal_name, &type, &ptr) == 0) {
|
||||
goto assign;
|
||||
}
|
||||
*status = 0;
|
||||
ERS("Named hal parameter #<%s> not found", nameBuf);
|
||||
}
|
||||
return INTERP_OK;
|
||||
|
||||
assign:
|
||||
switch (type) {
|
||||
case HAL_BIT: *value = (double) (ptr->b); break;
|
||||
case HAL_U32: *value = (double) (ptr->u); break;
|
||||
case HAL_S32: *value = (double) (ptr->s); break;
|
||||
case HAL_U64: *value = (double) (ptr->lu); break;
|
||||
case HAL_S64: *value = (double) (ptr->ls); break;
|
||||
case HAL_FLOAT: *value = (double) (ptr->f); break;
|
||||
default: return -1;
|
||||
}
|
||||
logOword("%s: value=%f", hal_name, *value);
|
||||
*status = 1;
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
int Interp::find_named_param(
|
||||
const char *nameBuf, //!< pointer to name to be read
|
||||
int *status, //!< pointer to return status 1 => found
|
||||
double *value //!< pointer to value of found parameter
|
||||
)
|
||||
{
|
||||
context_pointer frame;
|
||||
parameter_map_iterator pi;
|
||||
int level;
|
||||
|
||||
level = (nameBuf[0] == '_') ? 0 : _setup.call_level; // determine scope
|
||||
frame = &_setup.sub_context[level];
|
||||
*status = 0;
|
||||
|
||||
pi = frame->named_params.find(nameBuf);
|
||||
if (pi == frame->named_params.end()) { // not found
|
||||
int exists = 0;
|
||||
double inivalue;
|
||||
if (FEATURE(INI_VARS) && (strncasecmp(nameBuf,"_ini[",5) == 0)) {
|
||||
fetch_ini_param(nameBuf, &exists, &inivalue);
|
||||
if (exists) {
|
||||
logNP("parameter '%s' retrieved from INI: %f",nameBuf,inivalue);
|
||||
*value = inivalue;
|
||||
*status = 1;
|
||||
parameter_value param; // cache the value
|
||||
param.value = inivalue;
|
||||
param.attr = PA_GLOBAL | PA_READONLY | PA_FROM_INI;
|
||||
_setup.sub_context[0].named_params[strstore(nameBuf)] = param;
|
||||
return INTERP_OK;
|
||||
}
|
||||
}
|
||||
if (FEATURE(HAL_PIN_VARS) && (strncasecmp(nameBuf,"_hal[",5) == 0)) {
|
||||
fetch_hal_param(nameBuf, &exists, &inivalue);
|
||||
if (exists) {
|
||||
logNP("parameter '%s' retrieved from HAL: %f",nameBuf,inivalue);
|
||||
*value = inivalue;
|
||||
*status = 1;
|
||||
return INTERP_OK;
|
||||
}
|
||||
}
|
||||
*value = 0.0;
|
||||
*status = 0;
|
||||
} else {
|
||||
parameter_pointer pv = &pi->second;
|
||||
if (pv->attr & PA_UNSET)
|
||||
logNP("warning: referencing unset variable '%s'",nameBuf);
|
||||
if (pv->attr & PA_USE_LOOKUP) {
|
||||
CHP(lookup_named_param(nameBuf, pv->value, value));
|
||||
*status = 1;
|
||||
} else if (pv->attr & PA_PYTHON) {
|
||||
bp::object retval, tupleargs, kwargs;
|
||||
bp::list plist;
|
||||
|
||||
plist.append(*_setup.pythis); // self
|
||||
tupleargs = bp::tuple(plist);
|
||||
kwargs = bp::dict();
|
||||
|
||||
python_plugin->call(NAMEDPARAMS_MODULE, nameBuf, tupleargs, kwargs, retval);
|
||||
CHKS(python_plugin->plugin_status() == PLUGIN_EXCEPTION,
|
||||
"named param - pycall(%s):\n%s", nameBuf,
|
||||
python_plugin->last_exception().c_str());
|
||||
CHKS(retval.ptr() == Py_None, "Python namedparams.%s returns no value", nameBuf);
|
||||
if (PyUnicode_Check(retval.ptr())) {
|
||||
// returning a string sets the interpreter error message and aborts
|
||||
*status = 0;
|
||||
char *msg = bp::extract<char *>(retval);
|
||||
ERS("%s", msg);
|
||||
}
|
||||
if (PyLong_Check(retval.ptr())) { // widen
|
||||
*value = (double) bp::extract<int>(retval);
|
||||
*status = 1;
|
||||
return INTERP_OK;
|
||||
}
|
||||
if (PyFloat_Check(retval.ptr())) {
|
||||
*value = bp::extract<double>(retval);
|
||||
*status = 1;
|
||||
return INTERP_OK;
|
||||
}
|
||||
// ok, that callable returned something botched.
|
||||
*status = 0;
|
||||
PyObject *res_str = PyObject_Str(retval.ptr());
|
||||
Py_XDECREF(res_str);
|
||||
ERS("Python call %s.%s returned '%s' - expected double, int or string, got %s",
|
||||
NAMEDPARAMS_MODULE, nameBuf,
|
||||
PyUnicode_AsUTF8(res_str),
|
||||
retval.ptr()->ob_type->tp_name);
|
||||
} else {
|
||||
*value = pv->value;
|
||||
*status = 1;
|
||||
}
|
||||
}
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
|
||||
int Interp::store_named_param(setup_pointer settings,
|
||||
const char *nameBuf, //!< pointer to name to be written
|
||||
double value, //!< value to be written
|
||||
int override_readonly //!< set to true to init a r/o parameter
|
||||
)
|
||||
{
|
||||
context_pointer frame;
|
||||
int level;
|
||||
parameter_map_iterator pi;
|
||||
|
||||
level = (nameBuf[0] == '_') ? 0 : _setup.call_level; // determine scope
|
||||
frame = &settings->sub_context[level];
|
||||
|
||||
pi = frame->named_params.find(nameBuf);
|
||||
if (pi == frame->named_params.end()) {
|
||||
ERS(_("Internal error: Could not assign #<%s>"), nameBuf);
|
||||
} else {
|
||||
parameter_pointer pv = &pi->second;
|
||||
|
||||
CHKS(((pv->attr & PA_GLOBAL) && level),
|
||||
"BUG: variable '%s' marked global, but assigned at level %d", nameBuf, level);
|
||||
|
||||
if ((pv->attr & PA_READONLY) && !override_readonly) {
|
||||
ERS(_("Cannot assign to read-only parameter #<%s>"), nameBuf);
|
||||
} else {
|
||||
pv->value = value;
|
||||
pv->attr &= ~PA_UNSET;
|
||||
logNP("store_named_parameter: level[%d] %s value=%lf",
|
||||
level, nameBuf, value);
|
||||
}
|
||||
}
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int Interp::add_named_param(
|
||||
const char *nameBuf, //!< pointer to name to be added
|
||||
int attr) //!< see PA_* defs in interp_internal.hh
|
||||
{
|
||||
static char name[] = "add_named_param";
|
||||
int findStatus;
|
||||
double value;
|
||||
int level;
|
||||
parameter_value param;
|
||||
|
||||
// look it up to see if already exists
|
||||
CHP(find_named_param(nameBuf, &findStatus, &value));
|
||||
|
||||
if (findStatus) {
|
||||
logNP("%s: parameter:|%s| already exists", name, nameBuf);
|
||||
return INTERP_OK;
|
||||
}
|
||||
attr |= PA_UNSET;
|
||||
|
||||
if (nameBuf[0] != '_') { // local scope
|
||||
level = _setup.call_level;
|
||||
} else {
|
||||
level = 0; // call level zero is global scope
|
||||
attr |= PA_GLOBAL;
|
||||
}
|
||||
param.value = 0.0;
|
||||
param.attr = attr;
|
||||
_setup.sub_context[level].named_params[strstore(nameBuf)] = param;
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
|
||||
int Interp::free_named_parameters(context_pointer frame)
|
||||
{
|
||||
frame->named_params.clear();
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
|
||||
// just a shorthand
|
||||
int Interp::init_readonly_param(
|
||||
const char *nameBuf, //!< pointer to name to be added
|
||||
double value, //!< initial value
|
||||
int attr) //!< see PA_* defs in interp_internal.hh
|
||||
{
|
||||
// static char name[] = "init_readonly_param";
|
||||
CHKS( add_named_param((char *) nameBuf, PA_READONLY|attr),
|
||||
"adding r/o '%s'", nameBuf);
|
||||
CHKS(store_named_param(&_setup, (char *) nameBuf, value, OVERRIDE_READONLY),
|
||||
"storing r/o '%s' %f", nameBuf, value);
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
|
||||
int Interp::lookup_named_param(const char *nameBuf,
|
||||
double index,
|
||||
double *value)
|
||||
{
|
||||
int cmd = round_to_int(index);
|
||||
|
||||
switch (cmd) {
|
||||
|
||||
// some active_g_codes fields
|
||||
|
||||
case NP_LINE: // _line - sequence number
|
||||
*value = _setup.sequence_number;
|
||||
break;
|
||||
|
||||
case NP_MOTION_MODE: // _motion_mode
|
||||
*value = _setup.motion_mode;
|
||||
break;
|
||||
|
||||
case NP_PLANE: // _plane
|
||||
switch(_setup.plane) {
|
||||
case CANON_PLANE::XY:
|
||||
*value = G_17;
|
||||
break;
|
||||
case CANON_PLANE::XZ:
|
||||
*value = G_18;
|
||||
break;
|
||||
case CANON_PLANE::YZ:
|
||||
*value = G_19;
|
||||
break;
|
||||
case CANON_PLANE::UV:
|
||||
*value = G_17_1;
|
||||
break;
|
||||
case CANON_PLANE::UW:
|
||||
*value = G_18_1;
|
||||
break;
|
||||
case CANON_PLANE::VW:
|
||||
*value = G_19_1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case NP_CCOMP: // _ccomp - cutter compensation
|
||||
*value =
|
||||
(_setup.cutter_comp_side == CUTTER_COMP::RIGHT) ? G_42 :
|
||||
(_setup.cutter_comp_side == CUTTER_COMP::LEFT) ? G_41 : G_40;
|
||||
break;
|
||||
|
||||
case NP_METRIC: // _metric
|
||||
*value = (_setup.length_units == CANON_UNITS_MM);
|
||||
break;
|
||||
|
||||
case NP_IMPERIAL: // _imperial
|
||||
*value = (_setup.length_units == CANON_UNITS_INCHES);
|
||||
break;
|
||||
|
||||
case NP_ABSOLUTE: // _absolute - distance mode
|
||||
*value = (_setup.distance_mode == DISTANCE_MODE::ABSOLUTE);
|
||||
break;
|
||||
|
||||
case NP_INCREMENTAL: // _incremental - distance mode
|
||||
*value = (_setup.distance_mode == DISTANCE_MODE::INCREMENTAL);
|
||||
break;
|
||||
|
||||
case NP_INVERSE_TIME: // _inverse_time - feed mode
|
||||
*value = (_setup.feed_mode == FEED_MODE::INVERSE_TIME);
|
||||
break;
|
||||
|
||||
case NP_UNITS_PER_MINUTE: // _units_per_minute - feed mode
|
||||
*value = (_setup.feed_mode == FEED_MODE::UNITS_PER_MINUTE);
|
||||
break;
|
||||
|
||||
case NP_UNITS_PER_REV: // _units_per_rev - feed mode
|
||||
*value = (_setup.feed_mode == FEED_MODE::UNITS_PER_REVOLUTION);
|
||||
break;
|
||||
|
||||
case NP_COORD_SYSTEM: // _coord_system - 0-9
|
||||
*value =
|
||||
(_setup.origin_index < 7) ? (530 + (10 * _setup.origin_index)) :
|
||||
(584 + _setup.origin_index);
|
||||
break;
|
||||
|
||||
case NP_TOOL_OFFSET: // _tool_offset
|
||||
*value = (_setup.tool_offset.tran.x || _setup.tool_offset.tran.y || _setup.tool_offset.tran.z ||
|
||||
_setup.tool_offset.a || _setup.tool_offset.b || _setup.tool_offset.c ||
|
||||
_setup.tool_offset.u || _setup.tool_offset.v || _setup.tool_offset.w) ;
|
||||
break;
|
||||
|
||||
case NP_RETRACT_R_PLANE: // _retract_r_plane - G98
|
||||
*value = (_setup.retract_mode == RETRACT_MODE::R_PLANE);
|
||||
break;
|
||||
|
||||
case NP_RETRACT_OLD_Z: // _retract_old_z - G99
|
||||
*value = (_setup.retract_mode == RETRACT_MODE::OLD_Z);
|
||||
break;
|
||||
|
||||
case NP_SPINDLE_RPM_MODE: // _spindle_rpm_mode G97 currently only reports for spindle 0
|
||||
*value = (_setup.spindle_mode[0] == SPINDLE_MODE::CONSTANT_RPM);
|
||||
break;
|
||||
|
||||
case NP_SPINDLE_CSS_MODE: // _spindle_css_mode G96
|
||||
*value = (_setup.spindle_mode[0] == SPINDLE_MODE::CONSTANT_SURFACE);
|
||||
break;
|
||||
|
||||
case NP_IJK_ABSOLUTE_MODE: //_ijk_absolute_mode - G90.1
|
||||
*value = (_setup.ijk_distance_mode == DISTANCE_MODE::ABSOLUTE);
|
||||
break;
|
||||
|
||||
case NP_LATHE_DIAMETER_MODE: // _lathe_diameter_mode - G7
|
||||
*value = _setup.lathe_diameter_mode;
|
||||
break;
|
||||
|
||||
case NP_LATHE_RADIUS_MODE: // _lathe_radius_mode - G8
|
||||
*value = (_setup.lathe_diameter_mode == 0);
|
||||
break;
|
||||
|
||||
// some active_m_codes fields
|
||||
|
||||
case NP_SPINDLE_ON: // _spindle_on
|
||||
*value = (_setup.spindle_turning[0] != CANON_STOPPED);
|
||||
break;
|
||||
|
||||
case NP_SPINDLE_CW: // spindle_cw
|
||||
*value = (_setup.spindle_turning[0] == CANON_CLOCKWISE);
|
||||
break;
|
||||
|
||||
case NP_MIST: // mist
|
||||
*value = _setup.mist;
|
||||
break;
|
||||
|
||||
case NP_FLOOD: // flood
|
||||
*value = _setup.flood;
|
||||
break;
|
||||
|
||||
case NP_SPEED_OVERRIDE: // speed override
|
||||
*value = _setup.speed_override[0];
|
||||
break;
|
||||
|
||||
case NP_FEED_OVERRIDE: // feed override
|
||||
*value = _setup.feed_override;
|
||||
break;
|
||||
|
||||
case NP_ADAPTIVE_FEED: // adaptive feed
|
||||
*value = _setup.adaptive_feed;
|
||||
break;
|
||||
|
||||
case NP_FEED_HOLD: // feed hold
|
||||
*value = _setup.feed_hold;
|
||||
break;
|
||||
|
||||
// from active_settings:
|
||||
case NP_FEED: // feed
|
||||
*value = _setup.feed_rate;
|
||||
break;
|
||||
|
||||
case NP_RPM: // speed (rpm)
|
||||
*value = abs(_setup.speed[0]);
|
||||
break;
|
||||
|
||||
case NP_CURRENT_TOOL:
|
||||
*value = _setup.parameters[5400];
|
||||
break;
|
||||
|
||||
case NP_SELECTED_POCKET:
|
||||
if(_setup.random_toolchanger){//random changers already report the real pocket number
|
||||
*value = _setup.selected_pocket;
|
||||
}
|
||||
else{//non random get it from the tool table
|
||||
if(_setup.tool_table[_setup.selected_pocket].pocketno == 0){//pocket 0 is special on non-random changers
|
||||
*value = -1;
|
||||
}
|
||||
else{
|
||||
*value = _setup.tool_table[_setup.selected_pocket].pocketno;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case NP_CURRENT_POCKET:
|
||||
if (_setup.current_pocket == -1) {
|
||||
*value = -1;
|
||||
break;
|
||||
}
|
||||
if(_setup.random_toolchanger){//random changers already report the real pocket number
|
||||
*value = _setup.current_pocket;
|
||||
}
|
||||
else{//non random get it from the tool table
|
||||
*value = _setup.tool_table[_setup.current_pocket].pocketno;
|
||||
}
|
||||
break;
|
||||
|
||||
case NP_SELECTED_TOOL:
|
||||
*value = _setup.selected_tool;
|
||||
break;
|
||||
|
||||
case NP_X: // current position
|
||||
*value = _setup.current_x;
|
||||
break;
|
||||
|
||||
case NP_Y: // current position
|
||||
*value = _setup.current_y;
|
||||
break;
|
||||
|
||||
case NP_Z: // current position
|
||||
*value = _setup.current_z;
|
||||
break;
|
||||
|
||||
case NP_A: // current position
|
||||
*value = _setup.AA_current;
|
||||
break;
|
||||
|
||||
case NP_B: // current position
|
||||
*value = _setup.BB_current;
|
||||
break;
|
||||
|
||||
case NP_C: // current position
|
||||
*value = _setup.CC_current;
|
||||
break;
|
||||
|
||||
case NP_U: // current position
|
||||
*value = _setup.u_current;
|
||||
break;
|
||||
|
||||
case NP_V: // current position
|
||||
*value = _setup.v_current;
|
||||
break;
|
||||
|
||||
case NP_W: // current position
|
||||
*value = _setup.w_current;
|
||||
break;
|
||||
|
||||
case NP_ABS_X: // abs position
|
||||
{
|
||||
double x = _setup.current_x + _setup.axis_offset_x;
|
||||
double y = _setup.current_y + _setup.axis_offset_y;
|
||||
rotate(&x, &y, _setup.rotation_xy);
|
||||
*value = x + _setup.origin_offset_x + _setup.tool_offset.tran.x;
|
||||
}
|
||||
break;
|
||||
|
||||
case NP_ABS_Y: // abs position
|
||||
{
|
||||
double x = _setup.current_x + _setup.axis_offset_x;
|
||||
double y = _setup.current_y + _setup.axis_offset_y;
|
||||
rotate(&x, &y, _setup.rotation_xy);
|
||||
*value = y + _setup.origin_offset_y + _setup.tool_offset.tran.y;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case NP_ABS_Z: // abs position
|
||||
*value = _setup.current_z + _setup.axis_offset_z +
|
||||
_setup.origin_offset_z + _setup.tool_offset.tran.z;
|
||||
break;
|
||||
|
||||
case NP_ABS_A: // abs position
|
||||
*value = _setup.AA_current + _setup.AA_axis_offset +
|
||||
_setup.AA_origin_offset + _setup.tool_offset.a;
|
||||
break;
|
||||
|
||||
case NP_ABS_B: // abs position
|
||||
*value = _setup.BB_current + _setup.BB_axis_offset +
|
||||
_setup.BB_origin_offset + _setup.tool_offset.b;
|
||||
break;
|
||||
|
||||
case NP_ABS_C: // abs position
|
||||
*value = _setup.CC_current + _setup.CC_axis_offset +
|
||||
_setup.CC_origin_offset + _setup.tool_offset.c;
|
||||
break;
|
||||
|
||||
// o-word subs may optionally have an
|
||||
// expression after endsub and return
|
||||
// this 'function return value' is accessible as '_value'
|
||||
case NP_VALUE:
|
||||
*value = _setup.return_value;
|
||||
break;
|
||||
|
||||
// predicate: the last NGC procedure did/did not return a value
|
||||
case NP_VALUE_RETURNED:
|
||||
*value = _setup.value_returned;
|
||||
break;
|
||||
|
||||
case NP_CALL_LEVEL:
|
||||
*value = _setup.call_level;
|
||||
break;
|
||||
|
||||
case NP_REMAP_LEVEL:
|
||||
*value = _setup.remap_level;
|
||||
break;
|
||||
|
||||
case NP_TASK:
|
||||
extern int _task; // zero in gcodemodule, 1 in milltask
|
||||
*value = _task;
|
||||
break;
|
||||
|
||||
default:
|
||||
ERS(_("BUG: lookup_named_param(%s): unhandled index=%fn"),
|
||||
nameBuf,index);
|
||||
}
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
int Interp::init_python_predef_parameter(const char *name)
|
||||
{
|
||||
int exists = 0;
|
||||
double value;
|
||||
parameter_value param;
|
||||
|
||||
if (name[0] == '_') { // globals only
|
||||
find_named_param(name, &exists, &value);
|
||||
if (exists) {
|
||||
fprintf(stderr, "warning: redefining named parameter %s\n",name);
|
||||
_setup.sub_context[0].named_params.erase(name);
|
||||
}
|
||||
param.value = 0.0;
|
||||
param.attr = PA_READONLY|PA_PYTHON|PA_GLOBAL;
|
||||
_setup.sub_context[0].named_params[strstore(name)] = param;
|
||||
}
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
int Interp::init_named_parameters()
|
||||
{
|
||||
|
||||
// version major minor Note
|
||||
// ------------ -------- ---------- -------------------------------------
|
||||
// M.N.m M.N 0.m normal format
|
||||
// M.N.m~xxx M.N 0.m pre-release format
|
||||
const char *pkgversion = PACKAGE_VERSION; //examples: 2.4.6, 2.5.0~pre
|
||||
const char *version_major = "_vmajor";// named_parameter name (use lower case)
|
||||
const char *version_minor = "_vminor";// named_parameter name (use lower case)
|
||||
const char *metric_machine = "_metric_machine";// named_parameter name (use lower case)
|
||||
double vmajor=0.0, vminor=0.0, munits = 1.0;
|
||||
sscanf(pkgversion, "%lf%lf", &vmajor, &vminor);
|
||||
|
||||
init_readonly_param(version_major,vmajor,0);
|
||||
init_readonly_param(version_minor,vminor,0);
|
||||
|
||||
munits = inicheck();
|
||||
init_readonly_param(metric_machine,munits,0);
|
||||
|
||||
// params tagged with PA_USE_LOOKUP will call the lookup_named_param()
|
||||
// method. The value is used as a index for the switch() statement.
|
||||
|
||||
// the active_g_codes fields
|
||||
|
||||
// I guess this is the line number
|
||||
init_readonly_param("_line", NP_LINE, PA_USE_LOOKUP);
|
||||
|
||||
// any of G1 G2 G3 G5.2 G73 G80 G82 G83 G86 G87 G88 G89
|
||||
// value is number after 'G' multiplied by 10 (10,20,30,52..)
|
||||
|
||||
init_readonly_param("_motion_mode", NP_MOTION_MODE, PA_USE_LOOKUP);
|
||||
|
||||
// G17/18/19/17.1/18.1/19.1 -> return 170/180/190/171/181/191
|
||||
init_readonly_param("_plane", NP_PLANE, PA_USE_LOOKUP);
|
||||
|
||||
// return 400,410,420 depending if (G40,G41,G42) is on
|
||||
init_readonly_param("_ccomp", NP_CCOMP, PA_USE_LOOKUP);
|
||||
|
||||
// 1.0 if G21 is on
|
||||
init_readonly_param("_metric", NP_METRIC, PA_USE_LOOKUP);
|
||||
|
||||
// 1.0 if G20 is on
|
||||
init_readonly_param("_imperial", NP_IMPERIAL, PA_USE_LOOKUP);
|
||||
|
||||
//1.0 if G90 is on
|
||||
init_readonly_param("_absolute", NP_ABSOLUTE, PA_USE_LOOKUP);
|
||||
|
||||
//1.0 if G91 is on
|
||||
init_readonly_param("_incremental", NP_INCREMENTAL, PA_USE_LOOKUP);
|
||||
|
||||
// 1.0 if G93 is on
|
||||
init_readonly_param("_inverse_time", NP_INVERSE_TIME, PA_USE_LOOKUP);
|
||||
|
||||
// 1.0 if G94 is on
|
||||
init_readonly_param("_units_per_minute", NP_UNITS_PER_MINUTE, PA_USE_LOOKUP);
|
||||
|
||||
// 1.0 if G95 is on
|
||||
init_readonly_param("_units_per_rev", NP_UNITS_PER_REV, PA_USE_LOOKUP);
|
||||
|
||||
// 0..9 for G54..G59.3
|
||||
init_readonly_param("_coord_system", NP_COORD_SYSTEM, PA_USE_LOOKUP);
|
||||
|
||||
// 1.0 if G43 is on
|
||||
init_readonly_param("_tool_offset", NP_TOOL_OFFSET, PA_USE_LOOKUP);
|
||||
|
||||
// 1 if G98 set
|
||||
init_readonly_param("_retract_r_plane", NP_RETRACT_R_PLANE, PA_USE_LOOKUP);
|
||||
|
||||
// 1 if G99 set
|
||||
init_readonly_param("_retract_old_z", NP_RETRACT_OLD_Z, PA_USE_LOOKUP);
|
||||
|
||||
// really esoteric
|
||||
// init_readonly_param("_control_mode", 110, PA_USE_LOOKUP);
|
||||
|
||||
|
||||
// 1 if G97 is on
|
||||
init_readonly_param("_spindle_rpm_mode", NP_SPINDLE_RPM_MODE, PA_USE_LOOKUP);
|
||||
|
||||
init_readonly_param("_spindle_css_mode", NP_SPINDLE_CSS_MODE, PA_USE_LOOKUP);
|
||||
|
||||
// 1 if G90.1 is on
|
||||
init_readonly_param("_ijk_absolute_mode", NP_IJK_ABSOLUTE_MODE, PA_USE_LOOKUP);
|
||||
|
||||
// 1 if G7 is on
|
||||
init_readonly_param("_lathe_diameter_mode", NP_LATHE_DIAMETER_MODE, PA_USE_LOOKUP);
|
||||
|
||||
// 1 if G8 is on
|
||||
init_readonly_param("_lathe_radius_mode", NP_LATHE_RADIUS_MODE, PA_USE_LOOKUP);
|
||||
|
||||
|
||||
// the active_m_codes fields
|
||||
init_readonly_param("_spindle_on", NP_SPINDLE_ON, PA_USE_LOOKUP);
|
||||
init_readonly_param("_spindle_cw", NP_SPINDLE_CW, PA_USE_LOOKUP);
|
||||
|
||||
init_readonly_param("_mist", NP_MIST, PA_USE_LOOKUP);
|
||||
init_readonly_param("_flood", NP_FLOOD, PA_USE_LOOKUP);
|
||||
init_readonly_param("_speed_override", NP_SPEED_OVERRIDE, PA_USE_LOOKUP);
|
||||
init_readonly_param("_feed_override", NP_FEED_OVERRIDE, PA_USE_LOOKUP);
|
||||
init_readonly_param("_adaptive_feed", NP_ADAPTIVE_FEED, PA_USE_LOOKUP);
|
||||
init_readonly_param("_feed_hold", NP_FEED_HOLD, PA_USE_LOOKUP);
|
||||
|
||||
// active_settings
|
||||
init_readonly_param("_feed", NP_FEED, PA_USE_LOOKUP);
|
||||
init_readonly_param("_rpm", NP_RPM, PA_USE_LOOKUP);
|
||||
|
||||
|
||||
// tool related
|
||||
init_readonly_param("_current_tool", NP_CURRENT_TOOL, PA_USE_LOOKUP);
|
||||
init_readonly_param("_current_pocket", NP_CURRENT_POCKET, PA_USE_LOOKUP);
|
||||
init_readonly_param("_selected_pocket", NP_SELECTED_POCKET, PA_USE_LOOKUP);
|
||||
init_readonly_param("_selected_tool", NP_SELECTED_TOOL, PA_USE_LOOKUP);
|
||||
|
||||
// current position - alias to #5420-#5429
|
||||
init_readonly_param("_x", NP_X, PA_USE_LOOKUP);
|
||||
init_readonly_param("_y", NP_Y, PA_USE_LOOKUP);
|
||||
init_readonly_param("_z", NP_Z, PA_USE_LOOKUP);
|
||||
init_readonly_param("_a", NP_A, PA_USE_LOOKUP);
|
||||
init_readonly_param("_b", NP_B, PA_USE_LOOKUP);
|
||||
init_readonly_param("_c", NP_C, PA_USE_LOOKUP);
|
||||
init_readonly_param("_u", NP_U, PA_USE_LOOKUP);
|
||||
init_readonly_param("_v", NP_V, PA_USE_LOOKUP);
|
||||
init_readonly_param("_w", NP_W, PA_USE_LOOKUP);
|
||||
|
||||
// current abs position, does not include any offset
|
||||
init_readonly_param("_abs_x", NP_ABS_X, PA_USE_LOOKUP);
|
||||
init_readonly_param("_abs_y", NP_ABS_Y, PA_USE_LOOKUP);
|
||||
init_readonly_param("_abs_z", NP_ABS_Z, PA_USE_LOOKUP);
|
||||
init_readonly_param("_abs_a", NP_ABS_A, PA_USE_LOOKUP);
|
||||
init_readonly_param("_abs_b", NP_ABS_B, PA_USE_LOOKUP);
|
||||
init_readonly_param("_abs_c", NP_ABS_C, PA_USE_LOOKUP);
|
||||
|
||||
// last (optional) endsub/return value
|
||||
init_readonly_param("_value", NP_VALUE, PA_USE_LOOKUP);
|
||||
|
||||
// predicate: last NGC procedure did return a value on endsub/return
|
||||
init_readonly_param("_value_returned", NP_VALUE_RETURNED, PA_USE_LOOKUP);
|
||||
|
||||
// predicate: 1 in milltask instance, 0 in UI - control preview behaviour
|
||||
init_readonly_param("_task", NP_TASK, PA_USE_LOOKUP);
|
||||
|
||||
// debugging aids
|
||||
init_readonly_param("_call_level", NP_CALL_LEVEL, PA_USE_LOOKUP);
|
||||
init_readonly_param("_remap_level", NP_REMAP_LEVEL, PA_USE_LOOKUP);
|
||||
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
double Interp::inicheck()
|
||||
{
|
||||
const char *filename;
|
||||
|
||||
if ((filename = getenv("INI_FILE_NAME")) == NULL) {
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
IniFile inifile(filename);
|
||||
if (!inifile) {
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
if (auto inistring = inifile.findString("LINEAR_UNITS", "TRAJ")) {
|
||||
if (*inistring == "inch") {
|
||||
return 0.0;
|
||||
} else {
|
||||
return 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1.0;
|
||||
}
|
||||
1222
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_o_word.cc
vendored
Normal file
1222
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_o_word.cc
vendored
Normal file
File diff suppressed because it is too large
Load Diff
204
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_parameter_def.hh
vendored
Normal file
204
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_parameter_def.hh
vendored
Normal file
@@ -0,0 +1,204 @@
|
||||
/**
|
||||
* @file interp_parameter_def.hh
|
||||
* Named global parameters used by the interpreter.
|
||||
*
|
||||
* This file exists mostly to avoid magic numbers in interpreter code.
|
||||
*
|
||||
* @author Robert W. Ellenberg <rwe24g@gmail.com>
|
||||
*
|
||||
* Copyright (c) 2019, Robert W. Ellenberg
|
||||
*
|
||||
* This source code is released for free distribution under the terms of the
|
||||
* GNU General Public License (V2) as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef INTERP_PARAMETER_DEF_H
|
||||
#define INTERP_PARAMETER_DEF_H
|
||||
|
||||
namespace interp_param_global
|
||||
{
|
||||
// 31-5000 - G-code user parameters. These parameters are global in the G-code file, and available for general use. Volatile.
|
||||
enum InterpParameterIndex {
|
||||
// 5061-5069 - Coordinates of a G38 probe result (X, Y, Z, A, B, C, U, V & W). Coordinates are in the coordinate system in which the G38 took place. Volatile.
|
||||
G38_X=5061,
|
||||
G38_Y,
|
||||
G38_Z,
|
||||
G38_A,
|
||||
G38_B,
|
||||
G38_C,
|
||||
G38_U,
|
||||
G38_V,
|
||||
G38_W,
|
||||
// 5070 - G38 probe result: 1 if success, 0 if probe failed to close. Used with G38.3 and G38.5. Volatile.
|
||||
G38_TRIPPED=5070,
|
||||
// 5161-5169 - "G28" Home for X, Y, Z, A, B, C, U, V & W. Persistent.
|
||||
G28_X=5161,
|
||||
G28_Y,
|
||||
G28_Z,
|
||||
G28_A,
|
||||
G28_B,
|
||||
G28_C,
|
||||
G28_U,
|
||||
G28_V,
|
||||
G28_W,
|
||||
// 5181-5189 - "G30" Home for X, Y, Z, A, B, C, U, V & W. Persistent.
|
||||
G30_X=5181,
|
||||
G30_Y,
|
||||
G30_Z,
|
||||
G30_A,
|
||||
G30_B,
|
||||
G30_C,
|
||||
G30_U,
|
||||
G30_V,
|
||||
G30_W,
|
||||
// 5210 - 1 if "G92" offset is currently applied, 0 otherwise. Persistent.
|
||||
// 5211-5219 - "G92" offset for X, Y, Z, A, B, C, U, V & W. Persistent.
|
||||
G92_APPLIED=5210,
|
||||
G92_X=5211,
|
||||
G92_Y,
|
||||
G92_Z,
|
||||
G92_A,
|
||||
G92_B,
|
||||
G92_C,
|
||||
G92_U,
|
||||
G92_V,
|
||||
G92_W,
|
||||
// 5220 - Coordinate System number 1 - 9 for G54 - G59.3. Persistent.
|
||||
// 5221-5230 - Coordinate System 1, G54 for X, Y, Z, A, B, C, U, V, W & R. R denotes the XY rotation angle around the Z axis. Persistent.
|
||||
// 5241-5250 - Coordinate System 2, G55 for X, Y, Z, A, B, C, U, V, W & R. Persistent.
|
||||
// 5261-5270 - Coordinate System 3, G56 for X, Y, Z, A, B, C, U, V, W & R. Persistent.
|
||||
// 5281-5290 - Coordinate System 4, G57 for X, Y, Z, A, B, C, U, V, W & R. Persistent.
|
||||
// 5301-5310 - Coordinate System 5, G58 for X, Y, Z, A, B, C, U, V, W & R. Persistent.
|
||||
// 5321-5330 - Coordinate System 6, G59 for X, Y, Z, A, B, C, U, V, W & R. Persistent.
|
||||
// 5341-5350 - Coordinate System 7, G59.1 for X, Y, Z, A, B, C, U, V, W & R. Persistent.
|
||||
// 5361-5370 - Coordinate System 8, G59.2 for X, Y, Z, A, B, C, U, V, W & R. Persistent.
|
||||
// 5381-5390 - Coordinate System 9, G59.3 for X, Y, Z, A, B, C, U, V, W & R. Persistent.
|
||||
ACTIVE_WORK_CSYS=5220,
|
||||
G54_X=5221,
|
||||
G54_Y,
|
||||
G54_Z,
|
||||
G54_A,
|
||||
G54_B,
|
||||
G54_C,
|
||||
G54_U,
|
||||
G54_V,
|
||||
G54_W,
|
||||
G54_R,
|
||||
G55_X=5241,
|
||||
G55_Y,
|
||||
G55_Z,
|
||||
G55_A,
|
||||
G55_B,
|
||||
G55_C,
|
||||
G55_U,
|
||||
G55_V,
|
||||
G55_W,
|
||||
G55_R,
|
||||
G56_X=5261,
|
||||
G56_Y,
|
||||
G56_Z,
|
||||
G56_A,
|
||||
G56_B,
|
||||
G56_C,
|
||||
G56_U,
|
||||
G56_V,
|
||||
G56_W,
|
||||
G56_R,
|
||||
G57_X=5281,
|
||||
G57_Y,
|
||||
G57_Z,
|
||||
G57_A,
|
||||
G57_B,
|
||||
G57_C,
|
||||
G57_U,
|
||||
G57_V,
|
||||
G57_W,
|
||||
G57_R,
|
||||
G58_X=5301,
|
||||
G58_Y,
|
||||
G58_Z,
|
||||
G58_A,
|
||||
G58_B,
|
||||
G58_C,
|
||||
G58_U,
|
||||
G58_V,
|
||||
G58_W,
|
||||
G58_R,
|
||||
G59_X=5321,
|
||||
G59_Y,
|
||||
G59_Z,
|
||||
G59_A,
|
||||
G59_B,
|
||||
G59_C,
|
||||
G59_U,
|
||||
G59_V,
|
||||
G59_W,
|
||||
G59_R,
|
||||
G59_1_X=5341,
|
||||
G59_1_Y,
|
||||
G59_1_Z,
|
||||
G59_1_A,
|
||||
G59_1_B,
|
||||
G59_1_C,
|
||||
G59_1_U,
|
||||
G59_1_V,
|
||||
G59_1_W,
|
||||
G59_1_R,
|
||||
G59_2_X=5361,
|
||||
G59_2_Y,
|
||||
G59_2_Z,
|
||||
G59_2_A,
|
||||
G59_2_B,
|
||||
G59_2_C,
|
||||
G59_2_U,
|
||||
G59_2_V,
|
||||
G59_2_W,
|
||||
G59_2_R,
|
||||
G59_3_X=5381,
|
||||
G59_3_Y,
|
||||
G59_3_Z,
|
||||
G59_3_A,
|
||||
G59_3_B,
|
||||
G59_3_C,
|
||||
G59_3_U,
|
||||
G59_3_V,
|
||||
G59_3_W,
|
||||
G59_3_R,
|
||||
// 5399 - Result of M66 - Check or wait for input. Volatile.
|
||||
M66_RESULT=5399,
|
||||
// 5400 - Tool Number. Volatile.
|
||||
// 5401-5409 - Tool Offsets for X, Y, Z, A, B, C, U, V & W. Volatile.
|
||||
TOOL_NUMBER=5400,
|
||||
TOOL_OFFSET_X=5401,
|
||||
TOOL_OFFSET_Y,
|
||||
TOOL_OFFSET_Z,
|
||||
TOOL_OFFSET_A,
|
||||
TOOL_OFFSET_B,
|
||||
TOOL_OFFSET_C,
|
||||
TOOL_OFFSET_U,
|
||||
TOOL_OFFSET_V,
|
||||
TOOL_OFFSET_W,
|
||||
// 5410 - Tool Diameter. Volatile.
|
||||
TOOL_DIAMETER=5410,
|
||||
// 5411 - Tool Front Angle. Volatile.
|
||||
TOOL_FRONT_ANGLE=5411,
|
||||
// 5412 - Tool Back Angle. Volatile.
|
||||
TOOL_BACK_ANGLE=5412,
|
||||
// 5413 - Tool Orientation. Volatile.
|
||||
TOOL_ORIENTATION=5413,
|
||||
// 5420-5428 - Current relative position in the active coordinate system including all offsets and in the current program units for X, Y, Z, A, B, C, U, V & W, volatile.
|
||||
RELATIVE_POSITION_X=5420,
|
||||
RELATIVE_POSITION_Y,
|
||||
RELATIVE_POSITION_Z,
|
||||
RELATIVE_POSITION_A,
|
||||
RELATIVE_POSITION_B,
|
||||
RELATIVE_POSITION_C,
|
||||
RELATIVE_POSITION_U,
|
||||
RELATIVE_POSITION_V,
|
||||
RELATIVE_POSITION_W,
|
||||
// 5599 - Flag for controlling the output of (DEBUG,) statements. 1=output, 0=no output; default=1. Volatile.
|
||||
DEBUG_LEVEL_FLAG=5599,
|
||||
RS274NGC_MAX_PARAMETERS=5602
|
||||
};
|
||||
}
|
||||
#endif // INTERP_PARAMETER_DEF_H
|
||||
692
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_queue.cc
vendored
Normal file
692
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_queue.cc
vendored
Normal file
@@ -0,0 +1,692 @@
|
||||
/********************************************************************
|
||||
* Description: interp_queue.cc
|
||||
*
|
||||
* Author: Chris Radek
|
||||
* License: GPL Version 2
|
||||
* System: Linux
|
||||
*
|
||||
* Copyright (c) 2009 All rights reserved.
|
||||
*
|
||||
********************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "rs274ngc.hh"
|
||||
#include "rs274ngc_return.hh"
|
||||
#include "interp_queue.hh"
|
||||
#include "interp_internal.hh"
|
||||
#include "rs274ngc_interp.hh"
|
||||
|
||||
static int debug_qc = 0;
|
||||
|
||||
// lathe tools have strange origin points that are not at
|
||||
// the center of the radius. This means that the point that
|
||||
// radius compensation controls (center of radius) is not at
|
||||
// the tool's origin. These functions do the necessary
|
||||
// translation. Notice tool orientations 0 (mill) and 9, and
|
||||
// those with radius 0 (a point) do not need any translation.
|
||||
|
||||
static double latheorigin_x(setup_pointer settings, double x) {
|
||||
int o = settings->cutter_comp_orientation;
|
||||
double r = settings->cutter_comp_radius;
|
||||
if(settings->plane != CANON_PLANE::XZ) return x;
|
||||
|
||||
if(o==2 || o==6 || o==1) x -= r;
|
||||
if(o==3 || o==8 || o==4) x += r;
|
||||
return x;
|
||||
}
|
||||
|
||||
static double latheorigin_z(setup_pointer settings, double z) {
|
||||
int o = settings->cutter_comp_orientation;
|
||||
double r = settings->cutter_comp_radius;
|
||||
if(settings->plane != CANON_PLANE::XZ) return z;
|
||||
|
||||
if(o==2 || o==7 || o==3) z -= r;
|
||||
if(o==1 || o==5 || o==4) z += r;
|
||||
return z;
|
||||
}
|
||||
|
||||
static double endpoint[2];
|
||||
static int endpoint_valid = 0;
|
||||
|
||||
std::vector<queued_canon>& qc(void) {
|
||||
static std::vector<queued_canon> c;
|
||||
#if 0
|
||||
printf("len %d\n", (int)c.size());
|
||||
#endif
|
||||
return c;
|
||||
}
|
||||
|
||||
void qc_reset(void) {
|
||||
if(debug_qc) printf("qc cleared\n");
|
||||
qc().clear();
|
||||
endpoint_valid = 0;
|
||||
}
|
||||
|
||||
void enqueue_SET_FEED_RATE(double feed) {
|
||||
if(qc().empty()) {
|
||||
if(debug_qc) printf("immediate set feed rate %f\n", feed);
|
||||
SET_FEED_RATE(feed);
|
||||
return;
|
||||
}
|
||||
queued_canon q;
|
||||
q.type = QSET_FEED_RATE;
|
||||
q.data.set_feed_rate.feed = feed;
|
||||
if(debug_qc) printf("enqueue set feed rate %f\n", feed);
|
||||
qc().push_back(q);
|
||||
}
|
||||
|
||||
void enqueue_DWELL(double time) {
|
||||
if(qc().empty()) {
|
||||
if(debug_qc) printf("immediate dwell %f\n", time);
|
||||
DWELL(time);
|
||||
return;
|
||||
}
|
||||
queued_canon q;
|
||||
q.type = QDWELL;
|
||||
q.data.dwell.time = time;
|
||||
if(debug_qc) printf("enqueue dwell %f\n", time);
|
||||
qc().push_back(q);
|
||||
}
|
||||
|
||||
void enqueue_SET_FEED_MODE(int spindle, int mode) {
|
||||
if(qc().empty()) {
|
||||
if(debug_qc) printf("immediate set feed mode %d\n", mode);
|
||||
SET_FEED_MODE(spindle, mode);
|
||||
return;
|
||||
}
|
||||
queued_canon q;
|
||||
q.type = QSET_FEED_MODE;
|
||||
q.data.set_feed_mode.spindle = spindle;
|
||||
q.data.set_feed_mode.mode = mode;
|
||||
if(debug_qc) printf("enqueue set feed mode %d\n", mode);
|
||||
qc().push_back(q);
|
||||
}
|
||||
|
||||
void enqueue_MIST_ON(void) {
|
||||
if(qc().empty()) {
|
||||
if(debug_qc) printf("immediate mist on\n");
|
||||
MIST_ON();
|
||||
return;
|
||||
}
|
||||
queued_canon q;
|
||||
q.type = QMIST_ON;
|
||||
if(debug_qc) printf("enqueue mist on\n");
|
||||
qc().push_back(q);
|
||||
}
|
||||
|
||||
void enqueue_MIST_OFF(void) {
|
||||
if(qc().empty()) {
|
||||
if(debug_qc) printf("immediate mist off\n");
|
||||
MIST_OFF();
|
||||
return;
|
||||
}
|
||||
queued_canon q;
|
||||
q.type = QMIST_OFF;
|
||||
if(debug_qc) printf("enqueue mist off\n");
|
||||
qc().push_back(q);
|
||||
}
|
||||
|
||||
void enqueue_FLOOD_ON(void) {
|
||||
if(qc().empty()) {
|
||||
if(debug_qc) printf("immediate flood on\n");
|
||||
FLOOD_ON();
|
||||
return;
|
||||
}
|
||||
queued_canon q;
|
||||
q.type = QFLOOD_ON;
|
||||
if(debug_qc) printf("enqueue flood on\n");
|
||||
qc().push_back(q);
|
||||
}
|
||||
|
||||
void enqueue_FLOOD_OFF(void) {
|
||||
if(qc().empty()) {
|
||||
if(debug_qc) printf("immediate flood on\n");
|
||||
FLOOD_OFF();
|
||||
return;
|
||||
}
|
||||
queued_canon q;
|
||||
q.type = QFLOOD_OFF;
|
||||
if(debug_qc) printf("enqueue flood off\n");
|
||||
qc().push_back(q);
|
||||
}
|
||||
|
||||
void enqueue_START_SPINDLE_CLOCKWISE(int spindle) {
|
||||
if(qc().empty()) {
|
||||
if(debug_qc) printf("immediate spindle clockwise\n");
|
||||
START_SPINDLE_CLOCKWISE(spindle);
|
||||
return;
|
||||
}
|
||||
queued_canon q;
|
||||
q.type = QSTART_SPINDLE_CLOCKWISE;
|
||||
q.data.set_spindle_speed.spindle = spindle;
|
||||
if(debug_qc) printf("enqueue spindle clockwise\n");
|
||||
qc().push_back(q);
|
||||
}
|
||||
|
||||
void enqueue_START_SPINDLE_COUNTERCLOCKWISE(int spindle) {
|
||||
if(qc().empty()) {
|
||||
if(debug_qc) printf("immediate spindle counterclockwise\n");
|
||||
START_SPINDLE_COUNTERCLOCKWISE(spindle);
|
||||
return;
|
||||
}
|
||||
queued_canon q;
|
||||
q.type = QSTART_SPINDLE_COUNTERCLOCKWISE;
|
||||
q.data.set_spindle_speed.spindle = spindle;
|
||||
if(debug_qc) printf("enqueue spindle counterclockwise\n");
|
||||
qc().push_back(q);
|
||||
}
|
||||
|
||||
void enqueue_STOP_SPINDLE_TURNING(int spindle) {
|
||||
if(qc().empty()) {
|
||||
if(debug_qc) printf("immediate spindle stop\n");
|
||||
STOP_SPINDLE_TURNING(spindle);
|
||||
return;
|
||||
}
|
||||
queued_canon q;
|
||||
q.type = QSTOP_SPINDLE_TURNING;
|
||||
q.data.set_spindle_speed.spindle = spindle;
|
||||
if(debug_qc) printf("enqueue spindle stop\n");
|
||||
qc().push_back(q);
|
||||
}
|
||||
|
||||
void enqueue_ORIENT_SPINDLE(int spindle, double orientation, int mode) {
|
||||
if(qc().empty()) {
|
||||
if(debug_qc) printf("immediate spindle orient\n");
|
||||
ORIENT_SPINDLE(spindle, orientation, mode);
|
||||
return;
|
||||
}
|
||||
queued_canon q;
|
||||
q.type = QORIENT_SPINDLE;
|
||||
q.data.orient_spindle.spindle = spindle;
|
||||
q.data.orient_spindle.orientation = orientation;
|
||||
q.data.orient_spindle.mode = mode;
|
||||
if(debug_qc) printf("enqueue spindle orient\n");
|
||||
qc().push_back(q);
|
||||
}
|
||||
|
||||
void enqueue_WAIT_ORIENT_SPINDLE_COMPLETE(int spindle, double timeout) {
|
||||
if(qc().empty()) {
|
||||
if(debug_qc) printf("immediate wait spindle orient complete\n");
|
||||
WAIT_SPINDLE_ORIENT_COMPLETE(spindle, timeout);
|
||||
return;
|
||||
}
|
||||
queued_canon q;
|
||||
q.type = QWAIT_ORIENT_SPINDLE_COMPLETE;
|
||||
q.data.wait_orient_spindle_complete.spindle = spindle;
|
||||
q.data.wait_orient_spindle_complete.timeout = timeout;
|
||||
if(debug_qc) printf("enqueue wait spindle orient complete\n");
|
||||
qc().push_back(q);
|
||||
}
|
||||
|
||||
void enqueue_SET_SPINDLE_MODE(int spindle, double mode) {
|
||||
if(qc().empty()) {
|
||||
if(debug_qc) printf("immediate spindle mode %f\n", mode);
|
||||
SET_SPINDLE_MODE(spindle, mode);
|
||||
return;
|
||||
}
|
||||
queued_canon q;
|
||||
q.type = QSET_SPINDLE_MODE;
|
||||
q.data.set_spindle_mode.spindle = spindle;
|
||||
q.data.set_spindle_mode.mode = mode;
|
||||
if(debug_qc) printf("enqueue spindle mode %f\n", mode);
|
||||
qc().push_back(q);
|
||||
}
|
||||
|
||||
void enqueue_SET_SPINDLE_SPEED(int spindle, double speed) {
|
||||
if(qc().empty()) {
|
||||
if(debug_qc) printf("immediate set spindle speed %f\n", speed);
|
||||
SET_SPINDLE_SPEED(spindle, speed);
|
||||
return;
|
||||
}
|
||||
queued_canon q;
|
||||
q.type = QSET_SPINDLE_SPEED;
|
||||
q.data.set_spindle_speed.spindle = spindle;
|
||||
q.data.set_spindle_speed.speed = speed;
|
||||
if(debug_qc) printf("enqueue set spindle speed %f\n", speed);
|
||||
qc().push_back(q);
|
||||
}
|
||||
|
||||
void enqueue_COMMENT(const char *c) {
|
||||
if(qc().empty()) {
|
||||
if(debug_qc) printf("immediate comment \"%s\"\n", c);
|
||||
COMMENT(c);
|
||||
return;
|
||||
}
|
||||
queued_canon q;
|
||||
q.type = QCOMMENT;
|
||||
q.data.comment.comment = strdup(c);
|
||||
if(debug_qc) printf("enqueue comment \"%s\"\n", c);
|
||||
qc().push_back(q);
|
||||
}
|
||||
|
||||
int enqueue_STRAIGHT_FEED(setup_pointer settings, int l,
|
||||
double dx, double dy, double dz,
|
||||
double x, double y, double z,
|
||||
double a, double b, double c,
|
||||
double u, double v, double w) {
|
||||
queued_canon q;
|
||||
q.type = QSTRAIGHT_FEED;
|
||||
q.data.straight_feed.line_number = l;
|
||||
switch(settings->plane) {
|
||||
case CANON_PLANE::XY:
|
||||
q.data.straight_feed.dx = dx;
|
||||
q.data.straight_feed.dy = dy;
|
||||
q.data.straight_feed.dz = dz;
|
||||
q.data.straight_feed.x = x;
|
||||
q.data.straight_feed.y = y;
|
||||
q.data.straight_feed.z = z;
|
||||
break;
|
||||
case CANON_PLANE::XZ:
|
||||
q.data.straight_feed.dz = dx;
|
||||
q.data.straight_feed.dx = dy;
|
||||
q.data.straight_feed.dy = dz;
|
||||
q.data.straight_feed.z = x;
|
||||
q.data.straight_feed.x = y;
|
||||
q.data.straight_feed.y = z;
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
q.data.straight_feed.a = a;
|
||||
q.data.straight_feed.b = b;
|
||||
q.data.straight_feed.c = c;
|
||||
q.data.straight_feed.u = u;
|
||||
q.data.straight_feed.v = v;
|
||||
q.data.straight_feed.w = w;
|
||||
qc().push_back(q);
|
||||
if(debug_qc) printf("enqueue straight feed lineno %d to %f %f %f direction %f %f %f\n", l, x,y,z, dx, dy, dz);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int enqueue_STRAIGHT_TRAVERSE(setup_pointer settings, int l,
|
||||
double dx, double dy, double dz,
|
||||
double x, double y, double z,
|
||||
double a, double b, double c,
|
||||
double u, double v, double w) {
|
||||
queued_canon q;
|
||||
q.type = QSTRAIGHT_TRAVERSE;
|
||||
q.data.straight_traverse.line_number = l;
|
||||
switch(settings->plane) {
|
||||
case CANON_PLANE::XY:
|
||||
q.data.straight_traverse.dx = dx;
|
||||
q.data.straight_traverse.dy = dy;
|
||||
q.data.straight_traverse.dz = dz;
|
||||
q.data.straight_traverse.x = x;
|
||||
q.data.straight_traverse.y = y;
|
||||
q.data.straight_traverse.z = z;
|
||||
break;
|
||||
case CANON_PLANE::XZ:
|
||||
q.data.straight_traverse.dz = dx;
|
||||
q.data.straight_traverse.dx = dy;
|
||||
q.data.straight_traverse.dy = dz;
|
||||
q.data.straight_traverse.z = x;
|
||||
q.data.straight_traverse.x = y;
|
||||
q.data.straight_traverse.y = z;
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
q.data.straight_traverse.a = a;
|
||||
q.data.straight_traverse.b = b;
|
||||
q.data.straight_traverse.c = c;
|
||||
q.data.straight_traverse.u = u;
|
||||
q.data.straight_traverse.v = v;
|
||||
q.data.straight_traverse.w = w;
|
||||
if(debug_qc) printf("enqueue straight traverse lineno %d to %f %f %f direction %f %f %f\n", l, x,y,z, dx, dy, dz);
|
||||
qc().push_back(q);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void enqueue_ARC_FEED(setup_pointer /*settings*/, int l,
|
||||
double original_turns,
|
||||
double end1, double end2, double center1, double center2,
|
||||
int turn,
|
||||
double end3,
|
||||
double a, double b, double c,
|
||||
double u, double v, double w) {
|
||||
queued_canon q;
|
||||
|
||||
q.type = QARC_FEED;
|
||||
q.data.arc_feed.line_number = l;
|
||||
q.data.arc_feed.original_turns = original_turns;
|
||||
q.data.arc_feed.end1 = end1;
|
||||
q.data.arc_feed.end2 = end2;
|
||||
q.data.arc_feed.center1 = center1;
|
||||
q.data.arc_feed.center2 = center2;
|
||||
q.data.arc_feed.turn = turn;
|
||||
q.data.arc_feed.end3 = end3;
|
||||
q.data.arc_feed.a = a;
|
||||
q.data.arc_feed.b = b;
|
||||
q.data.arc_feed.c = c;
|
||||
q.data.arc_feed.u = u;
|
||||
q.data.arc_feed.v = v;
|
||||
q.data.arc_feed.w = w;
|
||||
|
||||
if(debug_qc) printf("enqueue arc lineno %d to %f %f center %f %f turn %d sweeping %f\n", l, end1, end2, center1, center2, turn, original_turns);
|
||||
qc().push_back(q);
|
||||
}
|
||||
|
||||
void enqueue_M_USER_COMMAND (int index, double p_number, double q_number) {
|
||||
if(qc().empty()) {
|
||||
if(debug_qc) printf("immediate M_USER_COMMAND index=%d p=%f q=%f\n",
|
||||
index,p_number,q_number);
|
||||
(*(USER_DEFINED_FUNCTION[index - 100])) (index - 100,p_number,q_number);
|
||||
return;
|
||||
}
|
||||
queued_canon q;
|
||||
q.type = QM_USER_COMMAND;
|
||||
q.data.mcommand.index = index;
|
||||
q.data.mcommand.p_number = p_number;
|
||||
q.data.mcommand.q_number = q_number;
|
||||
if(debug_qc) printf("enqueue M_USER_COMMAND index=%d p=%f q=%f\n",
|
||||
index,p_number,q_number);
|
||||
qc().push_back(q);
|
||||
}
|
||||
|
||||
void qc_scale(double scale) {
|
||||
|
||||
if(qc().empty()) {
|
||||
if(debug_qc) printf("not scaling because qc is empty\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if(debug_qc) printf("scaling qc by %f\n", scale);
|
||||
|
||||
for(unsigned int i = 0; i<qc().size(); i++) {
|
||||
queued_canon &q = qc()[i];
|
||||
endpoint[0] *= scale;
|
||||
endpoint[1] *= scale;
|
||||
switch(q.type) {
|
||||
case QARC_FEED:
|
||||
q.data.arc_feed.end1 *= scale;
|
||||
q.data.arc_feed.end2 *= scale;
|
||||
q.data.arc_feed.end3 *= scale;
|
||||
q.data.arc_feed.center1 *= scale;
|
||||
q.data.arc_feed.center2 *= scale;
|
||||
q.data.arc_feed.u *= scale;
|
||||
q.data.arc_feed.v *= scale;
|
||||
q.data.arc_feed.w *= scale;
|
||||
break;
|
||||
case QSTRAIGHT_FEED:
|
||||
q.data.straight_feed.x *= scale;
|
||||
q.data.straight_feed.y *= scale;
|
||||
q.data.straight_feed.z *= scale;
|
||||
q.data.straight_feed.u *= scale;
|
||||
q.data.straight_feed.v *= scale;
|
||||
q.data.straight_feed.w *= scale;
|
||||
break;
|
||||
case QSTRAIGHT_TRAVERSE:
|
||||
q.data.straight_traverse.x *= scale;
|
||||
q.data.straight_traverse.y *= scale;
|
||||
q.data.straight_traverse.z *= scale;
|
||||
q.data.straight_traverse.u *= scale;
|
||||
q.data.straight_traverse.v *= scale;
|
||||
q.data.straight_traverse.w *= scale;
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dequeue_canons(setup_pointer settings) {
|
||||
|
||||
if(debug_qc) printf("dequeueing: endpoint is now invalid\n");
|
||||
endpoint_valid = 0;
|
||||
|
||||
if(qc().empty()) return;
|
||||
|
||||
for(unsigned int i = 0; i<qc().size(); i++) {
|
||||
queued_canon &q = qc()[i];
|
||||
|
||||
switch(q.type) {
|
||||
case QARC_FEED:
|
||||
if(debug_qc) printf("issuing arc feed lineno %d\n", q.data.arc_feed.line_number);
|
||||
ARC_FEED(q.data.arc_feed.line_number,
|
||||
latheorigin_z(settings, q.data.arc_feed.end1),
|
||||
latheorigin_x(settings, q.data.arc_feed.end2),
|
||||
latheorigin_z(settings, q.data.arc_feed.center1),
|
||||
latheorigin_x(settings, q.data.arc_feed.center2),
|
||||
q.data.arc_feed.turn,
|
||||
q.data.arc_feed.end3,
|
||||
q.data.arc_feed.a, q.data.arc_feed.b, q.data.arc_feed.c,
|
||||
q.data.arc_feed.u, q.data.arc_feed.v, q.data.arc_feed.w);
|
||||
break;
|
||||
case QSTRAIGHT_FEED:
|
||||
if(debug_qc) printf("issuing straight feed lineno %d\n", q.data.straight_feed.line_number);
|
||||
STRAIGHT_FEED(q.data.straight_feed.line_number,
|
||||
latheorigin_x(settings, q.data.straight_feed.x),
|
||||
q.data.straight_feed.y,
|
||||
latheorigin_z(settings, q.data.straight_feed.z),
|
||||
q.data.straight_feed.a, q.data.straight_feed.b, q.data.straight_feed.c,
|
||||
q.data.straight_feed.u, q.data.straight_feed.v, q.data.straight_feed.w);
|
||||
break;
|
||||
case QSTRAIGHT_TRAVERSE:
|
||||
if(debug_qc) printf("issuing straight traverse lineno %d\n", q.data.straight_traverse.line_number);
|
||||
STRAIGHT_TRAVERSE(q.data.straight_traverse.line_number,
|
||||
latheorigin_x(settings, q.data.straight_traverse.x),
|
||||
q.data.straight_traverse.y,
|
||||
latheorigin_z(settings, q.data.straight_traverse.z),
|
||||
q.data.straight_traverse.a, q.data.straight_traverse.b, q.data.straight_traverse.c,
|
||||
q.data.straight_traverse.u, q.data.straight_traverse.v, q.data.straight_traverse.w);
|
||||
break;
|
||||
case QSET_FEED_RATE:
|
||||
if(debug_qc) printf("issuing set feed rate\n");
|
||||
SET_FEED_RATE(q.data.set_feed_rate.feed);
|
||||
break;
|
||||
case QDWELL:
|
||||
if(debug_qc) printf("issuing dwell\n");
|
||||
DWELL(q.data.dwell.time);
|
||||
break;
|
||||
case QSET_FEED_MODE:
|
||||
if(debug_qc) printf("issuing set feed mode\n");
|
||||
SET_FEED_MODE(q.data.set_feed_mode.spindle,
|
||||
q.data.set_feed_mode.mode);
|
||||
break;
|
||||
case QMIST_ON:
|
||||
if(debug_qc) printf("issuing mist on\n");
|
||||
MIST_ON();
|
||||
break;
|
||||
case QMIST_OFF:
|
||||
if(debug_qc) printf("issuing mist off\n");
|
||||
MIST_OFF();
|
||||
break;
|
||||
case QFLOOD_ON:
|
||||
if(debug_qc) printf("issuing flood on\n");
|
||||
FLOOD_ON();
|
||||
break;
|
||||
case QFLOOD_OFF:
|
||||
if(debug_qc) printf("issuing flood off\n");
|
||||
FLOOD_OFF();
|
||||
break;
|
||||
case QSTART_SPINDLE_CLOCKWISE:
|
||||
if(debug_qc) printf("issuing spindle clockwise\n");
|
||||
START_SPINDLE_CLOCKWISE(q.data.set_spindle_speed.spindle);
|
||||
break;
|
||||
case QSTART_SPINDLE_COUNTERCLOCKWISE:
|
||||
if(debug_qc) printf("issuing spindle counterclockwise\n");
|
||||
START_SPINDLE_COUNTERCLOCKWISE(q.data.set_spindle_speed.spindle);
|
||||
break;
|
||||
case QSTOP_SPINDLE_TURNING:
|
||||
if(debug_qc) printf("issuing stop spindle\n");
|
||||
STOP_SPINDLE_TURNING(q.data.set_spindle_speed.spindle);
|
||||
break;
|
||||
case QSET_SPINDLE_MODE:
|
||||
if(debug_qc) printf("issuing set spindle mode\n");
|
||||
SET_SPINDLE_MODE(q.data.set_spindle_speed.spindle,
|
||||
q.data.set_spindle_mode.mode);
|
||||
break;
|
||||
case QSET_SPINDLE_SPEED:
|
||||
if(debug_qc) printf("issuing set spindle speed\n");
|
||||
SET_SPINDLE_SPEED(q.data.set_spindle_speed.spindle,
|
||||
q.data.set_spindle_speed.speed);
|
||||
break;
|
||||
case QCOMMENT:
|
||||
if(debug_qc) printf("issuing comment\n");
|
||||
COMMENT(q.data.comment.comment);
|
||||
free(q.data.comment.comment);
|
||||
break;
|
||||
case QM_USER_COMMAND:
|
||||
if(debug_qc) printf("issuing mcommand\n");
|
||||
{int index=q.data.mcommand.index;
|
||||
(*(USER_DEFINED_FUNCTION[index - 100])) (index -100,
|
||||
q.data.mcommand.p_number,
|
||||
q.data.mcommand.q_number);
|
||||
}
|
||||
break;
|
||||
case QORIENT_SPINDLE:
|
||||
if(debug_qc) printf("issuing orient spindle\n");
|
||||
ORIENT_SPINDLE(q.data.set_spindle_speed.spindle,
|
||||
q.data.orient_spindle.orientation,
|
||||
q.data.orient_spindle.mode);
|
||||
break;
|
||||
case QWAIT_ORIENT_SPINDLE_COMPLETE:
|
||||
if(debug_qc) printf("issuing wait orient spindle complete\n");
|
||||
WAIT_SPINDLE_ORIENT_COMPLETE(q.data.wait_orient_spindle_complete.spindle,
|
||||
q.data.wait_orient_spindle_complete.timeout);
|
||||
break;
|
||||
}
|
||||
}
|
||||
qc().clear();
|
||||
}
|
||||
|
||||
int Interp::move_endpoint_and_flush(setup_pointer settings, double x, double y) {
|
||||
double x1;
|
||||
double y1;
|
||||
double x2;
|
||||
double y2;
|
||||
double dot;
|
||||
|
||||
if(qc().empty()) return 0;
|
||||
|
||||
for(unsigned int i = 0; i<qc().size(); i++) {
|
||||
// there may be several moves in the queue, and we need to
|
||||
// change all of them. consider moving into a concave corner,
|
||||
// then up and back down, then continuing on. there will be
|
||||
// three moves to change.
|
||||
|
||||
queued_canon &q = qc()[i];
|
||||
|
||||
switch(q.type) {
|
||||
case QARC_FEED:
|
||||
double r1, r2, l1, l2;
|
||||
r1 = hypot(q.data.arc_feed.end1 - q.data.arc_feed.center1,
|
||||
q.data.arc_feed.end2 - q.data.arc_feed.center2);
|
||||
l1 = q.data.arc_feed.original_turns;
|
||||
q.data.arc_feed.end1 = x;
|
||||
q.data.arc_feed.end2 = y;
|
||||
r2 = hypot(x - q.data.arc_feed.center1,
|
||||
y - q.data.arc_feed.center2);
|
||||
l2 = find_turn(endpoint[0], endpoint[1],
|
||||
q.data.arc_feed.center1, q.data.arc_feed.center2,
|
||||
q.data.arc_feed.turn,
|
||||
x, y);
|
||||
if(debug_qc) printf("moving endpoint of arc lineno %d old sweep %f new sweep %f\n", q.data.arc_feed.line_number, l1, l2);
|
||||
|
||||
if(fabs(r1-r2) > .01)
|
||||
ERS(_("BUG: cutter compensation has generated an invalid arc with mismatched radii r1 %f r2 %f\n"), r1, r2);
|
||||
if(l1 != 0.0 && endpoint_valid && fabs(l2) > fabs(l1) + (settings->length_units == CANON_UNITS_MM? .0254 : .001)) {
|
||||
ERS(_("Arc move in concave corner cannot be reached by the tool without gouging"));
|
||||
}
|
||||
q.data.arc_feed.end1 = x;
|
||||
q.data.arc_feed.end2 = y;
|
||||
break;
|
||||
case QSTRAIGHT_TRAVERSE:
|
||||
switch(settings->plane) {
|
||||
case CANON_PLANE::XY:
|
||||
x1 = q.data.straight_traverse.dx; // direction of original motion
|
||||
y1 = q.data.straight_traverse.dy;
|
||||
x2 = x - endpoint[0]; // new direction after clipping
|
||||
y2 = y - endpoint[1];
|
||||
break;
|
||||
case CANON_PLANE::XZ:
|
||||
x1 = q.data.straight_traverse.dz; // direction of original motion
|
||||
y1 = q.data.straight_traverse.dx;
|
||||
x2 = x - endpoint[0]; // new direction after clipping
|
||||
y2 = y - endpoint[1];
|
||||
break;
|
||||
default:
|
||||
ERS(_("BUG: Unsupported plane in cutter compensation"));
|
||||
}
|
||||
|
||||
dot = x1 * x2 + y1 * y2; // not normalized; we only care about the angle
|
||||
if(debug_qc) printf("moving endpoint of traverse old dir %f new dir %f dot %f endpoint_valid %d\n", atan2(y1,x1), atan2(y2,x2), dot, endpoint_valid);
|
||||
|
||||
if(endpoint_valid && dot<0) {
|
||||
// oops, the move is the wrong way. this means the
|
||||
// path has crossed because we backed up further
|
||||
// than the line is long. this will gouge.
|
||||
ERS(_("Straight traverse in concave corner cannot be reached by the tool without gouging"));
|
||||
}
|
||||
switch(settings->plane) {
|
||||
case CANON_PLANE::XY:
|
||||
q.data.straight_traverse.x = x;
|
||||
q.data.straight_traverse.y = y;
|
||||
break;
|
||||
case CANON_PLANE::XZ:
|
||||
q.data.straight_traverse.z = x;
|
||||
q.data.straight_traverse.x = y;
|
||||
break;
|
||||
default:
|
||||
ERS(_("BUG: Unsupported plane in cutter compensation"));
|
||||
}
|
||||
break;
|
||||
case QSTRAIGHT_FEED:
|
||||
switch(settings->plane) {
|
||||
case CANON_PLANE::XY:
|
||||
x1 = q.data.straight_feed.dx; // direction of original motion
|
||||
y1 = q.data.straight_feed.dy;
|
||||
x2 = x - endpoint[0]; // new direction after clipping
|
||||
y2 = y - endpoint[1];
|
||||
break;
|
||||
case CANON_PLANE::XZ:
|
||||
x1 = q.data.straight_feed.dz; // direction of original motion
|
||||
y1 = q.data.straight_feed.dx;
|
||||
x2 = x - endpoint[0]; // new direction after clipping
|
||||
y2 = y - endpoint[1];
|
||||
break;
|
||||
default:
|
||||
ERS(_("BUG: Unsupported plane [%d] in cutter compensation"),
|
||||
static_cast<int>(settings->plane));
|
||||
}
|
||||
|
||||
dot = x1 * x2 + y1 * y2;
|
||||
if(debug_qc) printf("moving endpoint of feed old dir %f new dir %f dot %f endpoint_valid %d\n", atan2(y1,x1), atan2(y2,x2), dot, endpoint_valid);
|
||||
|
||||
if(endpoint_valid && dot<0) {
|
||||
// oops, the move is the wrong way. this means the
|
||||
// path has crossed because we backed up further
|
||||
// than the line is long. this will gouge.
|
||||
ERS(_("Straight feed in concave corner cannot be reached by the tool without gouging"));
|
||||
}
|
||||
switch(settings->plane) {
|
||||
case CANON_PLANE::XY:
|
||||
q.data.straight_feed.x = x;
|
||||
q.data.straight_feed.y = y;
|
||||
break;
|
||||
case CANON_PLANE::XZ:
|
||||
q.data.straight_feed.z = x;
|
||||
q.data.straight_feed.x = y;
|
||||
break;
|
||||
default:
|
||||
ERS(_("BUG: Unsupported plane in cutter compensation"));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// other things are not moves - we don't have to mess with them.
|
||||
;
|
||||
}
|
||||
}
|
||||
dequeue_canons(settings);
|
||||
set_endpoint(x, y);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void set_endpoint(double x, double y) {
|
||||
if(debug_qc) printf("setting endpoint %f %f\n", x, y);
|
||||
endpoint[0] = x; endpoint[1] = y;
|
||||
endpoint_valid = 1;
|
||||
}
|
||||
149
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_queue.hh
vendored
Normal file
149
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_queue.hh
vendored
Normal file
@@ -0,0 +1,149 @@
|
||||
/********************************************************************
|
||||
* Description: interp_queue.hh
|
||||
*
|
||||
* Author: Chris Radek
|
||||
* License: GPL Version 2
|
||||
* System: Linux
|
||||
*
|
||||
* Copyright (c) 2009 All rights reserved.
|
||||
*
|
||||
********************************************************************/
|
||||
|
||||
#ifndef INTERP_QUEUE_HH
|
||||
#define INTERP_QUEUE_HH
|
||||
|
||||
#include "interp_internal.hh"
|
||||
#include <vector>
|
||||
|
||||
enum queued_canon_type {QSTRAIGHT_TRAVERSE, QSTRAIGHT_FEED, QARC_FEED, QSET_FEED_RATE, QDWELL, QSET_FEED_MODE,
|
||||
QMIST_ON, QMIST_OFF, QFLOOD_ON, QFLOOD_OFF,
|
||||
QSTART_SPINDLE_CLOCKWISE, QSTART_SPINDLE_COUNTERCLOCKWISE, QSTOP_SPINDLE_TURNING,
|
||||
QSET_SPINDLE_MODE, QSET_SPINDLE_SPEED,
|
||||
QCOMMENT, QM_USER_COMMAND,
|
||||
QORIENT_SPINDLE, QWAIT_ORIENT_SPINDLE_COMPLETE};
|
||||
|
||||
struct straight_traverse {
|
||||
int line_number;
|
||||
double dx, dy, dz; // direction of original motion
|
||||
double x,y,z, a,b,c, u,v,w;
|
||||
};
|
||||
|
||||
struct straight_feed {
|
||||
int line_number;
|
||||
double dx, dy, dz; // direction of original motion
|
||||
double x,y,z, a,b,c, u,v,w; // target
|
||||
};
|
||||
|
||||
struct arc_feed {
|
||||
int line_number;
|
||||
double original_turns;
|
||||
double end1, end2, center1, center2;
|
||||
int turn;
|
||||
double end3, a,b,c, u,v,w;
|
||||
};
|
||||
|
||||
struct set_feed_rate {
|
||||
double feed;
|
||||
};
|
||||
|
||||
struct set_feed_mode {
|
||||
int spindle;
|
||||
int mode;
|
||||
};
|
||||
|
||||
struct dwell {
|
||||
double time;
|
||||
};
|
||||
|
||||
struct set_spindle_mode {
|
||||
int spindle;
|
||||
double mode;
|
||||
};
|
||||
|
||||
struct set_spindle_speed {
|
||||
int spindle;
|
||||
double speed;
|
||||
};
|
||||
|
||||
struct comment {
|
||||
char *comment;
|
||||
};
|
||||
|
||||
struct mcommand {
|
||||
int index;
|
||||
double p_number;
|
||||
double q_number;
|
||||
};
|
||||
|
||||
struct orient_spindle {
|
||||
int spindle;
|
||||
double orientation;
|
||||
int mode;
|
||||
};
|
||||
|
||||
struct wait_orient_spindle_complete {
|
||||
int spindle;
|
||||
double timeout;
|
||||
};
|
||||
|
||||
struct queued_canon {
|
||||
queued_canon_type type;
|
||||
union {
|
||||
struct straight_traverse straight_traverse;
|
||||
struct straight_feed straight_feed;
|
||||
struct arc_feed arc_feed;
|
||||
struct set_feed_rate set_feed_rate;
|
||||
struct dwell dwell;
|
||||
struct set_feed_mode set_feed_mode;
|
||||
struct set_spindle_mode set_spindle_mode;
|
||||
struct set_spindle_speed set_spindle_speed;
|
||||
struct comment comment;
|
||||
struct mcommand mcommand;
|
||||
struct orient_spindle orient_spindle;
|
||||
struct wait_orient_spindle_complete wait_orient_spindle_complete;
|
||||
} data;
|
||||
};
|
||||
|
||||
std::vector<queued_canon>& qc(void);
|
||||
|
||||
void enqueue_SET_FEED_RATE(double feed);
|
||||
void enqueue_DWELL(double time);
|
||||
void enqueue_SET_FEED_MODE(int spindle, int mode);
|
||||
void enqueue_MIST_ON(void);
|
||||
void enqueue_MIST_OFF(void);
|
||||
void enqueue_FLOOD_ON(void);
|
||||
void enqueue_FLOOD_OFF(void);
|
||||
void enqueue_START_SPINDLE_CLOCKWISE(int spindle);
|
||||
void enqueue_START_SPINDLE_COUNTERCLOCKWISE(int spinde);
|
||||
void enqueue_STOP_SPINDLE_TURNING(int spindle);
|
||||
void enqueue_SET_SPINDLE_MODE(int spindle, double mode);
|
||||
void enqueue_SET_SPINDLE_SPEED(int spindle, double speed);
|
||||
void enqueue_COMMENT(const char *c);
|
||||
int enqueue_STRAIGHT_FEED(setup_pointer settings, int l,
|
||||
double dx, double dy, double dz,
|
||||
double x, double y, double z,
|
||||
double a, double b, double c,
|
||||
double u, double v, double w);
|
||||
int enqueue_STRAIGHT_TRAVERSE(setup_pointer settings, int l,
|
||||
double dx, double dy, double dz,
|
||||
double x, double y, double z,
|
||||
double a, double b, double c,
|
||||
double u, double v, double w);
|
||||
void enqueue_ARC_FEED(setup_pointer settings, int l,
|
||||
double original_arclen,
|
||||
double end1, double end2, double center1, double center2,
|
||||
int turn,
|
||||
double end3,
|
||||
double a, double b, double c,
|
||||
double u, double v, double w);
|
||||
void enqueue_M_USER_COMMAND(int index,double p_number,double q_number);
|
||||
void enqueue_ORIENT_SPINDLE(int spindle, double orientation, int mode);
|
||||
void enqueue_WAIT_ORIENT_SPINDLE_COMPLETE(int spindle, double timeout);
|
||||
void dequeue_canons(setup_pointer settings);
|
||||
void set_endpoint(double x, double y);
|
||||
void set_endpoint_zx(double z, double x);
|
||||
int move_endpoint_and_flush(setup_pointer settings, double x, double y);
|
||||
void qc_reset(void);
|
||||
void qc_scale(double scale);
|
||||
|
||||
#endif
|
||||
3475
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_read.cc
vendored
Normal file
3475
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_read.cc
vendored
Normal file
File diff suppressed because it is too large
Load Diff
370
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_write.cc
vendored
Normal file
370
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/interp_write.cc
vendored
Normal file
@@ -0,0 +1,370 @@
|
||||
/********************************************************************
|
||||
* Description: interp_write.cc
|
||||
*
|
||||
* Derived from a work by Thomas Kramer
|
||||
*
|
||||
* Author:
|
||||
* License: GPL Version 2
|
||||
* System: Linux
|
||||
*
|
||||
* Copyright (c) 2004 All rights reserved.
|
||||
*
|
||||
********************************************************************/
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include "rs274ngc.hh"
|
||||
#include "nml_intf/interp_return.hh"
|
||||
#include "interp_internal.hh"
|
||||
#include "rs274ngc_interp.hh"
|
||||
|
||||
/****************************************************************************/
|
||||
/*! write_g_codes
|
||||
|
||||
Returned Value: int (INTERP_OK)
|
||||
|
||||
Side effects:
|
||||
The active_g_codes in the settings are updated.
|
||||
|
||||
Called by:
|
||||
Interp::execute
|
||||
Interp::init
|
||||
|
||||
The block may be NULL.
|
||||
|
||||
This writes active g_codes into the settings->active_g_codes array by
|
||||
examining the interpreter settings. The array of actives is composed
|
||||
of ints, so (to handle codes like 59.1) all g_codes are reported as
|
||||
ints ten times the actual value. For example, 59.1 is reported as 591.
|
||||
|
||||
The correspondence between modal groups and array indexes is as follows
|
||||
(no apparent logic to it).
|
||||
|
||||
The group 0 entry is taken from the block (if there is one), since its
|
||||
codes are not modal.
|
||||
|
||||
group 0 - array[2] g4, g10, g28, g30, g53, g92 g92.1, g92.2, g92.3 - misc
|
||||
group 1 - array[1] g0, g1, g2, g3, g38.2, g80, g81, g82, g83, g84, g85,
|
||||
g86, g87, g88, g89 - motion
|
||||
group 2 - array[3] g17, g18, g19 - plane selection
|
||||
group 3 - array[6] g90, g91 - distance mode
|
||||
group 4 - array[14] g90.1, g91.1 - IJK distance mode for arcs
|
||||
group 5 - array[7] g93, g94, g95 - feed rate mode
|
||||
group 6 - array[5] g20, g21 - units
|
||||
group 7 - array[4] g40, g41, g42 - cutter radius compensation
|
||||
group 8 - array[9] g43, g49 - tool length offset
|
||||
group 9 - no such group
|
||||
group 10 - array[10] g98, g99 - return mode in canned cycles
|
||||
group 11 - no such group
|
||||
group 12 - array[8] g54, g55, g56, g57, g58, g59, g59.1, g59.2, g59.3
|
||||
- coordinate system
|
||||
group 13 - array[11] g61, g61.1, g64 - control mode
|
||||
group 14 - array[12] g50, g51 - adaptive feed mode
|
||||
group 15 - array[13] g96, g97 - spindle speed mode
|
||||
group 16 - array[15] g7,g8 - lathe diameter mode
|
||||
|
||||
*/
|
||||
|
||||
int Interp::write_g_codes(block_pointer block, //!< pointer to a block of RS274/NGC instructions
|
||||
setup_pointer settings) //!< pointer to machine settings
|
||||
{
|
||||
settings->active_g_codes[0] = settings->sequence_number;
|
||||
settings->active_g_codes[1] = settings->motion_mode;
|
||||
settings->active_g_codes[2] = ((block == NULL) ? -1 : block->g_modes[GM_MODAL_0]);
|
||||
switch(settings->plane) {
|
||||
case CANON_PLANE::XY:
|
||||
settings->active_g_codes[3] = G_17;
|
||||
break;
|
||||
case CANON_PLANE::XZ:
|
||||
settings->active_g_codes[3] = G_18;
|
||||
break;
|
||||
case CANON_PLANE::YZ:
|
||||
settings->active_g_codes[3] = G_19;
|
||||
break;
|
||||
case CANON_PLANE::UV:
|
||||
settings->active_g_codes[3] = G_17_1;
|
||||
break;
|
||||
case CANON_PLANE::UW:
|
||||
settings->active_g_codes[3] = G_18_1;
|
||||
break;
|
||||
case CANON_PLANE::VW:
|
||||
settings->active_g_codes[3] = G_19_1;
|
||||
break;
|
||||
}
|
||||
settings->active_g_codes[4] =
|
||||
(settings->cutter_comp_side == CUTTER_COMP::RIGHT) ? G_42 :
|
||||
(settings->cutter_comp_side == CUTTER_COMP::LEFT) ? G_41 : G_40;
|
||||
settings->active_g_codes[5] = (settings->length_units == CANON_UNITS_INCHES) ? G_20 : G_21;
|
||||
settings->active_g_codes[6] = (settings->distance_mode == DISTANCE_MODE::ABSOLUTE) ? G_90 : G_91;
|
||||
settings->active_g_codes[7] = (settings->feed_mode == FEED_MODE::INVERSE_TIME) ? G_93 :
|
||||
(settings->feed_mode == FEED_MODE::UNITS_PER_MINUTE) ? G_94 : G_95;
|
||||
settings->active_g_codes[8] =
|
||||
(settings->origin_index <
|
||||
7) ? (530 + (10 * settings->origin_index)) : (584 +
|
||||
settings->origin_index);
|
||||
settings->active_g_codes[9] =
|
||||
(settings->g43_with_zero_offset ||
|
||||
settings->tool_offset.tran.x || settings->tool_offset.tran.y || settings->tool_offset.tran.z ||
|
||||
settings->tool_offset.a || settings->tool_offset.b || settings->tool_offset.c ||
|
||||
settings->tool_offset.u || settings->tool_offset.v || settings->tool_offset.w) ? G_43 : G_49;
|
||||
settings->active_g_codes[10] = (settings->retract_mode == RETRACT_MODE::OLD_Z) ? G_98 : G_99;
|
||||
// Three modes: G_64, G_61, G_61_1 or CANON_CONTINUOUS/EXACT_PATH/EXACT_STOP
|
||||
settings->active_g_codes[11] =
|
||||
(settings->control_mode == CANON_CONTINUOUS) ? G_64 :
|
||||
(settings->control_mode == CANON_EXACT_PATH) ? G_61 : G_61_1;
|
||||
settings->active_g_codes[12] = -1;
|
||||
settings->active_g_codes[13] = //I don't even know how to display the mode of an arbitrary number of spindles (andypugh 17/6/16)
|
||||
(settings->spindle_mode[0] == SPINDLE_MODE::CONSTANT_RPM) ? G_97 : G_96;
|
||||
settings->active_g_codes[14] = (settings->ijk_distance_mode == DISTANCE_MODE::ABSOLUTE) ? G_90_1 : G_91_1;
|
||||
settings->active_g_codes[15] = (settings->lathe_diameter_mode) ? G_7 : G_8;
|
||||
// 'G52','G92' are handled in modal group 0 which is cleared on startup, m2/m30 and abort, hence there
|
||||
// is no indication of active G92 offsets after such events so we need modal group 16 as a workaround
|
||||
if (block == NULL){ // this handles config startup
|
||||
if (settings->parameters[5210] == 1){
|
||||
settings->active_g_codes[16] = G_92_3;
|
||||
} else {
|
||||
settings->active_g_codes[16] = -1;
|
||||
}
|
||||
} else if (settings->parameters[5210] == 1 && block->g_modes[GM_MODAL_0] == -1){ // this handles aborts, m2/m30
|
||||
settings->active_g_codes[16] = G_92_3;
|
||||
} else {
|
||||
settings->active_g_codes[16] = block->g_modes[GM_G92_IS_APPLIED];
|
||||
}
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*! write_m_codes
|
||||
|
||||
Returned Value: int (INTERP_OK)
|
||||
|
||||
Side effects:
|
||||
The settings->active_m_codes are updated.
|
||||
|
||||
Called by:
|
||||
Interp::execute
|
||||
Interp::init
|
||||
|
||||
This is testing only the feed override to see if overrides is on.
|
||||
Might add check of speed override.
|
||||
|
||||
*/
|
||||
|
||||
int Interp::write_m_codes(block_pointer block, //!< pointer to a block of RS274/NGC instructions
|
||||
setup_pointer settings) //!< pointer to machine settings
|
||||
{
|
||||
settings->active_m_codes[0] = settings->sequence_number; /* 0 seq number */
|
||||
settings->active_m_codes[1] = (block == NULL) ? -1 : block->m_modes[4]; /* 1 stopping */
|
||||
settings->active_m_codes[2] = (settings->spindle_turning[0] == CANON_STOPPED) ? 5 : /* 2 spindle */
|
||||
(settings->spindle_turning[0] == CANON_CLOCKWISE) ? 3 : 4;
|
||||
settings->active_m_codes[3] = /* 3 tool change */
|
||||
(block == NULL) ? -1 : block->m_modes[6];
|
||||
settings->active_m_codes[4] = /* 4 mist */
|
||||
(settings->mist) ? 7 : (settings->flood) ? -1 : 9;
|
||||
settings->active_m_codes[5] = /* 5 flood */
|
||||
(settings->flood) ? 8 : -1;
|
||||
// This only considers spindle 0. This function //
|
||||
//doesn't even know how many spindles there are //
|
||||
if (settings->feed_override) {
|
||||
if (settings->speed_override[0]) settings->active_m_codes[6] = 48;
|
||||
else settings->active_m_codes[6] = 50;
|
||||
} else if (settings->speed_override[0]) {
|
||||
settings->active_m_codes[6] = 51;
|
||||
} else settings->active_m_codes[6] = 49;
|
||||
|
||||
settings->active_m_codes[7] = /* 7 overrides */
|
||||
(settings->adaptive_feed) ? 52 : -1;
|
||||
|
||||
settings->active_m_codes[8] = /* 8 overrides */
|
||||
(settings->feed_hold) ? 53 : -1;
|
||||
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*! write_settings
|
||||
|
||||
Returned Value: int (INTERP_OK)
|
||||
|
||||
Side effects:
|
||||
The settings->active_settings array of doubles is updated with the
|
||||
sequence number, feed, and speed settings.
|
||||
|
||||
Called by:
|
||||
Interp::execute
|
||||
Interp::init
|
||||
|
||||
*/
|
||||
|
||||
int Interp::write_settings(setup_pointer settings) //!< pointer to machine settings
|
||||
{
|
||||
settings->active_settings[0] = settings->sequence_number; /* 0 sequence number */
|
||||
settings->active_settings[1] = settings->feed_rate; /* 1 feed rate */
|
||||
settings->active_settings[2] = settings->speed[0]; /* 2 spindle speed */
|
||||
settings->active_settings[3] = settings->tolerance; /* 3 blend tolerance */
|
||||
settings->active_settings[4] = settings->naivecam_tolerance; /* 4 naive CAM tolerance */
|
||||
|
||||
return INTERP_OK;
|
||||
}
|
||||
|
||||
int Interp::write_state_tag(block_pointer block,
|
||||
setup_pointer settings,
|
||||
StateTag &state)
|
||||
{
|
||||
|
||||
state.fields[GM_FIELD_LINE_NUMBER] = settings->sequence_number;
|
||||
//FIXME refactor these into setup methods, and maybe put this
|
||||
//whole method in setup struct
|
||||
bool in_remap = (settings->remap_level > 0);
|
||||
bool in_sub = (settings->call_level > 0 && settings->remap_level == 0);
|
||||
bool external_sub = strcmp(settings->filename,
|
||||
settings->sub_context[0].filename);
|
||||
strncpy(state.filename, settings->filename, sizeof(state.filename));
|
||||
state.filename[sizeof(state.filename)-1] = 0;
|
||||
|
||||
state.flags[GM_FLAG_IN_REMAP] = in_remap;
|
||||
state.flags[GM_FLAG_IN_SUB] = in_sub;
|
||||
state.flags[GM_FLAG_EXTERNAL_FILE] = external_sub;
|
||||
state.flags[GM_FLAG_RESTORABLE] = !in_remap && !in_sub;
|
||||
state.fields[GM_FIELD_G_MODE_0] =
|
||||
((block == NULL) ? -1 : block->g_modes[GM_MODAL_0]);
|
||||
state.fields[GM_FIELD_MOTION_MODE] = settings->motion_mode;
|
||||
switch(settings->plane) {
|
||||
case CANON_PLANE::XY:
|
||||
state.fields[GM_FIELD_PLANE] = G_17;
|
||||
break;
|
||||
case CANON_PLANE::XZ:
|
||||
state.fields[GM_FIELD_PLANE] = G_18;
|
||||
break;
|
||||
case CANON_PLANE::YZ:
|
||||
state.fields[GM_FIELD_PLANE] = G_19;
|
||||
break;
|
||||
case CANON_PLANE::UV:
|
||||
state.fields[GM_FIELD_PLANE] = G_17_1;
|
||||
break;
|
||||
case CANON_PLANE::UW:
|
||||
state.fields[GM_FIELD_PLANE] = G_18_1;
|
||||
break;
|
||||
case CANON_PLANE::VW:
|
||||
state.fields[GM_FIELD_PLANE] = G_19_1;
|
||||
break;
|
||||
}
|
||||
|
||||
state.fields[GM_FIELD_CUTTER_COMP] =
|
||||
(settings->cutter_comp_side == CUTTER_COMP::RIGHT) ? G_42 :
|
||||
(settings->cutter_comp_side == CUTTER_COMP::LEFT) ? G_41 : G_40;
|
||||
|
||||
state.flags[GM_FLAG_UNITS] =
|
||||
(settings->length_units == CANON_UNITS_INCHES);
|
||||
|
||||
state.flags[GM_FLAG_DISTANCE_MODE] =
|
||||
(settings->distance_mode == DISTANCE_MODE::ABSOLUTE);
|
||||
state.flags[GM_FLAG_FEED_INVERSE_TIME] =
|
||||
(settings->feed_mode == FEED_MODE::INVERSE_TIME);
|
||||
state.flags[GM_FLAG_FEED_UPM] =
|
||||
(settings->feed_mode == FEED_MODE::UNITS_PER_MINUTE);
|
||||
|
||||
|
||||
state.fields[GM_FIELD_ORIGIN] =
|
||||
((settings->origin_index < 7) ?
|
||||
(530 + (10 * settings->origin_index)) :
|
||||
(584 + settings->origin_index));
|
||||
|
||||
state.flags[GM_FLAG_G92_IS_APPLIED] = settings->parameters[5210];
|
||||
|
||||
state.flags[GM_FLAG_TOOL_OFFSETS_ON] =
|
||||
(settings->g43_with_zero_offset ||
|
||||
settings->tool_offset.tran.x ||
|
||||
settings->tool_offset.tran.y ||
|
||||
settings->tool_offset.tran.z ||
|
||||
settings->tool_offset.a ||
|
||||
settings->tool_offset.b ||
|
||||
settings->tool_offset.c ||
|
||||
settings->tool_offset.u ||
|
||||
settings->tool_offset.v ||
|
||||
settings->tool_offset.w);
|
||||
state.flags[GM_FLAG_RETRACT_OLDZ] =
|
||||
(settings->retract_mode == RETRACT_MODE::OLD_Z);
|
||||
|
||||
state.flags[GM_FLAG_BLEND] =
|
||||
(settings->control_mode == CANON_CONTINUOUS);
|
||||
state.flags[GM_FLAG_EXACT_STOP] =
|
||||
(settings->control_mode == CANON_EXACT_STOP);
|
||||
state.fields_float[GM_FIELD_FLOAT_PATH_TOLERANCE] =
|
||||
settings->tolerance;
|
||||
state.fields_float[GM_FIELD_FLOAT_NAIVE_CAM_TOLERANCE] =
|
||||
settings->naivecam_tolerance;
|
||||
|
||||
state.flags[GM_FLAG_CSS_MODE] =
|
||||
(settings->spindle_mode[0] == SPINDLE_MODE::CONSTANT_RPM);
|
||||
state.flags[GM_FLAG_IJK_ABS] =
|
||||
(settings->ijk_distance_mode == DISTANCE_MODE::ABSOLUTE);
|
||||
state.flags[GM_FLAG_DIAMETER_MODE] =
|
||||
(settings->lathe_diameter_mode);
|
||||
|
||||
|
||||
state.fields[GM_FIELD_M_MODES_4] =
|
||||
(block == NULL) ? -1 : block->m_modes[4];
|
||||
|
||||
state.flags[GM_FLAG_SPINDLE_ON] =
|
||||
(settings->spindle_turning[0] != CANON_STOPPED);
|
||||
state.flags[GM_FLAG_SPINDLE_CW] =
|
||||
(settings->spindle_turning[0] == CANON_CLOCKWISE);
|
||||
|
||||
state.fields[GM_FIELD_TOOLCHANGE] =
|
||||
(block == NULL) ? -1 : block->m_modes[6];
|
||||
|
||||
state.flags[GM_FLAG_MIST] = (settings->mist) ;
|
||||
state.flags[GM_FLAG_FLOOD] = (settings->flood);
|
||||
|
||||
state.flags[GM_FLAG_FEED_OVERRIDE] = settings->feed_override;
|
||||
state.flags[GM_FLAG_SPEED_OVERRIDE] = settings->speed_override[0];
|
||||
|
||||
state.flags[GM_FLAG_ADAPTIVE_FEED] = (settings->adaptive_feed);
|
||||
|
||||
state.flags[GM_FLAG_FEED_HOLD] = (settings->feed_hold);
|
||||
|
||||
state.fields_float[GM_FIELD_FLOAT_FEED] = settings->feed_rate;
|
||||
state.fields_float[GM_FIELD_FLOAT_SPEED] = settings->speed[0];
|
||||
|
||||
// Pack new geometric data. block is NULL on the M70 save path
|
||||
// (save_settings() in interp_convert.cc), so guard against null deref.
|
||||
if(nullptr != block){
|
||||
state.fields_float[GM_FIELD_FLOAT_STRAIGHT_HEADING] = block->arc_heading;
|
||||
state.fields_float[GM_FIELD_FLOAT_ARC_RADIUS] = block->arc_radius;
|
||||
state.fields_float[GM_FIELD_FLOAT_ARC_CENTER_X] = block->arc_center_x;
|
||||
state.fields_float[GM_FIELD_FLOAT_ARC_CENTER_Y] = block->arc_center_y;
|
||||
state.fields_float[GM_FIELD_FLOAT_ARC_CENTER_Z] = block->arc_center_z;
|
||||
state.fields_float[GM_FIELD_FLOAT_NORMAL_HEADING] = block->normal_heading;
|
||||
state.flags[GM_FLAG_IS_CIRCLE] = block->iscircle;
|
||||
}
|
||||
else{
|
||||
state.fields_float[GM_FIELD_FLOAT_STRAIGHT_HEADING] = 0.0;
|
||||
state.fields_float[GM_FIELD_FLOAT_ARC_RADIUS] = 0.0;
|
||||
state.fields_float[GM_FIELD_FLOAT_ARC_CENTER_X] = 0.0;
|
||||
state.fields_float[GM_FIELD_FLOAT_ARC_CENTER_Y] = 0.0;
|
||||
state.fields_float[GM_FIELD_FLOAT_ARC_CENTER_Z] = 0.0;
|
||||
state.fields_float[GM_FIELD_FLOAT_NORMAL_HEADING] = 0.0;
|
||||
state.flags[GM_FLAG_IS_CIRCLE] = false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Interp::write_canon_state_tag(block_pointer block, setup_pointer settings)
|
||||
{
|
||||
StateTag tag;
|
||||
write_state_tag(block, settings, tag);
|
||||
update_tag(tag);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
70
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/modal_state.cc
vendored
Normal file
70
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/modal_state.cc
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
/********************************************************************
|
||||
* Description: modal_state.cc
|
||||
*
|
||||
* State storage class for interpreter
|
||||
*
|
||||
* Copyright © 2014 Robert W. Ellenberg
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
********************************************************************/
|
||||
#include "interp_base.hh"
|
||||
#include "modal_state.hh"
|
||||
#include <string.h>
|
||||
|
||||
StateTag::StateTag(): flags(0)
|
||||
{
|
||||
memset(fields,-1,sizeof(fields));
|
||||
packed_flags = 0;
|
||||
memset(fields_float,-1,sizeof(fields_float));
|
||||
memset(filename, 0, sizeof(filename));
|
||||
}
|
||||
|
||||
StateTag::StateTag(struct state_tag_t const & basetag):
|
||||
state_tag_t(basetag), flags(basetag.packed_flags)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Return true if the tag is a valid state, and false if not
|
||||
*/
|
||||
int StateTag::is_valid(void) const
|
||||
{
|
||||
|
||||
if (fields[GM_FIELD_LINE_NUMBER] <= 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//TODO magic numbers
|
||||
if (fields[GM_FIELD_ORIGIN] < 540) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fields[GM_FIELD_PLANE] < 170 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the C-equivalent state_tag version of the current state.
|
||||
*/
|
||||
state_tag_t StateTag::get_state_tag() const
|
||||
{
|
||||
state_tag_t out = static_cast<state_tag_t> (*this);
|
||||
out.packed_flags = flags.to_ulong();
|
||||
return out;
|
||||
}
|
||||
|
||||
53
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/modal_state.hh
vendored
Normal file
53
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/modal_state.hh
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
/********************************************************************
|
||||
* Description: modal_state.hh
|
||||
*
|
||||
* State storage class for interpreter
|
||||
*
|
||||
* Copyright © 2014 Robert W. Ellenberg
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
********************************************************************/
|
||||
|
||||
#ifndef MODAL_STATE_HH
|
||||
#define MODAL_STATE_HH
|
||||
#include <vector>
|
||||
#include <bitset>
|
||||
|
||||
// Bring in C struct for a state tag from motion
|
||||
extern "C" {
|
||||
#include "motion/state_tag.h"
|
||||
}
|
||||
|
||||
/**
|
||||
* C++ version of state_tag_t structure to stuff interp state info in
|
||||
* a motion message. Previously, this information was stored only in
|
||||
* the interpreter, and as vectors of g codes, m codes, and
|
||||
* settings. Considering that the write_XXX and gen_XXX functions had
|
||||
* to jump through hoops to translate from a settings struct, the
|
||||
* extra packing here isn't much more complex to deal with, and will
|
||||
* cost much less space in an NML message.
|
||||
*
|
||||
* Using this class means we can work with a bitset instead of raw
|
||||
* bitmasking operations. Also, because we're inheriting from the C
|
||||
* struct, copy / assignment is valid.
|
||||
*/
|
||||
struct StateTag : public state_tag_t {
|
||||
StateTag();
|
||||
StateTag(state_tag_t const &basetag);
|
||||
std::bitset<64> flags;
|
||||
int is_valid(void) const;
|
||||
state_tag_t get_state_tag() const;
|
||||
};
|
||||
#endif
|
||||
82
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/rs274ngc.hh
vendored
Normal file
82
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/rs274ngc.hh
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
/********************************************************************
|
||||
* Description: rs274ngc.hh
|
||||
*
|
||||
* Derived from a work by Thomas Kramer
|
||||
*
|
||||
* Author:
|
||||
* License: GPL Version 2
|
||||
* System: Linux
|
||||
*
|
||||
* Copyright (c) 2004 All rights reserved.
|
||||
*
|
||||
********************************************************************/
|
||||
#ifndef RS274NGC_HH
|
||||
#define RS274NGC_HH
|
||||
|
||||
#include "interp_base.hh"
|
||||
|
||||
|
||||
|
||||
/**********************/
|
||||
/* INCLUDE DIRECTIVES */
|
||||
/**********************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "nml_intf/canon.hh"
|
||||
#include "nml_intf/emc.hh"
|
||||
#include "nml_intf/debugflags.h"
|
||||
#include "interp_fwd.hh"
|
||||
|
||||
// Declare class so that we can use it in the typedef.
|
||||
class Interp;
|
||||
typedef int (Interp::*read_function_pointer) (char *, int *, block_pointer, double *);
|
||||
|
||||
#define DBG(level,fmt,args...) \
|
||||
do { \
|
||||
if (level < _setup.loggingLevel) { \
|
||||
fprintf(stderr,fmt, ## args); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// print to if RS274NGC/LOG_LEVEL > 1:
|
||||
|
||||
#define MSG(fmt,args...) \
|
||||
do { \
|
||||
DBG(0, fmt, ##args); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#undef DEBUG_EMC
|
||||
|
||||
|
||||
#define _logDebug(mask,dlflags,level, fmt, args...) \
|
||||
do { \
|
||||
if (((mask & _setup.debugmask) && \
|
||||
(level < _setup.loggingLevel)) || \
|
||||
(mask & EMC_DEBUG_UNCONDITIONAL)) { \
|
||||
doLog(dlflags, \
|
||||
__FILE__, \
|
||||
__LINE__ , \
|
||||
fmt "\n", \
|
||||
## args); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
//#define logDebug(fmt, args...) _logDebug(EMC_DEBUG_INTERP,LOG_FILENAME,1,fmt, ## args)
|
||||
#define logDebug(fmt, args...) _logDebug(EMC_DEBUG_INTERP,0,1,fmt, ## args)
|
||||
|
||||
#define logConfig(fmt, args...) _logDebug(EMC_DEBUG_CONFIG,0,1,fmt, ## args)
|
||||
#define logOword(fmt, args...) _logDebug(EMC_DEBUG_OWORD,0,1,fmt, ## args)
|
||||
#define logRemap(fmt, args...) _logDebug(EMC_DEBUG_REMAP,0,1,fmt, ## args)
|
||||
#define logPy(fmt, args...) _logDebug(EMC_DEBUG_PYTHON,0,1,fmt, ## args)
|
||||
#define logNP(fmt, args...) _logDebug(EMC_DEBUG_NAMEDPARAM,0,1,fmt, ## args)
|
||||
#define logStateTags(fmt, args...) \
|
||||
_logDebug(EMC_DEBUG_STATE_TAGS,0,1,fmt, ## args)
|
||||
|
||||
// log always
|
||||
#define Log(fmt, args...) _logDebug(EMC_DEBUG_UNCONDITIONAL,LOG_PID|LOG_FILENAME,-1,fmt, ## args)
|
||||
#define Error(fmt, args...) _logDebug(EMC_DEBUG_UNCONDITIONAL,0,-1,fmt, ## args)
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
701
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/rs274ngc_interp.hh
vendored
Normal file
701
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/rs274ngc_interp.hh
vendored
Normal file
@@ -0,0 +1,701 @@
|
||||
// Copyright 2009-2011, various authors
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
#ifndef RS274NGC_INTERP_H
|
||||
#define RS274NGC_INTERP_H
|
||||
#include "rs274ngc.hh"
|
||||
#include "interp_internal.hh"
|
||||
#include "nml_intf/interp_return.hh"
|
||||
|
||||
class Interp : public InterpBase {
|
||||
|
||||
public:
|
||||
Interp();
|
||||
~Interp() override;
|
||||
|
||||
/* Interface functions to call to tell the interpreter what to do.
|
||||
Return values indicate status of execution.
|
||||
These functions may change the state of the interpreter. */
|
||||
|
||||
// close the currently open NC code file
|
||||
int close() override;
|
||||
|
||||
// execute a line of NC code
|
||||
int execute(const char *command) override;
|
||||
int execute() override;
|
||||
|
||||
int execute(const char *command, int line_no) override; //used for MDI calls to specify the pseudo MDI line number
|
||||
|
||||
// stop running
|
||||
int exit() override;
|
||||
|
||||
// get ready to run
|
||||
int init() override;
|
||||
void set_loop_on_main_m99(bool state) override;
|
||||
|
||||
// load a tool table
|
||||
int load_tool_table();
|
||||
|
||||
// open a file of NC code
|
||||
int open(const char *filename) override;
|
||||
|
||||
// read the mdi or the next line of the open NC code file
|
||||
int read(const char *mdi) override;
|
||||
int read() override;
|
||||
|
||||
// reset yourself
|
||||
int reset() override;
|
||||
|
||||
// restore interpreter variables from a file
|
||||
int restore_parameters(const char *filename);
|
||||
|
||||
// save interpreter variables to file
|
||||
int save_parameters(const char *filename,
|
||||
const double parameters[]);
|
||||
|
||||
// synchronize your internal model with the external world
|
||||
int synch() override;
|
||||
|
||||
/* Interface functions to call to get information from the interpreter.
|
||||
If a function has a return value, the return value contains the information.
|
||||
If a function returns nothing, information is copied into one of the
|
||||
arguments to the function. These functions do not change the state of
|
||||
the interpreter. */
|
||||
|
||||
// copy active G-codes into array [0]..[15]
|
||||
void active_g_codes(int *codes) override;
|
||||
|
||||
// copy active M-codes into array [0]..[9]
|
||||
void active_m_codes(int *codes) override;
|
||||
|
||||
// copy active F, S settings into array [0]..[2]
|
||||
void active_settings(double *settings) override;
|
||||
|
||||
// Update the state vectors from a state tag
|
||||
int active_modes(int *g_codes,
|
||||
int *mcodes,
|
||||
double *settings,
|
||||
StateTag const &tag) override;
|
||||
|
||||
// Print contents of state tag for debugging
|
||||
void print_state_tag(StateTag const &tag) override;
|
||||
|
||||
// copy the text of the error message whose number is error_code into the
|
||||
// error_text array, but stop at max_size if the text is longer.
|
||||
char *error_text(int error_code, char *error_text,
|
||||
size_t max_size) override;
|
||||
|
||||
void setError(const char *fmt, ...) __attribute__((format(printf,2,3)));
|
||||
|
||||
// copy the name of the currently open file into the file_name array,
|
||||
// but stop at max_size if the name is longer
|
||||
char *file_name(char *file_name, size_t max_size) override;
|
||||
|
||||
// return the length of the most recently read line
|
||||
size_t line_length() override;
|
||||
|
||||
// copy the text of the most recently read line into the line_text array,
|
||||
// but stop at max_size if the text is longer
|
||||
char *line_text(char *line_text, size_t max_size) override;
|
||||
|
||||
// return the current sequence number (how many lines read)
|
||||
int sequence_number() override;
|
||||
|
||||
// copy the function name from the stack_index'th position of the
|
||||
// function call stack at the time of the most recent error into
|
||||
// the function name string, but stop at max_size if the name is longer
|
||||
char *stack_name(int stack_index, char *function_name,
|
||||
size_t max_size) override;
|
||||
|
||||
// Get the parameter file name from the INI file.
|
||||
int ini_load(const char *filename) override;
|
||||
|
||||
int line() override { return sequence_number(); }
|
||||
int call_level() override;
|
||||
|
||||
char *command(char *buf, size_t len) override { line_text(buf, len); return buf; }
|
||||
|
||||
char *file(char *buf, size_t len) override { file_name(buf, len); return buf; }
|
||||
|
||||
int init_tool_parameters();
|
||||
int default_tool_parameters();
|
||||
int set_tool_parameters();
|
||||
|
||||
int on_abort(int reason, const char *message) override;
|
||||
|
||||
void set_loglevel(int level) override;
|
||||
|
||||
// for now, public - for boost.python access
|
||||
int find_named_param(const char *nameBuf, int *status, double *value);
|
||||
int store_named_param(setup_pointer settings,const char *nameBuf, double value, int override_readonly = 0);
|
||||
int add_named_param(const char *nameBuf, int attr = 0);
|
||||
int fetch_ini_param( const char *nameBuf, int *status, double *value);
|
||||
int fetch_hal_param( const char *nameBuf, int *status, double *value);
|
||||
double inicheck();
|
||||
|
||||
// common combination of add_named_param and store_named_param
|
||||
// int assign_named_param(const char *nameBuf, int attr = 0, double value = 0.0);
|
||||
remap_pointer remapping(const char *code);
|
||||
remap_pointer remapping(const char letter, int number = -1);
|
||||
int find_tool_pocket(setup_pointer settings, int toolno, int *pocket);
|
||||
int find_tool_index(setup_pointer settings, int toolno, int *index);
|
||||
|
||||
/* Function prototypes for all functions */
|
||||
|
||||
int arc_data_comp_ijk(int move,
|
||||
CANON_PLANE plane,
|
||||
CUTTER_COMP side,
|
||||
double tool_radius,
|
||||
double current_x,
|
||||
double current_y,
|
||||
double end_x,
|
||||
double end_y,
|
||||
int ij_absolute,
|
||||
double i_number,
|
||||
double j_number,
|
||||
int p_number,
|
||||
double *center_x,
|
||||
double *center_y,
|
||||
int *turn,
|
||||
double radius_tolerance,
|
||||
double spiral_abs_tolerance,
|
||||
double spiral_rel_tolerance);
|
||||
|
||||
int arc_data_comp_r(int move,
|
||||
CANON_PLANE plane,
|
||||
CUTTER_COMP side,
|
||||
double tool_radius,
|
||||
double current_x,
|
||||
double current_y,
|
||||
double end_x,
|
||||
double end_y,
|
||||
double big_radius,
|
||||
int p_number,
|
||||
double *center_x,
|
||||
double *center_y,
|
||||
int *turn,
|
||||
double radius_tolerance);
|
||||
|
||||
int arc_data_ijk(int move,
|
||||
CANON_PLANE plane,
|
||||
double current_x,
|
||||
double current_y,
|
||||
double end_x,
|
||||
double end_y,
|
||||
int ij_absolute,
|
||||
double i_number,
|
||||
double j_number,
|
||||
int p_number,
|
||||
double *center_x,
|
||||
double *center_y,
|
||||
int *turn,
|
||||
double radius_tolerance,
|
||||
double spiral_abs_tolerance,
|
||||
double spiral_rel_tolerance);
|
||||
|
||||
int arc_data_r(int move,
|
||||
CANON_PLANE plane,
|
||||
double current_x,
|
||||
double current_y,
|
||||
double end_x,
|
||||
double end_y,
|
||||
double radius,
|
||||
int p_number,
|
||||
double *center_x,
|
||||
double *center_y,
|
||||
int *turn,
|
||||
double radius_tolerance);
|
||||
int check_g_codes(block_pointer block, setup_pointer settings);
|
||||
int check_items(block_pointer block, setup_pointer settings);
|
||||
int check_m_codes(block_pointer block);
|
||||
int check_other_codes(block_pointer block);
|
||||
int close_and_downcase(char *line);
|
||||
void nurbs_reset_global_variables(void);
|
||||
int convert_nurbs(int move, block_pointer block, setup_pointer settings);
|
||||
int convert_spline(int move, block_pointer block, setup_pointer settings);
|
||||
int convert_g7x(int move, block_pointer block, setup_pointer settings);
|
||||
int comp_get_current(setup_pointer settings, double *x, double *y, double *z);
|
||||
int comp_set_current(setup_pointer settings, double x, double y, double z);
|
||||
int comp_get_programmed(setup_pointer settings, double *x, double *y, double *z);
|
||||
int comp_set_programmed(setup_pointer settings, double x, double y, double z);
|
||||
int convert_arc(int move, block_pointer block, setup_pointer settings);
|
||||
int convert_arc2(int move, block_pointer block,
|
||||
setup_pointer settings,
|
||||
double *current1, double *current2, double *current3,
|
||||
double end1, double end2, double end3,
|
||||
double AA_end, double BB_end, double CC_end,
|
||||
double u_end, double v_end, double w_end,
|
||||
double offset1, double offset2);
|
||||
|
||||
int convert_arc_comp1(int move, block_pointer block,
|
||||
setup_pointer settings,
|
||||
double end_x, double end_y, double end_z,
|
||||
double offset_x, double offset_y,
|
||||
double AA_end, double BB_end, double CC_end,
|
||||
double u_end, double v_end, double w_end);
|
||||
|
||||
int convert_arc_comp2(int move, block_pointer block,
|
||||
setup_pointer settings,
|
||||
double end_x, double end_y, double end_z,
|
||||
double offset_x, double offset_y,
|
||||
double AA_end, double BB_end, double CC_end,
|
||||
double u_end, double v_end, double w_end);
|
||||
char arc_axis1(CANON_PLANE plane);
|
||||
char arc_axis2(CANON_PLANE plane);
|
||||
int convert_axis_offsets(int g_code, block_pointer block,
|
||||
setup_pointer settings);
|
||||
int convert_param_comment(char *comment, char *expanded, int len);
|
||||
int convert_comment(char *comment, bool enqueue = true);
|
||||
int convert_control_mode(int g_code, double tolerance, double naivecam_tolerance, setup_pointer settings);
|
||||
int convert_adaptive_mode(int g_code, setup_pointer settings);
|
||||
|
||||
int convert_coordinate_system(int g_code, setup_pointer settings);
|
||||
int convert_cutter_compensation(int g_code, block_pointer block,
|
||||
setup_pointer settings);
|
||||
int convert_cutter_compensation_off(setup_pointer settings);
|
||||
int convert_cutter_compensation_on(CUTTER_COMP side, block_pointer block,
|
||||
setup_pointer settings);
|
||||
int convert_cycle(int motion, block_pointer block,
|
||||
setup_pointer settings);
|
||||
int convert_cycle_g81(block_pointer block, CANON_PLANE plane, double x, double y,
|
||||
double clear_z, double bottom_z);
|
||||
int convert_cycle_g82(block_pointer block, CANON_PLANE plane, double x, double y,
|
||||
double clear_z, double bottom_z, double dwell);
|
||||
int convert_cycle_g73(block_pointer block, CANON_PLANE plane, double x, double y,
|
||||
double r, double clear_z, double bottom_z,
|
||||
double delta);
|
||||
int convert_cycle_g83(block_pointer block, CANON_PLANE plane, double x, double y,
|
||||
double r, double clear_z, double bottom_z,
|
||||
double delta);
|
||||
int convert_cycle_g74_g84(block_pointer block, CANON_PLANE plane, double x, double y,
|
||||
double clear_z, double bottom_z,
|
||||
CANON_DIRECTION direction, CANON_SPEED_FEED_MODE mode,
|
||||
int motion, double dwell, int spindle);
|
||||
int convert_cycle_g85(block_pointer block, CANON_PLANE plane, double x, double y,
|
||||
double r, double clear_z, double bottom_z);
|
||||
int convert_cycle_g86(block_pointer block, CANON_PLANE plane, double x, double y,
|
||||
double clear_z, double bottom_z, double dwell,
|
||||
CANON_DIRECTION direction, int spindle);
|
||||
int convert_cycle_g87(block_pointer block, CANON_PLANE plane, double x, double offset_x,
|
||||
double y, double offset_y, double r,
|
||||
double clear_z, double middle_z, double bottom_z,
|
||||
CANON_DIRECTION direction, int spindle);
|
||||
int convert_cycle_g88(block_pointer block, CANON_PLANE plane, double x, double y,
|
||||
double bottom_z, double dwell,
|
||||
CANON_DIRECTION direction, int spindle);
|
||||
int convert_cycle_g89(block_pointer block, CANON_PLANE plane, double x, double y,
|
||||
double clear_z, double bottom_z, double dwell);
|
||||
int convert_cycle_xy(int motion, block_pointer block,
|
||||
setup_pointer settings);
|
||||
int convert_cycle_yz(int motion, block_pointer block,
|
||||
setup_pointer settings);
|
||||
int convert_cycle_zx(int motion, block_pointer block,
|
||||
setup_pointer settings);
|
||||
int convert_cycle_uv(int motion, block_pointer block,
|
||||
setup_pointer settings);
|
||||
int convert_cycle_vw(int motion, block_pointer block,
|
||||
setup_pointer settings);
|
||||
int convert_cycle_wu(int motion, block_pointer block,
|
||||
setup_pointer settings);
|
||||
int convert_distance_mode(int g_code, setup_pointer settings);
|
||||
int convert_ijk_distance_mode(int g_code, setup_pointer settings);
|
||||
int convert_lathe_diameter_mode(int g_code, block_pointer block, setup_pointer settings);
|
||||
int convert_dwell(setup_pointer settings, double time);
|
||||
int convert_feed_mode(int g_code, setup_pointer settings);
|
||||
int convert_feed_rate(block_pointer block, setup_pointer settings);
|
||||
int convert_g(block_pointer block, setup_pointer settings);
|
||||
int convert_home(int move, block_pointer block,
|
||||
setup_pointer settings);
|
||||
int convert_savehome(int move, block_pointer block,
|
||||
setup_pointer settings);
|
||||
int convert_length_units(int g_code, setup_pointer settings);
|
||||
int convert_m(block_pointer block, setup_pointer settings);
|
||||
int convert_modal_0(int code, block_pointer block,
|
||||
setup_pointer settings);
|
||||
int convert_g92_is_applied(int code, block_pointer block, setup_pointer settings);
|
||||
int convert_motion(int motion, block_pointer block,
|
||||
setup_pointer settings);
|
||||
int convert_probe(block_pointer block, int g_code, setup_pointer settings);
|
||||
int convert_retract_mode(int g_code, setup_pointer settings);
|
||||
int convert_setup(block_pointer block, setup_pointer settings);
|
||||
int convert_setup_tool(block_pointer block, setup_pointer settings);
|
||||
int convert_set_plane(int g_code, setup_pointer settings);
|
||||
int convert_speed(int spindle, block_pointer block, setup_pointer settings);
|
||||
int convert_spindle_mode(int spindle, block_pointer block, setup_pointer settings);
|
||||
int convert_stop(block_pointer block, setup_pointer settings);
|
||||
int convert_straight(int move, block_pointer block,
|
||||
setup_pointer settings);
|
||||
int convert_straight_comp1(int move, block_pointer block,
|
||||
setup_pointer settings,
|
||||
double px, double py, double end_z,
|
||||
double AA_end, double BB_end, double CC_end,
|
||||
double u_end, double v_end, double w_end);
|
||||
int convert_straight_comp2(int move, block_pointer block,
|
||||
setup_pointer settings,
|
||||
double px, double py, double end_z,
|
||||
double AA_end, double BB_end, double CC_end,
|
||||
double u_end, double v_end, double w_end);
|
||||
int convert_threading_cycle(block_pointer block, setup_pointer settings,
|
||||
double end_x, double end_y, double end_z);
|
||||
int convert_tool_change(setup_pointer settings);
|
||||
int convert_tool_length_offset(int g_code, block_pointer block,
|
||||
setup_pointer settings);
|
||||
int convert_tool_select(block_pointer block, setup_pointer settings);
|
||||
int update_tag(StateTag &tag);
|
||||
int cycle_feed(block_pointer block, CANON_PLANE plane, double end1,
|
||||
double end2, double end3);
|
||||
int cycle_traverse(block_pointer block, CANON_PLANE plane, double end1, double end2,
|
||||
double end3);
|
||||
int enhance_block(block_pointer block, setup_pointer settings);
|
||||
int _execute(const char *command = 0);
|
||||
int execute_binary(double *left, int operation, double *right);
|
||||
int execute_binary1(double *left, int operation, double *right);
|
||||
int execute_binary2(double *left, int operation, double *right);
|
||||
int execute_block(block_pointer block, setup_pointer settings);
|
||||
int execute_unary(double *double_ptr, int operation);
|
||||
double find_arc_length(double x1, double y1, double z1,
|
||||
double center_x, double center_y, int turn,
|
||||
double x2, double y2, double z2);
|
||||
int find_current_in_system(setup_pointer s, int system, double *x, double *y, double *z,
|
||||
double *a, double *b, double *c,
|
||||
double *u, double *v, double *w);
|
||||
int find_current_in_system_without_tlo(setup_pointer s, int system, double *x, double *y, double *z,
|
||||
double *a, double *b, double *c,
|
||||
double *u, double *v, double *w);
|
||||
int find_ends(block_pointer block, setup_pointer settings,
|
||||
double *px, double *py, double *pz,
|
||||
double *AA_p, double *BB_p, double *CC_p,
|
||||
double *u_p, double *v_p, double *w_p);
|
||||
int find_relative(double x1, double y1, double z1,
|
||||
double AA_1, double BB_1, double CC_1,
|
||||
double u_1, double v_1, double w_1,
|
||||
double *x2, double *y2, double *z2,
|
||||
double *AA_2, double *BB_2, double *CC_2,
|
||||
double *u_2, double *v_2, double *w_2,
|
||||
setup_pointer settings);
|
||||
double find_straight_length(double x2, double y2, double z2,
|
||||
double AA_2, double BB_2, double CC_2,
|
||||
double u_w, double v_2, double w_2,
|
||||
double x1, double y1, double z1,
|
||||
double AA_1, double BB_1, double CC_1,
|
||||
double u_1, double v_1, double w_1);
|
||||
double find_turn(double x1, double y1, double center_x,
|
||||
double center_y, int turn, double x2, double y2);
|
||||
int init_block(block_pointer block);
|
||||
int inverse_time_rate_arc(double x1, double y1, double z1,
|
||||
double cx, double cy, int turn, double x2,
|
||||
double y2, double z2, block_pointer block,
|
||||
setup_pointer settings);
|
||||
int inverse_time_rate_straight(double end_x, double end_y, double end_z,
|
||||
double AA_end, double BB_end, double CC_end,
|
||||
double u_end, double v_end, double w_end,
|
||||
block_pointer block,
|
||||
setup_pointer settings);
|
||||
int move_endpoint_and_flush(setup_pointer, double, double);
|
||||
int parse_line(char *line, block_pointer block,
|
||||
setup_pointer settings);
|
||||
int precedence(int an_operator);
|
||||
int _read(const char *command);
|
||||
int read_a(char *line, int *counter, block_pointer block,
|
||||
double *parameters);
|
||||
int read_atan(char *line, int *counter, double *double_ptr,
|
||||
double *parameters);
|
||||
int read_atsign(char *line, int *counter, block_pointer block,
|
||||
double *parameters);
|
||||
int read_b(char *line, int *counter, block_pointer block,
|
||||
double *parameters);
|
||||
int read_c(char *line, int *counter, block_pointer block,
|
||||
double *parameters);
|
||||
int read_carat(char *line, int *counter, block_pointer block,
|
||||
double *parameters);
|
||||
int read_comment(char *line, int *counter, block_pointer block,
|
||||
double *parameters);
|
||||
int read_semicolon(char *line, int *counter, block_pointer block,
|
||||
double *parameters);
|
||||
int read_d(char *line, int *counter, block_pointer block,
|
||||
double *parameters);
|
||||
int read_dollar(char *line, int *counter, block_pointer block,
|
||||
double *parameters);
|
||||
int read_e(char *line, int *counter, block_pointer block,
|
||||
double *parameters);
|
||||
int read_f(char *line, int *counter, block_pointer block,
|
||||
double *parameters);
|
||||
int read_g(char *line, int *counter, block_pointer block,
|
||||
double *parameters);
|
||||
int read_h(char *line, int *counter, block_pointer block,
|
||||
double *parameters);
|
||||
int read_i(char *line, int *counter, block_pointer block,
|
||||
double *parameters);
|
||||
int read_integer_unsigned(char *line, int *counter, int *integer_ptr);
|
||||
int read_integer_value(char *line, int *counter, int *integer_ptr,
|
||||
double *parameters);
|
||||
int read_items(block_pointer block, char *line, double *parameters);
|
||||
int read_j(char *line, int *counter, block_pointer block,
|
||||
double *parameters);
|
||||
int read_k(char *line, int *counter, block_pointer block,
|
||||
double *parameters);
|
||||
int read_l(char *line, int *counter, block_pointer block,
|
||||
double *parameters);
|
||||
int read_n_number(char *line, int *counter, block_pointer block);
|
||||
int read_m(char *line, int *counter, block_pointer block,
|
||||
double *parameters);
|
||||
int read_o(char *line, int *counter, block_pointer block,
|
||||
double *parameters);
|
||||
|
||||
|
||||
int read_one_item(char *line, int *counter, block_pointer block,
|
||||
double *parameters);
|
||||
int read_operation(char *line, int *counter, int *operation);
|
||||
int read_operation_unary(char *line, int *counter, int *operation);
|
||||
int read_p(char *line, int *counter, block_pointer block,
|
||||
double *parameters);
|
||||
|
||||
|
||||
|
||||
int lookup_named_param(const char *nameBuf, double index, double *value);
|
||||
int init_readonly_param(const char *nameBuf, double value, int attr);
|
||||
int free_named_parameters(context_pointer frame);
|
||||
int save_settings(setup_pointer settings);
|
||||
int restore_settings(setup_pointer settings, int from_level);
|
||||
int restore_from_tag(StateTag const &tag) override;
|
||||
int gen_settings(
|
||||
int *int_current, int *int_saved,
|
||||
double *float_current, double *float_saved,
|
||||
std::string &cmd);
|
||||
int gen_m_codes(int *current, int *saved, std::string &cmd);
|
||||
int gen_restore_cmd(int *current_g,
|
||||
int *current_m,
|
||||
double *current_settings,
|
||||
StateTag const &saved,
|
||||
std::string &cmd);
|
||||
int read_name(char *line, int *counter, char *nameBuf);
|
||||
int read_named_parameter(char *line, int *counter, double *double_ptr,
|
||||
double *parameters, bool check_exists);
|
||||
int read_parameter(char *line, int *counter, double *double_ptr,
|
||||
double *parameters, bool check_exists);
|
||||
int read_parameter_setting(char *line, int *counter,
|
||||
block_pointer block, double *parameters);
|
||||
int read_bracketed_parameter(char *line, int *counter, double *double_ptr,
|
||||
double *parameters, bool check_exists);
|
||||
int read_named_parameter_setting(char *line, int *counter,
|
||||
char **param, double *parameters);
|
||||
int read_q(char *line, int *counter, block_pointer block,
|
||||
double *parameters);
|
||||
int read_r(char *line, int *counter, block_pointer block,
|
||||
double *parameters);
|
||||
int read_real_expression(char *line, int *counter,
|
||||
double *hold2, double *parameters);
|
||||
int read_real_number(char *line, int *counter, double *double_ptr);
|
||||
int read_real_value(char *line, int *counter, double *double_ptr,
|
||||
double *parameters);
|
||||
int read_s(char *line, int *counter, block_pointer block,
|
||||
double *parameters);
|
||||
int read_t(char *line, int *counter, block_pointer block,
|
||||
double *parameters);
|
||||
int read_text(const char *command, FILE * inport, char *raw_line,
|
||||
char *line, int *length);
|
||||
int read_unary(char *line, int *counter, double *double_ptr,
|
||||
double *parameters);
|
||||
int read_u(char *line, int *counter, block_pointer block,
|
||||
double *parameters);
|
||||
int read_v(char *line, int *counter, block_pointer block,
|
||||
double *parameters);
|
||||
int read_w(char *line, int *counter, block_pointer block,
|
||||
double *parameters);
|
||||
int read_x(char *line, int *counter, block_pointer block,
|
||||
double *parameters);
|
||||
int read_y(char *line, int *counter, block_pointer block,
|
||||
double *parameters);
|
||||
int read_z(char *line, int *counter, block_pointer block,
|
||||
double *parameters);
|
||||
int refresh_actual_position(setup_pointer settings);
|
||||
void rotate(double *x, double *y, double t);
|
||||
int set_probe_data(setup_pointer settings);
|
||||
int write_g_codes(block_pointer block, setup_pointer settings);
|
||||
int write_m_codes(block_pointer block, setup_pointer settings);
|
||||
int write_settings(setup_pointer settings);
|
||||
int write_state_tag(block_pointer block, setup_pointer settings,
|
||||
StateTag &state);
|
||||
int write_canon_state_tag(block_pointer block, setup_pointer settings);
|
||||
int unwrap_rotary(double *, double, double, double, char);
|
||||
|
||||
// O_word stuff
|
||||
|
||||
int findFile( // ARGUMENTS
|
||||
char *direct, // the directory to start looking in
|
||||
char *target, // the name of the file to find
|
||||
char *foundFileDirect); // where to store the result
|
||||
|
||||
int control_save_offset( /* ARGUMENTS */
|
||||
// int line, /* (o-word) line number */
|
||||
block_pointer block, /* pointer to a block of RS274/NGC instructions */
|
||||
setup_pointer settings); /* pointer to machine settings */
|
||||
|
||||
int control_save_offset(
|
||||
block_pointer block,
|
||||
const char *o_name, /* o_name key */
|
||||
setup_pointer settings);
|
||||
|
||||
int control_find_oword( /* ARGUMENTS */
|
||||
const char *o_name, /* o-word name */
|
||||
setup_pointer settings, /* pointer to machine settings */
|
||||
offset_pointer *ppo);
|
||||
|
||||
int control_find_oword( /* ARGUMENTS */
|
||||
block_pointer block, /* block pointer to get (o-word) name */
|
||||
setup_pointer settings, /* pointer to machine settings */
|
||||
offset_pointer *ppo);
|
||||
// int *o_index); /* the index of o-word (returned) */
|
||||
|
||||
int control_back_to( /* ARGUMENTS */
|
||||
block_pointer block, // pointer to block
|
||||
setup_pointer settings); /* pointer to machine settings */
|
||||
|
||||
// establish a new subroutine context
|
||||
int enter_context(setup_pointer settings, block_pointer block);
|
||||
// leave current subroutine context
|
||||
int leave_context(setup_pointer settings, bool restore = true);
|
||||
|
||||
//int call_fsm(setup_pointer settings, int event);
|
||||
//int execute_pycall(setup_pointer settings, const char *name, int call_phase);
|
||||
int execute_call(setup_pointer settings, context_pointer current_frame, int call_type);
|
||||
int execute_return(setup_pointer settings, context_pointer current_frame, int call_type);
|
||||
void loop_to_beginning(setup_pointer settings);
|
||||
//int execute_remap(setup_pointer settings, int call_phase); // remap call state machine
|
||||
int handler_returned( setup_pointer settings,
|
||||
context_pointer active_frame, const char *name, bool osub);
|
||||
int read_inputs(setup_pointer settings);
|
||||
|
||||
int convert_control_functions( /* ARGUMENTS */
|
||||
block_pointer block, /* pointer to a block of RS274/NGC instructions */
|
||||
setup_pointer settings); /* pointer to machine settings */
|
||||
|
||||
|
||||
// parse a REMAP= descriptor from the INI file
|
||||
int parse_remap(const char *inistring, int lineno);
|
||||
|
||||
// step through parsed block and collect remapped items in
|
||||
// block.remappings set
|
||||
int find_remappings(block_pointer block, setup_pointer settings);
|
||||
|
||||
// establish a new remapping context
|
||||
int enter_remap(void);
|
||||
// leave current remapping context
|
||||
int leave_remap(void);
|
||||
|
||||
// callback when remapping handler done
|
||||
int remap_finished( int status);
|
||||
|
||||
int report_error(setup_pointer settings,int status,const char *text);
|
||||
|
||||
// add named params/param dict if argspec given
|
||||
// present optional words to the subroutine's local variables and Py dict
|
||||
int add_parameters(setup_pointer settings, block_pointer cblock,
|
||||
char *posarglist);
|
||||
|
||||
int init_named_parameters();
|
||||
int init_python_predef_parameter(const char *name);
|
||||
|
||||
bool remap_in_progress(const char *code);
|
||||
int convert_remapped_code(block_pointer block,
|
||||
setup_pointer settings,
|
||||
int phase,
|
||||
char letter,
|
||||
int number = -1);
|
||||
|
||||
bool is_pycallable(setup_pointer settings, const char *module, const char *funcname);
|
||||
|
||||
#define OWORD_MODULE "oword"
|
||||
#define REMAP_MODULE "remap"
|
||||
#define NAMEDPARAMS_MODULE "namedparams"
|
||||
// describes intended use, and hence parameter and return value
|
||||
// interpretation
|
||||
enum py_calltype { PY_OWORDCALL,
|
||||
PY_FINISH_OWORDCALL,
|
||||
PY_PROLOG,
|
||||
PY_FINISH_PROLOG,
|
||||
PY_BODY,
|
||||
PY_FINISH_BODY,
|
||||
PY_EPILOG,
|
||||
PY_FINISH_EPILOG,
|
||||
PY_INTERNAL,
|
||||
PY_EXECUTE,
|
||||
PY_PLUGIN_CALL
|
||||
};
|
||||
int pycall(setup_pointer settings,
|
||||
context_pointer frame,
|
||||
const char *module,
|
||||
const char *funcname,
|
||||
int calltype);
|
||||
int py_execute(const char *cmd, bool as_file = false); // for (py, ....) comments
|
||||
int py_reload();
|
||||
FILE *find_ngc_file(setup_pointer settings,const char *basename, char *foundhere = NULL);
|
||||
|
||||
const char *getSavedError();
|
||||
// set error message text without going through printf format interpretation
|
||||
int setSavedError(const char *msg);
|
||||
|
||||
int unwind_call(int status, const char *file, int line, const char *function);
|
||||
|
||||
|
||||
int convert_straight_indexer(int anum, int jnum, block* blk, setup* settings);
|
||||
int issue_straight_index(int anum, int jnum, double end, int lineno, setup* settings);
|
||||
|
||||
void doLog(unsigned int flags, const char *file, int line,
|
||||
const char *fmt, ...) __attribute__((format(printf,5,6)));
|
||||
|
||||
/* State Tags Helpers */
|
||||
int tag_straight(block_pointer block, double x, double y);
|
||||
int tag_arc(block_pointer block, double x, double y, double z, double center_x, double center_y, double center_z, int move, CANON_PLANE plane);
|
||||
|
||||
const char *interp_status(int status);
|
||||
|
||||
//technically this violates encapsulation rules but is needed for
|
||||
// the Python introspection module
|
||||
|
||||
FILE *log_file;
|
||||
|
||||
read_function_pointer _readers[256];
|
||||
static const read_function_pointer default_readers[256];
|
||||
|
||||
setup _setup;
|
||||
|
||||
enum {
|
||||
AXIS_MASK_X = 1, AXIS_MASK_Y = 2, AXIS_MASK_Z = 4,
|
||||
AXIS_MASK_A = 8, AXIS_MASK_B = 16, AXIS_MASK_C = 32,
|
||||
AXIS_MASK_U = 64, AXIS_MASK_V = 128, AXIS_MASK_W = 256,
|
||||
};
|
||||
|
||||
InterpReturn check_g74_g84_spindle(GCodes motion, CANON_DIRECTION dir);
|
||||
|
||||
private:
|
||||
[[nodiscard]] static bool is_parameter_readonly(int index);
|
||||
|
||||
[[nodiscard]] static bool is_any_m_code_remapped(block_pointer block, setup_pointer settings);
|
||||
[[nodiscard]] static bool is_user_defined_m_code(block_pointer block, setup_pointer settings,
|
||||
int m_group);
|
||||
[[nodiscard]] static bool is_m_code_remappable(int m_code);
|
||||
[[nodiscard]] static bool is_g_code_remappable(int g_code);
|
||||
[[nodiscard]] bool is_user_defined_g_code(int g_code);
|
||||
|
||||
static const int gees[];
|
||||
static const int ems[];
|
||||
static const int required_parameters[];
|
||||
static const int readonly_parameters[];
|
||||
static const int n_readonly_parameters;
|
||||
};
|
||||
|
||||
#endif
|
||||
2775
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/rs274ngc_pre.cc
vendored
Normal file
2775
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/rs274ngc_pre.cc
vendored
Normal file
File diff suppressed because it is too large
Load Diff
219
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/rs274ngc_return.hh
vendored
Normal file
219
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/rs274ngc_return.hh
vendored
Normal file
@@ -0,0 +1,219 @@
|
||||
// Copyright 2004-2010 various authors.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#ifndef RS274NGC_RETURN_HH
|
||||
#define RS274NGC_RETURN_HH
|
||||
#include "nml_intf/interp_return.hh"
|
||||
#define NCE_A_FILE_IS_ALREADY_OPEN _("A file is already open")
|
||||
#define NCE_ALL_AXES_MISSING_WITH_G52_OR_G92 \
|
||||
_("All axes missing with g52 or g92")
|
||||
#define NCE_ALL_AXES_MISSING_WITH_MOTION_CODE _("All axes missing with motion code")
|
||||
#define NCE_ARC_RADIUS_TOO_SMALL_TO_REACH_END_POINT _("Arc radius too small to reach end point")
|
||||
#define NCE_ARGUMENT_TO_ACOS_OUT_OF_RANGE _("Argument to acos out of range")
|
||||
#define NCE_ARGUMENT_TO_ASIN_OUT_OF_RANGE _("Argument to asin out of range")
|
||||
#define NCE_ATTEMPT_TO_DIVIDE_BY_ZERO _("Attempt to divide by zero")
|
||||
#define NCE_ATTEMPT_TO_RAISE_NEGATIVE_TO_NON_INTEGER_POWER _("Attempt to raise negative to non integer power")
|
||||
#define NCE_BAD_FORMAT_UNSIGNED_INTEGER _("Bad format unsigned integer")
|
||||
#define NCE_BAD_NUMBER_FORMAT _("Bad number format")
|
||||
#define NCE_BUG_BAD_G_CODE_MODAL_GROUP_0 _("Bug bad g code modal group 0")
|
||||
#define NCE_BUG_CODE_NOT_G0_OR_G1 _("Bug code not g0 or g1")
|
||||
#define NCE_BUG_CODE_NOT_G17_G18_OR_G19 _("Bug code not g17 g18 or g19")
|
||||
#define NCE_BUG_CODE_NOT_G20_OR_G21 _("Bug code not g20 or g21")
|
||||
#define NCE_BUG_CODE_NOT_G28_OR_G30 _("Bug code not g28 or g30")
|
||||
#define NCE_BUG_CODE_NOT_G2_OR_G3 _("Bug code not g2 or g3")
|
||||
#define NCE_BUG_CODE_NOT_G4_G10_G28_G30_G52_G53_OR_G92_SERIES \
|
||||
_("Bug code not g4 g10 g28 g30 g52 g53 or g92 series")
|
||||
#define NCE_BUG_CODE_NOT_G61_G61_1_OR_G64 _("Bug code not g61 g61.1 or g64")
|
||||
#define NCE_BUG_CODE_NOT_G90_OR_G91 _("Bug code not g90 or g91")
|
||||
#define NCE_BUG_CODE_NOT_G98_OR_G99 _("Bug code not g98 or g99")
|
||||
#define NCE_BUG_CODE_NOT_IN_G52_G92_SERIES _("Bug code not in g52 or g92 series")
|
||||
#define NCE_BUG_CODE_NOT_IN_RANGE_G54_TO_G593 _("Bug code not in range g54 to g593")
|
||||
#define NCE_BUG_CODE_NOT_M0_M1_M2_M30_M60_M99 _("Bug code not m0 m1 m2 m30 m60 m99")
|
||||
#define NCE_BUG_DISTANCE_MODE_NOT_G90_OR_G91 _("Bug distance mode not g90 or g91")
|
||||
#define NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED _("Bug function should not have been called")
|
||||
#define NCE_BUG_IN_TOOL_RADIUS_COMP _("Bug in tool radius comp")
|
||||
#define NCE_BUG_PLANE_NOT_XY_YZ_OR_XZ _("Bug plane not xy yz or xz")
|
||||
#define NCE_BUG_SIDE_NOT_RIGHT_OR_LEFT _("Bug side not right or left")
|
||||
#define NCE_BUG_UNKNOWN_MOTION_CODE _("Bug unknown motion code")
|
||||
#define NCE_BUG_UNKNOWN_OPERATION _("Bug unknown operation")
|
||||
#define NCE_CANNOT_CHANGE_AXIS_OFFSETS_WITH_CUTTER_RADIUS_COMP _("Cannot change axis offsets with cutter radius comp")
|
||||
#define NCE_CANNOT_CREATE_BACKUP_FILE _("Cannot create backup file")
|
||||
#define NCE_CANNOT_DO_G1_WITH_ZERO_FEED_RATE _("Cannot do g1 with zero feed rate")
|
||||
#define NCE_CANNOT_DO_ZERO_REPEATS_OF_CYCLE _("Cannot do zero repeats of cycle")
|
||||
#define NCE_CANNOT_MAKE_ARC_WITH_ZERO_FEED_RATE _("Cannot make arc with zero feed rate")
|
||||
#define NCE_CANNOT_OPEN_BACKUP_FILE _("Cannot open backup file")
|
||||
#define NCE_CANNOT_OPEN_VARIABLE_FILE _("Cannot open variable file")
|
||||
#define NCE_CANNOT_PROBE_WITH_CUTTER_RADIUS_COMP_ON _("Cannot probe with cutter radius comp on")
|
||||
#define NCE_CANNOT_PROBE_WITH_ZERO_FEED_RATE _("Cannot probe with zero feed rate")
|
||||
#define NCE_CANNOT_PUT_A_B_IN_CANNED_CYCLE _("Cannot put a b in canned cycle")
|
||||
#define NCE_CANNOT_PUT_A_C_IN_CANNED_CYCLE _("Cannot put a c in canned cycle")
|
||||
#define NCE_CANNOT_PUT_AN_A_IN_CANNED_CYCLE _("Cannot put an a in canned cycle")
|
||||
#define NCE_CANNOT_TURN_CUTTER_RADIUS_COMP_ON_WHEN_ON _("Cannot turn cutter radius comp on when on")
|
||||
#define NCE_CANNOT_USE_AXIS_VALUES_WITH_G80 _("Cannot use axis values with g80")
|
||||
#define NCE_CANNOT_USE_AXIS_VALUES_WITHOUT_A_G_CODE_THAT_USES_THEM _("Cannot use axis values without a g code that uses them")
|
||||
#define NCE_CANNOT_USE_G28_OR_G30_WITH_CUTTER_RADIUS_COMP _("Cannot use g28 or g30 with cutter radius comp")
|
||||
#define NCE_CANNOT_USE_G53_INCREMENTAL _("Cannot use g53 incremental")
|
||||
#define NCE_CANNOT_USE_G53_WITH_CUTTER_RADIUS_COMP _("Cannot use g53 with cutter radius comp")
|
||||
#define NCE_CANNOT_USE_TWO_G_CODES_THAT_BOTH_USE_AXIS_VALUES _("Cannot use two g codes that both use axis values")
|
||||
#define NCE_COMMAND_TOO_LONG _("Command too long")
|
||||
#define NCE_CURRENT_POINT_SAME_AS_END_POINT_OF_ARC _("Current point same as end point of arc")
|
||||
#define NCE_DWELL_TIME_MISSING_WITH_G4 _("Dwell time missing with g4")
|
||||
#define NCE_DWELL_TIME_P_WORD_MISSING_WITH_G82 _("Dwell time p word missing with g82")
|
||||
#define NCE_DWELL_TIME_P_WORD_MISSING_WITH_G86 _("Dwell time p word missing with g86")
|
||||
#define NCE_DWELL_TIME_P_WORD_MISSING_WITH_G88 _("Dwell time p word missing with g88")
|
||||
#define NCE_DWELL_TIME_P_WORD_MISSING_WITH_G89 _("Dwell time p word missing with g89")
|
||||
#define NCE_EQUAL_SIGN_MISSING_IN_PARAMETER_SETTING _("Equal sign missing in parameter setting")
|
||||
#define NCE_F_WORD_MISSING_WITH_INVERSE_TIME_ARC_MOVE _("F word missing with inverse time arc move")
|
||||
#define NCE_F_WORD_MISSING_WITH_INVERSE_TIME_G1_MOVE _("F word missing with inverse time g1 move")
|
||||
#define NCE_FILE_ENDED_WITH_NO_PERCENT_SIGN _("File ended with no percent sign (%%)")
|
||||
#define NCE_FILE_ENDED_WITH_NO_PERCENT_SIGN_OR_PROGRAM_END _("File ended with no percent sign (%%) or program end (M2)")
|
||||
#define NCE_FILE_NAME_TOO_LONG _("File name too long")
|
||||
#define NCE_G_CODE_OUT_OF_RANGE _("G-code out of range")
|
||||
#define NCE_I_WORD_GIVEN_FOR_ARC_IN_YZ_PLANE _("I word given for arc in yz plane")
|
||||
#define NCE_I_WORD_MISSING_WITH_G87 _("I word missing with g87")
|
||||
#define NCE_J_WORD_GIVEN_FOR_ARC_IN_XZ_PLANE _("J word given for arc in xz plane")
|
||||
#define NCE_J_WORD_MISSING_WITH_G87 _("J word missing with g87")
|
||||
#define NCE_K_WORD_GIVEN_FOR_ARC_IN_XY_PLANE _("K word given for arc in xy plane")
|
||||
#define NCE_K_WORD_MISSING_WITH_G87 _("K word missing with g87")
|
||||
#define NCE_LEFT_BRACKET_MISSING_AFTER_SLASH_WITH_ATAN _("Left bracket missing after slash with atan")
|
||||
#define NCE_LEFT_BRACKET_MISSING_AFTER_UNARY_OPERATION_NAME _("Left bracket missing after unary operation name")
|
||||
#define NCE_M_CODE_GREATER_THAN_199 _("M-code greater than 199: M%d")
|
||||
#define NCE_MIXED_RADIUS_IJK_FORMAT_FOR_ARC _("Mixed radius ijk format for arc")
|
||||
#define NCE_MULTIPLE_$_WORDS_ON_ONE_LINE _("Multiple spindle choice ($) words on one line")
|
||||
#define NCE_MULTIPLE_A_WORDS_ON_ONE_LINE _("Multiple a words on one line")
|
||||
#define NCE_MULTIPLE_B_WORDS_ON_ONE_LINE _("Multiple b words on one line")
|
||||
#define NCE_MULTIPLE_C_WORDS_ON_ONE_LINE _("Multiple c words on one line")
|
||||
#define NCE_MULTIPLE_D_WORDS_ON_ONE_LINE _("Multiple d words on one line")
|
||||
#define NCE_MULTIPLE_F_WORDS_ON_ONE_LINE _("Multiple f words on one line")
|
||||
#define NCE_MULTIPLE_H_WORDS_ON_ONE_LINE _("Multiple h words on one line")
|
||||
#define NCE_MULTIPLE_I_WORDS_ON_ONE_LINE _("Multiple i words on one line")
|
||||
#define NCE_MULTIPLE_J_WORDS_ON_ONE_LINE _("Multiple j words on one line")
|
||||
#define NCE_MULTIPLE_K_WORDS_ON_ONE_LINE _("Multiple k words on one line")
|
||||
#define NCE_MULTIPLE_L_WORDS_ON_ONE_LINE _("Multiple l words on one line")
|
||||
#define NCE_MULTIPLE_P_WORDS_ON_ONE_LINE _("Multiple p words on one line")
|
||||
#define NCE_MULTIPLE_Q_WORDS_ON_ONE_LINE _("Multiple q words on one line")
|
||||
#define NCE_MULTIPLE_R_WORDS_ON_ONE_LINE _("Multiple r words on one line")
|
||||
#define NCE_MULTIPLE_S_WORDS_ON_ONE_LINE _("Multiple s words on one line")
|
||||
#define NCE_MULTIPLE_T_WORDS_ON_ONE_LINE _("Multiple t words on one line")
|
||||
#define NCE_MULTIPLE_X_WORDS_ON_ONE_LINE _("Multiple x words on one line")
|
||||
#define NCE_MULTIPLE_Y_WORDS_ON_ONE_LINE _("Multiple y words on one line")
|
||||
#define NCE_MULTIPLE_Z_WORDS_ON_ONE_LINE _("Multiple z words on one line")
|
||||
#define NCE_MUST_USE_G0_OR_G1_WITH_G53 _("Must use g0 or g1 with g53")
|
||||
#define NCE_NEGATIVE_ARGUMENT_TO_SQRT _("Negative argument to sqrt")
|
||||
#define NCE_NEGATIVE_D_WORD_TOOL_RADIUS_INDEX_USED _("Negative d word tool radius index used")
|
||||
#define NCE_NEGATIVE_F_WORD_USED _("Negative f word used")
|
||||
#define NCE_NEGATIVE_G_CODE_USED _("Negative g code used")
|
||||
#define NCE_NEGATIVE_H_WORD_USED _("Negative h word used")
|
||||
#define NCE_NEGATIVE_L_WORD_USED _("Negative l word used")
|
||||
#define NCE_NEGATIVE_M_CODE_USED _("Negative m code used")
|
||||
#define NCE_NEGATIVE_OR_ZERO_Q_VALUE_USED _("Negative or zero q value used")
|
||||
#define NCE_NEGATIVE_P_WORD_USED _("Negative p word used")
|
||||
#define NCE_NEGATIVE_SPINDLE_SPEED_USED _("Negative spindle speed used")
|
||||
#define NCE_NEGATIVE_TOOL_ID_USED _("Negative tool id (tool not found)")
|
||||
#define NCE_NESTED_COMMENT_FOUND _("Nested comment found")
|
||||
#define NCE_NO_CHARACTERS_FOUND_IN_READING_REAL_VALUE _("No characters found in reading real value")
|
||||
#define NCE_NON_INTEGER_VALUE_FOR_INTEGER _("Non integer value for integer")
|
||||
#define NCE_NULL_MISSING_AFTER_NEWLINE _("Null missing after newline")
|
||||
#define NCE_PARAMETER_FILE_OUT_OF_ORDER _("Parameter file out of order")
|
||||
#define NCE_PARAMETER_NUMBER_OUT_OF_RANGE _("Parameter number out of range")
|
||||
#define NCE_PARAMETER_NUMBER_READONLY _("Parameter is readonly")
|
||||
#define NCE_Q_WORD_MISSING_WITH_G83 _("Q word missing with g83")
|
||||
#define NCE_QUEUE_IS_NOT_EMPTY_AFTER_PROBING _("Queue is not empty after probing")
|
||||
#define NCE_R_CLEARANCE_PLANE_UNSPECIFIED_IN_CYCLE _("R clearance plane unspecified in cycle")
|
||||
#define NCE_R_I_J_K_WORDS_ALL_MISSING_FOR_ARC _("R i j k words all missing for arc")
|
||||
#define NCE_R_LESS_THAN_X_IN_CYCLE_IN_YZ_PLANE _("R less than x in cycle in yz plane")
|
||||
#define NCE_R_LESS_THAN_Y_IN_CYCLE_IN_XZ_PLANE _("R less than y in cycle in xz plane")
|
||||
#define NCE_R_LESS_THAN_Z_IN_CYCLE_IN_XY_PLANE _("R less than z in cycle in xy plane")
|
||||
#define NCE_R_WORD_WITH_NO_G_CODE_THAT_USES_IT _("R word with no g code that uses it")
|
||||
#define NCE_SLASH_MISSING_AFTER_FIRST_ATAN_ARGUMENT _("Slash missing after first atan argument")
|
||||
#define NCE_SPINDLE_NOT_TURNING_CLOCKWISE_IN_G84 _("Spindle not turning clockwise in g84")
|
||||
#define NCE_SPINDLE_NOT_TURNING_IN_G86 _("Spindle not turning in g86")
|
||||
#define NCE_SPINDLE_NOT_TURNING_IN_G87 _("Spindle not turning in g87")
|
||||
#define NCE_SPINDLE_NOT_TURNING_IN_G88 _("Spindle not turning in g88")
|
||||
#define NCE_SSCANF_FAILED _("Sscanf failed")
|
||||
#define NCE_START_POINT_TOO_CLOSE_TO_PROBE_POINT _("Start point too close to probe point")
|
||||
#define NCE_TOO_MANY_M_CODES_ON_LINE _("Too many m codes on line")
|
||||
#define NCE_POCKET_MAX_TOO_LARGE _("Pocket max too large")
|
||||
#define NCE_TOOL_RADIUS_NOT_LESS_THAN_ARC_RADIUS_WITH_COMP _("Tool radius not less than arc radius with comp")
|
||||
#define NCE_TWO_G_CODES_USED_FROM_SAME_MODAL_GROUP _("Two g codes used from same modal group")
|
||||
#define NCE_TWO_M_CODES_USED_FROM_SAME_MODAL_GROUP _("Two m codes used from same modal group")
|
||||
#define NCE_UNABLE_TO_OPEN_FILE _("Unable to open file <%s>")
|
||||
#define NCE_UNCLOSED_COMMENT_FOUND _("Unclosed comment found")
|
||||
#define NCE_UNCLOSED_EXPRESSION _("Unclosed expression")
|
||||
#define NCE_UNKNOWN_G_CODE_USED _("Unknown g code used")
|
||||
#define NCE_UNKNOWN_M_CODE_USED _("Unknown m code used: M%d")
|
||||
#define NCE_UNKNOWN_OPERATION _("Unknown operation")
|
||||
#define NCE_UNKNOWN_OPERATION_NAME_STARTING_WITH_A _("Unknown operation name starting with a")
|
||||
#define NCE_UNKNOWN_OPERATION_NAME_STARTING_WITH_M _("Unknown operation name starting with m")
|
||||
#define NCE_UNKNOWN_OPERATION_NAME_STARTING_WITH_O _("Unknown operation name starting with o")
|
||||
#define NCE_UNKNOWN_OPERATION_NAME_STARTING_WITH_X _("Unknown operation name starting with x")
|
||||
#define NCE_UNKNOWN_WORD_STARTING_WITH_A _("Unknown word starting with a")
|
||||
#define NCE_UNKNOWN_WORD_STARTING_WITH_C _("Unknown word starting with c")
|
||||
#define NCE_UNKNOWN_WORD_STARTING_WITH_E _("Unknown word starting with e")
|
||||
#define NCE_UNKNOWN_WORD_STARTING_WITH_F _("Unknown word starting with f")
|
||||
#define NCE_UNKNOWN_WORD_STARTING_WITH_L _("Unknown word starting with l")
|
||||
#define NCE_UNKNOWN_WORD_STARTING_WITH_R _("Unknown word starting with r")
|
||||
#define NCE_UNKNOWN_WORD_STARTING_WITH_S _("Unknown word starting with s")
|
||||
#define NCE_UNKNOWN_WORD_STARTING_WITH_T _("Unknown word starting with t")
|
||||
#define NCE_UNKNOWN_WORD_WHERE_UNARY_OPERATION_COULD_BE _("Unknown word where unary operation could be")
|
||||
#define NCE_X_AND_Y_WORDS_MISSING_FOR_ARC_IN_XY_PLANE _("X and y words missing for arc in xy plane")
|
||||
#define NCE_X_AND_Z_WORDS_MISSING_FOR_ARC_IN_XZ_PLANE _("X and z words missing for arc in xz plane")
|
||||
#define NCE_X_VALUE_UNSPECIFIED_IN_YZ_PLANE_CANNED_CYCLE _("X value unspecified in yz plane canned cycle")
|
||||
#define NCE_Y_AND_Z_WORDS_MISSING_FOR_ARC_IN_YZ_PLANE _("Y and z words missing for arc in yz plane")
|
||||
#define NCE_Y_VALUE_UNSPECIFIED_IN_XZ_PLANE_CANNED_CYCLE _("Y value unspecified in xz plane canned cycle")
|
||||
#define NCE_Z_VALUE_UNSPECIFIED_IN_XY_PLANE_CANNED_CYCLE _("Z value unspecified in xy plane canned cycle")
|
||||
#define NCE_ZERO_OR_NEGATIVE_ARGUMENT_TO_LN _("Zero or negative argument to ln")
|
||||
#define NCE_ZERO_RADIUS_ARC _("Zero radius arc")
|
||||
#define NCE_K_WORD_MISSING_WITH_G33 _("K word missing with g33/g33.1")
|
||||
#define NCE_F_WORD_USED_WITH_G33 _("F word used with a g33/g33.1")
|
||||
#define NCE_UNKNOWN_OPERATION_NAME_STARTING_WITH_E _("Unknown operation name starting with e")
|
||||
#define NCE_UNKNOWN_OPERATION_NAME_STARTING_WITH_N _("Unknown operation name starting with n")
|
||||
#define NCE_UNKNOWN_OPERATION_NAME_STARTING_WITH_G _("Unknown operation name starting with g")
|
||||
#define NCE_UNKNOWN_OPERATION_NAME_STARTING_WITH_L _("Unknown operation name starting with l")
|
||||
#define NCE_TOO_MANY_SUBROUTINE_PARAMETERS _("Too many subroutine parameters")
|
||||
#define NCE_TOO_MANY_SUBROUTINE_LEVELS _("Too many subroutine levels")
|
||||
#define NCE_CALL_STACK_UNDERRUN _("Bug: call stack underrun")
|
||||
#define NCE_UNKNOWN_COMMAND_IN_O_LINE _("Unknown control command in o word")
|
||||
#define NCE_TOO_MANY_OWORD_LABELS _("Too many oword labels")
|
||||
#define NCE_UNKNOWN_OWORD_NUMBER _("Unknown oword number")
|
||||
#define NCE_NESTED_SUBROUTINE_DEFN _("Nested subroutine definition")
|
||||
#define NCE_NOT_IN_SUBROUTINE_DEFN _("Not in subroutine definition")
|
||||
#define NCE_FILE_NOT_OPEN _("File not open")
|
||||
#define NCE_CANNOT_REOPEN_FILE _("cannot reopen file %s - removed or renamed? (%s)")
|
||||
#define NCE_TXX_MISSING_FOR_M6 _("Need tool prepared -Txx- for toolchange")
|
||||
#define NCE_CANNOT_CHANGE_PLANES_WITH_CUTTER_RADIUS_COMP_ON _("Cannot change planes with cutter radius compensation on")
|
||||
#define NCE_RADIUS_COMP_ONLY_IN_XY_OR_XZ _("Cutter radius compensation allowed only in XY, XZ planes")
|
||||
#define NCE_P_WORD_MISSING_WITH_G76 _("P word missing with G76")
|
||||
#define NCE_I_J_OR_K_WORDS_MISSING_WITH_G76 _("I J or K words missing with G76")
|
||||
#define NCE_CANNOT_MOVE_ROTARY_AXES_WITH_G76 _("Cannot move rotary axes with G76")
|
||||
#define NCE_MULTIPLE_E_WORDS_ON_ONE_LINE _("Multiple e words on one line")
|
||||
#define NCE_NAMED_PARAMETER_NOT_TERMINATED _("Named parameter not terminated")
|
||||
#define NCE_OUT_OF_MEMORY _("Out of memory")
|
||||
#define NCE_S_WORD_MISSING_WITH_G96 _("S word missing with G96")
|
||||
#define NCE_QUEUE_IS_NOT_EMPTY_AFTER_INPUT _("Queue is not empty after external input")
|
||||
#define NCE_ANALOG_INPUT_WITH_WAIT_NOT_IMMEDIATE _("Can't select analog input with wait type != immediate return")
|
||||
#define NCE_ZERO_TIMEOUT_WITH_WAIT_NOT_IMMEDIATE _("Zero timeout with wait type != immediate return")
|
||||
#define NCE_BOTH_DIGITAL_AND_ANALOG_INPUT_SELECTED _("Invalid to select both a digital and an analog input with M66")
|
||||
#define NCE_INVALID_OR_MISSING_P_AND_E_WORDS_FOR_WAIT_INPUT _("Need to have either a valid P or a valid E word with M66")
|
||||
#define NCE_Q_WORD_MISSING_WITH_G73 _("Q word missing with g73")
|
||||
#define NCE_DIGITAL_INPUT_INVALID_ON_M66 _("Digital input selected out of bounds")
|
||||
#define NCE_ANALOG_INPUT_INVALID_ON_M66 _("Analog input selected out of bounds")
|
||||
#define NCE_W_VALUE_UNSPECIFIED_IN_UV_PLANE_CANNED_CYCLE _("W value unspecified in UV plane canned cycle")
|
||||
#define NCE_U_VALUE_UNSPECIFIED_IN_VW_PLANE_CANNED_CYCLE _("U value unspecified in VW plane canned cycle")
|
||||
#define NCE_V_VALUE_UNSPECIFIED_IN_UW_PLANE_CANNED_CYCLE _("V value unspecified in UW plane canned cycle")
|
||||
#define NCE_R_LESS_THAN_W_IN_CYCLE_IN_UV_PLANE _("R less than W in cycle in UV plane")
|
||||
#define NCE_R_LESS_THAN_U_IN_CYCLE_IN_VW_PLANE _("R less than U in cycle in VW plane")
|
||||
#define NCE_R_LESS_THAN_V_IN_CYCLE_IN_UW_PLANE _("R less than V in cycle in UW plane")
|
||||
#endif
|
||||
37
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/units.h
vendored
Normal file
37
wasm-port/vendor/linuxcnc/src/emc/rs274ngc/units.h
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
/********************************************************************
|
||||
* Description: units.h
|
||||
* Unit conversion macros and constants
|
||||
*
|
||||
* Derived from a work by Fred Proctor & Will Shackleford
|
||||
*
|
||||
* License: GPL Version 2
|
||||
*
|
||||
* Copyright (c) 2005 All rights reserved.
|
||||
*
|
||||
* Last change:
|
||||
********************************************************************/
|
||||
|
||||
/* macros for converting internal (mm/deg) units to external units */
|
||||
#define TO_EXT_LEN(mm) ((mm) * GET_EXTERNAL_LENGTH_UNITS())
|
||||
#define TO_EXT_ANG(deg) ((deg) * GET_EXTERNAL_ANGLE_UNITS())
|
||||
|
||||
/* macros for converting external units to internal (mm/deg) units */
|
||||
#define FROM_EXT_LEN(ext) ((ext) / GET_EXTERNAL_LENGTH_UNITS())
|
||||
#define FROM_EXT_ANG(ext) ((ext) / GET_EXTERNAL_ANGLE_UNITS())
|
||||
|
||||
/* macros for converting internal (mm/deg) units to program units */
|
||||
#define TO_PROG_LEN(mm) ((mm) / (_setup.length_units == CANON_UNITS_INCHES ? 25.4 : _setup.length_units == CANON_UNITS_CM ? 10.0 : 1.0))
|
||||
#define TO_PROG_ANG(deg) (deg)
|
||||
|
||||
/* macros for converting program units to internal (mm/deg) units */
|
||||
#define FROM_PROG_LEN(prog) ((prog) * (_setup.length_units == CANON_UNITS_INCHES ? 25.4 : _setup.length_units == CANON_UNITS_CM ? 10.0 : 1.0))
|
||||
#define FROM_PROG_ANG(prog) (prog)
|
||||
|
||||
/* macros for converting between user units (INI file) and program units (G-code) */
|
||||
#define USER_TO_PROGRAM_LEN(u) (TO_PROG_LEN(FROM_EXT_LEN(u)))
|
||||
#define PROGRAM_TO_USER_LEN(p) (TO_EXT_LEN(FROM_PROG_LEN(p)))
|
||||
|
||||
#define USER_TO_PROGRAM_ANG(u) (TO_PROG_ANG(FROM_EXT_ANG(u)))
|
||||
#define PROGRAM_TO_USER_ANG(p) (TO_EXT_ANG(FROM_PROG_ANG(p)))
|
||||
|
||||
|
||||
854
wasm-port/vendor/linuxcnc/src/libnml/posemath/gomath.h
vendored
Normal file
854
wasm-port/vendor/linuxcnc/src/libnml/posemath/gomath.h
vendored
Normal file
@@ -0,0 +1,854 @@
|
||||
/********************************************************************
|
||||
* Description: gomath.h
|
||||
* Library file with various functions for working with matrices
|
||||
*
|
||||
* Derived from a work by Fred Proctor,
|
||||
* changed to work with emc2 and HAL
|
||||
*
|
||||
* Adapting Author: Alex Joni
|
||||
* License: LGPL Version 2
|
||||
* System: Linux
|
||||
*
|
||||
*******************************************************************
|
||||
Similar to posemath, but using different functions.
|
||||
|
||||
TODO:
|
||||
* find the new functions, add them to posemath, convert the rest
|
||||
*/
|
||||
|
||||
#ifndef __LINUXCNC_GO_MATH_H
|
||||
#define __LINUXCNC_GO_MATH_H
|
||||
|
||||
#include <stddef.h> /* sizeof */
|
||||
#include "rtapi_math.h" /* M_PI */
|
||||
#include <float.h> /* FLT,DBL_MIN,MAX,EPSILON */
|
||||
#include "gotypes.h" /* go_integer,real */
|
||||
|
||||
/*! Returns the square of \a x. */
|
||||
#define go_sq(x) ((x)*(x))
|
||||
/*! Returns the cube of \a x. */
|
||||
#define go_cub(x) ((x)*(x)*(x))
|
||||
/*! Returns \a x to the fourth power. */
|
||||
#define go_qua(x) ((x)*(x)*(x)*(x))
|
||||
|
||||
/*! Returns the sine and cosine of \a x (in radians) in \a s and \a c,
|
||||
respectively. Implemented as a single call when supported, to speed
|
||||
up the calculation of the two values. */
|
||||
extern void go_sincos(go_real x, go_real * s, go_real * c);
|
||||
|
||||
/*! Returns the cube root of \a x. */
|
||||
extern go_real go_cbrt(go_real x);
|
||||
|
||||
#ifdef M_PI
|
||||
/*! The value of Pi. */
|
||||
#define GO_PI M_PI
|
||||
#else
|
||||
/*! The value of Pi. */
|
||||
#define GO_PI 3.14159265358979323846
|
||||
#endif
|
||||
/*! The value of twice Pi. */
|
||||
#define GO_2_PI (2.0*GO_PI)
|
||||
|
||||
#ifdef M_PI_2
|
||||
/*! The value of half of Pi. */
|
||||
#define GO_PI_2 M_PI_2
|
||||
#else
|
||||
/*! The value of half of Pi. */
|
||||
#define GO_PI_2 1.57079632679489661923
|
||||
#endif
|
||||
|
||||
#ifdef M_PI_4
|
||||
/*! The value of one-fourth of Pi. */
|
||||
#define GO_PI_4 M_PI_4
|
||||
#else
|
||||
/*! The value of one-fourth of Pi. */
|
||||
#define GO_PI_4 0.78539816339744830962
|
||||
#endif
|
||||
|
||||
/*! Returns \a rad in radians as its value in degrees. */
|
||||
#define GO_TO_DEG(rad) ((rad)*57.295779513082323)
|
||||
/*! Returns \a deg in degrees as its value in radians. */
|
||||
#define GO_TO_RAD(deg) ((deg)*0.0174532925199432952)
|
||||
|
||||
/*! How close translational quantities must be to be equal. */
|
||||
#define GO_TRAN_CLOSE(x,y) (fabs((x)-(y)) < GO_REAL_EPSILON)
|
||||
/*! How small a translational quantity must be to be zero. */
|
||||
#define GO_TRAN_SMALL(x) (fabs(x) < GO_REAL_EPSILON)
|
||||
|
||||
/*! How close rotational quantities must be to be equal. */
|
||||
#define GO_ROT_CLOSE(x,y) (fabs((x)-(y)) < GO_REAL_EPSILON)
|
||||
/*! How small a rotational quantity must be to be zero. */
|
||||
#define GO_ROT_SMALL(x) (fabs(x) < GO_REAL_EPSILON)
|
||||
|
||||
/*! How close general quantities must be to be equal. Use this when
|
||||
you have something other than translational or rotational quantities,
|
||||
otherwise use one of \a GO_TRAN,ROT_CLOSE. */
|
||||
#define GO_CLOSE(x,y) (fabs((x)-(y)) < GO_REAL_EPSILON)
|
||||
/*! How small a general quantity must be to be zero. Use this when
|
||||
you have something other than a translational or rotational quantity,
|
||||
otherwise use one of \a GO_TRAN,ROT_SMALL. */
|
||||
#define GO_SMALL(x) (fabs(x) < GO_REAL_EPSILON)
|
||||
|
||||
/*! A point or vector in Cartesian coordinates. */
|
||||
typedef struct {
|
||||
go_real x;
|
||||
go_real y;
|
||||
go_real z;
|
||||
} go_cart;
|
||||
|
||||
/*! A point or vector in spherical coordinates, with \a phi as
|
||||
the angle down from the zenith, not up from the XY plane. */
|
||||
typedef struct {
|
||||
go_real theta;
|
||||
go_real phi;
|
||||
go_real r;
|
||||
} go_sph;
|
||||
|
||||
/*! A point or vector in cylindrical coordinates. */
|
||||
typedef struct {
|
||||
go_real theta;
|
||||
go_real r;
|
||||
go_real z;
|
||||
} go_cyl;
|
||||
|
||||
/*! A rotation vector, whose direction points along the axis of positive
|
||||
rotation, and whose magnitude is the amount of rotation around this
|
||||
axis, in radians. */
|
||||
typedef struct {
|
||||
go_real x;
|
||||
go_real y;
|
||||
go_real z;
|
||||
} go_rvec;
|
||||
|
||||
/* | m.x.x m.y.x m.z.x | */
|
||||
/* go_mat m = | m.x.y m.y.y m.z.y | */
|
||||
/* | m.x.z m.y.z m.z.z | */
|
||||
|
||||
/*! A rotation matrix. */
|
||||
typedef struct {
|
||||
go_cart x; /*!< X unit vector */
|
||||
go_cart y; /*!< Y unit vector */
|
||||
go_cart z; /*!< Z unit vector */
|
||||
} go_mat;
|
||||
|
||||
/*! A quaternion. \a s is the cosine of the half angle of rotation,
|
||||
and the \a xyz elements comprise the vector that points in the direction
|
||||
of positive rotation and whose magnitude is the sine of the half
|
||||
angle of rotation. */
|
||||
typedef struct {
|
||||
go_real s;
|
||||
go_real x;
|
||||
go_real y;
|
||||
go_real z;
|
||||
} go_quat;
|
||||
|
||||
/*! ZYZ Euler angles. \a z is the amount of the first rotation around the
|
||||
Z axis. \a y is the amount of the second rotation around the new \a Y
|
||||
axis. \a zp is the amount of the third rotation around the new \a Z axis. */
|
||||
typedef struct {
|
||||
go_real z;
|
||||
go_real y;
|
||||
go_real zp;
|
||||
} go_zyz;
|
||||
|
||||
/*! ZYX Euler angles. \a z is the amount of the first rotation around the
|
||||
Z axis. \a y is the amount of the second rotation around the new \a Y
|
||||
axis. \a x is the amount of the third rotation around the new \a X axis. */
|
||||
typedef struct {
|
||||
go_real z;
|
||||
go_real y;
|
||||
go_real x;
|
||||
} go_zyx;
|
||||
|
||||
/*! Roll-pitch-yaw angles. \a r is the amount of the first rotation
|
||||
(roll) around the X axis. \a p is the amount of the second rotation
|
||||
(pitch) around the original Y axis. \a y is the amount of the third
|
||||
rotation (yaw) around the original Z axis. */
|
||||
typedef struct {
|
||||
go_real r;
|
||||
go_real p;
|
||||
go_real y;
|
||||
} go_rpy;
|
||||
|
||||
/*!
|
||||
A \a go_pose represents the Cartesian position vector and quaternion
|
||||
orientation of a frame.
|
||||
*/
|
||||
typedef struct {
|
||||
go_cart tran;
|
||||
go_quat rot;
|
||||
} go_pose;
|
||||
|
||||
/*!
|
||||
A \a go_screw represents the linear- and angular velocity vectors
|
||||
of a frame. \a v is the Cartesian linear velocity vector.
|
||||
\a w is the Cartesian angular velocity vector, the instantaneous
|
||||
vector about which the frame is rotating.
|
||||
*/
|
||||
typedef struct {
|
||||
go_cart v;
|
||||
go_cart w;
|
||||
} go_screw;
|
||||
|
||||
/*! Convenience function that returns a \a go_pose given individual
|
||||
elements. */
|
||||
extern go_pose
|
||||
go_pose_this(go_real x, go_real y, go_real z,
|
||||
go_real rs, go_real rx, go_real ry, go_real rz);
|
||||
|
||||
/*! Returns the zero vector. */
|
||||
extern go_cart
|
||||
go_cart_zero(void);
|
||||
|
||||
/*! Returns the identity (zero) quaternion, i.e., no rotation. */
|
||||
extern go_quat
|
||||
go_quat_identity(void);
|
||||
|
||||
/*! Returns the identity pose, no translation or rotation. */
|
||||
extern go_pose
|
||||
go_pose_identity(void);
|
||||
|
||||
typedef struct {
|
||||
go_cart tran;
|
||||
go_mat rot;
|
||||
} go_hom;
|
||||
|
||||
/* lines, planes and related functions */
|
||||
|
||||
/*!
|
||||
Lines are represented in point-direction form
|
||||
(point p, direction v) as
|
||||
(x - px)/vx = (y - py)/vy = (z - pz)vz
|
||||
*/
|
||||
typedef struct {
|
||||
go_cart point;
|
||||
go_cart direction; /* always a unit vector */
|
||||
} go_line;
|
||||
|
||||
/*!
|
||||
Given a plane as Ax + By + Cz + D = 0, the normal vector
|
||||
\a normal is the Cartesian vector (A,B,C), and the number
|
||||
\a d is the value D.
|
||||
|
||||
Planes have a handedness, given by the direction of the normal
|
||||
vector, so two planes that appear coincident may be different by the
|
||||
direction of their anti-parallel normal vectors.
|
||||
*/
|
||||
typedef struct {
|
||||
go_cart normal;
|
||||
go_real d;
|
||||
} go_plane;
|
||||
|
||||
/*! Fills in \a line given \a point and \a direction. Returns GO_RESULT_OK
|
||||
if \a direction is non-zero, otherwise GO_RESULT_ERROR. */
|
||||
extern int go_line_from_point_direction(const go_cart * point, const go_cart * direction, go_line * line);
|
||||
|
||||
/*! Fills in \a line given two points. Returns GO_RESULT_OK if the points
|
||||
are different, otherwise GO_RESULT_ERROR. */
|
||||
extern int go_line_from_points(const go_cart * point1, const go_cart * point2, go_line * line);
|
||||
|
||||
/*! Fill in \a line with the intersection of the two planes. Returns GO_RESULT_OK if the planes are not parallel, otherwise GO_RESULT_ERROR. */
|
||||
extern int go_line_from_planes(const go_plane * plane1, const go_plane * plane2, go_line * line);
|
||||
|
||||
/*! Returns non-zero if the lines are the same, otherwise zero. */
|
||||
extern go_flag go_line_line_compare(const go_line * line1, const go_line * line2);
|
||||
|
||||
/*! Fills in \a point with the point located distance \a d along \a line */
|
||||
extern int go_line_evaluate(const go_line * line, go_real d, go_cart * point);
|
||||
|
||||
/*! Fills in \a distance with the distance from \a point to \a line */
|
||||
extern int go_point_line_distance(const go_cart * point, const go_line * line, go_real * distance);
|
||||
|
||||
/*! Fills in \a pout with the nearest point on \a line to \a point */
|
||||
extern int go_point_line_proj(const go_cart * point, const go_line * line, go_cart * pout);
|
||||
|
||||
/*! Fills in \a proj with the projection of \a point onto \a plane */
|
||||
extern int go_point_plane_proj(const go_cart * point, const go_plane * plane, go_cart * proj);
|
||||
|
||||
/*! Fills in \a proj with the projection of \a line onto \a plane */
|
||||
extern int go_line_plane_proj(const go_line * line, const go_plane * plane, go_line * proj);
|
||||
|
||||
/*! Fills in \a plane give a \a point on the plane and the normal \a direction. */
|
||||
extern int go_plane_from_point_normal(const go_cart * point, const go_cart * normal, go_plane * plane);
|
||||
|
||||
/*! Fills in \a plane given the A, B, C and D values in the canonical
|
||||
form Ax + By + Cz + D = 0. Returns GO_RESULT_OK
|
||||
if not all of A, B and C are zero, otherwise GO_RESULT_ERROR. */
|
||||
extern int go_plane_from_abcd(go_real A, go_real B, go_real C, go_real D, go_plane * plane);
|
||||
|
||||
/*! Fills in \a plane given three points. Returns GO_RESULT_OK
|
||||
if the points are distinct, otherwise GO_RESULT_ERROR. */
|
||||
extern int go_plane_from_points(const go_cart * point1, const go_cart * point2, const go_cart * point3, go_plane * plane);
|
||||
|
||||
/*! Fills in \a plane given a \a point on the plane and a \a line
|
||||
in the plane. Returns GO_RESULT_OK if the point is not on the line,
|
||||
GO_RESULT_ERROR otherwise. */
|
||||
extern int go_plane_from_point_line(const go_cart * point, const go_line * line, go_plane * plane);
|
||||
|
||||
/*! Returns non-zero if the planes are coincident and have the same
|
||||
normal direction, otherwise zero. */
|
||||
extern go_flag go_plane_plane_compare(const go_plane * plane1, const go_plane * plane2);
|
||||
|
||||
/*! Fills in the \a distance from the \a point to the \a plane. */
|
||||
extern int go_point_plane_distance(const go_cart * point, const go_plane * plane, go_real * distance);
|
||||
|
||||
/*! Fills in \a point with the point located distances \a u and \a v along
|
||||
some orthogonal planar coordinate system in \a plane */
|
||||
extern int go_plane_evaluate(const go_plane * plane, go_real u, go_real v, go_cart * point);
|
||||
|
||||
/*! Fills in \a point with the intersection point of
|
||||
\a line with \a plane, and \a distance with the distance along the
|
||||
line to the intersection point. Returns GO_RESULT_ERROR if the line
|
||||
is parallel to the plane and not lying in the plane, otherwise
|
||||
GO_RESULT_OK. */
|
||||
extern int go_line_plane_intersect(const go_line * line, const go_plane * plane, go_cart * point, go_real * distance);
|
||||
|
||||
/*
|
||||
struct arguments are passed to functions as const pointers since the
|
||||
speed is at least as fast for all but structs of one or two elements.
|
||||
*/
|
||||
|
||||
/* translation rep conversion functions */
|
||||
|
||||
extern int go_cart_sph_convert(const go_cart *, go_sph *);
|
||||
extern int go_cart_cyl_convert(const go_cart *, go_cyl *);
|
||||
extern int go_sph_cart_convert(const go_sph *, go_cart *);
|
||||
extern int go_sph_cyl_convert(const go_sph *, go_cyl *);
|
||||
extern int go_cyl_cart_convert(const go_cyl *, go_cart *);
|
||||
extern int go_cyl_sph_convert(const go_cyl *, go_sph *);
|
||||
|
||||
/* rotation rep conversion functions */
|
||||
|
||||
extern int go_rvec_quat_convert(const go_rvec *, go_quat *);
|
||||
extern int go_rvec_mat_convert(const go_rvec *, go_mat *);
|
||||
extern int go_rvec_zyz_convert(const go_rvec *, go_zyz *);
|
||||
extern int go_rvec_zyx_convert(const go_rvec *, go_zyx *);
|
||||
extern int go_rvec_rpy_convert(const go_rvec *, go_rpy *);
|
||||
|
||||
extern int go_quat_rvec_convert(const go_quat *, go_rvec *);
|
||||
extern int go_quat_mat_convert(const go_quat *, go_mat *);
|
||||
extern int go_quat_zyz_convert(const go_quat *, go_zyz *);
|
||||
extern int go_quat_zyx_convert(const go_quat *, go_zyx *);
|
||||
extern int go_quat_rpy_convert(const go_quat *, go_rpy *);
|
||||
|
||||
extern int go_mat_rvec_convert(const go_mat *, go_rvec *);
|
||||
extern int go_mat_quat_convert(const go_mat *, go_quat *);
|
||||
extern int go_mat_zyz_convert(const go_mat *, go_zyz *);
|
||||
extern int go_mat_zyx_convert(const go_mat *, go_zyx *);
|
||||
extern int go_mat_rpy_convert(const go_mat *, go_rpy *);
|
||||
|
||||
extern int go_zyz_rvec_convert(const go_zyz *, go_rvec *);
|
||||
extern int go_zyz_quat_convert(const go_zyz *, go_quat *);
|
||||
extern int go_zyz_mat_convert(const go_zyz *, go_mat *);
|
||||
extern int go_zyz_zyx_convert(const go_zyz *, go_zyx *);
|
||||
extern int go_zyz_rpy_convert(const go_zyz *, go_rpy *);
|
||||
|
||||
extern int go_zyx_rvec_convert(const go_zyx *, go_rvec *);
|
||||
extern int go_zyx_quat_convert(const go_zyx *, go_quat *);
|
||||
extern int go_zyx_mat_convert(const go_zyx *, go_mat *);
|
||||
extern int go_zyx_zyz_convert(const go_zyx *, go_zyz *);
|
||||
extern int go_zyx_rpy_convert(const go_zyx *, go_rpy *);
|
||||
|
||||
extern int go_rpy_rvec_convert(const go_rpy *, go_rvec *);
|
||||
extern int go_rpy_quat_convert(const go_rpy *, go_quat *);
|
||||
extern int go_rpy_mat_convert(const go_rpy *, go_mat *);
|
||||
extern int go_rpy_zyz_convert(const go_rpy *, go_zyz *);
|
||||
extern int go_rpy_zyx_convert(const go_rpy *, go_zyx *);
|
||||
|
||||
/* combined rep conversion functions */
|
||||
|
||||
extern int go_pose_hom_convert(const go_pose *, go_hom *);
|
||||
extern int go_hom_pose_convert(const go_hom *, go_pose *);
|
||||
|
||||
/* misc conversion functions */
|
||||
/*!
|
||||
go_cart_rvec_convert and go_rvec_cart_convert convert between
|
||||
Cartesian vectors and rotation vectors. The conversion is trivial
|
||||
but keeps types distinct.
|
||||
*/
|
||||
extern int go_cart_rvec_convert(const go_cart * cart, go_rvec * rvec);
|
||||
extern int go_rvec_cart_convert(const go_rvec * rvec, go_cart * cart);
|
||||
|
||||
/* translation functions, that work only with the preferred
|
||||
go_cart type. Other types must be converted to go_cart
|
||||
to use these, e.g., there's no go_sph_cyl_compare() */
|
||||
|
||||
extern go_flag go_cart_cart_compare(const go_cart *, const go_cart *);
|
||||
extern int go_cart_cart_dot(const go_cart *, const go_cart *,
|
||||
go_real *);
|
||||
extern int go_cart_cart_cross(const go_cart *, const go_cart *,
|
||||
go_cart *);
|
||||
extern int go_cart_mag(const go_cart *, go_real *);
|
||||
extern int go_cart_magsq(const go_cart *, go_real *);
|
||||
extern go_flag go_cart_cart_par(const go_cart *, const go_cart *);
|
||||
extern go_flag go_cart_cart_perp(const go_cart *, const go_cart *);
|
||||
|
||||
/*! Places the Cartesian displacement between two vectors \a v1 and
|
||||
\a v2 in \a disp, returning \a GO_RESULT_OK. */
|
||||
extern int go_cart_cart_disp(const go_cart * v1,
|
||||
const go_cart * v2,
|
||||
go_real * disp);
|
||||
|
||||
extern int go_cart_cart_add(const go_cart *, const go_cart *,
|
||||
go_cart *);
|
||||
extern int go_cart_cart_sub(const go_cart *, const go_cart *,
|
||||
go_cart *);
|
||||
extern int go_cart_scale_mult(const go_cart *, go_real, go_cart *);
|
||||
extern int go_cart_neg(const go_cart *, go_cart *);
|
||||
extern int go_cart_unit(const go_cart *, go_cart *);
|
||||
|
||||
/*!
|
||||
Given two non-zero vectors \a v1 and \a v2, fill in \a quat with
|
||||
the minimum rotation that brings \a v1 to \a v2.
|
||||
*/
|
||||
extern int go_cart_cart_rot(const go_cart * v1,
|
||||
const go_cart * v2,
|
||||
go_quat * quat);
|
||||
|
||||
/*!
|
||||
Project vector \a v1 onto \a v2, with the resulting vector placed
|
||||
into \a vout. Returns GO_RESULT_OK if it can be done, otherwise
|
||||
something else.
|
||||
*/
|
||||
extern int go_cart_cart_proj(const go_cart * v1, const go_cart * v2,
|
||||
go_cart * vout);
|
||||
extern int go_cart_plane_proj(const go_cart *, const go_cart *,
|
||||
go_cart *);
|
||||
extern int go_cart_cart_angle(const go_cart *, const go_cart *,
|
||||
go_real *);
|
||||
/*!
|
||||
go_cart_normal finds one of the infinite vectors perpendicular
|
||||
to \a v, putting the result in \a vout.
|
||||
*/
|
||||
extern int go_cart_normal(const go_cart * v, go_cart * vout);
|
||||
extern int go_cart_centroid(const go_cart * varray,
|
||||
go_integer num,
|
||||
go_cart * centroid);
|
||||
extern int go_cart_centroidize(const go_cart * vinarray,
|
||||
go_integer num,
|
||||
go_cart * centroid,
|
||||
go_cart * voutarray);
|
||||
extern int go_cart_cart_pose(const go_cart *, const go_cart *,
|
||||
go_cart *, go_cart *,
|
||||
go_integer, go_pose *);
|
||||
|
||||
/*!
|
||||
Returns the Cartesian point \a p whose distances from three other points
|
||||
\a c1, \a c2 and \a c3 are \a l1, \a l2 and \a l3, respectively. In
|
||||
general there are 0, 1 or two points possible. If no point is possible,
|
||||
this returns GO_RESULT_ERROR, otherwise the points are returned in \a
|
||||
p1 and \a p2, which may be the same point.
|
||||
*/
|
||||
|
||||
int go_cart_trilaterate(const go_cart * c1,
|
||||
const go_cart * c2,
|
||||
const go_cart * c3,
|
||||
go_real l1,
|
||||
go_real l2,
|
||||
go_real l3,
|
||||
go_cart * p1,
|
||||
go_cart * p2);
|
||||
|
||||
/* quat functions */
|
||||
|
||||
extern go_flag go_quat_quat_compare(const go_quat *, const go_quat *);
|
||||
extern int go_quat_mag(const go_quat *, go_real *);
|
||||
|
||||
/*!
|
||||
go_quat_unit takes a quaternion rotation \a q and converts it into
|
||||
a unit rotation about the same axis, \a qout.
|
||||
*/
|
||||
extern int go_quat_unit(const go_quat * q, go_quat * qout);
|
||||
extern int go_quat_norm(const go_quat *, go_quat *);
|
||||
extern int go_quat_inv(const go_quat *, go_quat *);
|
||||
extern go_flag go_quat_is_norm(const go_quat *);
|
||||
extern int go_quat_scale_mult(const go_quat *, go_real, go_quat *);
|
||||
extern int go_quat_quat_mult(const go_quat *, const go_quat *,
|
||||
go_quat *);
|
||||
extern int go_quat_cart_mult(const go_quat *, const go_cart *,
|
||||
go_cart *);
|
||||
|
||||
/* rotation vector functions */
|
||||
|
||||
extern go_flag go_rvec_rvec_compare(const go_rvec * r1, const go_rvec * r2);
|
||||
extern int go_rvec_scale_mult(const go_rvec *, go_real, go_rvec *);
|
||||
|
||||
/* rotation matrix functions */
|
||||
|
||||
/* | m.x.x m.y.x m.z.x | */
|
||||
/* M = | m.x.y m.y.y m.z.y | */
|
||||
/* | m.x.z m.y.z m.z.z | */
|
||||
|
||||
/*!
|
||||
Normalizes rotation matrix \a m so that all columns are mutually
|
||||
perpendicular unit vectors, placing the result in \a mout.
|
||||
*/
|
||||
extern int go_mat_norm(const go_mat * m, go_mat * mout);
|
||||
|
||||
extern go_flag go_mat_is_norm(const go_mat *);
|
||||
extern int go_mat_inv(const go_mat *, go_mat *);
|
||||
extern int go_mat_cart_mult(const go_mat *, const go_cart *, go_cart *);
|
||||
extern int go_mat_mat_mult(const go_mat *, const go_mat *, go_mat *);
|
||||
|
||||
/* pose functions*/
|
||||
|
||||
extern go_flag go_pose_pose_compare(const go_pose *, const go_pose *);
|
||||
extern int go_pose_inv(const go_pose *, go_pose *);
|
||||
extern int go_pose_cart_mult(const go_pose *, const go_cart *, go_cart *);
|
||||
extern int go_pose_pose_mult(const go_pose *, const go_pose *, go_pose *);
|
||||
extern int go_pose_scale_mult(const go_pose *, go_real, go_pose *);
|
||||
|
||||
/*! Given two times \a t1 and \a t2, and associated poses \a p1 and \a
|
||||
p2, interpolates (or extrapolates) to find pose \a p3 at time \a
|
||||
t3. The result is stored in \a p3. Returns GO_RESULT_OK if \a t1 and
|
||||
\a t2 are distinct and \a p1 and \a p2 are valid poses, otherwise it
|
||||
can't interpolate and returns a relevant error. */
|
||||
extern int
|
||||
go_pose_pose_interp(go_real t1,
|
||||
const go_pose * p1,
|
||||
go_real t2,
|
||||
const go_pose * p2,
|
||||
go_real t3,
|
||||
go_pose * p3);
|
||||
|
||||
/* homogeneous transform functions */
|
||||
|
||||
extern int go_hom_inv(const go_hom *, go_hom *);
|
||||
|
||||
/* screw functions */
|
||||
|
||||
/*! Given \a pose transformation from frame A to B, and a screw \a screw
|
||||
in frame A, transform the screw into frame B and place in \a out. */
|
||||
extern int go_pose_screw_mult(const go_pose * pose, const go_screw * screw, go_screw * out);
|
||||
|
||||
/* declarations for general MxN matrices */
|
||||
|
||||
/*!
|
||||
Declare a matrix variable \a m with \a rows rows and \a cols columns.
|
||||
Allocates \a rows X \a columns of space in \a mspace.
|
||||
*/
|
||||
|
||||
typedef go_real go_vector;
|
||||
|
||||
typedef struct {
|
||||
go_integer rows;
|
||||
go_integer cols;
|
||||
go_real ** el;
|
||||
go_real ** elcpy;
|
||||
go_real * v;
|
||||
go_integer * index;
|
||||
} go_matrix;
|
||||
|
||||
#define GO_MATRIX_DECLARE(M,Mspace,_rows,_cols) \
|
||||
go_matrix M = {0, 0, 0, 0, 0, 0}; \
|
||||
struct { \
|
||||
go_real * el[_rows]; \
|
||||
go_real * elcpy[_rows]; \
|
||||
go_real stg[_rows][_cols]; \
|
||||
go_real stgcpy[_rows][_cols]; \
|
||||
go_real v[_rows]; \
|
||||
go_integer index[_rows]; \
|
||||
} Mspace
|
||||
|
||||
#define go_matrix_init(M,Mspace,_rows,_cols) \
|
||||
M.el = Mspace.el; \
|
||||
M.elcpy = Mspace.elcpy; \
|
||||
for (M.rows = 0; M.rows < (_rows); M.rows++) { \
|
||||
M.el[M.rows] = Mspace.stg[M.rows]; \
|
||||
M.elcpy[M.rows] = Mspace.stgcpy[M.rows]; \
|
||||
} \
|
||||
M.rows = (_rows); \
|
||||
M.cols = (_cols); \
|
||||
M.v = Mspace.v; \
|
||||
M.index = Mspace.index
|
||||
|
||||
extern go_real
|
||||
go_get_singular_epsilon(void);
|
||||
|
||||
extern int
|
||||
go_set_singular_epsilon(go_real epsilon);
|
||||
|
||||
extern int
|
||||
ludcmp(go_real ** a,
|
||||
go_real * scratchrow,
|
||||
go_integer n,
|
||||
go_integer * indx,
|
||||
go_real * d);
|
||||
|
||||
extern int
|
||||
lubksb(go_real ** a,
|
||||
go_integer n,
|
||||
go_integer * indx,
|
||||
go_real * b);
|
||||
|
||||
/* MxN matrix, Mx1 vector functions */
|
||||
|
||||
extern int
|
||||
go_cart_vector_convert(const go_cart * c,
|
||||
go_vector * v);
|
||||
extern int
|
||||
go_vector_cart_convert(const go_real * v,
|
||||
go_cart * c);
|
||||
|
||||
extern int
|
||||
go_quat_matrix_convert(const go_quat * quat,
|
||||
go_matrix * matrix);
|
||||
|
||||
extern int
|
||||
go_mat_matrix_convert(const go_mat * mat,
|
||||
go_matrix * matrix);
|
||||
|
||||
extern int
|
||||
go_matrix_matrix_add(const go_matrix * a,
|
||||
const go_matrix * b,
|
||||
go_matrix * apb);
|
||||
|
||||
extern int
|
||||
go_matrix_matrix_copy(const go_matrix * src,
|
||||
go_matrix * dst);
|
||||
|
||||
extern int
|
||||
go_matrix_matrix_mult(const go_matrix * a,
|
||||
const go_matrix * b,
|
||||
go_matrix * ab);
|
||||
|
||||
extern int
|
||||
go_matrix_vector_mult(const go_matrix * a,
|
||||
const go_vector * v,
|
||||
go_vector * av);
|
||||
|
||||
/*!
|
||||
The matrix-vector cross product is a matrix of the same dimension,
|
||||
whose columns are the column-wise cross products of the matrix
|
||||
and the vector. The matrices must be 3xN, the vector 3x1.
|
||||
*/
|
||||
extern int
|
||||
go_matrix_vector_cross(const go_matrix * a,
|
||||
const go_vector * v,
|
||||
go_matrix * axv);
|
||||
|
||||
extern int
|
||||
go_matrix_transpose(const go_matrix * a,
|
||||
go_matrix * at);
|
||||
|
||||
extern int
|
||||
go_matrix_inv(const go_matrix * a,
|
||||
go_matrix * ainv);
|
||||
|
||||
/* Square matrix functions, where matN is an NxN matrix, and vecN
|
||||
is an Nx1 vector */
|
||||
|
||||
/* Optimized 3x3 functions */
|
||||
extern int go_mat3_inv(const go_real a[3][3],
|
||||
go_real ainv[3][3]);
|
||||
extern int go_mat3_mat3_mult(const go_real a[3][3],
|
||||
const go_real b[3][3],
|
||||
go_real axb[3][3]);
|
||||
extern int go_mat3_vec3_mult(const go_real a[3][3],
|
||||
const go_real v[3],
|
||||
go_real axv[3]);
|
||||
|
||||
/* Optimized 4x4 functions */
|
||||
extern int go_mat4_inv(const go_real a[4][4],
|
||||
go_real ainv[4][4]);
|
||||
extern int go_mat4_mat4_mult(const go_real a[4][4],
|
||||
const go_real b[4][4],
|
||||
go_real axb[4][4]);
|
||||
extern int go_mat4_vec4_mult(const go_real a[4][4],
|
||||
const go_real v[4],
|
||||
go_real axv[4]);
|
||||
|
||||
/*!
|
||||
Given a 6x6 matrix \a a, computes the inverse and returns it in
|
||||
\a ainv. Leaves \a a untouched. Returns GO_RESULT_OK if there is an
|
||||
inverse, else GO_RESULT_SINGULAR if the matrix is singular.
|
||||
*/
|
||||
extern int go_mat6_inv(const go_real a[6][6],
|
||||
go_real ainv[6][6]);
|
||||
|
||||
/*!
|
||||
Given two 6x6 matrices \a a and \a b, multiplies them and returns
|
||||
the result in \a axb. Leaves \a a and \a b untouched.
|
||||
Returns GO_RESULT_OK.
|
||||
*/
|
||||
extern int go_mat6_mat6_mult(const go_real a[6][6],
|
||||
const go_real b[6][6],
|
||||
go_real axb[6][6]);
|
||||
|
||||
/*!
|
||||
Given a 6x6 matrix \a a and a 6x1 vector \a v, multiplies them
|
||||
and returns the result in \a axv. Leaves \a a and \a v untouched.
|
||||
Returns GO_RESULT_OK.
|
||||
*/
|
||||
extern int go_mat6_vec6_mult(const go_real a[6][6],
|
||||
const go_real v[6],
|
||||
go_real axv[6]);
|
||||
|
||||
/* Denavit-Hartenberg to pose conversions */
|
||||
|
||||
/*
|
||||
The link frame is assumed to be
|
||||
|
||||
| i-1
|
||||
| T
|
||||
| i
|
||||
|
||||
that is, elements of the link frame expressed wrt the
|
||||
previous link frame.
|
||||
*/
|
||||
|
||||
/*!
|
||||
These DH parameters follow the convention in John J. Craig,
|
||||
_Introduction to Robotics: Mechanics and Control_.
|
||||
*/
|
||||
typedef struct {
|
||||
go_real a; /*< a[i-1] */
|
||||
go_real alpha; /*< alpha[i-1] */
|
||||
/* either d or theta are the free variable, depending on quantity */
|
||||
go_real d; /*< d[i] */
|
||||
go_real theta; /*< theta[i] */
|
||||
} go_dh;
|
||||
|
||||
/*!
|
||||
PK parameters are used for parallel kinematic mechanisms, and
|
||||
represent the Cartesian positions of the ends of the link in the
|
||||
stationary base frame and the moving platform frame. Currently this
|
||||
only supports prismatic links.
|
||||
*/
|
||||
typedef struct {
|
||||
go_cart base; /*< position of fixed end in base frame */
|
||||
go_cart platform; /*< position of moving end in platform frame */
|
||||
go_real d; /*< the length of the link */
|
||||
} go_pk;
|
||||
|
||||
/*!
|
||||
PP parameters represent the pose of the link with respect to the
|
||||
previous link. Revolute joints rotate about the Z axis, prismatic
|
||||
joints slide along the Z axis.
|
||||
*/
|
||||
typedef struct {
|
||||
go_pose pose; /*< the pose of the link wrt to the previous link */
|
||||
} go_pp;
|
||||
|
||||
/*! Types of link parameter representations */
|
||||
enum {
|
||||
GO_LINK_DH = 1, /*< for Denavit-Hartenberg params */
|
||||
GO_LINK_PK, /*< for parallel kinematics */
|
||||
GO_LINK_PP /*< for serial kinematics */
|
||||
};
|
||||
|
||||
#define go_link_to_string(L) \
|
||||
(L) == GO_LINK_DH ? "DH" : \
|
||||
(L) == GO_LINK_PK ? "PK" : \
|
||||
(L) == GO_LINK_PP ? "PP" : "None"
|
||||
|
||||
/*!
|
||||
This is the generic link structure for PKM sliding/cable links and
|
||||
serial revolute/prismatic links.
|
||||
*/
|
||||
typedef struct {
|
||||
union {
|
||||
go_dh dh; /*< if you have DH params and don't want to convert to PP */
|
||||
go_pk pk; /*< if you have a parallel machine, e.g., hexapod or robot crane */
|
||||
go_pp pp; /*< if you have a serial machine, e.g., an industrial robot */
|
||||
} u;
|
||||
go_flag type; /*< one of GO_LINK_DH,PK,PP */
|
||||
go_flag quantity; /*< one of GO_QUANTITY_LENGTH,ANGLE */
|
||||
} go_link;
|
||||
|
||||
/*!
|
||||
Converts DH parameters in \a dh to their pose equivalent, stored
|
||||
in \a pose.
|
||||
*/
|
||||
extern int go_dh_pose_convert(const go_dh * dh, go_pose * pose);
|
||||
|
||||
/*!
|
||||
Converts \a pose to the equivalent DH parameters, stored in \a dh.
|
||||
Warning! Conversion from these DH parameters back to a pose via \a
|
||||
go_dh_pose_convert will NOT in general result in the same
|
||||
pose. Poses have 6 degrees of freedom, DH parameters have 4, and
|
||||
conversion to DH parameters loses some information. The source of
|
||||
this information loss is the convention imposed on DH parameters for
|
||||
choice of X-Y-Z axis directions. With poses, there is no such
|
||||
convention, and poses are thus freer than DH parameters.
|
||||
*/
|
||||
extern int go_pose_dh_convert(const go_pose * pose, go_dh * dh);
|
||||
|
||||
/*!
|
||||
Fixes the link in \a link to its value when the joint
|
||||
variable is \a joint, storing the result in \a linkout.
|
||||
*/
|
||||
extern int go_link_joint_set(const go_link * link, go_real joint, go_link * linkout);
|
||||
|
||||
/*!
|
||||
Takes the link description of the device in \a links, and the number
|
||||
of these in \a num, and builds the pose of the device and stores in
|
||||
\a pose. \a links should have the value of the free link parameter
|
||||
filled in with the current joint value, e.g., with a prior call to
|
||||
go_link_joint_set.
|
||||
*/
|
||||
extern int go_link_pose_build(const go_link * links, go_integer num, go_pose * pose);
|
||||
|
||||
typedef struct {
|
||||
go_real re;
|
||||
go_real im;
|
||||
} go_complex;
|
||||
|
||||
extern go_complex go_complex_add(go_complex z1, go_complex z2);
|
||||
extern go_complex go_complex_sub(go_complex z1, go_complex z2);
|
||||
extern go_complex go_complex_mult(go_complex z1, go_complex z2);
|
||||
extern go_complex go_complex_div(go_complex z1, go_complex z2, int * result);
|
||||
extern go_complex go_complex_scale(go_complex z, go_real scale);
|
||||
extern go_real go_complex_mag(go_complex z);
|
||||
extern go_real go_complex_arg(go_complex z);
|
||||
extern void go_complex_sqrt(go_complex z, go_complex * z1, go_complex * z2);
|
||||
extern void go_complex_cbrt(go_complex z, go_complex * z1, go_complex * z2, go_complex * z3);
|
||||
|
||||
typedef struct {
|
||||
/* leading coefficient is 1, x^2 + ax + b = 0 */
|
||||
go_real a;
|
||||
go_real b;
|
||||
} go_quadratic;
|
||||
|
||||
typedef struct {
|
||||
/* leading coefficient is 1, x^3 + ax^2 + bx + c = 0 */
|
||||
go_real a;
|
||||
go_real b;
|
||||
go_real c;
|
||||
} go_cubic;
|
||||
|
||||
typedef struct {
|
||||
/* leading coefficient is 1, x^4 + ax^3 + bx^2 + cx + d = 0 */
|
||||
go_real a;
|
||||
go_real b;
|
||||
go_real c;
|
||||
go_real d;
|
||||
} go_quartic;
|
||||
|
||||
extern int go_quadratic_solve(const go_quadratic * quad,
|
||||
go_complex * z1,
|
||||
go_complex * z2);
|
||||
|
||||
extern int go_cubic_solve(const go_cubic * cub,
|
||||
go_complex * z1,
|
||||
go_complex * z2,
|
||||
go_complex * z3);
|
||||
|
||||
extern int go_quartic_solve(const go_quartic * quart,
|
||||
go_complex * z1,
|
||||
go_complex * z2,
|
||||
go_complex * z3,
|
||||
go_complex * z4);
|
||||
|
||||
extern int go_tridiag_reduce(go_real ** a,
|
||||
go_integer n,
|
||||
go_real * d,
|
||||
go_real * e);
|
||||
|
||||
extern int go_tridiag_ql(go_real * d,
|
||||
go_real * e,
|
||||
go_integer n,
|
||||
go_real ** z);
|
||||
|
||||
#endif /* GO_MATH_H */
|
||||
|
||||
169
wasm-port/vendor/linuxcnc/src/libnml/posemath/gotypes.h
vendored
Normal file
169
wasm-port/vendor/linuxcnc/src/libnml/posemath/gotypes.h
vendored
Normal file
@@ -0,0 +1,169 @@
|
||||
/********************************************************************
|
||||
* Description: gotypes.h
|
||||
* Library file with various functions for working with matrices
|
||||
*
|
||||
* Derived from a work by Fred Proctor,
|
||||
* changed to work with emc2 and HAL
|
||||
*
|
||||
* Adapting Author: Alex Joni
|
||||
* License: LGPL Version 2
|
||||
* System: Linux
|
||||
*
|
||||
*******************************************************************
|
||||
Similar to posemath, but using different functions.
|
||||
|
||||
TODO:
|
||||
* find the new functions, add them to posemath, convert the rest
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __LINUXCNC_GO_TYPES_H
|
||||
#define __LINUXCNC_GO_TYPES_H
|
||||
|
||||
#include <float.h> /* DBL_MAX, FLOAT_MAX */
|
||||
|
||||
/*!
|
||||
GO_RESULT symbols run through a small range of values, on the
|
||||
order of tens, suitable for a byte. GO_RESULT_OK is zero for easy
|
||||
detection of error conditions, e.g., if (result) { handle error }
|
||||
*/
|
||||
enum {
|
||||
GO_RESULT_OK = 0,
|
||||
GO_RESULT_IGNORED, /* action can't be done, ignored */
|
||||
GO_RESULT_BAD_ARGS, /* arguments bad, e.g., null pointer */
|
||||
GO_RESULT_RANGE_ERROR, /* supplied range value out of bounds */
|
||||
GO_RESULT_DOMAIN_ERROR, /* resulting domain out of bounds */
|
||||
GO_RESULT_ERROR, /* action can't be done, a problem */
|
||||
GO_RESULT_IMPL_ERROR, /* function not implemented */
|
||||
GO_RESULT_NORM_ERROR, /* a value is expected to be normalized */
|
||||
GO_RESULT_DIV_ERROR, /* divide by zero */
|
||||
GO_RESULT_SINGULAR, /* a matrix is singular */
|
||||
GO_RESULT_NO_SPACE, /* no space for append operation */
|
||||
GO_RESULT_EMPTY, /* data structure is empty */
|
||||
GO_RESULT_BUG /* a bug in Go, e.g., unknown case */
|
||||
};
|
||||
|
||||
#define go_result_to_string(r) \
|
||||
(r) == GO_RESULT_OK ? "Ok" : \
|
||||
(r) == GO_RESULT_IGNORED ? "Ignored" : \
|
||||
(r) == GO_RESULT_BAD_ARGS ? "Bad Args" : \
|
||||
(r) == GO_RESULT_RANGE_ERROR ? "Range Error" : \
|
||||
(r) == GO_RESULT_DOMAIN_ERROR ? "Domain Error" : \
|
||||
(r) == GO_RESULT_ERROR ? "General Error" : \
|
||||
(r) == GO_RESULT_IMPL_ERROR ? "Implementation Error" : \
|
||||
(r) == GO_RESULT_NORM_ERROR ? "Norm Error" : \
|
||||
(r) == GO_RESULT_DIV_ERROR ? "Div Error" : \
|
||||
(r) == GO_RESULT_SINGULAR ? "Singular" : \
|
||||
(r) == GO_RESULT_NO_SPACE ? "No Space" : \
|
||||
(r) == GO_RESULT_EMPTY ? "Empty" : \
|
||||
(r) == GO_RESULT_BUG ? "Bug" : "?"
|
||||
|
||||
/*!
|
||||
Joints are characterized by the quantities they affect, such as
|
||||
length for linear joints and angle for rotary joints.
|
||||
*/
|
||||
enum {
|
||||
GO_QUANTITY_NONE = 0,
|
||||
GO_QUANTITY_LENGTH,
|
||||
GO_QUANTITY_ANGLE
|
||||
};
|
||||
|
||||
#define go_quantity_to_string(q) \
|
||||
(q) == GO_QUANTITY_LENGTH ? "Length" : \
|
||||
(q) == GO_QUANTITY_ANGLE ? "Angle" : "None"
|
||||
|
||||
/* go_real: float, long double, default double; GO_INF is defined as
|
||||
the associated max value from float.h */
|
||||
|
||||
/*
|
||||
In IEEE floating point,
|
||||
|
||||
FLT_MIN = 1.175494e-38, FLT_EPSILON 1.192093e-07
|
||||
DBL_MIN = 2.225074e-308, DBL_EPSILON 2.220446e-16
|
||||
*/
|
||||
|
||||
#if defined(GO_REAL_FLOAT)
|
||||
typedef float go_real;
|
||||
#define GO_REAL go_real_float
|
||||
extern int go_real_float;
|
||||
#define GO_REAL_MIN FLT_MIN
|
||||
#define GO_REAL_MAX FLT_MAX
|
||||
#define GO_REAL_EPSILON (1.0e-4)
|
||||
#define GO_INF FLT_MAX
|
||||
|
||||
#elif defined(GO_REAL_LONG_DOUBLE)
|
||||
typedef long double go_real;
|
||||
#define GO_REAL go_real_long_double
|
||||
extern int go_real_long_double;
|
||||
#define GO_REAL_MIN DBL_MIN
|
||||
#define GO_REAL_MAX DBL_MAX
|
||||
#define GO_REAL_EPSILON (1.0e-10)
|
||||
#define GO_INF DBL_MAX
|
||||
|
||||
#else
|
||||
#define GO_REAL_DOUBLE
|
||||
typedef double go_real;
|
||||
#define GO_REAL go_real_double
|
||||
extern int go_real_double;
|
||||
#define GO_REAL_MIN DBL_MIN
|
||||
#define GO_REAL_MAX DBL_MAX
|
||||
#define GO_REAL_EPSILON (1.0e-7)
|
||||
#define GO_INF DBL_MAX
|
||||
#endif
|
||||
|
||||
/* go_integer: short, long, long long, default int */
|
||||
|
||||
#if defined(GO_INTEGER_SHORT)
|
||||
typedef short int go_integer;
|
||||
#define GO_INTEGER go_integer_short
|
||||
extern int go_integer_short;
|
||||
#if defined(SHRT_MAX)
|
||||
#define GO_INTEGER_MAX SHRT_MAX
|
||||
#endif
|
||||
|
||||
#elif defined(GO_INTEGER_LONG)
|
||||
typedef long int go_integer;
|
||||
#define GO_INTEGER go_integer_long
|
||||
extern int go_integer_long;
|
||||
#if defined(LONG_MAX)
|
||||
#define GO_INTEGER_MAX LONG_MAX
|
||||
#endif
|
||||
|
||||
#elif defined(GO_INTEGER_LONG_LONG)
|
||||
typedef long long int go_integer;
|
||||
#define GO_INTEGER go_integer_long_long
|
||||
extern int go_integer_long_long;
|
||||
#if defined(LONG_MAX)
|
||||
#define GO_INTEGER_MAX LONG_MAX
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define GO_INTEGER_INT
|
||||
typedef int go_integer;
|
||||
#define GO_INTEGER go_integer_int
|
||||
extern int go_integer_int;
|
||||
#if defined(INT_MAX)
|
||||
#define GO_INTEGER_MAX INT_MAX
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* go_flag: unsigned short, unsigned int, default unsigned char */
|
||||
|
||||
#if defined(GO_FLAG_USHORT)
|
||||
typedef unsigned short go_flag;
|
||||
#define GO_FLAG go_flag_ushort
|
||||
extern int go_flag_ushort;
|
||||
|
||||
#elif defined(GO_FLAG_UINT)
|
||||
typedef unsigned int go_flag;
|
||||
#define GO_FLAG go_flag_uint
|
||||
extern int go_flag_uint;
|
||||
|
||||
#else
|
||||
#define GO_FLAG_UCHAR
|
||||
typedef unsigned char go_flag;
|
||||
#define GO_FLAG go_flag_uchar
|
||||
extern int go_flag_uchar;
|
||||
#endif
|
||||
|
||||
#endif /* GO_TYPES_H */
|
||||
1015
wasm-port/vendor/linuxcnc/src/libnml/posemath/posemath.h
vendored
Normal file
1015
wasm-port/vendor/linuxcnc/src/libnml/posemath/posemath.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
20
wasm-port/vendor/linuxcnc/src/libnml/posemath/sincos.h
vendored
Normal file
20
wasm-port/vendor/linuxcnc/src/libnml/posemath/sincos.h
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
/********************************************************************
|
||||
* Description: sincos.h
|
||||
* support for native sincos functions
|
||||
*
|
||||
* Derived from a work by Fred Proctor & Will Shackleford
|
||||
*
|
||||
* Author:
|
||||
* License: LGPL Version 2
|
||||
* System: Linux
|
||||
*
|
||||
* Copyright (c) 2004 All rights reserved.
|
||||
*
|
||||
* Last change:
|
||||
********************************************************************/
|
||||
#ifndef __LINUXCNC_SINCOS_H
|
||||
#define __LINUXCNC_SINCOS_H
|
||||
|
||||
extern void pm_sincos(double x, double *sx, double *cx);
|
||||
|
||||
#endif /* #ifndef SINCOS_H */
|
||||
44
wasm-port/vendor/linuxcnc/src/rtapi/rtapi_byteorder.h
vendored
Normal file
44
wasm-port/vendor/linuxcnc/src/rtapi/rtapi_byteorder.h
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Jeff Epler <jepler@unpythonic.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
#ifndef __LINUXCNC_RTAPI_BYTEORDER_H
|
||||
#define __LINUXCNC_RTAPI_BYTEORDER_H
|
||||
#ifdef __KERNEL__
|
||||
#include <asm/byteorder.h>
|
||||
#ifdef __BIG_ENDIAN
|
||||
#define RTAPI_BIG_ENDIAN 1
|
||||
#define RTAPI_LITTLE_ENDIAN 0
|
||||
#define RTAPI_FLOAT_BIG_ENDIAN 1
|
||||
#else
|
||||
#define RTAPI_LITTLE_ENDIAN 1
|
||||
#define RTAPI_BIG_ENDIAN 0
|
||||
#define RTAPI_FLOAT_BIG_ENDIAN 0
|
||||
#endif
|
||||
#else
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/endian.h>
|
||||
#define RTAPI_BIG_ENDIAN (_BYTE_ORDER == _BIG_ENDIAN)
|
||||
#define RTAPI_LITTLE_ENDIAN (_BYTE_ORDER == _LITTLE_ENDIAN)
|
||||
#define RTAPI_FLOAT_BIG_ENDIAN (_FLOAT_WORD_ORDER == _BIG_ENDIAN)
|
||||
#else
|
||||
#include <endian.h>
|
||||
#define RTAPI_BIG_ENDIAN (__BYTE_ORDER == __BIG_ENDIAN)
|
||||
#define RTAPI_LITTLE_ENDIAN (__BYTE_ORDER == __LITTLE_ENDIAN)
|
||||
#define RTAPI_FLOAT_BIG_ENDIAN (__FLOAT_WORD_ORDER == __BIG_ENDIAN)
|
||||
#endif /* !__FreeBSD__ */
|
||||
#endif
|
||||
#endif
|
||||
52
wasm-port/vendor/linuxcnc/src/rtapi/rtapi_gfp.h
vendored
Normal file
52
wasm-port/vendor/linuxcnc/src/rtapi/rtapi_gfp.h
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright 2014 Jeff Epler
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#ifndef __LINUXCNC_RTAPI_GFP_H
|
||||
#define __LINUXCNC_RTAPI_GFP_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/gfp.h>
|
||||
|
||||
// types
|
||||
#define rtapi_gpf_e gpf_e
|
||||
#define rtapi_gpf_t gpf_t
|
||||
|
||||
// enumerated values
|
||||
#define RTAPI_GFP_BUFFER GFP_BUFFER
|
||||
#define RTAPI_GFP_ATOMIC GFP_ATOMIC
|
||||
#define RTAPI_GFP_KERNEL GFP_KERNEL
|
||||
#define RTAPI_GFP_USER GFP_USER
|
||||
#define RTAPI_GFP_NOBUFFER GFP_NOBUFFER
|
||||
#define RTAPI_GFP_NFS GFP_NFS
|
||||
#define RTAPI_GFP_DMA GFP_DMA
|
||||
|
||||
#else
|
||||
|
||||
enum rtapi_gfp_e {
|
||||
RTAPI_GFP_BUFFER,
|
||||
RTAPI_GFP_ATOMIC,
|
||||
RTAPI_GFP_KERNEL,
|
||||
RTAPI_GFP_USER,
|
||||
RTAPI_GFP_NOBUFFER,
|
||||
RTAPI_GFP_NFS,
|
||||
RTAPI_GFP_DMA
|
||||
};
|
||||
|
||||
typedef unsigned long rtapi_gfp_t;
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
132
wasm-port/vendor/linuxcnc/src/rtapi/rtapi_math.h
vendored
Normal file
132
wasm-port/vendor/linuxcnc/src/rtapi/rtapi_math.h
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
// Copyright 2006-2010 Various Authors
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#ifndef __LINUXCNC_RTAPI_MATH_H
|
||||
#define __LINUXCNC_RTAPI_MATH_H
|
||||
|
||||
#include "rtapi.h" /* Because of all the rtapi refs */
|
||||
#include <float.h> /* DBL_MAX and other FP goodies */
|
||||
|
||||
#ifndef M_PIl
|
||||
#define M_PIl 3.1415926535897932384626433832795029L /* pi */
|
||||
#endif
|
||||
#ifndef M_PI_2l
|
||||
#define M_PI_2l 1.570796326794896619231321691639751442L /* pi/2 */
|
||||
#endif
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.1415926535897932384626433832795029 /* pi */
|
||||
#endif
|
||||
|
||||
#if defined(__KERNEL__)
|
||||
extern double sin(double);
|
||||
extern double cos(double);
|
||||
extern double tan(double);
|
||||
extern double sqrt(double);
|
||||
extern double fabs(double);
|
||||
extern double atan(double);
|
||||
extern double atan2(double, double);
|
||||
extern double asin(double);
|
||||
extern double acos(double);
|
||||
extern double exp(double);
|
||||
extern double pow(double, double);
|
||||
extern double fmin(double, double);
|
||||
extern double fmax(double, double);
|
||||
extern double fmod(double, double);
|
||||
|
||||
extern double round(double);
|
||||
extern double ceil(double);
|
||||
extern double floor(double);
|
||||
|
||||
#define frexp(p,q) __builtin_frexp((p),(q))
|
||||
#define isnan(x) __builtin_isnan((x))
|
||||
#define signbit(x) __builtin_signbit((x))
|
||||
#define nan(x) __builtin_nan((x))
|
||||
|
||||
#define isinf(x) __builtin_isinf((x))
|
||||
#define isfinite(x) __builtin_isfinite((x))
|
||||
|
||||
#ifdef __i386__
|
||||
#include "rtapi_math_i386.h"
|
||||
#endif
|
||||
|
||||
#else
|
||||
#include <math.h>
|
||||
#endif
|
||||
|
||||
#include "rtapi_byteorder.h"
|
||||
|
||||
// adapted from ieee754.h
|
||||
union ieee754_double
|
||||
{
|
||||
double d;
|
||||
|
||||
/* This is the IEEE 754 double-precision format. */
|
||||
struct
|
||||
{
|
||||
#if RTAPI_BIG_ENDIAN
|
||||
unsigned int negative:1;
|
||||
unsigned int exponent:11;
|
||||
/* Together these comprise the mantissa. */
|
||||
unsigned int mantissa0:20;
|
||||
unsigned int mantissa1:32;
|
||||
#endif /* Big endian. */
|
||||
#if RTAPI_LITTLE_ENDIAN
|
||||
# if RTAPI_FLOAT_BIG_ENDIAN
|
||||
unsigned int mantissa0:20;
|
||||
unsigned int exponent:11;
|
||||
unsigned int negative:1;
|
||||
unsigned int mantissa1:32;
|
||||
# else
|
||||
/* Together these comprise the mantissa. */
|
||||
unsigned int mantissa1:32;
|
||||
unsigned int mantissa0:20;
|
||||
unsigned int exponent:11;
|
||||
unsigned int negative:1;
|
||||
# endif
|
||||
#endif /* Little endian. */
|
||||
} ieee;
|
||||
|
||||
/* This format makes it easier to see if a NaN is a signalling NaN. */
|
||||
struct
|
||||
{
|
||||
#if RTAPI_BIG_ENDIAN
|
||||
unsigned int negative:1;
|
||||
unsigned int exponent:11;
|
||||
unsigned int quiet_nan:1;
|
||||
/* Together these comprise the mantissa. */
|
||||
unsigned int mantissa0:19;
|
||||
unsigned int mantissa1:32;
|
||||
#else
|
||||
# if RTAPI_FLOAT_BIG_ENDIAN
|
||||
unsigned int mantissa0:19;
|
||||
unsigned int quiet_nan:1;
|
||||
unsigned int exponent:11;
|
||||
unsigned int negative:1;
|
||||
unsigned int mantissa1:32;
|
||||
# else
|
||||
/* Together these comprise the mantissa. */
|
||||
unsigned int mantissa1:32;
|
||||
unsigned int mantissa0:19;
|
||||
unsigned int quiet_nan:1;
|
||||
unsigned int exponent:11;
|
||||
unsigned int negative:1;
|
||||
# endif
|
||||
#endif
|
||||
} ieee_nan;
|
||||
};
|
||||
|
||||
#define IEEE754_DOUBLE_BIAS 0x3ff /* Added to exponent. */
|
||||
|
||||
#endif
|
||||
78
wasm-port/vendor/linuxcnc/src/rtapi/rtapi_stdint.h
vendored
Normal file
78
wasm-port/vendor/linuxcnc/src/rtapi/rtapi_stdint.h
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
// Copyright 2014 Jeff Epler
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#ifndef __LINUXCNC_RTAPI_STDINT_H
|
||||
#define __LINUXCNC_RTAPI_STDINT_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include <asm/types.h>
|
||||
typedef s8 rtapi_s8;
|
||||
typedef s16 rtapi_s16;
|
||||
typedef s32 rtapi_s32;
|
||||
typedef s64 rtapi_s64;
|
||||
typedef long rtapi_intptr_t;
|
||||
typedef u8 rtapi_u8;
|
||||
typedef u16 rtapi_u16;
|
||||
typedef u32 rtapi_u32;
|
||||
typedef u64 rtapi_u64;
|
||||
typedef unsigned long rtapi_uintptr_t;
|
||||
|
||||
#define RTAPI_INT8_MAX (127)
|
||||
#define RTAPI_INT8_MIN (-128)
|
||||
#define RTAPI_UINT8_MAX (255)
|
||||
|
||||
#define RTAPI_INT16_MAX (32767)
|
||||
#define RTAPI_INT16_MIN (-32768)
|
||||
#define RTAPI_UINT16_MAX (65535)
|
||||
|
||||
#define RTAPI_INT32_MAX (2147483647)
|
||||
#define RTAPI_INT32_MIN (-2147483647-1)
|
||||
#define RTAPI_UINT32_MAX (4294967295ul)
|
||||
|
||||
#define RTAPI_INT64_MAX (9223372036854775807)
|
||||
#define RTAPI_INT64_MIN (-9223372036854775807-1)
|
||||
#define RTAPI_UINT64_MAX (18446744073709551615ull)
|
||||
#else
|
||||
#include <inttypes.h>
|
||||
|
||||
typedef int8_t rtapi_s8;
|
||||
typedef int16_t rtapi_s16;
|
||||
typedef int32_t rtapi_s32;
|
||||
typedef int64_t rtapi_s64;
|
||||
typedef intptr_t rtapi_intptr_t;
|
||||
typedef uint8_t rtapi_u8;
|
||||
typedef uint16_t rtapi_u16;
|
||||
typedef uint32_t rtapi_u32;
|
||||
typedef uint64_t rtapi_u64;
|
||||
typedef uintptr_t rtapi_uintptr_t;
|
||||
|
||||
#define RTAPI_INT8_MAX INT8_MAX
|
||||
#define RTAPI_INT8_MIN INT8_MIN
|
||||
#define RTAPI_UINT8_MAX UINT8_MAX
|
||||
|
||||
#define RTAPI_INT16_MAX INT16_MAX
|
||||
#define RTAPI_INT16_MIN INT16_MIN
|
||||
#define RTAPI_UINT16_MAX UINT16_MAX
|
||||
|
||||
#define RTAPI_INT32_MAX INT32_MAX
|
||||
#define RTAPI_INT32_MIN INT32_MIN
|
||||
#define RTAPI_UINT32_MAX UINT32_MAX
|
||||
|
||||
#define RTAPI_INT64_MAX INT64_MAX
|
||||
#define RTAPI_INT64_MIN INT64_MIN
|
||||
#define RTAPI_UINT64_MAX UINT64_MAX
|
||||
#endif
|
||||
|
||||
#endif
|
||||
69
wasm-port/vendor/linuxcnc/src/rtapi/rtapi_string.h
vendored
Normal file
69
wasm-port/vendor/linuxcnc/src/rtapi/rtapi_string.h
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
// Copyright 2006-2009, Jeff Epler
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#ifndef __LINUXCNC_RTAPI_STRING_H
|
||||
#define __LINUXCNC_RTAPI_STRING_H
|
||||
|
||||
#include "rtapi.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <assert.h>
|
||||
#include <type_traits>
|
||||
#define rtapi_static_assert(a,b) static_assert(a,b)
|
||||
#define rtapi_is_array(x) (std::is_array<decltype(x)>::value)
|
||||
#else
|
||||
#define rtapi_static_assert(a,b) _Static_assert(a,b)
|
||||
#define rtapi_is_array(x) (!__builtin_types_compatible_p(__typeof__((x)), __typeof__(&(x)[0])))
|
||||
#endif
|
||||
|
||||
#ifdef MODULE
|
||||
/* Suspect only very early kernels are missing the basic string functions.
|
||||
To be sure, see what has been implemented by looking in linux/string.h
|
||||
and {linux_src_dir}/lib/string.c */
|
||||
#include <linux/string.h>
|
||||
#include <linux/version.h>
|
||||
#define rtapi_argv_split argv_split
|
||||
#define rtapi_argv_free argv_free
|
||||
#define rtapi_kstrdup(a,b) kstrdup(a,b)
|
||||
#else
|
||||
#include <string.h>
|
||||
#include "rtapi_gfp.h"
|
||||
RTAPI_BEGIN_DECLS
|
||||
extern char **rtapi_argv_split(rtapi_gfp_t, const char *argstr, int *argc);
|
||||
extern void rtapi_argv_free(char **argv);
|
||||
#define rtapi_kstrdup(a,b) strdup(a)
|
||||
RTAPI_END_DECLS
|
||||
#endif
|
||||
RTAPI_BEGIN_DECLS
|
||||
static inline size_t rtapi_strlcpy(char *dst, const char *src, size_t size) {
|
||||
return rtapi_snprintf(dst, size, "%s", src);
|
||||
}
|
||||
#define rtapi_strxcpy(dst, src) ({ \
|
||||
rtapi_static_assert(rtapi_is_array(dst), "dst must be non-const array"); \
|
||||
rtapi_strlcpy(dst, src, sizeof(dst)); \
|
||||
})
|
||||
|
||||
static inline size_t rtapi_strlcat(char *dst, const char *src, size_t size) {
|
||||
size_t l = strlen(dst);
|
||||
return rtapi_snprintf(dst+l, size-l, "%s", src);
|
||||
}
|
||||
|
||||
#define rtapi_strxcat(dst, src) ({ \
|
||||
rtapi_static_assert(rtapi_is_array(dst), "dst must be non-const array"); \
|
||||
rtapi_strlcat(dst, src, sizeof(dst)); \
|
||||
})
|
||||
RTAPI_END_DECLS
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user