Table of Contents

Interface Parameters

Two leaves of the Controller branch's machine plane put the controller's non-axis parameters into domain vocabulary instead of parameter numbers: Controller Parameters and Canned Cycle (Peck). They live on the General Setup page at /general-setup under the Control-Tree ids equipment/controller/machine/parameters and equipment/controller/machine/canned-cycle. Each value they edit that is a row of the brand parameter table is also reachable as a raw numbered row on the sibling leaf, Parameters (Native); the values stored elsewhere are named below, and they reach no native form at all.

Important

Anatomy makes no claim that any id named here is stable across versions. The migration hop that keeps an older ?tree= value resolving is described in Tree Ids and Routes.

Controller Parameters is ungated: the branch builder pushes it with the brand and the four per-axis leaves, so it exists wherever a runner resolves. Canned Cycle (Peck) is pushed behind the hasCannedCycle flag, which is true on all five shipped brand presets — see Brand Matrix.

The Five Fields, and Which Brand Shows Which

Controller Parameters renders at most five controls, in one column, in this fixed order. There is no tab, no group box and no scroll region; a field the brand does not have is not disabled but absent.

Field the user reads Control Backed by Fanuc, Mazak Syntec Siemens Heidenhain
Max spindle speed numeric, rpm, minimum 0 the brand parameter table #3741 Pr3741 MD35100 MP100
Cutter compensation startup / cancel type select — Type A / Type B / Type C the brand parameter table #5003 Pr5003
Tool-axis direction select — Z / Y / X the brand parameter table MP101
GOTO — max jumps per N target † numeric, minimum 1 an iteration-guard dependency Fanuc guard Fanuc guard Siemens guard
WHILE/DO — max iterations per loop † numeric, minimum 1 an iteration-guard dependency Fanuc guard Fanuc guard Siemens guard

† The Fanuc-family spelling. Siemens spells both guard labels differently — the two pairs are below.

The last two sit under a separator and the caption Macro loop guards (advanced), and that whole group is rendered only when at least one of the two guard values resolves. On Heidenhain neither does, so the separator, the caption and both fields are absent together; that brand shows two fields in total.

The two guard labels are chosen from the brand marker, not from the dependency that answered. The Siemens spellings — GOTOF/GOTOB — max jumps per label and WHILE / FOR / REPEAT / LOOP — max iterations per loop — are used when the brand marker string reads Siemens, and the Fanuc spellings otherwise. Syntec and Mazak therefore read the Fanuc spellings, which is correct: both presets carry the Fanuc guard types. The label and the value are independent lookups, so a runner whose brand marker was edited apart from its dependency list can show one brand's wording over the other brand's guard.

The three select options Type A / Type B / Type C are translated strings; the three tool-axis options Z, Y and X are literal letters written into the component and are the same in every locale.

Visibility Is Null-Driven, Not Flag-Driven

Which fields appear is decided per field, by a null in the read, and not by the shared runner snapshot the tree shape is built from. The reader answers one object with present plus five nullable numbers, computed by type-switching on the resolved dependencies:

  • Max spindle speed is non-null for each of the four brand parameter-table types, so it is present on all five brands. A ControllerParameterTableBase subclass outside those four answers null, and the field disappears while present stays true.
  • Cutter compensation type is non-null only for the Fanuc and the Syntec table.
  • Tool-axis direction is non-null only for the Heidenhain table.
  • Each guard is the Fanuc dependency's value if one resolves, otherwise the Siemens dependency's, otherwise null.

The panel's own conditions are != null on those five keys. No snapshot flag decides a field on this leaf; the only one read at all is the shared no-runner guard. The snapshot's brand marker is read twice more, but only to choose between the two guard label pairs — never to show or hide anything.

Three flags in the snapshot describe exactly these fields and are read by nothing. hasCutterComp, hasToolAxisDirection and hasIterationGuards are computed server-side, typed, defaulted and parsed in the client's API layer, and no component consults any of them. They remain a live part of the REST snapshot for any other client. Two notes about the third:

  • hasIterationGuards probes the Fanuc and the Siemens jump-guard types only. The Heidenhain preset carries a jump guard of its own type, so the flag reports false for a brand that has one. That matches what the panel shows on the shipped presets — the reader probes the same two types, so the Heidenhain guard has no field either — while under-describing the runner.
  • Its doc comment names the Fanuc GOTO / WHILE-DO guards alone while the code also matches the Siemens jump guard. The code is what ships.

The panel's whole body — the guards included — is hidden behind present, which reports the parameter table and nothing else: "No controller parameter table on the active runner." The guards live on separate dependencies with their own write endpoints, so a runner carrying guards but no parameter table would hide two reachable fields. All five brand presets carry a parameter-table proxy, so the combination does not arise on a shipped preset.

Units: Edited Versus Stored

Every value but one is stored in the unit it is edited in.

Value Edited as Stored as
Max spindle speed rpm rpm, in the table's system-parameter row
Cutter compensation type one of three named options the option's index, 0 / 1 / 2, as a number in the same row set
Tool-axis direction one of Z / Y / X 0 / 1 / 2 in the same row set
Macro guards a plain count the same count, on the guard dependency
Peck retraction clearance mm mm on Fanuc and Mazak, microns on Syntec, mm on the generic fallback

Syntec is the one brand whose stored unit differs from the edited one, and the peck clearance is the one value it happens to. The Syntec table's accessor divides its stored row by 1000 on read and the write multiplies by 1000, so this leaf shows 5 on every brand while the native leaf shows 5000 under Pr4002 on Syntec and 5 under #4002 on Fanuc and Mazak. An operator copying a number off a real controller reads the native form; an operator entering a clearance in millimetres reads this one. The two are the same setting.

The two select fields are the second unit hazard, in a milder form: the native leaf shows their stored number, 0, 1 or 2, with the brand table's own description of that number under the id, and never the words Type A or Z.

Not every value reaches the native form at all. The two macro guards are properties of their own runner-owned dependencies rather than rows of any table, so they appear there on no brand; the peck clearance does the same on Siemens and Heidenhain, where the generic fallback supplies it.

Peck Retraction Clearance

Canned Cycle (Peck) is a single numeric field labelled Peck retraction clearance (G83), in millimetres, at zero or above, with a caption naming where the value is stored. Its model is PeckRetractionDistance_mm, and the read reports which implementation answered. Three can, and between them they cover every shipped preset:

Caption the user reads Answered by Brands
Stored in the Fanuc parameter table (#4002, mm). FanucParameterTable Fanuc, Mazak
Stored in the Syntec parameter table (Pr4002, microns) — edited here in mm. SyntecParameterTable Syntec
This brand takes the clearance per call (CYCLE83 / CYCL DEF); this value is the fallback used when a call omits it. FallbackConfig Siemens, Heidenhain

That third caption describes an override the mapping does not implement. The Siemens and Heidenhain front-end syntaxes translate their own cycle vocabulary into the shared ISO cycle section, whose key set is fixed at X, Y, Z, R, Q, F, P and K — and none of those eight is a retraction clearance. The CYCLE83 mapping fills the R plane, the hole bottom Z and the first peck depth Q; the klartext cycle mapping fills the same three plus a bottom dwell and a feed, and folds the klartext set-up clearance into the R plane rather than keeping a slot of its own. The shared G83 expansion then reads the clearance from this dependency unconditionally. So on those two brands the value here is not a fallback for an omitted argument: it is the clearance every pecking cycle uses.

An ICannedCycleConfig implementation outside those three answers a fourth source token, which no caption is written for: the field renders at the value that implementation supplies and the line under it is blank. It is the peck counterpart of the null a parameter table outside the four returns on the other leaf.

Which storage answered also decides where the value lives. On Fanuc, Mazak and Syntec it is a row of the project's parameter table and appears in the native form; on Siemens and Heidenhain it is a field of a plain runner-owned dependency, so it appears in no native form and a brand apply returns it to the preset default — see Machine and Controller Plane.

The value is consumed by two cycle expansions and they use it differently. In G83 it is the clearance the tool rapids down to above the previous stroke bottom before feeding deeper; in G73 it is the whole chip-break retract distance between strokes. The field's label names G83 only. G73 expands on Fanuc, Mazak, Syntec and Siemens; the Heidenhain syntax list registers the G83 expansion without it.

What the Values Reach

Four of the six values are read by the parsing pipeline; the other two are stored declarations.

  • Peck retraction clearance drives the two cycle expansions above.
  • Tool-axis direction is read where a Heidenhain PLANE SPATIAL … COORD ROT block is resolved: it decides which spatial angle may be non-zero for the rotation to count as purely about the tool axis, which is the only case where COORD ROT suppresses rotary positioning and rotates the coordinate system instead.
  • The macro guards are soft caps with runtime counters. Above the cap the consuming block emits an iteration-limit warning and stops firing the jump or the loop back-edge, so a runaway macro ends as a diagnostic instead of an unbounded run. Each is keyed per source file and per target — per N target, per label or per loop — and the counters reset on the session-init edge while the cap does not.
  • Max spindle speed and cutter compensation type are stored, edited and serialized, and no syntax or semantic in the shipped pipeline reads either. Cutter radius compensation itself is resolved, by the G41 / G42 / G40 pass over the motion sections; what that pass does not consult is the A / B / C startup-and-cancel vector style this field records.

Defaults a Freshly Seeded Table Opens On

Each brand's default table decides what the fields show once that brand's table is cloned fresh into a project; the guards are plain preset entries and are re-created at their type defaults on every apply.

Value Fanuc, Mazak Syntec Siemens Heidenhain
Max spindle speed 60000 24000 60000 60000
Cutter compensation type Type A Type A
Tool-axis direction Z
GOTO jump cap 1000 1000 1000
Loop cap 10000 10000 10000
Peck retraction clearance 5 mm 5 mm (5000 stored) 5 mm (fallback) 5 mm (fallback)

The table-backed values — the first three rows, and the peck clearance on the three brands whose parameter table stores it — are reached only by an apply that leaves the project holding no table of the incoming proxy's type: the outgoing brand's table is swept and the incoming proxy clones its seed in place of it. Fanuc and Mazak share one table type, so the hop between those two re-binds the project's existing table instead, and every value in it survives with its edits. The two guards and the fallback clearance are runner-owned and return to the preset's on every apply, whichever brands it runs between.

The two caps differ by an order of magnitude on purpose: a jump is not the legitimate bulk-iteration primitive, so its cap stays tight, while loops are what generated drill grids and calibration sweeps are built from.

Reading a Field Can Create Its Row

Both readers reach the stored values through accessors that write a default into the table when the row is absent. Opening either leaf on a table whose max-spindle, cutter-comp, tool-axis or peck row was deleted from Parameters (Native) therefore re-creates that row at the type's default, in the live project-owned table, with no edit and no request from the user. On Heidenhain — which has neither a cutter-comp row nor a peck row — the max-spindle and tool-axis rows are the whole set. The native leaf's delete removes the row; the next read of this leaf puts it back.

The guard dependencies have no such behaviour — their values are ordinary properties with field initializers.

Editing a Field

Both leaves follow the branch's shared commit, rollback and toast rules, which are Editing Contract. Four details are specific to these two leaves:

  • The numeric fields commit on blur or on Enter, never per keystroke; their full contract is Numeric Input. The two selects commit on the pick.
  • Each write is one field. Every control has its own endpoint and sends only its own value; no edit here resends a neighbouring field.
  • A value the handler refuses is left on screen. Clearing a field parses to null and the handler returns before the request; a guard field additionally refuses anything that is not a whole number, and every numeric handler here refuses a non-finite one — the field accepts the words Infinity and NaN as text and turns them into numbers, and the handlers are what stop them. In each case the box keeps what was typed — blank, where the field was cleared — while the stored value stands, because nothing re-writes the box until the panel is remounted by selecting another node and coming back.
  • A bound violation never reaches a handler at all. The numeric field itself refuses a value below its minimum and shows an untranslated Must be ≥ … under the box. Each handler carries a lower-bound test of its own — 1 on a guard, 0 on the peck clearance — but the field's own minimum is the same number and stops every finite value first, so those tests decide nothing.

Layout

  • General Setup Control Tree — the left dock of /general-setup
    • Controller Node Row
      • Machine / Controller Group Row
        • Controller Parameters Node Row — equipment/controller/machine/parameters
        • Canned Cycle (Peck) Node Row — equipment/controller/machine/canned-cycle
  • Editor Row — the panel of whichever node is selected
    • Controller Parameters Panel — one column, gutter-spaced
      • Max spindle speed Numeric Field — dense, outlined, suffixed rpm, minimum 0
      • Cutter compensation startup / cancel type Select — dense, outlined; options Type A, Type B, Type C
      • Tool-axis direction Select — dense, outlined; options Z, Y, X
      • Guard Group — rendered only when at least one guard value resolves
        • Separator
        • Macro loop guards (advanced) Caption
        • Jump-Guard Numeric Field — minimum 1; labelled GOTO — max jumps per N target or GOTOF/GOTOB — max jumps per label
        • Loop-Guard Numeric Field — minimum 1; labelled WHILE/DO — max iterations per loop or WHILE / FOR / REPEAT / LOOP — max iterations per loop
      • No-Table Block — replaces every field above: "No controller parameter table on the active runner."
    • Canned Cycle (Peck) Panel — one column, gutter-spaced
      • Peck retraction clearance (G83) Numeric Field — dense, outlined, suffixed mm, minimum 0
      • Source Caption — one of the three sentences in the table above, or empty where a fourth implementation answered
      • No-Config Block — replaces both: "No canned-cycle config on the active runner."
    • Shared Empty State — replaces either panel's whole body while the snapshot reports no runner: "No NC runner — load a project first."

Neither panel has a table, an add-row control, a delete control or a Save button.

Source Code Path

See HiNC App Anatomy for git repository links.

Web Application

HiNC-2025-webservice (Quasar CLI SPA):

  • wwwroot-src/src/components/controlTree/SoftNcControllerParamsPanel.vue — the five-field panel: the per-field != null conditions, the guard group's combined condition, the brand-marker choice between the two guard label pairs, the translated compensation-type options beside the literal tool-axis letters, and the three commit handlers with their null, non-finite and integer refusals beside the lower-bound tests the field's own minimum shadows.
  • wwwroot-src/src/components/controlTree/SoftNcCannedCyclePanel.vue — the peck panel: the single field, the presence layer, and the caption chosen from the read's source token.
  • wwwroot-src/src/components/controlTree/SoftNcEmptyState.vue — the shared no-runner line both panels open with.
  • wwwroot-src/src/components/widgets/NumericInput.vue — the numeric field: the unit rendered as a suffix, commit on blur or Enter, the empty-text-to-null parse both panels reject, and the untranslated bound message that stops a value before it is emitted.
  • wwwroot-src/src/components/controlTree/softNcItemTypes.ts — the two node ids and their labels: Controller Parameters among the unconditional machine leaves, Canned Cycle (Peck) behind the peck-provider flag.
  • wwwroot-src/src/api/softNcRunner.ts — the two readers and their setters, the five nullable parameter keys, the peck source token, and the three snapshot flags that describe these fields and are declared, defaulted and parsed without a consumer.
  • wwwroot-src/src/composables/useSoftNcRunner.ts — the shared runner snapshot the first empty layer reads.
  • wwwroot-src/src/i18n/en/softNc.ts — the two node labels, the five field labels, the two guard label pairs, the compensation-type options, the macro-guard caption, the three peck source sentences and the two empty-state lines quoted above.
  • Mech/SoftNcRunnerController.cs — the REST surface: the parameter read's type switches and its table-only presence flag, one write per field, the guard writes that fall back from the Fanuc dependency to the Siemens one, the peck read with its source token, and the peck write that converts to microns for the Syntec table.

HiAPI Engine

  • HiMech/NcParsers/Dependencys/ControllerParameterTableBase.cs — the base every brand table extends, and the raw system-parameter dictionary the first three fields are rows of.
  • HiMech/NcParsers/Dependencys/Fanuc/FanucParameterTable.cs — the Fanuc and Mazak table: the max-spindle, peck-clearance and cutter-comp parameter numbers, the compensation-type enum with its three vector styles, the millimetre peck accessor, and the default seed.
  • HiMech/NcParsers/Dependencys/Syntec/SyntecParameterTable.cs — the Syntec table: the same three parameter numbers, the micron peck row and the accessor that converts it, and the default seed.
  • HiMech/NcParsers/Dependencys/Siemens/SiemensMachineDataTable.cs — the Siemens table: the max-spindle machine datum, and the absence of any compensation-type or peck member.
  • HiMech/NcParsers/Dependencys/Heidenhain/HeidenhainParameterTable.cs — the Heidenhain table: the max-spindle and tool-axis-direction machine parameters and their default seed.
  • HiMech/NcParsers/Dependencys/Fanuc/FanucParameterTableProxy.cs — the proxy shape all four brand tables share: the seed clone that fires only where the project holds no table of that type, and the pure take afterwards.
  • HiMech/NcParsers/Dependencys/ICannedCycleConfig.cs — the peck-clearance contract and its three implementations.
  • HiMech/NcParsers/Dependencys/Generic/FallbackConfig.cs — the runner-owned clearance the Siemens and Heidenhain presets carry, and its millimetre default.
  • HiMech/NcParsers/Dependencys/Fanuc/FanucGotoIterationDependency.cs, HiMech/NcParsers/Dependencys/Fanuc/FanucWhileDoIterationDependency.cs, HiMech/NcParsers/Dependencys/Siemens/SiemensGotoIterationDependency.cs, HiMech/NcParsers/Dependencys/Siemens/SiemensLoopIterationDependency.cs — the four guards the two advanced fields write: their caps, their per-file counters and the session reset that clears the counters alone.
  • HiMech/NcParsers/Dependencys/Heidenhain/HeidenhainGotoIterationDependency.cs — the fifth guard, the one the reader does not probe and no field edits.
  • HiMech/NcParsers/SoftNcRunner.cs — the five brand presets: which parameter-table proxy, which guards and whether a fallback clearance each one carries.
  • HiMech/NcParsers/LogicSyntaxs/CannedCycleSyntaxUtil.cs — the shared ISO cycle section: the fixed eight-key parameter set none of whose keys is a retraction clearance, and the modal merge that consumes them.
  • HiMech/NcParsers/LogicSyntaxs/PeckDrillingCycleSyntax.cs — the G83 expansion, which reads the clearance from the dependency rather than from the block.
  • HiMech/NcParsers/LogicSyntaxs/HighSpeedPeckCycleSyntax.cs — the G73 expansion that spends the same value as the chip-break retract distance.
  • HiMech/NcParsers/Syntaxs/FanucSyntaxUtil.cs, HiMech/NcParsers/Syntaxs/MazakSyntaxUtil.cs, HiMech/NcParsers/Syntaxs/SyntecSyntaxUtil.cs, HiMech/NcParsers/Syntaxs/SiemensSyntaxUtil.cs, HiMech/NcParsers/Syntaxs/HeidenhainSyntaxUtil.cs — the five brand syntax lists, and which of them register both peck expansions against the one that registers the G83 expansion alone.
  • HiMech/NcParsers/LogicSyntaxs/Siemens/SiemensModalCycleSyntax.cs — the CYCLE83 mapping onto the shared cycle section, and the arguments it drops.
  • HiMech/NcParsers/LogicSyntaxs/Heidenhain/HeidenhainCannedCycleSyntax.cs — the klartext cycle mapping onto the same section.
  • HiMech/NcParsers/LogicSyntaxs/Heidenhain/HeidenhainPlaneTiltSyntax.cs — the one consumer of the tool-axis direction: the pure-tool-axis test that decides whether COORD ROT suppresses rotary positioning.
  • HiMech/NcParsers/PostLogicSyntaxs/RadiusCompensationSyntax.cs — the cutter radius compensation that is resolved, and that does not consult the stored startup-and-cancel type.
  • HiGeom/Common/Collections/DictionaryUtil.cs — the get-or-create the table accessors read through, and therefore why a read re-creates a deleted parameter row.

See Also

  • Machine and Controller Plane — the plane these two leaves sit on, and which half of the project each of their values is stored in
  • Brand Matrix — why one of the two leaves is gated and the other is not, and which brand resolves which parameter table
  • Editing Contract — the fetch, commit, rollback and empty-layer rules these panels share with the rest of the branch
  • Native Parameters — the same rows by number, in their raw stored units, including the peck clearance this page shows converted