Namespace Hi.NcParsers.Dependencys
Classes
- CncBrandDependency
Explicit CNC controller brand identifier carried in PipelineNcDependencyList. Use
ncDependencyList.OfType<CncBrandDependency>().FirstOrDefault()to retrieve the brand.
- ControllerParameterTableBase
Base class for brand-specific controller parameter tables. Provides shared data structures, XML IO, and IHomeMcConfig
- IMachineAxisConfig implementations. Subclasses define brand-specific parameter numbers, XML attribute names, and derived convenience properties.
- HeidenhainDatumTable
Heidenhain datum preset and datum shift tables. CYCL DEF 247 Q339=N reads from DatumPresetTable, CYCL DEF 7 #N reads from DatumShiftTable. Each table maps an integer ID (1–20) to a vec3d_t offset.
On real Heidenhain controllers, preset and datum tables are separate disk files (e.g.
TNC:\table\preset.pr,*.d) — distinct from MP-prefixed Machine Parameters (held by HeidenhainParameterTable). HiNC mirrors that separation by keeping this dependency independent ofHeidenhainParameterTable.Implements IIsoCoordinateConfig by mapping the ISO/DIN G54–G59 codes to preset rows 1–6, the conventional Heidenhain compatibility mapping for ISO/DIN programs running on a Heidenhain.
- HeidenhainDatumTableProxy
Get-or-create INcDependencyProxy for HeidenhainDatumTable: a placeholder in the shared PipelineNcDependencyList that resolves the host project's own per-case datum preset / datum shift tables.
- IsoCoordinateAddressMap
Fanuc-style ISO coordinate parameter address mapping. G54–G59 → #5221+ (stride 20, three consecutive numbers per entry for X/Y/Z), G54.1 P1–P48 → #7001+ (stride 20). Shared between FanucParameterTable (which calls these “ParamId”) and SyntecParameterTable (which calls them “PrId”) because both follow the same numeric scheme.
- MCodeEffects
What one machine-declared M-code does. Real-machine OEM M-codes are frequently composite — e.g. an
M13that means “spindle CW + flood coolant on” — so a declaration carries every effect the code performs rather than a single meaning, and additionally an UnmodeledNote for the parts this simulation does not model. Declaring only the known parts and staying loud about the rest keeps a composite code from being half-consumed silently. Stored per machine in MCodeDeclarations and consumed by MCodeExpansionSyntax, which expands the declared code into the canonical ISO flags the regular consumers already understand.
- RotaryReadoutUtil
Internal Use Only. The machine coordinate of a wrap-around rotary axis as the controller's position screen shows it. The engine moves a rotary axis by a continuous angle: the tail pass McAbcCyclicPathSyntax walks every modular axis round from the previous block the way the controller does — the shortest way, or the control's own rule for the word (a SINUMERIK plain word under the factory MD30455 setting, a HEIDENHAIN word under M127) — so a table that keeps turning the same way stands at -720° after two turns and at -2520° after seven, and every position the engine records carries that continuous value. A controller with the usual wrap-around setting (Fanuc parameter No.1006 ROTx=1 ROSx=0, SINUMERIK MD30320 DISPLAY_IS_MODULO, HEIDENHAIN modulo axes, Mitsubishi #8213) displays the same axis folded into 0–360°: -720° reads 0°, -2520° reads 0°, -90° reads 270°, -180° reads 180°. The position readouts fold the continuous angle through Displayed_deg(double) for the axes IsDisplayedModulo(IMachineAxisConfig, string) and DisplayedModuloAxes(IEnumerable<INcDependency>) name: the modular rotary axes of the IMachineAxisConfig on the dependency list, judged by IsModularRotary(string), the predicate the tail pass folds by, so a readout wraps exactly the axes the motion wraps. A rotary axis that does not wrap (a tilting head with a limited travel) and every linear axis keep the raw value. Only the readouts fold: the motion, the NC writeback, the stroke and collision checks and the exported step file keep the continuous angle.
- StrokeLimitUtil
Load-time audit helpers for IStrokeLimitConfig: which machine-coordinate axes the chain has, and which of them the stroke limit check cannot judge because no limit is configured. Both checks — the per-block StrokeLimitCheckSemantic and the per-step CheckStrokeLimit(dvec3d_t, IProgress<IMessage>) — compare only axes that carry a limit, so a machine file without limits passes every position silently while
EnableStrokeLimitCheckreads as on. The session begin reports that gap once through these helpers.
Interfaces
- IBlockSkipConfig
Runtime state of the controller's Block Delete / Block Skip switches. Present in PipelineNcDependencyList exposes this to the runner so that blocks whose head carries
/or/N(parsed by BlockSkipSyntax into BlockSkip) are skipped at semantic time.Layers are 1..9; Layer 1 corresponds to the bare
/prefix. Controllers (Fanuc / Syntec / Mazak / Siemens) let each layer be toggled independently via panel switches or system parameters.When this dependency is absent from PipelineNcDependencyList, no block is skipped (safest default: simulate the full machining). The syntax still consumes the
/prefix so noUnparsedText--Remainingdiagnostic is produced.
- ICannedCycleConfig
Canned cycle configuration parameters. Implemented by brand-specific parameter tables (e.g., FanucParameterTable under its key 4002, SyntecParameterTable under Syntec's Pr4002) and by FallbackConfig as a safety net.
Siemens and Heidenhain specify peck clearance per-call (CYCLE83 parameter / CYCL DEF), so their tables do not implement this interface. The FallbackConfig provides the default value in those cases.
- IHomeMcConfig
G28 first reference position (home machine coordinate) per axis.
- IIndexingPositionConfig
Indexing-axis position table: maps 1-based indexing position numbers to axis coordinates for axes that only take up discrete stations (Hirth couplings, indexing rotary tables, turret-style workholders). Consumed by the coded-position coordinate functions (Siemens
CAC()/CIC()/CDC()/CACP()/CACN()— unwrapped by SiemensAcIcSyntax, resolved by McAbcSyntax / IncrementalResolveSyntax via CodedPositionUtil). Implemented by SiemensMachineDataTable using the Siemens machine data (MD30500$MA_INDEX_AX_ASSIGN_POS_TABper axis; global tables MD10910/MD10930; equidistant MD30501–MD30503).Positions are expressed in the axis' native units (degrees for rotary, mm for linear) in the coordinate frame the axis word itself is written in — machine coordinates for rotary words, program coordinates for linear words. Position numbering is 1-based: number 1 is the first table entry (the Siemens machine-data help and alarm texts count this way; the 0-based value range printed in some programming-manual editions describes the machine-data array index, not the programmable number).
- IIsoCoordinateConfig
ISO work coordinate offset provider. Maps a G-code work coordinate id (e.g. “G54”, “G59.2”, “G54.1P1”) to a machine-coordinate offset vec3d_t.
Implementations include IsoCoordinateTable (brand-agnostic standalone storage), FanucParameterTable / SyntecParameterTable (parameter-table integration via real Fanuc/Syntec parameter numbers #5221+ for G54–G59 and #7001+ for G54.1 P1–P48), SiemensFrameTable (Sinumerik
$P_UIFRframes), and HeidenhainDatumTable (Heidenhain preset rows).
- IMCodeDeclarationConfig
Machine-declared M-code map: what each machine-specific (OEM/PLC) M-code does, as MCodeEffects — possibly several effects per code (tool change, spindle direction, coolant) plus a note for behavior this simulation does not model. Consumed by MCodeExpansionSyntax, which expands declared codes into the canonical ISO flags ahead of the regular consumers. Machine-level (per-case parameter table) rather than brand vocabulary — implemented by ControllerParameterTableBase, alongside the narrower ISpindleControlConfig face over the same storage.
- IMachineAxisConfig
Machine axis configuration: which axes exist and their types. Compatible with Fanuc, Siemens, Heidenhain, Mazak, Okuma.
- INcDependency
Marker interface for objects that participate in the NC dependency list resolved by the soft-NC runtime.
- INcDependencyListHost
Hosts a per-case INcDependency list that INcDependencyProxy placeholders in a shared SoftNcRunner resolve their data against. Implemented by the object owning both the shared runner and the varied setting data — e.g.
MachiningProject.
- INcDependencyProxy
An INcDependency placeholder that resolves the real dependency lazily at pipeline-build time instead of carrying the data itself. Lets a shared SoftNcRunner hold only the fixed pipeline logic while the frequently-varied data lives on the owning INcDependencyListHost (e.g. a
MachiningProject)."Maker and taker": GetNcDependency() either constructs the dependency on demand (maker) or fetches one from the host wired by InitNcDependencyHost(INcDependencyListHost) (taker). A get-or-create proxy does both — it takes the host's instance when present and otherwise makes one, installing it into the host list so it persists and is editable per case.
A proxy may carry runtime-only state (the wired host, a memoized resolved dependency). That state is host-wired per run and MUST NOT be written by MakeXmlSource(string, string, bool) — same runtime-only posture as ProjectFolderDependency.
- IPowerResettable
Marks an INcDependency that holds volatile state which must be cleared when the controller performs a power reset (power off then on).
Implementers should clear only the volatile subset they own (e.g. Fanuc common volatile macro variables
#100-#499), and leave persistent state untouched (e.g.#500-#999, controller parameters).Call-frame local state (Fanuc
#1-#33, HeidenhainQ200-Q1199) is NOT in scope — that lives in theSyntaxPieceJSON dataflow and is bounded by call activation, not power cycle.
- IRapidFeedrateConfig
Provides per-axis rapid traverse feedrate for motion semantics. Implemented by ControllerParameterTableBase using brand-specific parameter numbers (e.g., Fanuc #1420, Siemens MD32000, Heidenhain MP1010).
- IRotaryAbsoluteWordConfig
How a controller moves a modular rotary axis to an absolute word that carries no direction of its own — a plain
C350underG90, or an explicitly absoluteAC()/CAC()word — and what it does with an absolute word outside the modulo range. Read per axis by McAbcCyclicPathSyntax for the words the RotaryWords record lists that have no directive of their own (DC(),ACP(),ACN(), an increment and the HeidenhainM127gate come first). A dependency list without an implementation takes Shortest, the engine's default for a modular axis: the Fanuc manuals (No. 1008 RABx = 0 “In which the distance to the target is shorter”, B-64310EN/02 p.38) and Mitsubishi #8213 = 1 describe the shortest path for an absolute word, so the Fanuc table does not implement this interface. A HEIDENHAIN control's own default is the long path — withoutM126, and with the machine parametershortestDistance(300401) off, “the control moves a rotary axis whose position display is reduced to less than 360° along a long path” (TNC 640 ISO 892909-2C p.440), which is the displayed difference below — but the engine has always assumed that parameter on, or the program underM126, untilM127says otherwise (the modalRotaryWrapgate the tail pass reads); that standing assumption is why the Heidenhain table does not implement this interface either.SiemensMachineDataTable implements it from MD30455 (
$MA_MISC_FUNCTION_MASK). The rule itself: "When programming AC exclusively or with G90, the traversing direction depends on the rotary-axis actual position. If the target position is greater than the actual position, the axis traverses in the positive direction, otherwise it traverses in the negative direction." (SINUMERIK 840D sl / 828D Function Manual Extended Functions 09/2011, 6FC5397-1BP40-2BA0, R2 Rotary axes §13.3.2 p.857; example ④ of that section:POS[C] = AC(0)from 240° "traverses to position 0° in the negative direction of rotation", a −240° turn where the shortest way is +120°). Bit 2 configures what a plainG90word means — PlainWordPath(string): "Bit 2 = 0: with G90, modulo axis positioned as standard using AC; Bit 2 = 1: with G90, modulo axis positioned as standard using DC (shortest path)" (same page) — 0 is the factory setting and an absent row; an explicitly writtenAC()orCAC()is the AC rule itself whatever the bit says (ExplicitAbsoluteWordPath(string)). Bit 0 answers ConvertsOutOfRangeAbsoluteWord(string): "Bit 0 = 0: Modulo rotary axis/spindle: Programmed positions must be within the modulo range. Otherwise, an alarm is output. Bit 0 = 1: If positions outside the modulo range are programmed, no alarm is output. The position is modulo-converted internally. Example: B-5 is equivalent to B355" (Machine data and parameters, Parameter Manual 03/2013, 6FC5397-7AP40-3BA1, MD30455, p.449). The range the engine assumes is the factory one, 0°–359.999° (FB2 p.856); a range moved by MD30340 / MD30330 (−180°…+180°, FB2 p.855) is not modeled. Whether the axis is a modulo axis at all is IsModularRotary(string), which that table reads from MD30310: a modulo axis only when the row is 1 — the control's factory value is 0, and an axis without the row is not one.
- IRotaryHalfTurnTieConfig
How a controller turns a modular rotary axis when an absolute shortest-path target lies exactly opposite its current position: both ways round are a half turn, and the ±180° window of McAbcCyclicPathSyntax cannot pick one by itself (without a rule, the last bit of the target or the anchor decided). Read per axis by that tail pass through
OfType<IRotaryHalfTurnTieConfig>().FirstOrDefault()for every value the word itself does not decide — aDC()word carries its own documented positive preference and never asks (aCDC()word is taken the same way by analogy; the manuals state only its shortest path), and a SINUMERIK plain word under MD30455 bit 2 = 0, or anAC()/CAC()word whatever the bit, is decided, half turn included, by the displayed difference of IRotaryAbsoluteWordConfig before the band is reached. A dependency list without an implementation takes the engine default, the negative half turn (anchor − 180°) — the Fanuc manuals describe the shortest path without resolving the tie (B-64304EN-2/01 §5.4 p.95 “Rotating in the direction in which an angular displacement becomes shortest”; parameter No.1008 RABx=0 “In which the distance to the target is shorter”, B-64310EN/02 p.38), so the Fanuc table does not implement this interface.SiemensMachineDataTable answers ProgrammedSide for a plain,
AC()orCAC()word — "When programming AC exclusively or with G90, the traversing direction depends on the rotary-axis actual position. If the target position is greater than the actual position, the axis traverses in the positive direction, otherwise it traverses in the negative direction." (SINUMERIK 840D sl / 828D Function Manual Extended Functions 09/2011, 6FC5397-1BP40-2BA0, R2 Rotary axes §13.3.2 p.857), the rule that decides such a word's whole path through IRotaryAbsoluteWordConfig, so the band itself never sees such a word with bit 2 clear, nor anAC()/CAC()word at all — and Positive for an axis whose MD30455 ($MA_MISC_FUNCTION_MASK) has bit 2 set, which makes a plainG90word position asDC("Bit 2 = 1: with G90, modulo axis positioned as standard using DC (shortest path)", same page). TheDC()preference itself: "If the path to be traversed is the same in both directions (180°), the positive direction of rotation receives preference." (§13.3.2 p.858 for a modulo axis, §13.3.3 p.863 for one without modulo conversion; example ④ of §13.3.2, Figure 13-6:POS[C] = DC(60)from 240° "preference is given to the positive direction of rotation") — applied by the tail pass to the word.HeidenhainParameterTable answers ProgrammedSide: "If both equivalent positions are equidistant (i.e., 180° away), the control selects the direction of motion according to the programmed value." with the example "the axis is at 180°. If you program L C+0, the C axis will move to 0. The same is true when programming L C-360, etc. However, if you program L C+360 (or L C+720, etc.), then the C axis will move to 360°" (TNC 640 User's Manual for Setup, Testing and Running NC Programs 01/2021, 1261174-22, p.455 "Software limit switch with modulo axes"; TNC7 User's Manual for Programming and Testing 09/2024, 1358773-23, p.549: "If both equivalent target positions are 180° away, the control selects the direction of motion according to the programmed algebraic sign"). The
M126sections name no default of their own: "If the traverse paths in both directions are identical, you can pre-position the rotary axis and thus also influence the direction of rotation. Within the PLANE functions, you can also select a tilting solution." (TNC 640 ISO 10/2023, 892909-2C, p.440; TNC7 1358773-23, p.575) — so an angle no word programmed (aPLANEsolve) takes the engine default on this controller. The rule itself is stated in the software-limit-switch notes for modulo axes, the one place these manuals resolve the tie; the engine applies it to every programmed half-turn tie on this controller, limit switches or not.
- ISpindleControlConfig
Machine-specific spindle control codes: maps custom spindle direction M-codes to SpindleDirection — e.g., an ultrasonic spindle started by
M203(CW) and stopped byM205(STOP) instead of ISO M03/M05. Consulted by SpindleSpeedSyntax in addition to the built-in ISO defaults (M03/M04/M05), which always stay in effect; a configured code wins over its ISO meaning when both match. Machine-level (per-case parameter table) rather than brand vocabulary — implemented by ControllerParameterTableBase as a spindle-direction face over its MCodeDeclarations storage (the multi-effect IMCodeDeclarationConfig map), so one code is never half-recognized by two separate maps.
- IStrokeLimitConfig
Per-axis stroke (travel) limits. Unit is mm for linear axes, deg for rotary axes. Implemented by ControllerParameterTableBase under each brand table's storage keys (e.g. 1300 / 1320 on the Fanuc table, MD36100 / MD36110 on the Siemens one), which are not the controllers' parameter numbers for those limits (IsStorageKeyOnly(int)).
- IToolChangeTriggerConfig
Machine-level tool-change trigger mode. Machining centers with a magazine treat a bare
Tword as pre-selection only (the magazine rotates, no feed axis moves) and change the tool on the trigger M-code; lathes/turret machines index the turret — and thereby change the tool — on theTword itself. Real controllers declare this per machine (e.g. Siemens MD22550$MC_TOOL_CHANGE_MODE, where 0 means theTword performs the change). Consulted by ToolChangeSyntax; machine-level (per-case parameter table) rather than brand vocabulary — implemented by ControllerParameterTableBase. Custom trigger M-codes are the separate IMCodeDeclarationConfig concern (IsToolChange).
- IToolOffsetConfig
Tool offset configuration indexed by a single integer offset number. Applies to Fanuc (H/D numbers), Heidenhain (tool number), Mazak, Okuma, and other ISO-compatible controllers where one integer selects the offset row.
For Siemens (840D/Sinumerik) where offsets are addressed by (tool number, cutting edge D number), see ISiemensToolOffsetConfig.
- IToolingMcConfig
Machine position axes move to during tool change (M06).
Enums
- AxisType
Axis type: linear (translation), rotary (rotation), or spindle (speed/positioning dual mode).
- RotaryAbsoluteWordPath
The documented ways a controller moves a modular rotary axis to an absolute word without a direction of its own (see IRotaryAbsoluteWordConfig).
- RotaryHalfTurnTie
The documented ways a controller resolves a half-turn tie (see IRotaryHalfTurnTieConfig); a dependency list that states none takes the engine default, the negative half turn.
Delegates
- TryResolveCoordinateOffset
Resolves a G-code coordinate id to its work offset. Returns false when nothing holds an offset for
coordId— the shape a resolver over one or more IIsoCoordinateConfig providers takes, so that “no offset” is an answer of its own and never a vector value.