
PCM3168APAP breakout
fsanzeni/PCM3168APAP-breakout
A breakout board for the Texas Instruments PCM3168APAP audio codec, featuring 6 analog inputs and 8 analog outputs with high-quality buffering and filtering circuitry.

opensource combination of agent driven hardware development tools
Out is an open-source printed circuit board by maximmalin, from the maximmalin/simul repository on GitHub, published under the MIT licence. It is a 4-layer board of 88.6 × 85.1 mm with 60 parts on 32 nets, routed with 592 tracks and 167 vias.
It is built around the STM32F103C8T6, OPA2134UA and AMS1117-3.3. Its parts include 1 IC and 1 crystal. It belongs with the STM32 boards of this library.
Start here
AGENT_MAP.md — comprehensive functional map of the project (architecture, subsystems, data flow, entry points, how to run/verify).sim/COSIM_STATUS.md — co-simulation status: what is verified, what is blocked, and why.manifest.json — machine-readable project description, generated by python3 tools/dump_manifest.py.technical_task_en.md / technical_task.md — the technical task (EN / RU).LICENSE — MIT.| Product | Zero-IF (direct-conversion) SDR receiver |
| MCU | STM32F103C8T6 Blue Pill (Cortex-M3) |
| Frequency range | 0.5 – 30 MHz |
| Architecture | Direct conversion, quadrature I/Q, USB I/Q to host |
| Circuit source of truth | SKiDL (sim/scripts/sdr_skidl_circuit.py) — 60 parts, 38 nets |
| Analog simulator | ngspice 44.2 |
| Digital/co-sim | FMI 2.0 (pythonfmu / fmpy), QEMU (qemu-system-arm), PicSimLab |
| PCB / 3D | KiCad 9, tscircuit, FreeCAD, Elmer FEM, openEMS FDTD, NEC-2 |
| License | MIT |
The MCU is never "inside" ngspice. The analog/digital boundary is explicit at
the STM32 pins, and that contract (PA0/PA1 = ADC I/Q, PA6 = LO, PA7 = GAIN) is
asserted both by the firmware and by verify_pin_contract.py.
sim/scripts/sdr_skidl_circuit.py SKiDL = the single source of truth for connectivity
│
▼
sim/scripts/export_ngspice.py → sim/netlists/sdr_skidl_ngspice.cir (ngspice deck)
│
▼
sim/scripts/build_fmu.py → sim/fmu/SdrNgspiceFMU.fmu (FMI 2.0 slave)
│
▼
sim/scripts/cosim_fmu_stm32.py hard-lockstep: firmware model <-> ngspice
sim/scripts/test_fmu_cosim.py regression through fmpy's FMI master
sim/scripts/cosim_real_stm32.py the same, but the MCU is the real firmware.elf on QEMUThe system in one picture:
┌─────────────────────────────────────────────┐
│ HOST / OFF-BOARD │
sim/scripts/ │ SKiDL → ngspice deck → FMI FMU │
sdr_skidl_circuit.py │ └── sim/netlists/sdr_skidl_ngspice.cir │
export_ngspice.py │ │ │
build_fmu.py │ ▼ │
│ sim/fmu/SdrNgspiceFMU.fmu │
│ │ FMI 2.0 setReal/doStep │
└────────────────────┼─────────────────────────┘
│
┌───────────────────────────────┼───────────────────────────────┐
│ │ │
cosim_fmu_stm32.py cosim_real_stm32.py sdr_picsimlab_cosim.py
(firmware MODEL in Python) (REAL firmware.elf on QEMU) (PicSimLab rcontrol)
│ │ │
│ qemu-system-arm + GDB RSP PicSimLab NOGUI
│ firmware/src/cosim.h mailbox src/picsimlab_fmu/*
▼ ▼ ▼
┌──────────────────────────────── analog boundary (pins) ──────────────────┐
│ PA0 = ADC_I PA1 = ADC_Q PA6 = LO (TIM3_CH1) PA7 = GAIN │
└──────────────────────────────────────────────────────────────────────────┘Antennas have their own physics path:
sim/inputs/antenna_*.yaml → sim/scripts/antenna_fdtd.py → S11/Zin
→ sim/scripts/export_antenna_ngspice.py → Touchstone (ngspice)Every piece of functionality in the repository, grouped by subsystem.
sim/scripts/sdr_skidl_circuit.py — the unified SKiDL netlist generator. The
only place connectivity is defined: 60 parts, 38 nets. Writes the KiCad
schematic and the netlist consumed downstream. Never hand-edit generated
netlists; change this file and regenerate.sim/scripts/export_ngspice.py — emits the behavioral zero-IF receiver
chain to sim/netlists/sdr_skidl_ngspice.cir:
H = 1 − 2/(1+sRC)),sim/netlists/sdr_receiver.cir, sim/netlists/sdr_simplified.cir,
sim/netlists/bridge_check.cir.adc_bridge) with datasheet CMOS thresholds;
digital→analog modelled explicitly as a host-alterable source behind the pin's
output resistance and load capacitance (an ngspice dac_bridge input cannot be
driven from outside ngspice).sim/COSIM_STATUS.md.print 80-column truncation and non-uniform
adaptive timesteps) are documented there too.| Parameter | Value | Source |
|---|---|---|
| Output impedance | 65 Ω | DS5319 Table 30, IIO = 20 mA |
| Pin capacitance CIO | 5 pF | DS5319 Table 29 |
| Input low VIL | 0.35·VDD = 1.155 V | DS5319 Table 29 |
| Input high VIH | 0.65·VDD = 2.145 V | DS5319 Table 29 |
| Input leakage | 1 µA | DS5319 Table 29 |
Numbers are taken from the datasheet, not chosen for convenience.
| Script | What it proves |
|---|---|
sim/scripts/test_sdr_netlist.py | 22 regression checks on the SKiDL→ngspice export |
sim/scripts/verify_pin_contract.py | 31 closed-loop analog + pin-contract checks |
sim/scripts/test_ngspice_nets.py | Smoke tests for the ngspice decks |
sim/scripts/test_fmu_cosim.py | Drives the FMU through fmpy's FMI master, checks the pin boundary |
tests/requirements/** | Requirement-matrix tests (RF, antenna, AO, system) |
tests/stress/test_co_simulation.py | Bragg FMU + ngspice antenna 2-port stress test |
sim/scripts/sdr_ngspice_fmu.py — a self-contained FMI 2.0 co-simulation
slave bundling an embedded ngspice deck (self-contained on purpose: pythonfmu
bundles only this one file).sim/scripts/build_fmu.py — regenerates the netlist from SKiDL and splices
it into the FMU source, so the FMU and the deck are the same circuit by
construction.sim/fmu/SdrNgspiceFMU.fmu — the built slave.sim/scripts/cosim_fmu_stm32.py — hard-lockstep driver: STM32 firmware
model ↔ ngspice FMU. Real FMI calls (setReal/doStep/getReal) every step;
pulses cross the boundary at half an LO period; PA6 drives the mixer through the
65 Ω + 5 pF pin model.<venv>/bin/pythonfmu build -f sim/scripts/sdr_ngspice_fmu.py -d sim/fmu
(or python3 sim/scripts/build_fmu.py).The actual firmware.elf on an emulated Cortex-M, in lockstep with real ngspice.
sim/scripts/cosim_real_stm32.py — orchestrator.sim/scripts/gdb_remote.py — a minimal GDB remote-serial-protocol client
(QEMU's human monitor can read memory with xp but has no write command;
the GDB stub can read and write and single-step).firmware/src/cosim.h — the RAM mailbox both sides agree on (magic,
host_lo/host_gain in; mcu_stamp/adc_i/adc_q/adc_stamp out).sim/scripts/build_cosim_firmware.py — builds the COSIM_MODE ELF.sim/scripts/diag_*.py — forensic diagnostics that found the two setup()
blockers (USB CDC enumeration, PLL wait) and the current stop point.Status: the core reaches ADC1_2_IRQHandler; QEMU's STM32F103 peripheral model
starves loop() (an ADC/DMA emulator-fidelity limit). Everything around it —
mailbox, exchange, netlist, FMU — is verified. See sim/COSIM_STATUS.md.
src/picsimlab_fmu/)wrapper.py — PicSimLabFMU co-simulation wrapper (step() / run()).cosim_bridge.py — TCP rcontrol ↔ ngspice lockstep loop (+ parse_pinsl, MAX_SAMPLES).ngspice_bridge.py — prompt-synced ngspice CLI pipe (-p) bridge.pin_mapper.py — board pin allocation (ARDUINO_UNO, STM32_BLUE_PILL, ESP32_DEVKITC).live_scope.py — live co-sim oscilloscope (POSIX SHM + semaphores + matplotlib).examples/ — small usage examples.Drivers and probe scripts:
sim/scripts/start_picsimlab.py — launches PicSimLab NOGUI and polls until the
rcontrol port accepts (the board comes from the .ini; there is no board
command in rcontrol).sim/scripts/sdr_picsimlab_cosim.py — the SDR-specific driver.sim/scripts/rcontrol.py, rcontrol_analog.py, rcontrol_session.py —
low-level rcontrol probing / analog pin driving / one-shot evidence session.firmware/picsimlab_sdr.ini.Blocked upstream: with the QEMU backend running, rcontrol never binds (0.9.2);
0.9.3 has rcontrol but ships no libqemu-stm32.so. Full evidence in
sim/COSIM_STATUS.md.
firmware/)firmware/src/firmware.ino — minimal firmware that reaches loop() and
services the mailbox.
PA0 = ADC_I, PA1 = ADC_Q, PA6 = LO (TIM3_CH1), PA7 = GAIN.COSIM_MODE, overrides SystemClock_Config() to skip the PLL wait
(QEMU never sets PLLRDY).firmware/src/cosim.h — mailbox layout shared with the co-sim host.firmware/platformio.ini — two environments:
bluepill_f103c8 — the shipped image (USB CDC on);cosim — USB compiled out (a bench image and a co-sim image can never be
confused).firmware/scripts/hex.py — post-build objcopy to emit Intel HEX for
PicSimLab's loadhex.sim/inputs/antenna_*.yaml — one file per antenna; adding an antenna = add
a YAML file, no code edits. Present: dipole 7 MHz, meander 200 MHz, patch
2.45 GHz.sim/scripts/antenna_fdtd.py — YAML → S11/Zη → Touchstone. All three
shipped antennas run the real openEMS FDTD solver (fdtd: true); setting
fdtd: false falls back to an analytic thin-wire / transmission-line estimate
(marked model: analytic in the JSON).sim/scripts/mesh.py — openEMS mesh sizing with a hard memory budget.sim/scripts/export_antenna_ngspice.py — results → ngspice S-parameter networks.sim/scripts/antenna_sim.py, smoke_tutorial.py — openEMS workflow and
tutorial smoke test.sim/scripts/radiation.py, sim/nec/** — NEC-2 radiation patterns for
the three channels (sim/nec/channel_{a,b,c}.nec, run_nec.py).hardware/antenna/** — FreeCAD panel geometry (150 × 150 mm FR-4 0.8 mm):
geometry/build_antennas_fc.py rebuilds and exports
STEP/STL.sim/outputs/*.json, all model: fdtd):
eta_source: unavailable_no_radiated_power). A genuine full-wave
result, not a solver failure.sim/web_gui/app.py — Flask app that runs SdrNgspiceFMU.fmu via fmpy,
plots I/Q live, exposes stim_level / lo_frequency, and exports an
sdr_cosim.xcos diagram for Xcos.sim/web_gui/templates/index.html — Plotly dark dashboard.python3 sim/web_gui/app.py → http://localhost:5000.sim/scripts/diag_*.py (infinite, literal, mailbox, pc, regs, watch,
patch) are the forensic scripts used to find the QEMU blockers and validate the
patch antenna. Kept as the reproducible evidence trail, not scratch.
hardware/tscircuit/build_pcb.mjs — the PCB stage. Reads the SKiDL netlist
(sim/scripts/sdr_skidl_circuit.py → hardware/kicad/sdr_receiver.kicad_sch),
places parts, autoroutes with explicit Altium-grade design rules and exports
out/: board.kicad_pcb, board.kicad_sch, gerbers.zip, board.step,
board.{glb,gltf}, board.net, board_schematic.pdf, circuit.json.
Run node hardware/tscircuit/build_pcb.mjs (or make pcb).hardware/kicad/build_board.py (kinet2pcb + kicad-cli) path is
superseded by the tscircuit emitter.sim/octave/reliability_model.m (Octave) reads datasheet
parameters from sim/octave/reliability_parts.tsv (base FIT, Ea, T_ref/T_use,
π_Q) and computes system MTBF as parts-count + Arrhenius. Requirement REQ-REL-01
(MTBF ≥ 10 000 ч). Run make reliability → out/reliability.json;
tests in tests/requirements/reliability/.sim/scripts/thermal_pcb.py couples ngspice (DC operating
point → dissipated power) with the PCB CAD (circuit.json → outline,
stackup, placement). Two levels: fast T_j = T_a + P·θ_JA and a deep 2D FEM
of heat conduction/spreading over the board. Run make thermal →
out/thermal_{fast,fem}.json; tests in tests/requirements/thermal/.sim/scripts/link_budget.py computes the
receiver noise floor (REQ-PERF-02), MDS (REQ-PERF-02) and the Friis range per antenna
channel (A/B/C). Run make link-budget → out/link_budget.{json,svg};
«дальность приёма» сводится по разделам в requirements/reception_range.md
(и столбец Reception_Distance_m в requirements_matrix.csv).sim/scripts/direction_finding.py implements a phase
interferometer (Δφ = 2π·d·sinθ/λ), draws the combined bearing + range diagram,
and emits a NEC-2 .nec that opens in
EA1FUO/AntennaSim
(--antennasim-url posts to its /api/v1/simulate). Run make direction →
out/direction_finding.{json,svg}.tests/requirements/emc/ verifies REQ-EMC-01…04: skin depth and
shielding effectiveness, immunity to 3 V/m (IEC 61000-4-3 level 2), CISPR 22
Class B emission, supply filters and enclosure zoning.tools/spec.py, tools/blocks.py — the project spec (6 blocks, 24 parts) used
by the generators.hardware/pipeline.py — hardware build-pipeline orchestrator.hardware/kicad/kicad_lib.py — KiCad symbol / schematic helper;
hardware/kicad/generate_schematic.py — full single-sheet .kicad_sch
generation from code; test_any_schematic.py — prove the generator is
schematic-agnostic; verify_nets.py — cross-check the KiCad netlist against the
generator tables.hardware/tscircuit/build_pcb.mjs — netlist → TSX, placement, model offsets;
build_derived.py (build local derived tables from the JLCPCB part DB),
resolve_parts.py (part substitution by value/footprint), step2stl.py
(STEP → STL with orientation normalization), check_models3d.py (glb vs
circuit.json), make_viewer.py + site_assets.py (offline 3D viewer),
fetch_vendor_models.mjs / fetch_3dmodels*.sh (vendor 3D models),
check_net.py (verify the viewer makes no external requests).scripts/download-datasheets.js,
scripts/convert-kicad-to-circuit-json.js, scripts/post-build-datasheets.js,
scripts/lib/*.out/ (board.kicad_pcb, gerbers, BOM, PnP, GLB, STEP).gost_pipeline.py — STEP → cleaned → GOST drawing.block0_bus_power_calc.py — 5 V bus / buck / LC-filter calculation.gen_spice_from_kicad.py — KiCad .kicad_sch → SPICE netlist.picsimlab_rt_wrapper.py — PicSimLab real-time wrapper (from brig-receiver).The acousto-optic branch is kept as a toolbox, not part of the SDR signal path:
sim/scripts/bragg_sim.py — Gmsh → Elmer FEM pipeline (Δn = dn_scale·ε_zz).sim/scripts/bragg_fmu.py, test_fmu.py, test_antenna_fmu.py,
realtime_loop_fmu.py — FMI blocks and real-time FMU loop.sim/scripts/msh_to_elmer.py — Gmsh .msh → Elmer mesh.sim/inputs/bragg_inputs.yaml, config/params.yaml — parameters.sim/octave/bragg_formulas.m + README_formulas.md — formulas and an
analytic self-check (Hooke + photoelasticity).sim/cad/ — FreeCAD parametric Bragg-cell scripts: make_bragg_cell_fc.py
(build), refresh_cad.py (regenerate), import_elmer_mesh_fc.py, cad_dims.json.
No .FCStd/.step is checked in — they are generated.sim/outputs/elmer_results.json, sim/outputs/nec_results.json, openems_results.json.requirements/requirements_matrix.csv (37 requirements + header) and
per-subsystem requirements/*/REQ-*.md; SNR and noise floor are project-wide
requirements REQ-PERF-02 (SNR, noise floor, MDS).plan/plan.md, plan/blocks.md, plan/README.md, plan/checks.py.technical_task.md (RU), technical_task_en.md (EN),
technical_task_ua.md (UA), plus per-block TZ in work/tz-{a..e}/.tests/requirements/{antenna,rf,ao,system,reliability,thermal}/,
tests/stress/test_co_simulation.py (co-simulation, needs fmpy);
checklist at tests/requirements/checklist.csv..forgejo/workflows/push-{general,fix,feature,docs}.yml (Elmer-FEM
physical-constraint jobs on push).references/formulas_and_sources.md, issues/ (issue template folder).tools/dump_manifest.py — writes manifest.json.tools/init_project.py — create a fresh project from tracked files.cd <repo>
# --- Everything (netlist → PCB → docs → tests → reliability/thermal) ---
make all
# --- Circuit → netlist ---
.venv/bin/python sim/scripts/sdr_skidl_circuit.py # regenerate SKiDL netlist
.venv/bin/python sim/scripts/export_ngspice.py # regenerate ngspice deck
# --- Verify (fastest health check) ---
.venv/bin/python sim/scripts/test_sdr_netlist.py # 22/22 checks
.venv/bin/python sim/scripts/verify_pin_contract.py # 31/31 checks
.venv/bin/python sim/scripts/test_ngspice_nets.py
# --- FMU co-simulation ---
python3 sim/scripts/build_fmu.py # rebuild FMU from SKiDL
.venv/bin/python sim/scripts/cosim_fmu_stm32.py # lockstep firmware-model ↔ ngspice
.venv/bin/python sim/scripts/test_fmu_cosim.py # fmpy regression
# --- Real firmware on QEMU ---
.venv/bin/python sim/scripts/build_cosim_firmware.py # COSIM_MODE ELF
.venv/bin/python sim/scripts/cosim_real_stm32.py # real firmware ↔ ngspice
# --- PicSimLab ---
.venv/bin/pythonis the project venv (skidl,pythonfmu,fmpy,numpy,matplotlib). Pure-stdlib tools run fine under systempython3; the web GUI usesflask(systempython3), and antenna FDTD needs a separate openEMS-enabled interpreter.
Roles: source = keep and edit; derived = regenerated by scripts; data = external/binary.
| Path | Role | What it is |
|---|---|---|
sim/scripts/ | source | All physics, netlist, co-sim, antenna, diagnostic scripts |
sim/netlists/ | derived | ngspice decks (.cir) produced by export_ngspice.py |
sim/inputs/ | source | YAML parameter files (one per antenna) |
sim/outputs/ | derived | Physics result JSON/PNG |
sim/fmu/ | data | Built FMUs (SdrNgspiceFMU.fmu, antenna/Bragg blocks) |
sim/work/ | derived | Solver scratch (openEMS, Elmer, gmsh) |
sim/web_gui/ | source | Flask I/Q web GUI for the FMU |
firmware/ | source | STM32 Arduino sketch, cosim mailbox, PlatformIO config |
firmware/src/ | source | firmware.ino, cosim.h |
src/picsimlab_fmu/ | source | PicSimLab rcontrol ↔ ngspice bridge package |
hardware/ | source | KiCad generation, PCB/3D pipeline, antenna geometry, FEM |
hardware/kicad/ | source | Schematic generator + KiCad symbol/S-expression library |
hardware/tscircuit/ | source | PCB emitter, 3D model resolution, part selection, viewer |
tools/ | source | Spec (spec.py, blocks.py), manifest/init tooling |
tests/ | source | Requirement-matrix + stress tests |
requirements/, plan/, work/, tz/, references/, config/, issues/ | source | Requirements, plan, TZ, formulas, parameters |
local_footprints/ | external | Опциональный клон KiCad/kicad-footprints для ручной правки плат в KiCad. Не входит в репозиторий и не нужен для сборки: плату генерирует tscircuit, футпринты берутся из resolved-таблицы деталей. |
out/ | derived | Generated board artifacts (gerbers/BOM/GLB/STEP) |
node_modules/, .venv/ | derived | Dependency installs |
.forgejo/ | source | CI workflow definitions |
scripts/ | source | Node datasheet/part-selection helpers |
System tools: python3 (3.13), ngspice (44.2), kicad-cli (9.0.2),
node/npm (22 / 10), pio (PlatformIO 6.2), qemu-system-arm (10.0),
gdb-multiarch (16.3), gmsh (4.13), Elmer FEM (26.2), openEMS, NEC-2
(nec2c), FreeCAD.
Python venv (.venv): skidl 2.3.0, pythonfmu 0.7.0, fmpy 0.3.32,
numpy 2.5.3, matplotlib. flask is not installed here — the web GUI runs
under system python3 (flask 3.1); pytest is installed separately for the
tests/ suites. Antenna FDTD needs a separate openEMS-enabled interpreter.
External data / installs:
/usr/share/kicad/{symbols,footprints}$HOME/opt/openEMS — openEMS install (used via LD_LIBRARY_PATH)/mnt/ext4data/jlcparts — JLCPCB parts DB used by the part resolverPicSimLab: NOGUI AppImages in /mnt/ext4data/downloads/
(PICSimLab_NOGUI-0.9.2 has the STM32 backend; 0.9.3 has a working rcontrol but
ships no libqemu-stm32.so). See sim/COSIM_STATUS.md.
| Stage | Evidence |
|---|---|
| SKiDL netlist | 60 parts, 38 nets, KiCad schematic written |
| ngspice deck | sim/netlists/sdr_skidl_ngspice.cir, 0 warnings / 0 errors |
| Direct conversion | LO is a real 7.2 MHz timer waveform; beat lands at 48.1 kHz (IF offset 50 kHz); I/Q ratio 0.965; phase +91.6° |
| Q channel | driven by a real 90° all-pass on the LO, not wired to zero |
| STM32 pin model | 65 Ω @ 20 mA; Cio 5 pF; VIL/VIH 0.35/0.65·VDD |
| Regression tests | test_sdr_netlist.py — 22/22 |
| Analog + pin contract | verify_pin_contract.py — 31/31 |
| Firmware | cosim build artifacts present (firmware/.pio/build/cosim/): firmware.elf ≈ 23 KB, firmware.bin ≈ 4.6 KB; .hex via pio run -t hex |
| Antennas | all real openEMS FDTD (model: fdtd): dipole 6.90 MHz / S11 −15.7 dB / ηrad 98 %; patch 2442.5 MHz / −3.6 dB / 31 %; meander reactive with no in-band match (S11 ≈ 0 dB, ηrad 0 %) — sim/outputs/*.json |
| PicSimLab NOGUI rcontrol | answers version, pinsl, sim, loadhex |
| STM32 backend | qemu-stm32 -M stm32-f103c8-picsimlab-new, 48 pins |
ADC1_2_IRQHandler — QEMU's STM32F103
ADC/DMA model is not faithful enough for loop() to be serviced. Emulator
fidelity limit, not a project defect.libqemu-stm32.so.out/ artifacts are text templates, not manufacturing outputs.config/params.yaml
points at /home/mirrage/brig-receiver/...); adapt before use. Likewise
sim/README.md is the brig Bragg-cell module README, kept as reference.docs/ is empty; AGENT_MAP.md + sim/COSIM_STATUS.md + manifest.json are
the authoritative documentation.hardware/antenna/geometry/build_antennas_fc.py)
it is a low-Q reactive resonator — S11 ≈ 0 dB across 50–800 MHz, no net
radiation (η = 0 %). The project's own definitions also disagree: the YAML/CAD
use 3 × 63.5 mm arms (220 mm), while sim/nec/run_nec.py uses 3 × 130 mm arms
(430 mm) and its GN 1 0 0 0 1.0 0.0 ground card is rejected by nec2c. Treat
the meander figures as a design warning, not a finished antenna.sim/scripts/* entry points; parameters = YAML in sim/inputs/.sim/netlists/, sim/outputs/, out/).verify_pin_contract.py and by firmware.ino.test_sdr_netlist.py / verify_pin_contract.py / test_fmu_cosim.py.build_fmu.py exists precisely so the FMU can't
drift from SKiDL.See AGENT_MAP.md for the deep functional map and
sim/COSIM_STATUS.md for the co-simulation narrative and
evidence.
Заказ приходит текстом, проходит граф функций-агентов и превращается
в сборку. Движок не знает про Krystal Radio — всё, что касается
конкретного изделия, лежит в agents.project.yaml.
POST /api/order "посчитай дальность и пеленгацию"
│
▼
┌──────────┐ модель получает инструменты и решает:
│supervisor│ list_targets → submit_plan → run_target → read_artifacts
└────┬─────┘ (или ask_human, когда нужен человек)
▼
┌──────┐ выполняет вызовы, возвращает модели результат
│ tools│
└──┬───┘
├─ нужна помощь ─► await_human ─► interrupt() ─► ответ оператора ─┐
├─ есть модель ──► supervisor (цикл: думаю → действую → смотрю) │
└─ нет модели ───► plan_rules → execute_rules → review │
│
┌────────┐ ◄───────────────────────────────────────────────────────┘
│ report │ факты из артефактов → структурный отчёт (+ резюме модели)
└────────┘Проверено по документации LangChain: LangGraph — это agent runtime, LangChain — framework, Deep Agents — harness. Runtime даёт наибольший контроль над тем, что именно выполняется.
Здесь контроль — главное требование. Модель выбирает из объявленных целей, а исполняет система сборки. Harness вроде CrewAI или Deep Agents даёт ReAct-агента с доступом к файловой системе — то есть ровно то, чего в инженерном проекте быть не должно: агент с правом писать что угодно был бы не помощью, а источником порчи.
Что взято из рантайма по-современному:
| Возможность | Как реализовано |
|---|---|
| Вызов инструментов | Типизированные схемы в backend/agents/tools.py, ответ приходит разобранным. Прежний разбор JSON регуляркой не нужен |
| Цикл «думаю — действую — смотрю» | Узлы supervisor ↔ tools, не один план на всё |
| Прерывание человека | interrupt() — граф встаёт, состояние сохранено, после ответа продолжается с места остановки |
| Долговременное состояние | SqliteSaver в .run/graph.db; переживает перезапуск моста |
| Устойчивость к обрыву | Недоступный провайдер уходит в паузу на KR_LLM_COOLDOWN секунд, чтобы не ждать таймаут на каждом вызове |
Без langgraph движок работает на запасном пути (run_plain): те же
узлы, те же проверки — теряются только чекпоинты и прерывание.
Authorization не отправляется, если ключа нет — поэтому один и тот же
код работает и с облаком, и с локальным сервером. Локальные серверы
находятся сами: опрашиваются типовые порты (11434, 8080,
1234, 8000, 5000…), так что не важно, запущен Ollama, llama.cpp,
LM Studio или vLLM.
make llm-check # что включено, что отвечает, какие модели есть
KR_LLM_PRESET=hermes make llm-check # то же для другой открытой модели
KR_LLM_ENABLED=0 make llm-check # проверить, что будет при выключенной модели| Переменная | Смысл |
|---|---|
KR_LLM_ENABLED | Главный выключатель. 0 — план по правилам, сводки структурные |
KR_LLM_PRESET | hermes, qwen, llama, gemma, mistral |
KR_LLM_PROVIDER | ollama, llamacpp, lmstudio, vllm, openai, deepseek, groq, custom |
KR_LLM_MODEL | Модель. Если её нет на сервере — подставится та, что есть |
KR_LLM_MODEL_FAST | Отдельная модель для сводок (обычно локальная и дешёвая) |
KR_LLM_FALLBACK | auto — откат на живой локальный сервер, либо имя провайдера |
Роли разделены намеренно: планирование требует аккуратного разбора
формулировки, сводка — нет. Сводить второе на слабую локальную модель
безопасно, потому что модель не выдумывает числа: она читает их
из артефактов (backend/agents/reporter.py).
Про эту машину: 8 ядер, 11 ГБ RAM, GPU нет. Hermes 3 Llama 3.1 8B (4.9 ГБ) здесь даёт единицы токенов в секунду — для агентного цикла непригодно. Практичен
qwen2.5:3b-instruct; Hermes имеет смысл включать на машине с видеокартой.
Это проверяется тестом, а не обещанием: tests/requirements/agents
создаёт посторонние проекты (make, npm, just, пустой) и требует, чтобы
движок с ними работал. Отдельный тест разбирает AST движка и падает,
если в коде появятся имена целей или файлы артефактов этого проекта.
OpenCode умеет любой OpenAI-совместимый провайдер, поэтому работает на том же ключе и тех же моделях, что и наш движок:
./scripts/oc.py --write # обновить opencode.json
./scripts/oc.py # обновить и запустить
./scripts/oc.py run "собери всё и проверь тестами"scripts/oc.py не зашивает список моделей и не доверяет каталогу:
/v1/models, оставляет помеченные :free;:free — не гарантия:
из семи моделей в момент проверки шесть отвечали, одна отвечала
«This model is no longer free», несколько отдавали 429 по fair-share.
Без проверки модель по умолчанию могла оказаться нерабочей, а ошибка
выглядела бы как «Payment required» — будто ключ не тот;~/.hermes/auth.json и кладёт в .env (в .gitignore),
а не в конфиг: он живёт около часа, и захардкоженный завтра даст 401;settings.apiKey. Поле env управляет
хранилищем учётных данных самого OpenCode и пакету
openai-compatible ключа не передаёт.Там же прописан наш MCP-сервер, поэтому связка замкнута:
opencode run "посчитай дальность и пеленгацию"
# → бесплатная модель в облаке → MCP → граф → make → артефактыКаждый заказ выполняется в work/orders/<id>: исходники проекта копируются,
.venv и node_modules подключаются символическими ссылками, out/
создаётся свой. Проект — опора работы агентов, и заказ не имеет возможности
их переписать. Артефакты забираются наружу только при успешном выполнении.
Отключается, если песочница не нужна:
KR_SANDBOX=0 make runmake agents-check # что движок увидел в проекте
make agents-graph # узлы графа
make agents-ask TEXT="нужен водопад" # разобрать заказ, ничего не запуская
make agents-run TEXT="собери всё" # выполнить заказ
make run # мост + интерфейс по одному адресуПорядок живого прогона (что поднять, куда постить заказ, где песочница
и архив, какие env-ручки) — в docs/RUN_LIVE_ORDER.md.
MIT — see LICENSE.
| Qty | Value | Footprint | References |
|---|---|---|---|
| 11 | 100p | tscircuit:100p | C_AF_I, C_AF_Q, C_BS1, C_IN, C_LNA1, C_LO, C_MIX1, C_MIX2, C_OPI, C_OPQ, C_QWC |
| 6 | 10k | tscircuit:10k | R_AF_I, R_AF_Q, R_G1, R_G2, R_OPI, R_OPQ |
| 6 | TESTPOINT | tscircuit:TESTPOINT | TP_ADC_I, TP_ADC_Q, TP_ANT, TP_FIL, TP_LNA1_D, TP_LNA2_D |
| 5 | 100n | tscircuit:100n | C_ANA2, C_LDO2, C_MCU1, C_MCU2, C_MIX3 |
| 4 | 1k | tscircuit:1k | R_BS, R_QWC, R_S1, R_S2 |
| 2 | 100u | tscircuit:100u | C_LDO1, L_BS1 |
| 2 | 18u | tscircuit:18u | L_LNA1, L_LNA2 |
| 2 | 22 | tscircuit:22 | R_USB1, R_USB2 |
| 2 | 22p | tscircuit:22p | C_OSC1, C_OSC2 |
| 2 | 2N7002 | tscircuit:2N7002 | Q_LNA1, Q_LNA2 |
| 2 | 50 | tscircuit:50 | R_LO, R_TERM |
| 2 | 600R@100MHz | tscircuit:600R_100MHz | FB1, L_MIX |
| 1 | 10p | tscircuit:10p | C_BS2 |
| 1 | 10u | tscircuit:10u | C_ANA1 |
| 1 | 2k2 | tscircuit:2k2 | R_G4 |
| 1 | 4k7 | tscircuit:4k7 | R_G3 |
| 1 | 4u7 | tscircuit:4u7 | C_MCU3 |
| 1 | 5V_IN | tscircuit:5V_IN | J_PWR |
| 1 | 8MHz | tscircuit:8MHz | Y1 |
| 1 | AMS1117-3.3 | tscircuit:AMS1117-3_3 | U_LDO |
| 1 | LPJ-1 | tscircuit:LPJ-1 | X_QWC1 |
| 1 | LT5560 | tscircuit:LT5560 | U_MIX1 |
| 1 | OPA2134 | tscircuit:OPA2134 | U_OP1 |
| 1 | SMA_EDGE | tscircuit:SMA_EDGE | J_ANT |
| 1 | STM32F103C8T6 | tscircuit:STM32F103C8T6 | U1 |
| 1 | USB_CDC | tscircuit:USB_CDC | J_USB |
It measures 88.6 × 85.1 mm and has 4 copper layers, 1.6 mm thick.
60 parts, built around the STM32F103C8T6, OPA2134UA and AMS1117-3.3. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.
From the maximmalin/simul repository on GitHub, at the commit this page was made from: the board is out/board.kicad_pcb. PCBKit opens the board in the browser, with nothing to install.
Its repository publishes it under the MIT licence: you may reuse it on that licence's terms (keep the author's notice, and for a copyleft licence share your changes alike).

fsanzeni/PCM3168APAP-breakout
A breakout board for the Texas Instruments PCM3168APAP audio codec, featuring 6 analog inputs and 8 analog outputs with high-quality buffering and filtering circuitry.

hardenedlinux/cheap-pcb
Cheap PCB: Better understanding the current status of hardware supply chain

milar111/HEAT
An open-source STM32 SMD assembly station for precision soldering. Uses a custom Smart Pulse & Coast algorithm to drive 400W mains heaters via SSR. Features OLED UI, NTC feedback, and safety cooling.


minhle4397/Line-Follower-Robot-v2
Improved Hardware and Firmware for Line Follower Robot

mupfdev/TrackMAG
An open hardware development board primarily intended for the development of accessible input devices.

RaduAndre/DeskMixer
DeskMixer is a software that allows control of application volumes with real sliders, and action mapping on buttons using arduino like platforms. The project was inspired originally by deej.

abda-s/STM32-Phill-s-Lab-PCB-Course
A beginner-friendly introduction to STM32 hardware design and KiCad