Files
magdevandClaude Fable 5 d173328443 Point library references at the new Gitea home
kicad-visaton-lib moved to
ssh://git@src.bundespruefstelle.ch:2022/magdev/kicad-visaton-lib.git.

Also corrects the image source label, which named a repository that does not
exist: this repo is magdev/boxsim-fileformat-rev, not boxdev/re-boxsim.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-29 12:23:43 +02:00

5.1 KiB

Plan

Current state

v0.1.0 is delivered. The boxsim package decodes Boxsim containers in pure Python and generates KiCad 10 projects from their crossovers; see README.md for the format and the tool, and CHANGELOG.md for what changed.

Environment as of 2026-09-29: KiCad 10.0.6 installed natively, Python 3.13.15, Visaton library checked out at /home/magdev/workspaces/other/kicad-visaton-lib from ssh://git@src.bundespruefstelle.ch:2022/magdev/kicad-visaton-lib.git, upgraded to the KiCad 10 format as part of this work.

Reference project for all work: boxsim_dl/BoxSim 2.1 DE (Stand 12.2025)/Projekte/Default.BPJ.

v0.1.0 - boxsim CLI and KiCad project generation

Delivered 2026-09-29. All seven tickets landed; what follows records the outcome, including where it differed from the design.

What shipped

  • boxsim with decode, extract, netlist and build, installable and packaged as a python:3.13-slim image bundling the Visaton library and catalogue.
  • A pure Python A2F codec. Boxsim.exe and Unicorn are gone from the shipped tool and the image.
  • Grid to netlist extraction, catalogue-driven symbol resolution, KiCad 10 schematic generation preserving the Boxsim layout, and a netlist-equality verification gate.

Measured results

Gate Result
Codec vs Boxsim's own decoder 134 containers byte-identical, 270 pre-2.0 files rejected by both
Decode time for Default.BPJ 69 s to 14.5 s (hook binding) to 1.6 s (pure Python)
Default.BPJ netlist 22 components, 14 nets, no dangling terminal
Symbol resolution 22 of 22, one series inferred, two DC resistance deviations reported
ERC clean, 0 errors
KiCad netlist vs Boxsim netlist identical partition, 14 nets
Container vs host build .kicad_sch and .kicad_pro byte-identical
Tests / lint 32 passing, ruff clean

Where it differed from the design

  • The library needed changing after all. The plan said no library change was required. That was wrong: the KiCad 6 era syntax ((id N) properties, bare hide tokens) cannot be embedded into a current schematic's lib_symbols cache. kicad-visaton-lib was upgraded with kicad-cli sym upgrade and fp upgrade, and the tool now refuses a legacy library with an error naming the fix. A pre-existing broken footprint reference on the MKT 22μF symbol (Visaton:MKT-Kondensator, which never existed) was repointed at MKT 22mF; all 48 footprint references now resolve.
  • Derived symbols had to be flattened. 19 of the 98 symbols use (extends ...), and KiCad never writes extends into a schematic cache. Pin geometry follows the chain to the base symbol, and the base's graphics are inlined under the derived name.
  • The decoder needed a padding allowance. Boxsim reads past the end of its staging buffer for the final symbol's 16 bit lookup window. Five files failed until the reader tolerated a bounded number of zero padding bytes; the bound keeps genuine truncation loud.
  • Rotation could not be assumed. A symbol's origin is not its pin midpoint (Amplifier has both pins at px=3.81), and a symbol's pin axis does not follow its slot. Rotation is chosen per symbol from its own pin axis, the origin is derived so the transformed pin midpoint lands on the slot midpoint, and the four transform matrices were measured against KiCad's demo schematics rather than guessed.
  • The image self-check was decorative at first. cross_check only proves the catalogue is a subset of the library, so a truncated catalogue passed it and would have shipped an image rejecting valid parts. catalog.check_shape now asserts the catalogue's full shape, and the failure was reproduced deliberately before the fix was accepted.
  • Grid pitch is 25.4 mm, not 20 mm. The widest symbol spans 22.86 mm between pins, so 20 mm would overlap neighbouring cells. Default.BPJ therefore lands on A3 rather than A4.

Ticket outcomes

  • BOX-0 emulator bound to trap addresses, moved to boxsim/_oracle.py, reachable as boxsim decode --oracle.
  • BOX-1 boxsim/a2f.py, differentially tested by tools/difftest.py, self-test proves the comparison detects a corrupt digest.
  • BOX-2 boxsim/model.py, slot partition covered by tests, netlist cross-checked against crossover physics (600 Hz and 5.7 kHz corners).
  • BOX-3 boxsim/catalog.py and boxsim/symbols.py.
  • BOX-4 boxsim/schematic.py.
  • BOX-5 boxsim/cli.py and boxsim/project.py.
  • BOX-6 boxsim/verify.py, with test_gate_has_teeth mis-wiring a component to prove the gate fails when it should.
  • BOX-7 Dockerfile, tools/build-image.sh, tools/selfcheck.py.

Backlog

  • Multi-channel projects (nAmps up to 6), probably one hierarchical sheet per channel.
  • Active filter sections (#AktFilter<n>, #Aktfilter<n>), which Boxsim models as DSP biquads with no passive equivalent.
  • Per-driver symbols instead of the generic Speaker, if the library grows them. The 400 .BCH files provide the model names and TSP data.
  • Round trip: patch component values in a .bpj from an edited schematic. Needs the A2F compressor, of which only the decompressor is currently exercised.