laddercodec 0.2.2__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {laddercodec-0.2.2 → laddercodec-0.3.0}/AGENTS.md +8 -2
- {laddercodec-0.2.2 → laddercodec-0.3.0}/CHANGELOG.md +24 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/PKG-INFO +1 -1
- {laddercodec-0.2.2 → laddercodec-0.3.0}/devtools/dump_scr_tags.py +2 -1
- {laddercodec-0.2.2 → laddercodec-0.3.0}/docs/gen_reference.py +13 -1
- {laddercodec-0.2.2 → laddercodec-0.3.0}/docs/guides/adding-instructions.md +64 -4
- {laddercodec-0.2.2 → laddercodec-0.3.0}/docs/guides/csv-format.md +36 -1
- {laddercodec-0.2.2 → laddercodec-0.3.0}/docs/guides/decoding.md +21 -2
- {laddercodec-0.2.2 → laddercodec-0.3.0}/docs/guides/encoding.md +1 -1
- laddercodec-0.3.0/docs/internals/instruction-blobs.md +206 -0
- laddercodec-0.3.0/scratchpad/click-v4/captures/.gitignore +2 -0
- laddercodec-0.3.0/scratchpad/click-v4/captures/README.md +61 -0
- laddercodec-0.3.0/scratchpad/click-v4/captures/drum_fix_stubs.py +84 -0
- laddercodec-0.3.0/scratchpad/click-v4/captures/expected/drum.csv +40 -0
- laddercodec-0.3.0/scratchpad/click-v4/captures/expected/loop.csv +105 -0
- laddercodec-0.3.0/scratchpad/click-v4/captures/expected/math.csv +70 -0
- laddercodec-0.3.0/scratchpad/click-v4/captures/expected/out.csv +55 -0
- laddercodec-0.3.0/scratchpad/click-v4/captures/expected/pins.csv +56 -0
- laddercodec-0.3.0/scratchpad/click-v4/captures/math_edge_stubs.py +175 -0
- laddercodec-0.3.0/scratchpad/click-v4/captures/stubs/drum.csv +40 -0
- laddercodec-0.3.0/scratchpad/click-v4/captures/stubs/drum_fix.csv +118 -0
- laddercodec-0.3.0/scratchpad/click-v4/captures/stubs/drum_fix_te.csv +60 -0
- laddercodec-0.3.0/scratchpad/click-v4/captures/stubs/loop.csv +105 -0
- laddercodec-0.3.0/scratchpad/click-v4/captures/stubs/math.csv +70 -0
- laddercodec-0.3.0/scratchpad/click-v4/captures/stubs/math_edge.csv +92 -0
- laddercodec-0.3.0/scratchpad/click-v4/captures/stubs/math_neg2.csv +26 -0
- laddercodec-0.3.0/scratchpad/click-v4/captures/stubs/math_operands.csv +65 -0
- laddercodec-0.3.0/scratchpad/click-v4/captures/stubs/math_wide.csv +14 -0
- laddercodec-0.3.0/scratchpad/click-v4/captures/stubs/out.csv +55 -0
- laddercodec-0.3.0/scratchpad/click-v4/captures/stubs/pins.csv +47 -0
- laddercodec-0.3.0/scratchpad/click-v4/captures/v4_capture.py +539 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/__init__.py +9 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/_grid.py +1 -1
- laddercodec-0.3.0/src/laddercodec/compat.py +64 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/csv/converter.py +172 -314
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/csv/writer.py +100 -200
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/decode.py +6 -6
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/decode_program.py +54 -19
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/instructions/__init__.py +21 -4
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/instructions/coil.py +6 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/instructions/counter.py +33 -5
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/instructions/drum.py +184 -31
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/instructions/forloop.py +78 -11
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/instructions/math.py +124 -35
- laddercodec-0.3.0/src/laddercodec/instructions/out_variant.py +269 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/instructions/raw.py +3 -2
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/instructions/shift.py +18 -6
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/instructions/timer.py +18 -5
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/model.py +42 -2
- laddercodec-0.3.0/tests/__init__.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/csv/test_converter.py +110 -0
- laddercodec-0.3.0/tests/csv/test_pinned_or_inputs.py +289 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/csv/test_writer.py +2 -1
- laddercodec-0.3.0/tests/fixtures/coverage/golden/drum__v4.bin +0 -0
- laddercodec-0.3.0/tests/fixtures/coverage/golden/drum__v4.csv +40 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/event_drum__jog.bin +0 -0
- laddercodec-0.3.0/tests/fixtures/coverage/golden/loop__v4.bin +0 -0
- laddercodec-0.3.0/tests/fixtures/coverage/golden/loop__v4.csv +105 -0
- laddercodec-0.3.0/tests/fixtures/coverage/golden/math__negative.bin +0 -0
- laddercodec-0.3.0/tests/fixtures/coverage/golden/math__negative.csv +58 -0
- laddercodec-0.3.0/tests/fixtures/coverage/golden/math__v4.bin +0 -0
- laddercodec-0.3.0/tests/fixtures/coverage/golden/math__v4.csv +70 -0
- laddercodec-0.3.0/tests/fixtures/coverage/golden/out__v4.bin +0 -0
- laddercodec-0.3.0/tests/fixtures/coverage/golden/out__v4.csv +55 -0
- laddercodec-0.3.0/tests/fixtures/coverage/golden/pins__v4.bin +0 -0
- laddercodec-0.3.0/tests/fixtures/coverage/golden/pins__v4.csv +56 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/verify_progress.log +7 -1
- laddercodec-0.3.0/tests/fixtures/pinned_or/conf_counters_count_down.csv +22 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/scr_captures/README.md +2 -0
- laddercodec-0.3.0/tests/fixtures/scr_captures/pins.scr +0 -0
- laddercodec-0.3.0/tests/fixtures/v4_captures/drum.bin +0 -0
- laddercodec-0.3.0/tests/fixtures/v4_captures/drum_jog.bin +0 -0
- laddercodec-0.3.0/tests/fixtures/v4_captures/loop_exits.bin +0 -0
- laddercodec-0.3.0/tests/fixtures/v4_captures/math.bin +0 -0
- laddercodec-0.3.0/tests/fixtures/v4_captures/math_typed.bin +0 -0
- laddercodec-0.3.0/tests/fixtures/v4_captures/out.bin +0 -0
- laddercodec-0.3.0/tests/fixtures/v4_captures/out_debounce_example.bin +0 -0
- laddercodec-0.3.0/tests/fixtures/v4_captures/pins.bin +0 -0
- laddercodec-0.3.0/tests/fixtures/v4_captures/retyped/math_neg.bin +0 -0
- laddercodec-0.3.0/tests/fixtures/v4_captures/retyped/math_wide.bin +0 -0
- laddercodec-0.3.0/tests/fixtures/v4_captures/retyped/math_xd.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/ladder/test_decode_program.py +27 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/ladder/test_forloop.py +25 -1
- laddercodec-0.3.0/tests/ladder/test_math.py +147 -0
- laddercodec-0.3.0/tests/test_compat.py +75 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/test_public_api.py +5 -0
- laddercodec-0.3.0/tests/test_v4_captures.py +326 -0
- laddercodec-0.2.2/docs/internals/instruction-blobs.md +0 -69
- laddercodec-0.2.2/tests/ladder/test_math.py +0 -43
- {laddercodec-0.2.2 → laddercodec-0.3.0}/.claude/settings.local.json +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/.github/scripts/check_public_site.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/.github/scripts/prune_public_site.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/.github/workflows/ci.yml +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/.github/workflows/docs.yml +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/.github/workflows/publish.yml +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/.gitignore +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/CLAUDE.md +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/LICENSE +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/Makefile +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/README.md +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/add-features-workflow.md +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/devtools/analyze_scr.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/devtools/combine_coverage.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/devtools/compare_blobs.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/devtools/compare_csv.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/devtools/coverage_golden.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/devtools/create_mr_max_csv.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/devtools/diag_blob.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/devtools/gen_modbus_coverage.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/devtools/golden.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/devtools/inspect_bin.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/devtools/inspect_scr.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/devtools/lint.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/devtools/pdf_to_png.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/devtools/test_decode_scr.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/devtools/validate_scr.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/devtools/walk_scr.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/docs/AGENTS.md +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/docs/CLAUDE.md +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/docs/gen_llms.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/docs/guides/troubleshooting.md +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/docs/index.md +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/docs/internals/binary-format.md +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/docs/internals/wire-rendering.md +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/docs/stylesheets/extra.css +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/mkdocs.yml +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/pyproject.toml +0 -0
- /laddercodec-0.2.2/tests/__init__.py → /laddercodec-0.3.0/scratchpad/click-v4/captures/copyback/.gitkeep +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/binary_helpers.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/cell.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/csv/__init__.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/csv/ast.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/csv/bundle.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/csv/contract.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/csv/parser.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/csv/token_parser.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/empty_multirow.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/encode.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/encode_multi.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/instructions/call.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/instructions/comparison.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/instructions/contact.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/instructions/copy.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/instructions/email.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/instructions/end.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/instructions/family.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/instructions/home.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/instructions/position.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/instructions/return_.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/instructions/search.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/instructions/send_receive.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/instructions/velocity.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/resources/empty_multirow_rule_minimal.scaffold.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/src/laddercodec/topology.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/csv/test_bundle.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/csv/test_contract.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/csv/test_parser.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/csv/test_token_parser.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/csv/test_writer_raw_validator.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/coverage.ckp +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/blockcopy__block.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/blockcopy__block.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/blockcopy__oneshot.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/blockcopy__oneshot.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/blockcopy__to_ascii.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/blockcopy__to_ascii.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/blockcopy__to_value.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/blockcopy__to_value.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/call__basic.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/call__basic.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/cond__and.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/cond__and.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/cond__eq.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/cond__eq.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/cond__fall.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/cond__fall.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/cond__ge.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/cond__ge.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/cond__gt.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/cond__gt.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/cond__immediate.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/cond__immediate.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/cond__le.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/cond__le.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/cond__lt.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/cond__lt.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/cond__nc.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/cond__nc.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/cond__ne.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/cond__ne.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/cond__no.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/cond__no.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/cond__or.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/cond__or.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/cond__rise.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/cond__rise.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/copy__literal_float.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/copy__literal_float.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/copy__literal_int.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/copy__literal_int.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/copy__oneshot.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/copy__oneshot.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/copy__tag.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/copy__tag.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/copy__to_ascii.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/copy__to_ascii.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/copy__to_binary.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/copy__to_binary.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/copy__to_text.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/copy__to_text.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/copy__to_text_exp.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/copy__to_text_exp.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/copy__to_text_sz.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/copy__to_text_sz.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/copy__to_text_term.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/copy__to_text_term.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/copy__to_value.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/copy__to_value.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/count_down.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/count_down.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/count_up__down.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/count_up__down.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/count_up__reset.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/count_up__reset.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/end.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/end.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/event_drum__basic.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/event_drum__basic.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/event_drum__full.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/event_drum__full.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/event_drum__jog.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/event_drum__jump.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/event_drum__jump.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/event_drum__max.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/event_drum__max.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/fill__literal.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/fill__literal.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/fill__oneshot.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/fill__oneshot.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/fill__tag.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/fill__tag.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/forloop__basic.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/forloop__basic.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/forloop__oneshot.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/forloop__oneshot.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/latch__block.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/latch__block.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/latch__immediate.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/latch__immediate.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/latch__tag.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/latch__tag.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/math__decimal.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/math__decimal.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/math__hex.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/math__hex.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/math__oneshot.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/math__oneshot.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/off_delay__tof.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/off_delay__tof.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/on_delay__rton.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/on_delay__rton.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/on_delay__ton.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/on_delay__ton.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/out__block.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/out__block.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/out__immediate.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/out__immediate.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/out__oneshot.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/out__oneshot.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/out__tag.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/out__tag.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/pack_bits.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/pack_bits.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/pack_bits__oneshot.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/pack_bits__oneshot.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/pack_text.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/pack_text.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/pack_text__allow_whitespace.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/pack_text__allow_whitespace.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/pack_text__oneshot.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/pack_text__oneshot.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/pack_words.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/pack_words.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/pack_words__oneshot.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/pack_words__oneshot.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/raw_instructions__email.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/raw_instructions__email.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/raw_instructions__home.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/raw_instructions__home.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/raw_instructions__position.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/raw_instructions__position.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/raw_instructions__velocity.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/raw_instructions__velocity.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/receive__rtu_click_block.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/receive__rtu_click_block.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/receive__rtu_click_single.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/receive__rtu_click_single.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/receive__rtu_modbus_block.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/receive__rtu_modbus_block.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/receive__rtu_modbus_single.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/receive__rtu_modbus_single.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/receive__tcp_click_coil.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/receive__tcp_click_coil.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/receive__tcp_click_input.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/receive__tcp_click_input.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/receive__tcp_click_input_reg.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/receive__tcp_click_input_reg.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/receive__tcp_click_wordswap.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/receive__tcp_click_wordswap.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/reset__block.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/reset__block.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/reset__immediate.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/reset__immediate.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/reset__tag.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/reset__tag.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/return_early__basic.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/return_early__basic.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/search__continuous.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/search__continuous.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/search__eq.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/search__eq.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/search__ge.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/search__ge.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/search__gt.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/search__gt.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/search__le.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/search__le.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/search__lt.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/search__lt.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/search__ne.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/search__ne.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/search__oneshot.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/search__oneshot.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/send__error_off.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/send__error_off.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/send__errorcode_off.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/send__errorcode_off.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/send__rtu_click_block.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/send__rtu_click_block.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/send__rtu_click_single.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/send__rtu_click_single.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/send__rtu_modbus_block.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/send__rtu_modbus_block.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/send__rtu_modbus_single.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/send__rtu_modbus_single.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/send__sending_off.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/send__sending_off.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/send__success_off.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/send__success_off.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/send__tcp_click_coil.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/send__tcp_click_coil.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/send__tcp_click_coils.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/send__tcp_click_coils.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/send__tcp_click_wordswap.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/send__tcp_click_wordswap.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/shift__basic.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/shift__basic.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/time_drum__basic.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/time_drum__basic.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/time_drum__basic_td.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/time_drum__basic_td.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/unpack_to_bits.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/unpack_to_bits.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/unpack_to_bits__oneshot.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/unpack_to_bits__oneshot.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/unpack_to_words.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/unpack_to_words.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/unpack_to_words__oneshot.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/golden/unpack_to_words__oneshot.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/coverage/subroutines/coverage_sub.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/drum_weird_branch.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/cmt-1row-fullwire-nop.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/cmt-1row-fullwire-nop.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/cmt-1row-max1400.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/cmt-1row-max1400.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/cmt-1row-styled-mixed.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/cmt-1row-styled-mixed.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/cmt-2row-max1324.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/cmt-2row-max1324.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/cmt-2row-nop-wire.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/cmt-2row-nop-wire.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/cmt-32row-sparse.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/cmt-32row-sparse.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/cmt-3row-mixed.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/cmt-3row-mixed.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-2row-cond__and.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-2row-cond__and.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-2row-r0only.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-2row-r0only.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-2row-spread.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-2row-spread.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-3row-branch.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-3row-branch.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-3row-or-colA.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-3row-or-colA.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-3row-or.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-3row-or.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-3row-scatter.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-3row-scatter.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-6row-multi-output.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-6row-multi-output.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-coil-timer-ret.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-coil-timer-ret.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-compare-ge.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-compare-ge.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-compare-series.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-compare-series.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-compare-timer.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-compare-timer.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-cond__and.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-cond__and.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-copy-multirow-2af-T.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-copy-multirow-2af-T.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-copy-multirow-2af.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-copy-multirow-2af.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-count_down-row0-data.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-count_down-row0-data.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-no-out.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-no-out.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-series.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-series.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-timer-off.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-timer-off.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-timer-on.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-timer-on.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-timer-ret.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/instr-timer-ret.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/mr-2rung-2row.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/mr-2rung-2row.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/mr-2rung-wire.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/mr-2rung-wire.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/mr-3rung-wire-nop.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/mr-3rung-wire-nop.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/mr-cmt-2rung-2row.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/mr-cmt-2rung-2row.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/mr-cmt-2rung-both.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/mr-cmt-2rung-both.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/mr-cmt-2rung-r1-max1400.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/mr-cmt-2rung-r1-max1400.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/mr-cmt-3rung-all.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/mr-cmt-3rung-all.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/mr-cmt-3rung-multirow-multiinstructions.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/mr-cmt-3rung-multirow-multiinstructions.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/mr-cmt-3rung-multirow-nopaddedrows.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/mr-cmt-3rung-multirow-nopaddedrows.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/mr-cmt-3rung-multirow.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/mr-cmt-3rung-multirow.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/mr-instr-2rung.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/mr-instr-2rung.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/mr-instr-cond__and.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/mr-instr-cond__and.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/nc-1row-empty.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/nc-1row-empty.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/nc-1row-fullwire-nop.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/nc-1row-fullwire-nop.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/nc-32row-empty.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/nc-32row-empty.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/nc-3row-t-junction.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/nc-3row-t-junction.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/nc-4row-vertical.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/nc-4row-vertical.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/ladder_captures/golden/verify_progress.log +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/scr_captures/counter_scr.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/scr_captures/counter_scr.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/scr_captures/counter_scr.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/scr_captures/coverage.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/scr_captures/coverage.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/scr_captures/coverage.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/scr_captures/or_topology.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/scr_captures/or_topology.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/scr_captures/or_topology.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/scr_captures/shift_scr.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/scr_captures/shift_scr.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/scr_captures/shift_scr.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/scr_captures/time_drum_b_column.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/scr_captures/time_drum_b_column.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/scr_captures/time_drum_b_column.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/scr_captures/time_drum_insert_rows.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/scr_captures/time_drum_insert_rows.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/scr_captures/time_drum_insert_rows.png +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/scr_captures/time_drum_insert_rows.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/scr_captures/time_drums.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/scr_captures/time_drums.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/scr_captures/time_drums.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/main.clipboard.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/main.clipboard.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/main.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/main.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/AckAlarm.clipboard.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/AckAlarm.clipboard.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/AckAlarm.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/AckAlarm.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/AckAndClearAllAlarms.clipboard.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/AckAndClearAllAlarms.clipboard.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/AckAndClearAllAlarms.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/AckAndClearAllAlarms.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/AckWarning.clipboard.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/AckWarning.clipboard.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/AckWarning.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/AckWarning.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/AlmHistorian.clipboard.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/AlmHistorian.clipboard.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/AlmHistorian.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/AlmHistorian.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/Blower.clipboard.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/Blower.clipboard.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/Blower.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/Blower.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/DisableOutputs.clipboard.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/DisableOutputs.clipboard.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/DisableOutputs.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/DisableOutputs.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/Heat.clipboard.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/Heat.clipboard.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/Heat.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/Heat.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/Init.clipboard.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/Init.clipboard.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/Init.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/Init.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/Maint.clipboard.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/Maint.clipboard.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/Maint.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/Maint.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/Manual.clipboard.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/Manual.clipboard.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/Manual.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/Manual.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/ModeChange.clipboard.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/ModeChange.clipboard.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/ModeChange.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/ModeChange.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/PLCDateTime.clipboard.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/PLCDateTime.clipboard.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/PLCDateTime.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/PLCDateTime.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/PLCErrors.clipboard.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/PLCErrors.clipboard.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/PLCErrors.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/PLCErrors.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/ProductionBoilerplate.clipboard.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/ProductionBoilerplate.clipboard.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/ProductionBoilerplate.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/ProductionBoilerplate.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/ProductionErrors.clipboard.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/ProductionErrors.clipboard.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/ProductionErrors.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/ProductionErrors.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/ProductionExecuteSteps.clipboard.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/ProductionExecuteSteps.clipboard.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/ProductionExecuteSteps.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/ProductionExecuteSteps.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/ProductionHMI.clipboard.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/ProductionHMI.clipboard.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/ProductionHMI.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/ProductionHMI.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/ProductionStates.clipboard.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/ProductionStates.clipboard.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/ProductionStates.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/ProductionStates.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/ReadInputs.clipboard.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/ReadInputs.clipboard.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/ReadInputs.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/ReadInputs.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/RecipeChange.clipboard.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/RecipeChange.clipboard.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/RecipeChange.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/RecipeChange.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/Rotate.clipboard.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/Rotate.clipboard.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/Rotate.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/Rotate.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/SFCExample.clipboard.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/SFCExample.clipboard.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/SFCExample.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/SFCExample.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/SetOutputs.clipboard.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/SetOutputs.clipboard.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/SetOutputs.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/SetOutputs.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/SetOutputsManual.clipboard.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/SetOutputsManual.clipboard.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/SetOutputsManual.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/SetOutputsManual.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/ThermErrors.clipboard.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/ThermErrors.clipboard.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/ThermErrors.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/ThermErrors.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/Validation.clipboard.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/Validation.clipboard.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/Validation.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/Validation.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/WarnTimestamp.clipboard.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/WarnTimestamp.clipboard.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/WarnTimestamp.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/WarnTimestamp.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/sm_CopyOrJumpState.clipboard.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/sm_CopyOrJumpState.clipboard.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/sm_CopyOrJumpState.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/sm_CopyOrJumpState.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/sm_CtrlCmd2StateRequest.clipboard.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/sm_CtrlCmd2StateRequest.clipboard.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/sm_CtrlCmd2StateRequest.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/sm_CtrlCmd2StateRequest.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/sm_IsCmdValid.clipboard.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/sm_IsCmdValid.clipboard.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/sm_IsCmdValid.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/sm_IsCmdValid.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/sm_MapCmd2Val.clipboard.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/sm_MapCmd2Val.clipboard.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/sm_MapCmd2Val.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/sm_MapCmd2Val.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/sm_MapVal2State.clipboard.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/sm_MapVal2State.clipboard.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/sm_MapVal2State.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/sm_MapVal2State.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/sm_StateComplete2Request.clipboard.bin +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/sm_StateComplete2Request.clipboard.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/sm_StateComplete2Request.csv +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/fixtures/tumbler/subroutines/sm_StateComplete2Request.scr +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/golden_io.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/ladder/test_counter.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/ladder/test_decode.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/ladder/test_decode_multi.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/ladder/test_decode_program_tumbler.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/ladder/test_decode_rtf_oracle.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/ladder/test_empty_multirow.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/ladder/test_encode.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/ladder/test_encode_multi.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/ladder/test_model.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/ladder/test_shift.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/ladder/test_verify_status.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/test_coverage.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/tests/test_smoke.py +0 -0
- {laddercodec-0.2.2 → laddercodec-0.3.0}/uv.lock +0 -0
|
@@ -43,6 +43,7 @@ src/laddercodec/
|
|
|
43
43
|
├── binary_helpers.py # Shared binary primitives: UTF-16LE encode/decode, tagged fields
|
|
44
44
|
├── decode.py # Decoder: decode() + internal decode_rung(), decode_rungs()
|
|
45
45
|
├── decode_program.py # Program file decoder: decode_program() — Scr*.tmp to Program
|
|
46
|
+
├── compat.py # find_v4_only() / is_v4_only(): instructions an older CLICK would mangle
|
|
46
47
|
├── cell.py # Cell object builders: ClickCell, preamble, terminal, row
|
|
47
48
|
├── topology.py # Program header, rung preamble, cell offset math, wire flags
|
|
48
49
|
├── empty_multirow.py # Deterministic empty multi-row payload synthesis
|
|
@@ -52,6 +53,7 @@ src/laddercodec/
|
|
|
52
53
|
│ ├── contact.py # Contact (NO/NC/edge/immediate), build_blob(), cell_params(), parser
|
|
53
54
|
│ ├── comparison.py # CompareContact (==, !=, >, <, >=, <=), build_blob(), cell_params(), parser
|
|
54
55
|
│ ├── coil.py # Coil (out/latch/reset, range, immediate, oneshot), build_blob(), cell_params(), parser
|
|
56
|
+
│ ├── out_variant.py # OutVariant (CLICK v4 toggle/debounce/flasher/timed), build_blob(), cell_params(), parser
|
|
55
57
|
│ ├── timer.py # Timer (on_delay/off_delay, retentive), build_blob(), cell_params(), parser
|
|
56
58
|
│ ├── copy.py # Copy (single/block/fill), BlockCopy, Fill — build_blob(), cell_params(), parser
|
|
57
59
|
│ └── raw.py # RawInstruction (opaque blob passthrough), build_blob(), cell_params()
|
|
@@ -91,6 +93,7 @@ src/laddercodec/
|
|
|
91
93
|
tests/
|
|
92
94
|
├── test_smoke.py # Basic sanity check
|
|
93
95
|
├── test_coverage.py # Coverage golden fixture tests (instruction variants)
|
|
96
|
+
├── test_v4_captures.py # CLICK v4 captures: each rung decodes to its comment; native blob matching
|
|
94
97
|
├── golden_io.py # Golden CSV/BIN read/write helpers
|
|
95
98
|
├── ladder/
|
|
96
99
|
│ ├── test_encode.py # encode() pipeline, multi-row, comments, wires, NOP
|
|
@@ -112,7 +115,8 @@ tests/
|
|
|
112
115
|
└── fixtures/
|
|
113
116
|
├── ladder_captures/golden/ # Golden CSV/BIN fixtures
|
|
114
117
|
├── scr_captures/ # Scr program files + clipboard bins (decode_program)
|
|
115
|
-
|
|
118
|
+
├── tumbler/ # 34 real programs: <name>.scr + <name>.clipboard.{bin,csv}
|
|
119
|
+
└── v4_captures/ # CLICK v4 copy-backs of pyrung capture stubs (math, out, drum)
|
|
116
120
|
```
|
|
117
121
|
|
|
118
122
|
Ladder golden fixtures are verified through Click paste round-trip. In `scr_captures`, `time_drums.bin` is synthetic (see that directory's README); do not use its differences from SCR as evidence of native cleanup. The tumbler fixture pairs each Click internal program file (`.scr`) with a clipboard capture of the same program; `devtools/compare_csv.py <dir>` compares `<name>.csv` (scr decode) against `<name>.clipboard.csv` ground truth.
|
|
@@ -209,8 +213,10 @@ When the user provides a `.bin` + `.csv` from a Click capture:
|
|
|
209
213
|
|
|
210
214
|
1. **Inspect the capture:** `uv run devtools/inspect_bin.py <file.bin>` — shows known instructions with `to_csv()` output, and RawInstruction/Unknown blobs with full tagged-field breakdown (tag IDs, sentinel types, values).
|
|
211
215
|
2. **Identify what's new:** RawInstruction means the class name is recognized but the func code isn't. The field breakdown shows exactly which func code / field values differ from existing support.
|
|
212
|
-
3. **Update the code:** add func codes, fields, or new instruction modules as needed
|
|
216
|
+
3. **Update the code:** add func codes, fields, or new instruction modules as needed; CSV parsing goes through the family `SPEC`'s `parse_csv_call`.
|
|
213
217
|
4. **Update coverage CSV:** `tests/fixtures/coverage/golden/<name>.csv` — use kwargs style for boolean flags (e.g. `oneshot=1`).
|
|
214
218
|
5. **Verify:** `make test` + `make lint`.
|
|
215
219
|
|
|
220
|
+
For CLICK v4 instructions captured from pyrung stubs (`tests/fixtures/v4_captures/`, `tests/test_v4_captures.py`), see "Capturing from CLICK v4" in the guide.
|
|
221
|
+
|
|
216
222
|
See [`docs/guides/adding-instructions.md`](docs/guides/adding-instructions.md) for the full guide.
|
|
@@ -8,6 +8,30 @@
|
|
|
8
8
|
Review and condense before release — entries accumulate during development and
|
|
9
9
|
should be edited into shape before moving from Unreleased to a version heading. -->
|
|
10
10
|
|
|
11
|
+
## 0.3.0 (2026-11-01)
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
- **CLICK v4 Out variants**: `toggle(C1)`, `debounce(...)`, `flasher(...)` and `timed(...)` decode and encode as `OutVariant`, exported from the root package, matching Click-written blobs byte for byte.
|
|
15
|
+
- **CLICK v4 Time & Event drum**: `time_event_drum(outputs=[...],presets=[1000,None,DS1],events=[None,C1,C2],unit=Tms,...)` decodes and encodes as `Drum(drum_kind="time_event")`, with `None` marking a step without a preset or event.
|
|
16
|
+
- **CLICK v4 Break and Continue**: `break()` and `continue()` decode and encode as `Break` and `Continue`, exported from the root package; both used to decode as `next()`.
|
|
17
|
+
- **CLICK v4 Math**: wide ranges encode up to CLICK's limit of 5000 interior addresses, where more than 500 used to raise `ValueError`, and `XD`/`YD` registers are recognized as operands, including `XD0u` and its place inside a range.
|
|
18
|
+
- **CLICK v4 check**: `find_v4_only(rungs)` lists the instructions an older CLICK would silently change or may not hold (Break/Continue, Out variants, Time & Event drums, time drums with a duration from a register, v4 math functions, SUM over bits, Math ranges past 500 interior addresses), and `is_v4_only()` checks one.
|
|
19
|
+
- **Pin OR legs**: OR legs under a counter, shift or drum pin push the later pins down and grow the box as CLICK does, in clipboard and SCR, exposed as `pin_rows`.
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
- **CSV read**: a blank-AF row directly under `count_down` is an OR leg of its Down input rather than the bridge row.
|
|
23
|
+
- **CSV errors**: pins out of order or repeated raise `ConvertError` instead of being dropped, a pin a timer does not have (e.g. `.down()`) raises `ConvertError` instead of reading as a blank row, and `write_csv` refuses a leg drawn onto an unused pin's row, which CSV cannot express.
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
- **Math encode**: formulas and constants are written the way Click's editor writes them (`ABS(x)*2` → `ABS ( x ) * 2`, `RAND` in its infix form, range interiors listed, `Ah` → `UH10`, `-5` → `H-5`, `-2.5` → `F-2.5`), so pasted formulas no longer raise Math instruction errors or fail CLICK v4's syntax check.
|
|
27
|
+
- **Math encode**: `show_nicknames=True` wraps each operand once, where repeated or overlapping addresses (`DS10 + DS1 + DS1`) came out corrupted.
|
|
28
|
+
- **Math decode**: `XD`/`YD` formulas keep their display constants, instead of `XD0 AND 1h` reading back as `XD0 AND UH1`.
|
|
29
|
+
- **Drum encode**: with Jump off, Jog takes the func code Jump would have, so CLICK v4 no longer rejects a pasted drum with C000A ("all inputs of the box instruction must originate from the same branch").
|
|
30
|
+
- **Unknown coils and drums**: an Out coil with an unknown func code or a drum with an unknown base decodes as `raw(...)`, instead of silently decoding as a plain `out(...)` or `time_drum`.
|
|
31
|
+
- **Raw multi-part instructions**: a `raw(...)` token with part count 2+ rebuilds Click's part bytes, so `write_csv` no longer fails its round-trip check on raw drums and SCR raw blobs carry the right bytes.
|
|
32
|
+
- **CSV read, OR inputs on boxes**: OR legs under any timer, counter, shift or drum input push its later pins down, so a `count_down` fed by a 3+ row OR no longer raises and a retentive timer fed by a 2+ row OR keeps its `.reset()`.
|
|
33
|
+
- **CSV writer**: a box's empty pin rows and a `count_down`'s empty top row stay in place when a blank-AF row or a `count_down` follows, where `write_csv` used to fail its round-trip check.
|
|
34
|
+
|
|
11
35
|
## 0.2.2 (2026-09-10)
|
|
12
36
|
|
|
13
37
|
### Fixed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: laddercodec
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Binary codec for AutomationDirect CLICK PLC ladder clipboard format
|
|
5
5
|
Project-URL: Repository, https://github.com/ssweber/laddercodec
|
|
6
6
|
Project-URL: Documentation, https://pyrung.com/laddercodec/
|
|
@@ -31,7 +31,8 @@ def main() -> None:
|
|
|
31
31
|
row = data[cursor]
|
|
32
32
|
col = data[cursor + 1]
|
|
33
33
|
blob_start = cursor + 8
|
|
34
|
-
cls, typ, end_off,
|
|
34
|
+
cls, typ, end_off, part_rows = blob
|
|
35
|
+
m1 = len(part_rows)
|
|
35
36
|
next_pos = end_off + 2 + data[end_off] # trailer-aware advance
|
|
36
37
|
|
|
37
38
|
# Parse tagged fields
|
|
@@ -26,7 +26,16 @@ PAGES: tuple[ReferencePage, ...] = (
|
|
|
26
26
|
title="Codec API",
|
|
27
27
|
tier="Stable Core",
|
|
28
28
|
summary="Encode and decode Click clipboard binary and program files.",
|
|
29
|
-
symbols=(
|
|
29
|
+
symbols=(
|
|
30
|
+
"encode",
|
|
31
|
+
"decode",
|
|
32
|
+
"decode_program",
|
|
33
|
+
"Rung",
|
|
34
|
+
"Program",
|
|
35
|
+
"Project",
|
|
36
|
+
"find_v4_only",
|
|
37
|
+
"is_v4_only",
|
|
38
|
+
),
|
|
30
39
|
),
|
|
31
40
|
ReferencePage(
|
|
32
41
|
slug="csv",
|
|
@@ -44,6 +53,7 @@ PAGES: tuple[ReferencePage, ...] = (
|
|
|
44
53
|
"Contact",
|
|
45
54
|
"CompareContact",
|
|
46
55
|
"Coil",
|
|
56
|
+
"OutVariant",
|
|
47
57
|
"Timer",
|
|
48
58
|
"Counter",
|
|
49
59
|
"Copy",
|
|
@@ -60,6 +70,8 @@ PAGES: tuple[ReferencePage, ...] = (
|
|
|
60
70
|
"End",
|
|
61
71
|
"ForLoop",
|
|
62
72
|
"Next",
|
|
73
|
+
"Break",
|
|
74
|
+
"Continue",
|
|
63
75
|
"Send",
|
|
64
76
|
"Receive",
|
|
65
77
|
"ModbusAddress",
|
|
@@ -69,7 +69,14 @@ In `src/laddercodec/instructions/<module>.py`:
|
|
|
69
69
|
- Add any new fields to the dataclass (e.g. `oneshot: bool = False`)
|
|
70
70
|
- Update `build_blob()` to emit the new field value
|
|
71
71
|
- Update `to_csv()` to include the new parameter
|
|
72
|
-
- Update `
|
|
72
|
+
- Update `from_tags()` to extract the new field from the func code table
|
|
73
|
+
|
|
74
|
+
If the new variant shares a class name with an existing family (CLICK v4's toggle,
|
|
75
|
+
debounce, flasher and timed are all class `Out`, type 0x2715), the existing family's
|
|
76
|
+
`from_tags()` must return `None` for func codes it doesn't know. Otherwise the variant
|
|
77
|
+
decodes silently as the old instruction. `from_tags()` dispatch tries every family in
|
|
78
|
+
turn, so the new family can set `binary_class_names=()` and leave the class name's
|
|
79
|
+
registry entry to the existing one (see `out_variant.py`).
|
|
73
80
|
|
|
74
81
|
### 3. Update the CSV-facing parse path
|
|
75
82
|
|
|
@@ -101,7 +108,7 @@ Same as above. For new types, inspect will often show `RawInstruction` with a ne
|
|
|
101
108
|
In `src/laddercodec/instructions/`:
|
|
102
109
|
|
|
103
110
|
- New `@dataclass` inheriting from `AfInstruction` (or `ConditionInstruction`)
|
|
104
|
-
- Implement `to_csv()`, `build_blob()`, `cell_params()`, and `
|
|
111
|
+
- Implement `to_csv()`, `build_blob()`, `cell_params()`, and a module-level `from_tags()`
|
|
105
112
|
- Follow existing modules (coil.py, timer.py, copy.py) as templates
|
|
106
113
|
- Add `InstructionType` enum value in `model.py` if it uses a new type marker
|
|
107
114
|
|
|
@@ -114,11 +121,19 @@ If the instruction also needs auto-padding in CSV, set `min_csv_rows=N` on the f
|
|
|
114
121
|
|
|
115
122
|
Example: timers currently use `visual_rows=2` and `min_csv_rows=2`, while counter/shift/drum families use explicit higher CSV row counts because their lower rows have pin semantics.
|
|
116
123
|
|
|
124
|
+
`visual_rows` sets both cell header bytes, `+0x09` (rows spanned) and `+0x0A`
|
|
125
|
+
(sub-rows). When a native capture shows them differing, add `"sub_rows"` for
|
|
126
|
+
`+0x0A`: CLICK v4's timed coil spans 2 rows but writes 3 (`{"visual_rows": 2, "sub_rows": 3}`).
|
|
127
|
+
|
|
128
|
+
**Reading tags in `from_tags()`:** flag tags (`0x11xx`/`0x12xx`) are present in
|
|
129
|
+
`tags` with an empty value when set, and absent when `0`. Test them with
|
|
130
|
+
`0x1201 in tags`, not by value.
|
|
131
|
+
|
|
117
132
|
Also add a family `SPEC` in the module:
|
|
118
133
|
|
|
119
134
|
- `binary_class_names`
|
|
120
135
|
- `csv_names`
|
|
121
|
-
- `
|
|
136
|
+
- `from_tags`
|
|
122
137
|
- `parse_csv_call` (for AF families)
|
|
123
138
|
- `pin_names` if the family uses dot-prefixed continuation rows
|
|
124
139
|
- `min_csv_rows` if the family should auto-pad in CSV
|
|
@@ -129,6 +144,8 @@ Also add a family `SPEC` in the module:
|
|
|
129
144
|
|------|---------------|
|
|
130
145
|
| `instructions/__init__.py` | Register the family `SPEC` in `AF_FAMILY_SPECS` or `CONDITION_FAMILY_SPECS`, and re-export the new class |
|
|
131
146
|
| `__init__.py` | Re-export the new class in the public API |
|
|
147
|
+
| `tests/test_public_api.py` | Add the class to `EXPECTED_ROOT_EXPORTS`, which pins the root `__all__` |
|
|
148
|
+
| `docs/gen_reference.py` | Add the class to the Instructions API page; `make docs-build` fails on an unlisted export |
|
|
132
149
|
|
|
133
150
|
`KNOWN_AF_NAMES` is now derived from the registered family specs, so `csv/ast.py` does not need manual token updates.
|
|
134
151
|
|
|
@@ -162,7 +179,7 @@ Coverage golden fixtures live in `tests/fixtures/coverage/golden/`. Each fixture
|
|
|
162
179
|
|
|
163
180
|
### Adding a fixture
|
|
164
181
|
|
|
165
|
-
1. Create `tests/fixtures/coverage/golden/<rung_id>.csv` by hand
|
|
182
|
+
1. Create `tests/fixtures/coverage/golden/<rung_id>.csv` by hand in the 33-column canonical format. Usually one rung per file; a file can hold several rungs (`math__v4.csv` holds 23) and is verified as one paste.
|
|
166
183
|
2. Run `make coverage-golden` to generate the `.bin` from the CSV.
|
|
167
184
|
3. Paste-verify in Click using `clicknick-rung guided`.
|
|
168
185
|
4. `make test` — each `.csv` with a matching `.bin` gets a parametrized test comparing encoded output to golden binaries.
|
|
@@ -187,6 +204,49 @@ uv run devtools/combine_coverage.py --seed 42 # reproducible pick
|
|
|
187
204
|
|
|
188
205
|
This picks N random coverage CSVs, stacks their data rows into one multi-row rung, and writes `devtools/combined.csv` + `devtools/combined.bin` for paste-testing.
|
|
189
206
|
|
|
207
|
+
## Capturing from CLICK v4
|
|
208
|
+
|
|
209
|
+
New CLICK v4 instructions are captured in groups. The paste CSVs are built with
|
|
210
|
+
pyrung by `scratchpad/click-v4/captures/v4_capture.py`, whose README has the
|
|
211
|
+
CLICK-side steps and address map per group. Each rung's comment is its id, then
|
|
212
|
+
every AF token it should decode to, in row order:
|
|
213
|
+
|
|
214
|
+
```
|
|
215
|
+
#,drum__te_ds
|
|
216
|
+
#,"time_event_drum(outputs=[C1321,C1322],presets=[DS1301,None],...)"
|
|
217
|
+
#,.reset()
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Run clicknick against the local checkouts, so `load` encodes with the laddercodec
|
|
221
|
+
you are changing. From the clicknick directory:
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
make install-dev # editable ../pyclickplc, ../pyrung, ../laddercodec
|
|
225
|
+
UV_NO_SYNC=1 uv run --no-sync clicknick-rung load ../laddercodec/scratchpad/click-v4/captures/stubs/<group>.csv
|
|
226
|
+
# build each rung in CLICK as its comment says, copy them all back, then:
|
|
227
|
+
UV_NO_SYNC=1 uv run --no-sync clicknick-rung save ../laddercodec/scratchpad/click-v4/captures/copyback/<group>
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
A rung whose instruction laddercodec can't encode yet is pasted as a placeholder
|
|
231
|
+
(NOP, or a v3 instruction with `1` standing in for a blank or register preset);
|
|
232
|
+
its comment still names the target.
|
|
233
|
+
|
|
234
|
+
In laddercodec:
|
|
235
|
+
|
|
236
|
+
1. Copy `scratchpad/click-v4/captures/copyback/<group>.bin` to `tests/fixtures/v4_captures/`. `tests/test_v4_captures.py`
|
|
237
|
+
checks every labelled rung: one still decoding as `raw(...)` is xfail, any other
|
|
238
|
+
mismatch fails, and every capture must survive `write_csv`.
|
|
239
|
+
2. Map the fields of the raw blobs (`devtools/inspect_bin.py`, or the `raw(...)`
|
|
240
|
+
tokens in the saved CSV) and model the instruction until its rungs pass.
|
|
241
|
+
3. Add a test that re-encoding matches the blobs Click wrote, field for field
|
|
242
|
+
(see `test_out_variant_blobs_match_native` and `test_time_event_drum_blobs_match_native`).
|
|
243
|
+
4. For the encode side, copy `scratchpad/click-v4/captures/expected/<group>.csv` (real tokens in the
|
|
244
|
+
AF column) to a coverage golden `<family>__v4.csv`, run `make coverage-golden`,
|
|
245
|
+
and paste-verify it with `clicknick-rung guided`.
|
|
246
|
+
|
|
247
|
+
A typo made while building rungs in CLICK shows up as a failing rung, not an
|
|
248
|
+
xfail. Fix the rung in CLICK and save again.
|
|
249
|
+
|
|
190
250
|
## Clicknick compatibility
|
|
191
251
|
|
|
192
252
|
The `clicknick-rung guided` tool extracts operand addresses from CSV tokens for MDB provisioning. It uses `to_csv()` + regex to find address patterns, so **new instruction types work automatically** — no clicknick changes needed.
|
|
@@ -293,6 +293,38 @@ Builder side conditions are emitted as continuation rows with dot tokens in `AF`
|
|
|
293
293
|
Pin rows are independent left-rail paths, not AND-chained through the parent
|
|
294
294
|
output row conditions.
|
|
295
295
|
|
|
296
|
+
Pins go in a fixed order (timers: reset; `count_up`: down, reset; `count_down`:
|
|
297
|
+
reset; `shift`: clock, reset; drums: reset, jump, jog). Rows without an AF token
|
|
298
|
+
between the instruction and a pin, or between two pins, are OR legs of the input
|
|
299
|
+
above, and they push the later pins down. CLICK grows the box to match:
|
|
300
|
+
|
|
301
|
+
```csv
|
|
302
|
+
R,C1,-,...,-,"time_drum(...)"
|
|
303
|
+
,C2,T,-,...,-,.reset()
|
|
304
|
+
,C3,,...,,
|
|
305
|
+
,C4,-,...,-,.jump(DS2)
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
Here `.jump()` is on row 3, not row 2. An unused pin still takes a row of its
|
|
309
|
+
own, below the legs of the pin above it: with Jump off, `.reset()` with one leg
|
|
310
|
+
then `.jog()` puts Jog on row 4, with a blank Jump row 3 (CLICK lays out a leg
|
|
311
|
+
added with Insert Row the same way). Blank rows just above the next pin are read
|
|
312
|
+
as the unused pins' rows, not legs. Legs under the last pin sit below the box.
|
|
313
|
+
|
|
314
|
+
The same holds for legs under the main input:
|
|
315
|
+
|
|
316
|
+
```csv
|
|
317
|
+
R,X1,T:X2,T,-,...,-,"count_down(CT1,CTD1,preset=3)"
|
|
318
|
+
,,T:X3,|,,...,,
|
|
319
|
+
,,X4,,,...,,
|
|
320
|
+
,X9,-,...,-,.reset()
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
`count_down`'s main input is its Down input, on box row 1 under the unused Up,
|
|
324
|
+
so this box is 5 rows with Reset on row 4. A `count_up` without `.down()` puts
|
|
325
|
+
the unused Down row under the main input's legs. A timer without `.reset()`
|
|
326
|
+
stays 2 rows, with its main input's legs beside and below it.
|
|
327
|
+
|
|
296
328
|
## Parsing conveniences
|
|
297
329
|
|
|
298
330
|
`laddercodec.read_csv()` accepts a few parsing conveniences beyond the canonical
|
|
@@ -308,7 +340,9 @@ writer contract:
|
|
|
308
340
|
`forloop(count, oneshot=...)` lowers to:
|
|
309
341
|
|
|
310
342
|
1. `for(count)` or `for(count,oneshot=1)` row (`marker=R`)
|
|
311
|
-
2. Body
|
|
343
|
+
2. Body rungs (`marker=R` each): a bare body instruction is a wire-only rung; a
|
|
344
|
+
body rung with contacts keeps them, and holds `break()` / `continue()`
|
|
345
|
+
(CLICK v4). A nested loop is its own `for` .. `next()` run, up to three deep.
|
|
312
346
|
3. Closing `next()` row (`marker=R`)
|
|
313
347
|
|
|
314
348
|
## Subroutine tail guarantee
|
|
@@ -383,6 +417,7 @@ Producer may emit:
|
|
|
383
417
|
- `return()`
|
|
384
418
|
- `for(count)` or `for(count,oneshot=1)`
|
|
385
419
|
- `next()`
|
|
420
|
+
- `break()`, `continue()` (CLICK v4) - on a contacted rung inside a loop
|
|
386
421
|
- `raw(ClassName,hex)` - opaque instruction passthrough for binary round-trip
|
|
387
422
|
fidelity. `ClassName` is the Click binary class name (unquoted) and `hex` is
|
|
388
423
|
the raw blob as a hex string. Runtime no-op; preserved so CSV -> DSL -> CSV
|
|
@@ -29,14 +29,15 @@ All standard Click instruction types are decoded into domain objects:
|
|
|
29
29
|
- **Contacts** → `Contact` (NO, NC, edge, immediate)
|
|
30
30
|
- **Comparison contacts** → `CompareContact` (==, !=, >, <, >=, <=)
|
|
31
31
|
- **Coils** → `Coil` (out, latch, reset, immediate, range, oneshot)
|
|
32
|
+
- **CLICK v4 Out variants** → `OutVariant` (toggle, debounce, flasher, timed)
|
|
32
33
|
- **Timers** → `Timer` (on_delay, off_delay, retentive)
|
|
33
34
|
- **Counters** → `Counter` (count_up, count_down)
|
|
34
35
|
- **Copy family** → `Copy`, `BlockCopy`, `Fill`, `Pack`, `Unpack`
|
|
35
36
|
- **Math** → `Math` (decimal/hex expressions)
|
|
36
37
|
- **Shift registers** → `Shift`
|
|
37
|
-
- **Drum sequencers** → `Drum` (event
|
|
38
|
+
- **Drum sequencers** → `Drum` (event, time, and CLICK v4 time & event)
|
|
38
39
|
- **Table search** → `Search`
|
|
39
|
-
- **Flow control** → `Call`, `Return`, `End`, `ForLoop`, `Next`
|
|
40
|
+
- **Flow control** → `Call`, `Return`, `End`, `ForLoop`, `Next`, `Break`, `Continue` (CLICK v4)
|
|
40
41
|
- **Modbus** → `Send`, `Receive`
|
|
41
42
|
|
|
42
43
|
Unrecognised cells fall back to `RawInstruction` with the raw bytes preserved. This keeps the decoder forward-compatible — unknown instruction types don't crash the pipeline.
|
|
@@ -109,6 +110,24 @@ The returned `Program` dataclass has:
|
|
|
109
110
|
|
|
110
111
|
Each `Rung` in `program.rungs` has the same structure as clipboard-decoded rungs, so you can pass them to `encode()`, `write_csv()`, or any other API that accepts `Rung` objects.
|
|
111
112
|
|
|
113
|
+
## Check for CLICK v4 instructions
|
|
114
|
+
|
|
115
|
+
An older CLICK pastes v4 rungs without complaint and changes them: Break and
|
|
116
|
+
Continue come back as plain Next, which closes the loop early. Check before
|
|
117
|
+
pasting into a pre-v4 CLICK:
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
from laddercodec import find_v4_only
|
|
121
|
+
|
|
122
|
+
for index, instruction in find_v4_only(rungs):
|
|
123
|
+
print(f"rung {index}: {instruction.to_csv()} needs CLICK v4")
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
v4-only: `Break`, `Continue`, `OutVariant`, a time & event `Drum`, a time `Drum`
|
|
127
|
+
with a duration from a register, and `Math` using MAX, MIN, MDN, AVG, ABS, RAND,
|
|
128
|
+
SUM over a bit range, or ranges past 500 interior addresses. `is_v4_only()` checks
|
|
129
|
+
a single instruction.
|
|
130
|
+
|
|
112
131
|
## Round-trip identity
|
|
113
132
|
|
|
114
133
|
For all supported instruction types:
|
|
@@ -189,7 +189,7 @@ raw address for that operand.
|
|
|
189
189
|
All standard Click instruction families are supported from the root package:
|
|
190
190
|
|
|
191
191
|
- Condition side: `Contact`, `CompareContact`
|
|
192
|
-
- AF side: `Coil`, `Timer`, `Counter`, `Copy`, `BlockCopy`, `Fill`, `Pack`, `Unpack`, `Math`, `Shift`, `Search`, `Drum`, `Call`, `Return`, `End`, `ForLoop`, `Next`, `Send`, `Receive`
|
|
192
|
+
- AF side: `Coil`, `OutVariant`, `Timer`, `Counter`, `Copy`, `BlockCopy`, `Fill`, `Pack`, `Unpack`, `Math`, `Shift`, `Search`, `Drum`, `Call`, `Return`, `End`, `ForLoop`, `Next`, `Send`, `Receive`
|
|
193
193
|
|
|
194
194
|
Unknown AF blobs can still be preserved via `RawInstruction`, which keeps the
|
|
195
195
|
binary payload intact for lossless round-trip.
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# Instruction Blobs
|
|
2
|
+
|
|
3
|
+
This page documents the variable-length instruction data that follows the cell header in instruction cells. The blob starts at cell offset +0x25.
|
|
4
|
+
|
|
5
|
+
For field layouts, func code tables, and tag constants for each known instruction type, see the source in `src/laddercodec/instructions/` — each module (`contact.py`, `comparison.py`, `coil.py`, `timer.py`) is the authoritative reference.
|
|
6
|
+
|
|
7
|
+
## Generic blob structure
|
|
8
|
+
|
|
9
|
+
All instruction blobs follow the same pattern:
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
[UTF-16LE class name, null-terminated]
|
|
13
|
+
[type marker: uint32 LE, high byte always 0x27]
|
|
14
|
+
[part count: uint16 LE (0x01 for contacts/coils, 0x02 for timers)]
|
|
15
|
+
[extra bytes: (part_count - 1) bytes, if part_count > 1 — each later part's row]
|
|
16
|
+
[field count: uint32 LE]
|
|
17
|
+
[tagged fields...]
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### Part rows
|
|
21
|
+
|
|
22
|
+
A tall instruction's extra bytes give the row, below the main row, of each later
|
|
23
|
+
part: `01` for a timer's reset, `01 02` for a counter (down, reset) or shift
|
|
24
|
+
(clock, reset), `01 02 03` for a drum (reset, jump, jog). OR legs under an
|
|
25
|
+
input (the main one included) push the later parts down, and CLICK grows the
|
|
26
|
+
box: a drum with one leg under reset is `01 03 04`. A count_down's main part is
|
|
27
|
+
its unused Up input, so its Down input is the first extra byte. The AF cell's `+0x09` becomes the last part's row + 1;
|
|
28
|
+
`+0x0A` keeps the base height (`tests/fixtures/v4_captures/pins.bin`).
|
|
29
|
+
|
|
30
|
+
### Tagged fields
|
|
31
|
+
|
|
32
|
+
Each field is:
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
[2-byte tag]
|
|
36
|
+
[FF FF FF FF sentinel]
|
|
37
|
+
[UTF-16LE null-terminated value]
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Field values are string-encoded even for numeric data (e.g. `"1000"` for a timer preset). Timer fields 6–7 use a variant format with a 4-byte sub-marker instead of the `FF FF FF FF` sentinel.
|
|
41
|
+
|
|
42
|
+
## Known binary class names
|
|
43
|
+
|
|
44
|
+
| Class name | Type markers | Instruction | Source |
|
|
45
|
+
|---|---|---|---|
|
|
46
|
+
| `ContactNO` | 0x2711 (NO), 0x2712 (NC) | NO/NC contacts | `contact.py` |
|
|
47
|
+
| `Edge` | 0x2713 | Rising/falling edge contacts | `contact.py` |
|
|
48
|
+
| `Compare` | 0x2714 | Comparison contacts (==, !=, >, <, >=, <=) | `comparison.py` |
|
|
49
|
+
| `Out` | 0x2715, 0x2716, 0x2717 | All coil types (out, latch, reset) | `coil.py` |
|
|
50
|
+
| `Tmr` | 0x2718 | Timers (on_delay, off_delay) | `timer.py` |
|
|
51
|
+
|
|
52
|
+
The encoder uses `Out` as the class name for all coil types; the type marker and func code determine the variant. The decoder also recognizes `Latch` and `Reset` class names from native Click captures.
|
|
53
|
+
|
|
54
|
+
## Out variants (CLICK v4)
|
|
55
|
+
|
|
56
|
+
CLICK v4's toggle, debounce, flasher and timed coils are `Out` blobs with type
|
|
57
|
+
marker 0x2715, the same as a plain `out`. They carry 15 fields, and only the
|
|
58
|
+
func code separates them from plain coils. An `Out` blob whose func code is in
|
|
59
|
+
neither table decodes as `raw(Out,...)`. Source: `out_variant.py`.
|
|
60
|
+
|
|
61
|
+
| Tag | Field |
|
|
62
|
+
|---|---|
|
|
63
|
+
| `0x6066` | target |
|
|
64
|
+
| `0x6067` | range end (always empty) |
|
|
65
|
+
| `0x60B3` / `0x60B4` | on preset / on accumulator (`TD`) |
|
|
66
|
+
| `0x60B5` / `0x60B6` | off preset / off accumulator (debounce, flasher) |
|
|
67
|
+
| `0x11F8` | oneshot (always `0`) |
|
|
68
|
+
| `0x11F5` | immediate (toggle) |
|
|
69
|
+
| `0x1246` | `1` for toggle |
|
|
70
|
+
| `0x1247` | maintained (timed) |
|
|
71
|
+
| `0x21F9` | time unit: 0 ms, 1 s, 2 min |
|
|
72
|
+
| `0x2248` | variant: 0 toggle, 1 debounce, 2 flasher, 3 timed |
|
|
73
|
+
| `0x3218` | func code |
|
|
74
|
+
| `0x20CA` | always `2` |
|
|
75
|
+
|
|
76
|
+
| Variant | Func codes | Units | Rows (`+0x09` / `+0x0A`) |
|
|
77
|
+
|---|---|---|---|
|
|
78
|
+
| toggle | 8224, immediate 8225 | — | 1 / 1 |
|
|
79
|
+
| debounce | 8226 ms, 8227 s | ms, s | 3 / 3 |
|
|
80
|
+
| flasher | 8228 ms, 8229 s | ms, s | 3 / 3 |
|
|
81
|
+
| timed | 8230–8232 ms/s/min, maintained 8233–8235 | ms, s, min | 2 / 3 |
|
|
82
|
+
|
|
83
|
+
Each phase stores only its accumulator; Click claims the `T` of the same number
|
|
84
|
+
with it. Timed is the one AF instruction whose cell header has more visual
|
|
85
|
+
sub-rows (`+0x0A`) than rows spanned (`+0x09`).
|
|
86
|
+
|
|
87
|
+
## Time & Event drum (CLICK v4)
|
|
88
|
+
|
|
89
|
+
A drum's base is tag `0x2200`: `0` time, `1` event, `2` time & event. Any other
|
|
90
|
+
value decodes as `raw(Drum,...)`. Source: `drum.py`.
|
|
91
|
+
|
|
92
|
+
CLICK v4 copies every drum back with 82 fields: the 63 v3 fields, then 16 preset
|
|
93
|
+
slots (`0x6891`), `0x428A`, `0x6068` and the terminator. The encoder writes the
|
|
94
|
+
82-field layout for time & event drums only. Time and event drums keep the
|
|
95
|
+
64-field v3 layout, which CLICK v4 still accepts.
|
|
96
|
+
|
|
97
|
+
| Tag | Time & event drum |
|
|
98
|
+
|---|---|
|
|
99
|
+
| `0x6872` ×16 | events (blank for a step without one) |
|
|
100
|
+
| `0x6891` ×16 | presets (blank for a step without one) |
|
|
101
|
+
| `0x6068` | done bit of the accumulator's timer (`TD101` → `T101`) |
|
|
102
|
+
| `0x428A` | `-1` as written by the encoder; see below |
|
|
103
|
+
| `0x3A05` ×4 | func codes; no-jog base Tms 10503, Ts 10510, Tm 10517, Th 10524, Td 10532 |
|
|
104
|
+
|
|
105
|
+
The func codes have the same 7-code block shape as the time drum (base, reset,
|
|
106
|
+
jump, then jog group +3..+6) and the same Td skip.
|
|
107
|
+
|
|
108
|
+
In every drum the codes run consecutively over the enabled pins. With Jump off,
|
|
109
|
+
Jog takes Jump's code: event `8494, 8495, 0, 8496`, not `8497`. CLICK v3
|
|
110
|
+
accepts the skipped code. CLICK v4 pastes it, then fails the syntax check with
|
|
111
|
+
C000A ("All inputs of the box instruction must originate from the same branch")
|
|
112
|
+
until the drum is reopened and OK'd (`v4_captures/drum_jog.bin`).
|
|
113
|
+
|
|
114
|
+
`0x428A` looks like leftover editor state. Click fills in `-1` for a pasted drum
|
|
115
|
+
that lacks the field. A time drum switched to Time & Event and back came out
|
|
116
|
+
`-4`, with new func codes (Tms 10247/10248 where the v3 table has 8455/8456).
|
|
117
|
+
|
|
118
|
+
## Break and Continue (CLICK v4)
|
|
119
|
+
|
|
120
|
+
Break and Continue are class `Next` (type 0x2726), told apart by the func code in
|
|
121
|
+
tag `0x3218`. Source: `forloop.py`.
|
|
122
|
+
|
|
123
|
+
| `0x3218` | Instruction |
|
|
124
|
+
|---|---|
|
|
125
|
+
| absent | `next()`: v3 writes Next with the terminator field only |
|
|
126
|
+
| `9220` | `next()`: CLICK v4 writes the func code |
|
|
127
|
+
| `9232` | `continue()` |
|
|
128
|
+
| `9233` | `break()` |
|
|
129
|
+
|
|
130
|
+
Any other func code decodes as `raw(Next,...)`. Break and Continue are encoded
|
|
131
|
+
with the two fields Click writes; `next()` keeps the one-field v3 form. Each
|
|
132
|
+
version accepts either Next on paste and copies back its own: v3 drops `9220`,
|
|
133
|
+
v4 adds it.
|
|
134
|
+
|
|
135
|
+
## Math formulas
|
|
136
|
+
|
|
137
|
+
A Math blob (class `Math`, type 0x271A) has 1010 tagged fields: 9 header
|
|
138
|
+
fields, 500 operand slots (tag `0x6888`), 500 reserved slots (tag `0x688C`) and
|
|
139
|
+
a terminator. Source: `math.py`.
|
|
140
|
+
|
|
141
|
+
The formula appears four times in the header:
|
|
142
|
+
|
|
143
|
+
| Tag | Field | Example for `SUM ( DS1 : DS3 ) + 5` |
|
|
144
|
+
|---|---|---|
|
|
145
|
+
| `0x61FF` | template, display | `SUM ( @ : @ ) + 5` |
|
|
146
|
+
| `0x6228` | formula, display | `SUM ( DS1 : DS3 ) + 5` |
|
|
147
|
+
| `0x6229` | template, internal | `SUM#(#@#:#@#)#+#H5` |
|
|
148
|
+
| `0x61FD` | formula, internal | `SUM#(#DS1#:#DS3#)#+#H5` |
|
|
149
|
+
|
|
150
|
+
- **Display form** is spaced the way Click's formula editor spaces it: one space
|
|
151
|
+
on each side of every operator, paren, comma and range colon (`ABS ( x )`,
|
|
152
|
+
`RAND ( 1 , 100 )`). The encoder normalizes `ABS(x)*2` to this form. A sign
|
|
153
|
+
stays on its constant (`( -5 )`) and is spaced from an address (`- DS401`).
|
|
154
|
+
- **Internal form** is the display form with spaces replaced by `#` and each
|
|
155
|
+
bare decimal literal prefixed with `H`. Click splits it on `#`, so an
|
|
156
|
+
unspaced `ABS(` becomes a single unknown token. In CLICK v4 that pastes but
|
|
157
|
+
raises a Math instruction error.
|
|
158
|
+
- **RAND** is stored infix in the internal form: `RAND ( a , b )` becomes
|
|
159
|
+
`a#RAND#b`, followed by a trailing `#` when RAND ends the formula
|
|
160
|
+
(`H1#RAND#H100#`, `H1#RAND#H10#+#DS1`). The display form keeps the function
|
|
161
|
+
call.
|
|
162
|
+
|
|
163
|
+
### Operand and reserved slots
|
|
164
|
+
|
|
165
|
+
Each slot is `[2B tag][4B index LE][UTF-16LE value]`, and an empty slot is just
|
|
166
|
+
a null terminator. Operand slots hold every address in the formula, in order,
|
|
167
|
+
duplicates included. Reserved slots hold the interior addresses of each
|
|
168
|
+
`A : B` range, ranges in order. The endpoints are ordinary operands, so
|
|
169
|
+
`SUM ( DS201 : DS300 )` stores DS201 and DS300 as operands and DS202..DS299 in
|
|
170
|
+
the reserved slots.
|
|
171
|
+
|
|
172
|
+
An `XD` or `YD` range also lists the upper half of address 0:
|
|
173
|
+
`MAX ( XD0 : XD3 )` stores XD0u, XD1 and XD2.
|
|
174
|
+
|
|
175
|
+
CLICK v4 copies Math back with 5000 reserved slots, not 500, for 5510 fields.
|
|
176
|
+
A 500-slot blob still pastes into both v3 and v4, so the encoder writes 500
|
|
177
|
+
unless the ranges have more than 500 interiors. CLICK's editor stops listing
|
|
178
|
+
at 5000 without an error, even though the formula keeps the full range, and the
|
|
179
|
+
encoder does the same.
|
|
180
|
+
|
|
181
|
+
## Math nickname flag
|
|
182
|
+
|
|
183
|
+
Math blobs contain a `nickname_flag` field (tag `0x2224`). When set to `"1"`,
|
|
184
|
+
Click displays project-level tag names instead of raw addresses in the math
|
|
185
|
+
formula. The flag is purely a display hint — the expression itself always
|
|
186
|
+
stores concrete addresses.
|
|
187
|
+
|
|
188
|
+
The `encode()` API exposes this via `show_nicknames=True`, which sets the flag
|
|
189
|
+
on all math instructions in the buffer.
|
|
190
|
+
|
|
191
|
+
## Blob boundary detection
|
|
192
|
+
|
|
193
|
+
For unknown instruction types, the blob boundary can be detected using the generic multi-part formula:
|
|
194
|
+
|
|
195
|
+
1. Read the class name (UTF-16LE, null-terminated)
|
|
196
|
+
2. Read the type marker (uint32 LE)
|
|
197
|
+
3. Read part count (uint16 LE), skip `(part_count - 1)` extra bytes
|
|
198
|
+
4. Read field count (uint32 LE)
|
|
199
|
+
5. Walk through tagged fields (each: 2B tag + 4B sentinel/marker + UTF-16LE value)
|
|
200
|
+
6. The blob ends after all fields are consumed
|
|
201
|
+
|
|
202
|
+
The `RawInstruction` fallback uses this formula to capture the complete blob as opaque bytes, enabling round-trip for unsupported instruction types via `raw(ClassName,hex)` CSV tokens.
|
|
203
|
+
|
|
204
|
+
At the moment, `Email`, `Home`, `Position`, and `Velocity` still deliberately
|
|
205
|
+
travel through this raw path. They round-trip correctly, but they are not yet
|
|
206
|
+
modeled as dedicated DSL instruction classes.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# CLICK v4 captures
|
|
2
|
+
|
|
3
|
+
`v4_capture.py` writes one paste CSV per group into `stubs/`, plus pyrung's own export into `expected/`.
|
|
4
|
+
Each rung's comment is its id, then every AF token it should decode to. laddercodec's
|
|
5
|
+
`tests/test_v4_captures.py` checks every captured rung against that comment.
|
|
6
|
+
The laddercodec side of the loop is in `docs/guides/adding-instructions.md`, "Capturing from CLICK v4".
|
|
7
|
+
|
|
8
|
+
The generator builds the rungs with pyrung, so it runs in pyrung's environment. From the laddercodec root:
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
uv run --project ../pyrung python scratchpad/click-v4/captures/v4_capture.py
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Done so far: math, out, drum, pins (fixtures in `tests/fixtures/v4_captures/`, goldens `<group>__v4` in
|
|
15
|
+
`tests/fixtures/coverage/golden/`). loop: Break/Continue taken from a hand capture (`loop_exits.bin`); the
|
|
16
|
+
`loop__v4` golden (the whole group, real Break/Continue) is paste-verified, so `stubs/loop.csv` needs no copy-back.
|
|
17
|
+
|
|
18
|
+
## Per group
|
|
19
|
+
|
|
20
|
+
Run clicknick against the local checkouts (`make install-dev` in clicknick once, then `UV_NO_SYNC=1` and
|
|
21
|
+
`uv run --no-sync`). From the clicknick directory:
|
|
22
|
+
|
|
23
|
+
1. `clicknick-rung load ../laddercodec/scratchpad/click-v4/captures/stubs/<group>.csv`, then paste into CLICK v4.
|
|
24
|
+
2. Build each rung from its comment (see "What to do" below), then Syntax Check.
|
|
25
|
+
3. Select all the group's rungs and copy them, then
|
|
26
|
+
`clicknick-rung save ../laddercodec/scratchpad/click-v4/captures/copyback/<group>`
|
|
27
|
+
(this writes `<group>.bin` and `<group>.csv`; keep it out of `stubs/`, which the generator rewrites;
|
|
28
|
+
`save` does not create `copyback/`).
|
|
29
|
+
Once every rung matches its comment or decodes as `raw(...)`, copy the `.bin` to
|
|
30
|
+
`tests/fixtures/v4_captures/` and delete the copy-back.
|
|
31
|
+
4. In laddercodec, `make test`: rungs still decoded as `raw(...)` are xfail, and any other mismatch fails.
|
|
32
|
+
|
|
33
|
+
What to do in CLICK:
|
|
34
|
+
|
|
35
|
+
| Group | Placeholder | What to do |
|
|
36
|
+
|---|---|---|
|
|
37
|
+
| out | NOP | Replace it with Out using the variant in the comment. `on_acc=TD5` means TD5 in the dialog. |
|
|
38
|
+
| drum | v3 Time drum | Change the base to Time & Event. Set each event; blank the preset where the comment says `None`, and enter `DS....` where it names a register. |
|
|
39
|
+
| drum `time_ds*` | real instruction | Nothing, unless the paste is rejected. |
|
|
40
|
+
| math | real instruction | Nothing, unless the paste is rejected. If it is, rebuild it from the comment. |
|
|
41
|
+
| loop | NOP on a contacted body rung | Replace it with Break or Continue, as the rung's comment says. The other rungs are real. |
|
|
42
|
+
| pins | real instruction, each pin fed by one contact | The id names the OR'd pin(s). Under each, insert a row per extra leg and OR in the next contact up (see `expected/pins.csv`): `drum_reset_or` +1 leg on Reset, `drum_reset_or3` +2 on Reset, `drum_jump_or` +1 on Jump, `drum_all_or` +1 on each pin, `count_up_down_or` +1 on Down, `shift_clock_or` +1 on Clock. Let the box grow. Don't route a leg back up past the next pin. |
|
|
43
|
+
|
|
44
|
+
Math comments use CLICK's spelling, `NAME ( a , b )` (`SUM ( ... : ... )` and `RAND ( DD111 , DD112 )` are seen
|
|
45
|
+
natively; `ABS ( x )` is inferred). The `math__rand_*` bodies are stand-ins (pyrung has no `randint` yet) with
|
|
46
|
+
the token written by hand. Whatever the copy-back decodes to is the answer; fix the expected line to match.
|
|
47
|
+
|
|
48
|
+
A loop case is several rungs (For, body rungs, Next), each labelled `<id>/<k>` with its own AF tokens. Copy
|
|
49
|
+
every rung of the group back, Next rungs included.
|
|
50
|
+
|
|
51
|
+
## Address map
|
|
52
|
+
|
|
53
|
+
| Group | Contacts | Targets / outputs | Timers | Data |
|
|
54
|
+
|---|---|---|---|---|
|
|
55
|
+
| out | C1001–C1020 | C1101–C1117, Y001–Y003 | T1–T24 / TD1–TD24 | DS1001–DS1006 (presets) |
|
|
56
|
+
| drum | C1201–C1207 | C1311–C1372 (C13n1.. for drum n) | TD101–TD107 (accumulators) | DS1201–DS1207 (step), DS1210 (jump step), DS1301–DS1304 (durations); done C1401–C1407; events C1501–C1509; reset/jog/jump C1601–C1609 |
|
|
57
|
+
| math | C1701–C1723 | DS1501–DS1508, DD201–DD205, DF201–DF205, DH201–DH205 | — | DS1401–DS1412, DD101–DD112, DF101–DF111, DH101–DH106, C1801–C1816 |
|
|
58
|
+
| loop | C1901–C1906 (For rungs), C1921–C1926 (body rungs) | C1941–C1942 | — | DS1601–DS1613 (counters, limits) |
|
|
59
|
+
| pins | C1050–C1097 (rung n: enable C(1042+8n), pin legs the next 7) | C1021–C1024 (drum outputs), C1031–C1034 (done), C1041–C1048 (shift bits) | TD111–TD114, CT1/CTD1 | DS1701–DS1704 (step), DS1710 (jump step) |
|
|
60
|
+
|
|
61
|
+
T1–T40 are reserved for the Out family (C0112: an Out coil claims its whole timer number).
|