Commit Graph
35 Commits
Author SHA1 Message Date
misadeksandCopilot App fb0e93e49e Quiet the journal: default RUST_LOG=info + demote per-frame/per-burst logs
journald was rate-limiting bluestation-bs ("Suppressed ~6,200 messages" every
30s) because the stack logged a per-frame/per-burst firehose at debug/info by
default. Logging-only change; no protocol/timing/DSP behavior touched.

- debug.rs get_default_stdout_filter(): now honors RUST_LOG (full override, e.g.
  RUST_LOG=debug|trace or per-module) and otherwise defaults to a quiet `info`.
  Removed the hardcoded per-module `=debug` directives (umac/mle/llc/cmce/mm/...)
  that forced the flood; kept messagerouter/bitbuffer=warn.
- Demoted the highest-rate lines so steady-state is ~silent and `debug` stays
  readable:
  - every entity's per-message `rx_prim: {:?}` dump: debug -> trace (phy/lmac/
    umac/mle/mm/cmce/llc/sndcp, MS + BS).
  - per-frame PDU decode dumps (MacSync/MacSysinfo/MacResource/AccessAssign/
    AccessAssignFr18/DMleSync/DMleSysinfo `<- {:?}`): debug -> trace.
  - per-frame `rx_broadcast_sysinfo: Updated TdmaTime`: info -> debug.
  - per-burst PhyMs "queued uplink burst", Modulator(Ul) "pending burst vs TX
    window", Modulator "uplink burst active part emitted (SN0)": info -> debug.
- Kept at INFO (low-rate, useful): startup/SDR-open/freqs, retune, downlink
  synchronized, registration/cell-(re)selection/call/floor events, all warnings.
- example_config/bluestation-ms.service: Environment=RUST_LOG=info (documented
  how to bump). Supervisor: export RUST_LOG="${RUST_LOG:-info}".
- docs/MS_CONFIG.md: new "Logging verbosity" section.

