Skip to content

feat: add A (AND-junction) and F-system safety instructions#3

Merged
Czarnak merged 2 commits into
Czarnak:mainfrom
Demien76:feat/f-safety-instructions-and-junction
Jul 20, 2026
Merged

feat: add A (AND-junction) and F-system safety instructions#3
Czarnak merged 2 commits into
Czarnak:mainfrom
Demien76:feat/f-safety-instructions-and-junction

Conversation

@Demien76

Copy link
Copy Markdown
Contributor

Summary

Ran the decoder against a real V21 fail-safe FB (F_FBD, ~20 networks) and hit two catalog gaps:

  • A (AND-junction) was entirely missing. O (OR-junction) is supported, but its FBD counterpart A folded to Unhandled — this turned out to be the majority of the warnings (9 of 14), not the F-instructions themselves.
  • Four common F-system safety boxes (ACK_GL, ESTOP1, SFDOOR, FDBACK) were uncatalogued, so calls to them folded to Unhandled even though they're boxes like any other system FB (en/eno, optionally instanced) — no special-casing needed once catalogued.

While wiring these up, found and fixed a related bug: per-pin negation on junction/box Parts was silently dropped. <Negated Name="inN"/> directly on an A/O junction (distinct from a negated Contact feeding it) — and the equivalent on a BOX's input pins (e.g. FDBACK's ON/QBAD_FIO, which are commonly wired negated) — was never applied. Only Contact/Coil negation was handled before. Fixed for both Category.AND_JUNCTION/OR_JUNCTION (via a shared _junction_branches helper) and Category.BOX inputs, plus a regression test covering the pre-existing O gap.

Verification

  • Ran against the real safety FB before/after: 14 warnings → 0.
  • Manually cross-checked two of the trickiest networks (an AA(negated)→Sr flip-flop chain, and an FDBACK box with two negated inputs) wire-by-wire against the raw FlgNet XML — decoded SCL matches exactly, including which operand the negation lands on.
  • Regression-checked two already-passing blocks (PROFIsafe telegram wrappers) before/after: byte-identical output, no unintended side effects.
  • ruff check . clean; pytest --cov 222 passed (3 pre-existing, unrelated Windows-symlink-privilege skips), coverage 90.6% (gate: 80%).
  • No production project data included — new tests are synthetic model.* objects built directly, following the existing test_fold.py pattern (no XML fixtures, so no fixture-licensing concerns per CONTRIBUTING.md).

Test plan

  • ruff check .
  • pytest -q --cov=simaticml_decoder --cov-report=term-missing --cov-fail-under=80
  • Manual wire-by-wire cross-check of decoded output against raw XML for the AND-junction-negation and BOX-negation cases
  • Regression check against previously-clean blocks (byte-identical output)

Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com

…ESTOP1, SFDOOR, FDBACK)

Real-world V21 F-programs (fail-safe FBs) hit two gaps in the catalog:

- "A" (the AND-junction, FBD's counterpart to the already-supported "O" OR-junction)
  was entirely missing, so any AND fan-in folded to Unhandled.
- The four common F-system safety boxes (ACK_GL, ESTOP1, SFDOOR, FDBACK) were not
  catalogued, so calls to them folded to Unhandled even though they are boxes like
  any other system FB (en/eno, optionally instanced).

While adding these, found and fixed a related bug: per-pin negation
(`<Negated Name="inN"/>` on the junction/box Part itself, distinct from a negated
Contact feeding it) was silently dropped for AND/OR junctions and for BOX inputs
generally — only Contact/Coil negation was ever applied. Fixed for both categories,
plus a regression test for the pre-existing OR-junction gap.

Verified against a real V21 safety FB (F_FBD, ~20 networks mixing all of the above):
14 "unknown instruction"/negation-related warnings before the fix, 0 after, with the
decoded SCL cross-checked network-by-network against the raw FlgNet XML by hand.
No production project data is included here — only synthetic, license-clean test
fixtures following the existing test_fold.py pattern (model.* built directly, no XML).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@Czarnak Czarnak self-assigned this Jul 20, 2026
…pins

PR Czarnak#3 review found that per-pin negation was still silently dropped in
four spots: A/O junction NAND/NOR (Negated out), flip-flop set/reset
pins, box en pins, and box output pins read as sub-expressions. Each
now wraps the result in Not instead of dropping the inversion, closing
the exact "authoritative-looking but wrong" failure mode this decoder
is built to avoid.

Also corrects the ESTOP1 catalog entry, which listed placeholder
in1/in2 pins never observed on that block. Pin list confirmed against
a real ESTOP1 v1.6 export: en/E_STOP/ACK_NEC/ACK/TIME_DEL in,
Q/Q_DELAY/ACK_REQ/DIAG/eno out.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EsNpUYoWRowQLtXCo1DuZX
@Czarnak
Czarnak merged commit 4f19b27 into Czarnak:main Jul 20, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants