# Run Config Reference `run_config.json` is the stable runtime configuration consumed by the GUI, Python helpers, and C++ pipeline binaries. The active file is normally `run_config.json`; root-level `*.example.json` files are templates. JSON does not support comments. Keep notes in docs, not inside config files. ## Top-Level Sections ```json { "radar": {}, "switches": {}, "run": {}, "preprocess": {}, "gpr": {}, "rings": {} } ``` ## `radar` Selects the radar model and sweep settings. ```json "radar": { "model": "compact_m_k209", "serial": "", "remote_host": "127.0.0.1", "remote_port": 50209, "driver_mode": "native", "mock_signal_hz": 5000000.0, "multi_device": {}, "kamil_adc": {}, "laser_control": {}, "sweep": {} } ``` Fields: | Field | Meaning | | --- | --- | | `model` | `librevna`, `librevna_multi`, `compact_m_k209`, or `kamil_adc`. | | `serial` | LibreVNA serial. Empty means first device for single LibreVNA. For `librevna_multi`, this is the master serial. | | `remote_host` | K209 remote server host. Used by `compact_m_k209`; ignored by LibreVNA modes. | | `remote_port` | K209 remote server TCP port. Default is `50209`. | | `driver_mode` | `native` for hardware, `mock` for supported synthetic LibreVNA modes. K209 and Kamil ADC require `native`. | | `mock_signal_hz` | Existing LibreVNA mock signal parameter used by C++ mock acquisition. | | `multi_device` | Extra settings for `librevna_multi`. | | `kamil_adc` | External collector process and TTY settings for `kamil_adc`. | | `laser_control` | Laser board settings applied before `kamil_adc` collection starts. | | `sweep` | Frequency, point count, IFBW, and power settings. | ### `radar.sweep` ```json "sweep": { "start_hz": 1000000.0, "stop_hz": 6000000000.0, "points": 201, "if_bandwidth_hz": 50000.0, "stimulus_power_dbm": -10.0 } ``` Fields: | Field | Meaning | | --- | --- | | `start_hz` | Sweep start frequency in Hz. | | `stop_hz` | Sweep stop frequency in Hz. Must be `>= start_hz`. | | `points` | Number of frequency points. | | `if_bandwidth_hz` | IF bandwidth in Hz. | | `stimulus_power_dbm` | Output power in dBm. | K209 limits reported by the tested device: ```text frequency_hz: 9000 .. 9000000000 ifbw_hz: 1 .. 300000 power_dbm: -55 .. +5 points: 2 .. 500001 ``` ### `radar.multi_device` Used only when `radar.model == "librevna_multi"`. ```json "multi_device": { "slave_serials": [ "SLAVE_SERIAL_1", "SLAVE_SERIAL_2" ], "force_external_reference": true, "recovery_attempts": 3 } ``` Fields: | Field | Meaning | | --- | --- | | `slave_serials` | Exactly two slave LibreVNA serials. | | `force_external_reference` | Configure the synchronized external reference path. | | `recovery_attempts` | Reopen/retry attempts after native multi-device acquisition errors. | ### `radar.kamil_adc` Used only when `radar.model == "kamil_adc"`. ```json "kamil_adc": { "project_dir": "/home/europa/Documents/kamil_adc", "executable_path": "/home/europa/Documents/kamil_adc/kamil_adc_capture", "tty_path": "/tmp/ttyADC_data", "args": [ "profile:phase", "clock:internal", "internal_ref_hz:2000000", "mode:diff", "channels:2", "ch1:2", "ch2:3", "do1_toggle_per_frame", "do1_pair_subtract_avg" ], "env": {}, "startup_timeout_s": 5.0, "sweep_timeout_s": 5.0, "stop_timeout_s": 2.0 } ``` Fields: | Field | Meaning | | --- | --- | | `project_dir` | Working directory for the external ADC collector. Required. | | `executable_path` | Full path to the Raspberry Pi executable. Required; no filename is assumed. | | `tty_path` | TTY stream path, for example `/tmp/ttyADC_data`. The producer appends `tty:`. | | `args` | Explicit collector arguments, excluding any `tty:` argument. | | `env` | Extra environment variables for the collector process. | | `startup_timeout_s` | Time allowed for the collector to create a fresh TTY path. | | `sweep_timeout_s` | Time allowed to receive one full sweep packet. | | `stop_timeout_s` | Graceful stop timeout before killing the collector process. | The TTY frame format is strict: packet start is `0x000A 0xFFFF 0xFFFF 0xFFFF`, then each sweep point is `0x000A step data1 data2`. Steps must arrive as `1..N`; `N` is derived from the stream when the next packet start arrives. `radar.sweep.points` is not used by the Kamil ADC producer. `S21` is `data1 + j*data2`; `S11` is stored as explicit zeros. ### `radar.laser_control` Used with `kamil_adc` when the laser board must be configured before ADC collection starts. `laser_control` and `kamil_adc` are one hardware configuration unit: changing either section requires restarting acquisition. ```json "laser_control": { "enabled": true, "port": "/dev/ttyUSB0", "mode": "variation", "pi_coeff1_p": 2560, "pi_coeff1_i": 128, "pi_coeff2_p": 2560, "pi_coeff2_i": 128, "manual": { "temp1": 25.0, "temp2": 25.0, "current1": 30.0, "current2": 30.0 }, "variation": { "variation_type": "CHANGE_CURRENT_LD1", "static_temp1": 28.0, "static_temp2": 28.9, "static_current1": 33.0, "static_current2": 35.0, "min_value": 33.0, "max_value": 60.0, "step": 0.05, "time_step": 50, "delay_time": 10 } } ``` `mode="manual"` uses `manual`. `mode="variation"` uses `variation`. `variation_type` is the enum name from `laser_control`, for example `CHANGE_CURRENT_LD1` or `CHANGE_TEMPERATURE_LD2`. ## `switches` Two RF switch sections are used: ```json "switches": { "port1": {}, "port2": {} } ``` By convention in the C++ pipeline: ```text port1 -> output switch port2 -> input switch ``` Switch fields: | Field | Meaning | | --- | --- | | `name` | Human-readable switch name. | | `driver_mode` | `native` for GPIO, `mock` to avoid GPIO access. | | `driver` | `h7992` or `hmc349a`. | | `radar_port` | Physical radar port mapping, must be unique and either `1` or `2`. | | `positions` | Number of switch positions. | | `default_position` | Position selected on open. Zero-based. | | `gpio_chip` | Linux GPIO chip path, usually `/dev/gpiochip0`. | | `pin_a` | First GPIO control pin. | | `pin_b` | Second GPIO control pin for `h7992`. | | `invert_logic` | Logic inversion for supported switch drivers. | Use mock switches on a laptop without GPIO: ```json "driver_mode": "mock" ``` ## `run` Runtime behavior and combo selection. ```json "run": { "settling_ms": 0, "idle_sleep_ms": 2, "continuous": true, "processing_live_config_path": "python_app/runtime/processing_live.json", "locator_server": {}, "combos": [ {"input": 0, "output": 0} ] } ``` Fields: | Field | Meaning | | --- | --- | | `settling_ms` | Delay after switching before measuring. | | `idle_sleep_ms` | Sleep between continuous collections. | | `continuous` | `true` loops until stopped; `false` captures one collection and exits. | | `processing_live_config_path` | Runtime path used by processing live settings. | | `locator_server` | Embedded TCP server settings for publishing locator results. | | `combos` | Zero-based switch combinations to acquire. | `combos` entries use input/output switch positions: ```json {"input": 2, "output": 1} ``` For `librevna_multi`, the model constraints force the canonical virtual matrix: ```text input: 0..3 output: 0..1 ``` ## `run.locator_server` Settings for the embedded locator result TCP server. | Field | Meaning | | --- | --- | | `device_id` | Device identifier in locator payloads. | | `protocol_version` | Locator payload protocol version. | | `host` | Bind host, commonly `0.0.0.0`. | | `port` | TCP port, commonly `8888`. | | `max_payload_bytes` | Maximum result payload size. | | `client_queue_size` | Per-client queue size. | | `logger_name` | Logger name used by the service. | ## `preprocess` Names or bundle paths for calibration/reference assets used by preprocessing. ```json "preprocess": { "s21": { "calibration": {"set_name": "", "bundle_path": ""}, "reference": {"set_name": "", "bundle_path": ""} }, "s11": { "calibration": { "open": {"set_name": "", "bundle_path": ""}, "short": {"set_name": "", "bundle_path": ""}, "load": {"set_name": "", "bundle_path": ""} }, "reference": {"set_name": "", "bundle_path": ""} }, "notch": { "enabled": true, "bands_hz": [], "taper_width_hz": 40000000.0, "taper_type": "cosine" } } ``` `set_name` selects a stored set for the active radar key. `bundle_path` can point to an exported bundle. Empty values mean no asset is selected. `notch.bands_hz` is a list of `[low_hz, high_hz]` ranges. `taper_type` is `cosine` or `hard`. ## `gpr` GPR geometry and processing configuration. ```json "gpr": { "relative_permittivity": 1.0, "tx_geometry": [ {"output_pos": 0, "x_m": 0.905} ], "rx_geometry": [ {"input_pos": 0, "x_m": -0.18} ] } ``` Fields: | Field | Meaning | | --- | --- | | `relative_permittivity` | Medium relative permittivity used for propagation speed. | | `tx_geometry` | Transmitter positions keyed by output switch position. | | `rx_geometry` | Receiver positions keyed by input switch position. | Geometry positions must match configured switch positions. For example, an `output_pos` of `1` requires the output switch to have at least 2 positions. ## `rings` Shared-memory ring endpoints used by native processes. ```json "rings": { "raw": {"name": "/radar_raw", "capacity": 50, "slot_size_bytes": 2097152}, "raw_tap": {"name": "/radar_raw_tap", "capacity": 50, "slot_size_bytes": 2097152}, "preprocessed": {"name": "/radar_preprocessed", "capacity": 50, "slot_size_bytes": 2097152}, "preprocessed_tap": {"name": "/radar_preprocessed_tap", "capacity": 50, "slot_size_bytes": 2097152}, "results": {"name": "/radar_results", "capacity": 50, "slot_size_bytes": 2097152} } ``` Fields: | Field | Meaning | | --- | --- | | `name` | POSIX shared-memory object name. | | `capacity` | Number of slots. | | `slot_size_bytes` | Maximum serialized payload size per slot. | Use unique ring names for parallel tests to avoid collisions with a running GUI session. ## Minimal Model Examples Single LibreVNA: ```json "radar": { "model": "librevna", "serial": "", "driver_mode": "native" } ``` Multi-device LibreVNA: ```json "radar": { "model": "librevna_multi", "serial": "MASTER_SERIAL", "driver_mode": "native", "multi_device": { "slave_serials": ["SLAVE_1", "SLAVE_2"], "force_external_reference": true, "recovery_attempts": 3 } } ``` Compact-M K209 via remote server: ```json "radar": { "model": "compact_m_k209", "remote_host": "192.168.1.10", "remote_port": 50209, "driver_mode": "native" } ``` Kamil ADC: ```json "radar": { "model": "kamil_adc", "serial": "kamil_adc", "driver_mode": "native", "kamil_adc": { "project_dir": "/home/europa/Documents/kamil_adc", "executable_path": "/home/europa/Documents/kamil_adc/kamil_adc_capture", "tty_path": "/tmp/ttyADC_data" }, "laser_control": { "enabled": true, "port": "/dev/ttyUSB0", "mode": "variation" } } ```