Acceptance: default config -> registered idle emits only occasional lines, no
"Suppressed N messages"; RUST_LOG=debug/trace restores full detail.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-08-09 01:31:11 +02:00
misadeksandCopilot App d575cb3771 MS deploy: core isolation guidance + sample UI unit (FIFO alone insufficient)
Field finding: with CPUSchedulingPolicy=fifo/prio 73 active and get_throttled=0x0,
the MS still flapped (serving-cell downlink failure / MLE-BREAK) whenever the
local Slint UI ran. The SXceiver (driver=sx / SoapySX) delivers samples over an
I2S/ALSA DMA path, and hard IRQ/softirq/kernel-DMA work preempts even a
SCHED_FIFO userspace thread — so real-time priority is necessary but not
sufficient; the fix is CPU isolation (keep the UI and routine IRQs off the
radio's cores).

- example_config/bluestation-ms-ui.service: sample unit for a co-located
  operator UI, pinned to cores 0-1 (CPUAffinity=0 1, Nice=5) so it cannot
  contend with the radio on cores 2-3.
- docs/MS_CONFIG.md: new "When FIFO priority alone is not enough" subsection —
  the fast taskset confirmation test, kernel cmdline isolation
  (isolcpus=2,3 nohz_full=2,3 rcu_nocbs=2,3 irqaffinity=0,1), and steering the
  I2S/DMA IRQ via /proc/irq/<n>/smp_affinity.

Deployment guidance only; not yet field-verified.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-08-07 00:53:29 +02:00
misadeksandCopilot App cce4d7b31c MS deploy: real-time scheduling + CPU affinity so a co-located UI can't starve RX
The MS is receive-timed: if the SDR RX pipeline is starved of CPU (e.g. a Slint
UI / desktop compositor sharing the Pi), samples are dropped ("Lost N samples,
skipping ..."), the demodulator loses sync, and the MLE declares a serving-cell
downlink failure (MLE-BREAK). The radio then flaps in/out of service and never
completes registration (T351 timeouts) even though RSSI is healthy and bursts
CRC-pass. Symptom: the MS connects fine until the UI is started.

Give the stack real-time priority so its RX thread preempts the UI, and pin it
to dedicated cores:

- example_config/bluestation-ms.service: add CPUSchedulingPolicy=fifo,
  CPUSchedulingPriority=73, IOSchedulingClass=realtime, Nice=-10, LimitRTPRIO=99,
  LimitMEMLOCK=infinity, CPUAffinity=2 3, and KillSignal=SIGINT. Comments explain
  tuning (isolcpus, pinning the UI to the other cores) and that this is a
  scheduling, not RF, problem.
- example_config/bluestation-ms-supervisor.sh: launch the binary under
  `chrt -f $RT_PRIO` (default 73) and, when CPU_AFFINITY is set, `taskset -c`,
  each best-effort with graceful fallback when the tool/privilege is missing.
- docs/MS_CONFIG.md: new "Real-time scheduling" section documenting the failure
  signature and the fix (incl. UI-side guidance and vcgencmd get_throttled).

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-08-07 00:40:33 +02:00
misadeksandCopilot App 99d70bf04e refactor(ms): drop gateway kind (PABX/PSTN) — no functional purpose
TETRA has no on-air PABX/PSTN distinction; both are ordinary external-number
calls routed by the SwMI on the gateway subscriber + digits. The kind field
(and CfgGatewayKind enum) was a cosmetic UI label only, so remove it to keep the
codeplug lean. A gateway is now just id + name + gateway_issi + optional prefix.

Updated CfgGateway/GatewayDto/converters, example config, MS_CONFIG.md, and the
contacts/PSTN UI prompt. Config suite 64 green.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-08-02 15:26:22 +02:00
misadeksandCopilot App 30c0194b32 refactor(ms config): make [cell_info] optional for MS; reorganize codeplug
Analysis: in MS mode the stack reads nothing functional from [cell_info] — RF is
learned over the air (SYNC/SYSINFO, cl. 18.4.2), location_area is only a
pre-registration seed (overwritten by the registration confirm), and colour_code
just fills a cosmetic state-snapshot field. So [cell_info] is not needed for MS.

- Parser: root cell_info is now Option (serde default). BS mode still requires
  it (existing main_carrier/freq_band guard); MS may omit the whole section and
  the serializer drops it from canonical MS output.
- Reorganize example_config/config-ms.toml: drop [cell_info]; group ALL codeplug
  sections into one numbered region (settings -> networks -> frequencies ->
  carrier overrides -> folders -> talkgroups -> scanlists -> gateways -> contacts).
- net_info stays a shared top-level home-network section (used by both BS and MS);
  documented its relationship to the codeplug [[network]] allowed-networks list.
- Tests: MS config without any [cell_info] parses/validates; MS round-trip omits
  [cell_info]. Config suite 64 green (shipped BS + MS examples parse+validate).
- Docs: MS_CONFIG.md net_info/cell_info sections rewritten.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-08-02 15:19:53 +02:00
misadeksandCopilot App 8ad3615701 refactor(ms): home_display becomes a toggleable [codeplug.home_display] setting
Replace the flat codeplug home_display_pid with a dedicated
[codeplug.home_display] sub-table carrying enabled (bool) + pid (u8, SDS
protocol identifier cl. 29.4.3.9, default 130). Codeplug data only; surfaced to
the UI via the GetConfig/SetConfig TOML round-trip.

- CfgHomeDisplay { enabled, pid } (+ Default), CfgCodeplug.home_display: Option;
  home_display() accessor; is_empty updated.
- CodeplugSettingsDto.home_display: HomeDisplayDto (enabled/pid, pid defaults 130);
  codeplug_dto_to_cfg / cfg_to_codeplug_settings_dto round-trip.
- Example config [codeplug.home_display] + MS_CONFIG.md docs.
- Tests: settings round-trip + pid-defaulting; config suite 63 green, shipped
  example parses+validates.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-08-02 15:09:55 +02:00
misadeksandCopilot App 00b960c242 feat(ms): add codeplug home_display_pid setting
Add a scalar [codeplug] settings table with home_display_pid (8-bit SDS
protocol identifier, ETSI TS 100 392-2 cl. 29.4.3.9) for a 'home mode display'
status/text message. Codeplug data only (Plane B) — surfaced to the UI via the
existing GetConfig/SetConfig TOML round-trip; no on-air behaviour change.

- CfgCodeplug.home_display_pid: Option<u8> + is_empty + home_display_pid()
  accessor; CodeplugSettingsDto ([codeplug] table) + codeplug_dto_to_cfg /
  cfg_to_codeplug_settings_dto; parsing.rs root wiring.
- Example config [codeplug] section + MS_CONFIG.md docs.
- Test: settings round-trip via the DTO; config suite 62 green, shipped
  example config parses+validates.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-08-02 13:29:34 +02:00
misadeksandCopilot App 847344f710 feat(ms): contacts + PABX/PSTN gateway calls; fix group-call first-transmission silence
Contacts & gateways (codeplug, Plane B):
- CfgContact (name, optional callsign, ISSI or phone target) and CfgGateway
  (PABX/PSTN kind, gateway_issi, optional access-code prefix) in sec_codeplug.rs,
  with DTOs, both-direction converters, validation (24-bit ISSI, dangling-gateway
  refs, dial-digit set, prefix+number <= 24-digit IE limit, unique ids/names) and
  resolve_phone_contact(). Wired into parsing.rs + example config.

External (PABX/PSTN) call origination:
- External subscriber number IE codec per ETSI TS 100 392-2 cl. 14.8.20 / Table
  14.59 (4-bit digits, n <= 24, set 0-9 * # +) in tetra-pdus.
- send_u_setup carries the IE; originate_external_call addresses the gateway ISSI
  (CPTI=SSI) and encloses the dialled digits; handle_tncc_setup_request routes a
  TnccSetupRequest whose external_subscriber_number_called is set. No on-air
  PABX/PSTN flag exists (spec); the distinction is codeplug/UI only.

Group-call first-transmission fix (cl. 14.5.1.4 / 14.8.31):
- resolve_floor_grant() normalises a Granted(0) naming a different subscriber to
  GrantedToOtherUser so the simplex self-echo guard no longer suppresses a remote
  talker's first spurt; telemetry decision points in rd.rs use the resolved grant.

Tests: external-subscriber-number round-trip; CC-MS external-call U-SETUP decoded
via the BS parser; contact/gateway validation + resolve; grant-normalisation
regressions. tetra-config 61, tetra-pdus 38, tetra-entities lib 353 +
test_cmce_ms/test_umac_ms 17; bluestation-bs builds. Docs: MS_MODE.md + MS_CONFIG.md.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-08-02 02:00:30 +02:00
misadeksandCopilot App 97412c8822 feat(ms): scan carrier offsets in frequency_list Range mode
Range lists enumerated only the nominal 25 kHz raster (offset 0). Add an optional offsets key to [frequency_list.range] so each carrier is also probed at the ETSI-legal offsets (0, +6250, -6250, +12500 Hz; EN 300 392-2 D-MLE-SYNC Offset field). candidate_frequencies() expands carrier x offset (deduped); validation rejects any offset outside the four legal values. Absent/empty offsets = [0], preserving prior behaviour. List mode already supports any offset via absolute Hz. Docs + example config updated.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-07-25 19:29:27 +02:00
misadeksandCopilot App 96a75b4b1d docs(ms): fix frequency_list range to single-bracket [frequency_list.range]
The range sub-table maps to range: Option<FrequencyRangeDto> (one range per list), so it must be a single-bracket [frequency_list.range] table, not a [[...]] array of tables. The [[frequency_list.range]] form the docs/example showed fails to parse (invalid type: sequence, expected struct FrequencyRangeDto). Corrected MS_CONFIG.md and example_config/config-ms.toml.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-07-25 19:16:51 +02:00
misadeksandCopilot App eb9f451578 Make MS RF config scan-driven: drop fixed tx_freq/rx_freq + cell_info RF
A radio-style MS is programmed by downlink and learns its serving carrier,
uplink and duplex spacing over the air from the cell's D-MLE-SYNC/SYSINFO
(EN 300 392-2 cl. 18.4.2). So the fixed soapy tx_freq/rx_freq and the
[cell_info] RF block are no longer needed in an MS config and were only
confusing.

- sec_phy_soapy: tx_freq/rx_freq optional; add dl_freq_seeded flag so a
  seeded RX / unset UL round-trip without reintroducing fixed freqs.
- sec_cell: cell_info RF fields (main_carrier/freq_band/freq_offset/
  duplex_spacing/reverse_operation) optional; serializer omits them for MS.
- parsing: seed the SDR initial RX (dl_freq) from the first [[frequency_list]]
  scan candidate for MS; require cell RF + soapy freqs only for BS mode.
- config validate: gate the cell-derived DL/UL match check to BS; for MS
  require some RX source (a frequency_list or explicit tx_freq); drop the
  now-moot MS mismatch warning.
- soapyio/soapy_dev: leave MS TX unset (no TX chain) until ul_freq is known,
  i.e. until the MS camps and derives the uplink from SYSINFO.
- example_config/config-ms.toml: remove tx_freq/rx_freq and the [cell_info]
  RF block; explain the scan-driven / over-the-air model in comments.

Remove commitmsg.txt accidentally committed in the previous change.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-07-21 22:50:07 +02:00
misadeksandCopilot App f2d82515f4 Refactor codeplug scan config into named [[frequency_list]] tables
Replace the single [scan] section with multiple named [[frequency_list]]
array-of-tables. Each list is List or Range (the old Fixed mode is removed
- a single-frequency setup is just a List with one frequency). The radio
scans all lists combined into one candidate set (deduplicated, order
preserved).

- sec_codeplug: ScanMode -> FrequencyListMode (List/Range only), CfgScan ->
  CfgFrequencyList (+ name), CfgScanRange -> CfgFrequencyRange; codeplug field
  scan: Option<CfgScan> -> frequency_lists: Vec<CfgFrequencyList>; add
  scan_candidate_frequencies() combining+deduping all lists; per-list
  validation (unique non-empty names, List needs >=1 freq, Range needs range).
- parsing: TomlConfigRoot.scan -> frequency_list array; DTO/serialize plumbing.
- mle_ms: scan_candidate_carriers() now returns the combined set; drop
  ScanMode import.
- example_config/config-ms.toml: [[frequency_list]] with List + commented Range.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-07-21 22:34:39 +02:00
misadeksandCopilot App 38f16746ac Restructure codeplug to radio programming model
Reframe the Plane B codeplug around how a portable radio is programmed,
not how a BS is defined:

- Talkgroups are the user-selectable groups (folders + explicit order
  within a folder; talkgroups now carry an order field).
- Allowed networks move to a codeplug-wide [[network]] list (mcc/mnc +
  optional name + selection priority), replacing the per-scan
  allowed_networks.
- The scanner is driven by a list of absolute downlink requencies (Hz)
  or a carrier range, replacing the channel-name reference list.
- The old [[channel]] becomes [[carrier_override]]: an optional
  per-frequency override (colour-code lock, custom duplex, rx_only),
  matched by downlink frequency; no folder/talkgroup binding.

Added helpers: folders_sorted, talkgroups_in_folder, networks_sorted,
carrier_override_for_freq, CfgScan::candidate_frequencies (expands Range).
Renamed StackState.last_camped_channel -> last_camped_freq_hz (u32).
Updated parsing DTOs/round-trip, example config-ms.toml, and tests.

All values remain ETSI-bounded and validated. Config stays v0.7; pure
crates + entities/bins suites green (199 lib + all integration).

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-07-21 20:19:16 +02:00
misadeksandCopilot App 132b4a59f1 Phase B: radio-style codeplug schema + config v0.7
Add a Plane B codeplug so an MS is programmed like a radio (by downlink +
allowed networks) rather than like a BS. Data only: read by the UI/scan
engine in later phases; no on-air behaviour change yet. Every value maps
to a real ETSI element and is validated against its bit-width/allowed set.

tetra-config (sec_codeplug.rs):
- CfgCodeplug = folders + channels + talkgroups + optional scan.
  * Channel: band+carrier(+offset) OR absolute dl_freq (Hz), optional
    colour-code filter (6-bit), duplex_index hint (3-bit), custom duplex
    spacing, folder, rx_only, default talkgroups. DL math mirrors
    FreqInfo::get_freqs (band*100MHz + carrier*25kHz + offset).
  * Talkgroup: 24-bit GSSI, class_of_usage (3-bit), folder.
  * Scan: Fixed/List/Range modes, dwell, allowed_networks (empty = home
    MCC/MNC only; 10-bit MCC / 14-bit MNC).
  * validate(): ranges + cross-refs (folder/channel/talkgroup ids).
- Full DTO round-trip (channels serialize in canonical band+carrier form).

Config wiring:
- StackConfig.codeplug; parsed from [[folder]]/[[talkgroup]]/[[channel]]/
  [scan]; validated at parse with descriptive errors.
- config_version bumped to 0.7; 0.6 still accepted (legacy, no codeplug)
  so existing configs and inline test configs keep loading.
- Relax MS/Mon validation: DL/UL derived-vs-soapy mismatch is now a
  warning (a radio derives UL from the cell's SYSINFO at camp time,
  EN 300 392-2 cl. 18.4.2.2); BS still requires an exact match.
- StackState.last_camped_channel for future fast re-acquire.

Example configs: bump to 0.7; config-ms.toml gains a [duplex_table],
folders, talkgroups, two channels (band+carrier and dl_freq forms) and a
[scan] block with a range-scan example.

Tests: tetra-config 35 (codeplug ranges/cross-refs/round-trip, dl_freq
resolution, legacy-version acceptance, shipped example configs parse +
validate). WSL: 199 lib + all integration suites green, no warnings.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-07-21 20:03:11 +02:00
misadeksandCopilot App a25a9f2ac4 T4: move MS interface reference client + catalog to examples/ms-interface/
Per maintainer decision #4, land the MS external-interface artifacts in-repo
under a dedicated examples/ms-interface/ directory (the source of truth), not
example_config/:

- examples/ms-interface/README.md — the protocol/API documentation (message
  catalog): Plane A TNMM-SAP (cl. 15.3) + Plane B management, the HYBRID apply
  model, redact-on-wire / preserve-on-write secret handling, and a wscat quick
  example. Shippable API docs, not a planning note.
- examples/ms-interface/reference-client.py — the runnable language-neutral
  reference client (concise docstring pointing at the catalog).

Removes the interim example_config/ms-ui-reference-client.py. Deployment
artifacts (systemd unit + supervisor script) stay in example_config/. This
directly serves the "build different UIs on top of the stack" goal. Docs/sample
only; no code or wire-behaviour change. py_compile clean.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-07-20 01:46:33 +02:00
misadeksandCopilot App e32d1f794b T4: land MS interface reference client + catalog in example_config (Plane B)
Add example_config/ms-ui-reference-client.py: a runnable, language-neutral
reference client for the MS external interface (schema bluestation-ms-interface-1)
whose module docstring also serves as the full message catalog (Plane A TNMM-SAP
cl. 15.3 + Plane B management). Documents the redact-on-wire / preserve-on-write
secret handling and the HYBRID apply model (SetConfig stages; ApplyConfig drains
+ exits 75 for the supervisor). NON-STANDARD Plane B clearly marked; no ETSI
behaviour asserted. Sample only, not built/linked; py_compile clean.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-07-20 01:35:05 +02:00
misadeksandCopilot App 58cb161c08 feat(ms): T3 write-path — TOML config write-back + apply/restart (Plane B)
Complete the MS management interface (Plane B, NON-STANDARD) write path:
GetConfig / SetConfig / ApplyConfig, using the HYBRID apply model (structural
radio params staged to TOML + applied on a controlled restart; operational TNMM
actions stay live on Plane A). ETSI does not standardize radio programming over
the air, so this whole plane is implementation-defined and marked as such.

tetra-config — TOML write-back (inverse of from_toml_str):
- Derive Serialize on the on-disk DTO layer only (TomlConfigRoot, *Dto, StackMode)
  — NOT on StackConfig/SecretField (SecretField redaction is for logs only).
- Add cfg_to_*_dto inverses for every section (net/cell/ms/phy/soapy/control/
  telemetry/brew) mirroring the existing dto_to_cfg + apply_*_patch mappers, so
  there is ONE schema source of truth and the written file re-parses through the
  exact same validator (round-trip GetConfig->SetConfig->load provably closed).
- New parsing::to_toml_string(&StackConfig) -> canonical TOML; emits
  config_version = "0.6" verbatim; secrets written as plaintext (the TOML file
  is their canonical store). `extra` catch-alls skipped when empty (a loaded
  config has no unknowns — the parser rejects non-empty extra).
- Tests: MS-config round-trip (parse->serialize->reparse, key fields incl. soapy
  gains via non-empty flatten) + config_version emission.

tetra-entities — management commands + MM handlers:
- management: add ManagementCommand::{GetConfig,SetConfig,ApplyConfig} and
  ManagementResponse::{Config,Ack}; add restart_required to MsRuntimeState.
- MmMs: GetConfig serializes the active config; SetConfig validates via
  from_toml_str, normalizes via to_toml_string, writes to the config path and
  sets restart_required (does NOT bounce the process); ApplyConfig reuses the
  existing graceful de-registration drain (U-ITSI DETACH, cl. 16.6.1) then
  signals main to exit with the restart code. Management context (config path +
  shared restart/running flags) installed via a setter so existing test
  constructors are untouched; write/apply refuse gracefully when absent (keeps
  the "external UI must never panic the RF process" invariant — validate/reject,
  never unwrap).
- Tests: GetConfig round-trip, SetConfig without-context refusal, SetConfig
  validate+persist+flag-restart, SetConfig invalid-config rejection, ApplyConfig
  drain+restart-signal, ApplyConfig without-context refusal, plus a codec JSON
  round-trip for the new config variants.

bin + supervisor:
- main.rs: EXIT_RESTART = 75 constant; create restart/running flags before
  building the stack and thread them + the config path into build_ms_stack;
  after run_stack, exit(75) if a restart was requested. In-process relaunch is
  deliberately avoided (main owns the SDR handle + thread graph).
- Sample supervisor artifacts (example_config/): systemd unit
  (RestartForceExitStatus=75) and a POSIX wrapper-script loop.

BS code paths unchanged (Serialize derives are mechanical; no behaviour change).

Note (non-blocking): CfgBrew round-trips asymmetrically — DTO username:u32 vs
runtime Option<String> (parsed back, defaults 0) and DTO password:String vs
runtime Option<SecretField> (written plaintext). Brew is BS-only; MS configs
carry no [brew] section, so this never affects the MS write path.

Build+test: tetra-config green on Windows; tetra-entities 167 passed / 5 ignored
and bluestation-bs builds in WSL.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-07-20 01:19:08 +02:00
misadeksandCopilot App c089f23c30 chore(ms): add example MS-mode config (config-ms.toml)
Example configuration for MS mode connecting to a BS: DL/UL freqs derived from
freq_band 4, main_carrier 1593, custom duplex spacing 9.4 MHz, SXceiver gains,
and net/cell identity (MCC/MNC, colour code, LA). Used by the MS build-deploy
scripts.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-07-18 21:22:32 +02:00
misadeksandCopilot App 0682e31bde feat(ms): Phase 0 MS-mode wiring - config, PhyMs skeleton, build_ms_stack
- Add [ms] config section (CfgMs: issi, subscriber_class, attach_groups),
  wired through parsing/validation; reuses net_info/cell_info for radio.
- Add minimal PhyMs<D: RxTxDev> skeleton registered as the Phy entity
  (receive-driven; RX demod + RX-driven clock deferred to Phase 1).
- Add build_ms_stack() and switch on stack_mode in main() (single bin).
- Reconcile stale mle_ms.rs against the current SapMsg/SAP API (mirrors
  mle_bs) and declare it in mle/mod.rs so MleMs compiles/registers.

Grounded in ETSI TS 100 392-2. No air behaviour yet (assembly only).

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-07-18 20:17:15 +02:00
misadeks 4a51242c93 WIP merge with upstream main 2026-05-14 02:07:08 +02:00
misadeks 7ec908af57 large commit, wip 2026-03-03 19:02:18 +01:00
proxiboi69 62594acae4 Per-radio ISSIs with TetraPack safety filtering; MM improvements (#32)
* Per-radio ISSIs with TetraPack safety filtering; MM improvements

- Version to 0.4.9
- Send per-radio REGISTER/DEREGISTER/AFFILIATE/DEAFFILIATE with individual ISSIs
- Add TetraPack ISSI filter: only exactly 7-digit ISSIs sent over WS
- Restrict GSSI <= 90 filter to TetraPack only
- Filter GROUP_TX forwarding for non-routable source ISSIs
- Remove Brew ISSI config field and initial BTS registration
- Rename is_brew_routable to is_brew_gssi_routable
- MM: auto-register unknown MS on group attach
- MM: send D-LOCATION UPDATE COMMAND to returning radios for group report
- MM: fix group_identity_attachment_lifetime to ETSI default
- MM: rename TemporaryRegistration to MigratingLocationUpdating
2026-02-27 13:28:39 +01:00
Wouter Bokslag 9d16d5c300 Improved Stack <-> Brew gating, some refactors 2026-02-24 15:47:35 +01:00
Wouter Bokslag 6f3f6ca9a2 Added brew call ssi range restrictions
Added checks to restrict brew calls to whitelisted / non-blacklisted ssi ranges
Updated example config
2026-02-24 13:54:25 +01:00
misadeks cbfd50b79d Dynamic group attachment for Brew subscribers (#19) 2026-02-23 17:03:21 +01:00
misadeks 0284e48ca7 Signal Lone Site Trunking based on Brew connectivity (#25)
* implemented LST indication based on connection to Brew or enablement of Brew
With brew disabled, LST signalling follows optional user flag
With brew enabled, LST signalling dynamic, overriding user flag
* added Brew WebSocket ping/pong heartbeat
Co-authored-by: Wouter Bokslag <w.bokslag@midnightblue.nl>
2026-02-23 13:13:46 +01:00
Elliott Cooper ca97b70648 Feature: Adaptive JitterBuffer for Brew Originated Calls (#16)
* brew: replay adaptive jitter buffer and bump v0.4.3
2026-02-21 12:16:44 +01:00
Wouter Bokslag 78397cde8d Updated example config 2026-02-20 11:16:46 +01:00
proxiboi69 95f2cd61f6 Brew integration and local group calls
- Brew RX/TX: talkgroup subscription, DL voice routing, UL forwarding to TetraPack
- Local group calls: ETSI call setup, floor control, hangtime, late entry
- UL voice: TCH/S decode with continuous Viterbi, ACELP reorder, DL loopback
- Fix MAC fragmenter crash on header exceeding remaining slot capacity
- Fix MLE handle routing for individual call setup responses
- Fix Direction::Both in UMAC circuit manager
- Align circuit expiry with T5m call timeout

- Add DEAFFILIATE → DEREGISTER teardown on Brew worker disconnect
- Implement Drop for BrewEntity to trigger graceful shutdown
- Add Ctrl+C signal handler (ctrlc crate) so main loop exits cleanly
- Extract graceful_teardown() in worker, handle channel disconnect fallback
- Add build_subscriber_deaffiliate/deregister to protocol builders

- Pass target TS via chan_alloc in D-TX CEASED / D-TX GRANTED
- UMAC stealing path uses specified TS instead of always picking first active circuit
- Fixes missing PTT release signaling on TS3+ with multiple concurrent group calls
2026-02-17 18:51:32 +01:00
Wouter Bokslag 1b377fcee7 Work-in-progress stuff regarding channel allocations and voice calls 2026-02-06 14:01:21 +01:00
Wouter Bokslag a24666ec86 Indicate PPM error is a float value in example config 2026-01-10 22:17:17 +01:00
Wouter Bokslag c02e165345 Significant improvements, rewrites and restructuring
- Better support for uplink SCH/F
- More typed message parsing improvements and standardization
- MAC Scheduler bugfix, restructuring
- Improved stdout formatting
- Added debugging features; logging text and UL/DL RF samples to file
- Implemented various extra PDU types
- Added unit tests and test vectors for various PDU types
- Added near-full-stack tests for UMAC and above.
2026-01-07 16:35:37 +01:00
Wouter Bokslag 07ad483806 Added support for custom duplex spacings
You can now use the optional custom_duplex_spacing field to override the duplex spacing (distance between ul and dl) instead of using the values as specified by ETSI. This is useful if your radio uses a modified duplex spacing table.
2025-12-30 20:32:33 +01:00
Wouter Bokslag 872b58803d Updated example config file version 2025-12-28 17:09:36 +01:00
Wouter Bokslag 81c1f30bab Extensive work on Phy/SoapySDR layer and stack configuration options 2025-12-28 15:23:44 +01:00