Commit Graph

104 Commits

Author SHA1 Message Date
Claude 8e6623b39e [fix](trx-rs): use per-message rig_id for map marker tagging
The map module was tagging all decode markers (APRS, AIS, VDES,
FT8/FT4/FT2/WSPR locators) with the global rig picker's active rig
instead of the actual source rig. This made the map's own rig filter
dropdown ineffective in multi-rig setups.

- Add rig_id field to all decode message structs (AisMessage,
  VdesMessage, AprsPacket, CwEvent, Ft8Message, WsprMessage)
- Set rig_id on messages in audio_client before broadcasting, using
  the actual rig connection identifier
- Update history collector to prefer message rig_id over the global
  active rig fallback
- Pass rig_id through plugin normalize functions (AIS, APRS, VDES,
  HF-APRS) so it reaches the map add functions
- Update all map marker functions (aprsMapAddStation, aisMapAddVessel,
  vdesMapAddPoint, mapAddLocator) to use the message's rig_id with
  fallback to the global picker for backward compatibility

https://claude.ai/code/session_015gC7axHk2jmp7HbFPdbivN
Signed-off-by: Claude <noreply@anthropic.com>
2026-03-26 16:29:53 +01:00
Claude 449b877694 [refactor](trx-ftx): use HashSet for candidate deduplication
Replace Vec::contains() with HashSet::insert() for O(1) dedup lookups
instead of O(n), significantly reducing comparisons during decode.

https://claude.ai/code/session_01XzurkeuUmamBuhQwxVy7T4
Signed-off-by: Claude <noreply@anthropic.com>
2026-03-26 07:02:46 +01:00
sjg 3877de3c4f [fix](trx-wspr): rewrite decoder with soft-decision Fano from WSJT-X reference
Replace broken hard-decision pipeline with proper soft-decision decoding
matching the WSJT-X wsprd reference implementation. Key fixes: soft-symbol
demodulation using amplitude differences, soft-decision Fano decoder with
Es/No=6dB metric table and delta=60 threshold, deinterleave preserving soft
values instead of extracting hard bits, convolutional tail constraint, and
normalized sync correlation scoring.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-20 08:16:33 +01:00
sjg 11097a5133 [docs](trx-ftx): update README with new module architecture
Reflect the common/ft8/ft4/ft2 directory reorganization in the
architecture diagram, file tree, and signal flow description.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-20 00:08:38 +01:00
sjg ab8425c85c [refactor](trx-ftx): move ft2_encode to ft2 module, remove all allow clauses
Move ft2_encode from ft4/ to ft2/ where it belongs. Remove all
module-level #[allow] suppressions and fix the underlying issues:
- Remove dead code: wf_mag_at, xor_rows, unused Monitor IFFT fields, OsdBox.size
- Gate encode174_to_bits with #[cfg(test)] (only used in tests)
- Convert 40+ C-style index loops to idiomatic iterators
- Add targeted #[allow(clippy::too_many_arguments)] on two OSD functions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-20 00:05:11 +01:00
sjg bb18d90cbe [refactor](trx-ftx): reorganize into common/, ft8/, ft4/, ft2/ modules
Split flat src/ layout into protocol-oriented directory structure:
- common/: shared types, constants, LDPC/OSD decoders, monitor, message, CRC
- ft8/: FT8-specific sync scoring, likelihood extraction, tone encoding
- ft4/: FT4-specific sync scoring, likelihood extraction, tone encoding
- ft2/: FT2 pipeline, waterfall decode, bitmetrics, downsample, sync
- Top-level: lib.rs (mod declarations) and decoder.rs (public API)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-19 23:51:17 +01:00
sjg de0bc89705 [refactor](trx-ftx): flatten ft2/ submodules into top-level src/
Move ft2/osd.rs, ft2/bitmetrics.rs, ft2/downsample.rs, ft2/sync.rs
out of the ft2/ directory into src/ as top-level modules. Convert
ft2/mod.rs to ft2.rs. Update all imports from super:: to crate::ft2::.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-19 23:31:19 +01:00
sjg 2da749b978 [refactor](trx-ftx): optimize hot paths and deduplicate decoder internals
- Cache generator matrix with OnceLock (P0.1)
- Store raw complex in WfElem, eliminate powf round-trip (P0.2)
- Reuse FFT planners across decode cycles in Ft2Pipeline (P0.3)
- Deduplicate fast_atanh/ldpc_check into ldpc.rs (P1.1)
- Gate unused sum-product ldpc_decode behind #[cfg(test)] (P1.2)
- Eliminate double pack_bits in verify_crc_and_build_message (P1.3)
- Remove unnecessary unsafe impl Send for Ft8Decoder (P1.4)
- Convert key loops to iterator/zip patterns (P2.1)
- Remove resolved clippy::manual_memcpy suppressions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-19 23:22:58 +01:00
sjg 3dc6918082 [docs](trx-ftx): add README with attribution and architecture diagram
Replace FTX_CRATE.md with README.md documenting upstream origins
(kgoba/ft8_lib for FT8/FT4, iu8lmc/Decodium-3.0 for FT2) and a
Mermaid diagram of the crate architecture.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-19 20:01:29 +01:00
sjg 1fe63257a1 [fix](trx-ftx): align FT2 decoder with Fortran reference thresholds
Remove normalize_llr which was undoing the scalefac=2.83 scaling,
causing LLRs to be 2.83x too small for the BP+OSD decoder. Align
sync thresholds with reference: coarse 0.50->0.40, decode 0.65->0.55,
sync quality 10->9, maxosd 3->4. Revert norm_sqr back to norm in
bitmetrics since the metric difference is nonlinear.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-19 19:59:52 +01:00
sjg 9c9026e7ca [refactor](trx-ftx): eliminate heap allocations in LDPC and OSD decoders
Replace Vec<Vec<f32>> with flat stack arrays in ldpc_decode (~114KB),
convert 19+ Vec allocations to stack arrays in osd174_91, eliminate
per-call temp Vec in nextpat91 via in-place mutation, and replace
norm() with norm_sqr() in bitmetrics hot loop (~5.4M calls/frame).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-19 19:41:34 +01:00
sjg 9b49b41fb3 [refactor](trx-ftx): consolidate FT2 decoder with shared FT8 code
Eliminate duplicated code between FT2 and FT8/shared modules:
- Share parity8() from encode.rs, remove copies in ft2/mod.rs and osd.rs
- Share pack_bits() from decode.rs, remove pack_bits91() from osd.rs
- Add verify_crc_and_build_message() to decode.rs, used by both FT8 and FT2
- Add normalize_llr() to decode.rs, replacing per-module normalization
- Make encode174() pub(crate), add encode174_to_bits() for bit-array output
- Wire FT2 decode_hit to use full BP+OSD decoder from osd.rs instead of
  separate BP + sum-product + OSD-lite flow
- Align LLR scale factor to 2.83 matching reference implementation

Net -178 lines removed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-19 19:15:46 +01:00
sjg 4c728bd8da [fix](trx-ftx): fix infinite loop in callsign hash table when full
add() and lookup() had no wrap-around guard in their linear-probe loops.
Once 256 unique callsigns filled the table, any subsequent add or lookup
for an absent hash would cycle through all 256 slots forever, hanging the
FT8 decoder task permanently inside block_in_place. On a busy band this
could happen within a few minutes of operation.

- add(): evict the probe-start slot when a full cycle completes
- lookup(): return None after a full probe cycle
- reset(): call cleanup(10) each slot boundary to age out stale entries
- Add regression tests for both infinite-loop scenarios

Also includes cargo fmt reformatting of pre-existing style issues.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-19 18:38:27 +01:00
sjg 0b28900082 [refactor](trx-ftx): optimize ft2 decode hot paths
Reuse FT2 downsample and bitmetric work buffers, speed up\nsync2d_score with precomputed references, and cache peak-search\nFFT state on the pipeline.\n\nCo-authored-by: OpenAI Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-18 23:08:42 +01:00
sjg 7d20058c03 [chore](trx-rs): remove unused external ft8_lib
Delete the obsolete ft8_lib submodule and update documentation to point at the pure Rust trx-ftx decoder.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-18 22:44:35 +01:00
sjg ab30270a63 [chore](trx-rs): update SPDX copyright headers
Normalize tracked SPDX headers to the 2026 Stan Grams identity.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-18 22:39:06 +01:00
sjg 2609ce668a [fix](trx-ftx): clear decoder warnings
Quiet compiler and clippy warnings in the translated decoder modules.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-18 22:34:55 +01:00
sjg 7cc8490024 [fix](trx-wspr): clear decoder warnings
Keep protocol items before tests and rewrite warning-triggering loops.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-18 22:34:43 +01:00
sjg 5dabe32106 [refactor](trx-rs): remove trx-ft8 C FFI crate, use trx-ftx directly
Delete trx-ft8 (C wrapper around ft8_lib + ft2_ldpc) and update
trx-server to depend on trx-ftx (pure Rust) directly. Removes
~2,900 lines of C code and all unsafe FFI.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-18 22:22:20 +01:00
sjg de79e8a1e6 [feat](trx-ftx): add pure Rust FTx decoder crate
Replace the C FFI-based trx-ft8 with a pure Rust implementation
supporting FT8, FT4, and FT2 protocols. Eliminates cc/libc build
dependencies and all unsafe FFI code while providing the same
Ft8Decoder/Ft8DecodeResult public API.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-18 22:21:12 +01:00
sjg 353be875be [style](trx-wspr): apply cargo fmt formatting
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
2026-03-18 21:29:23 +01:00
sjg cf4c262456 [fix](trx-wspr): reduce false positives with stricter validation
Restrict accepted power levels to the 19 valid WSPR values instead of
any 0-60. Require a digit at position 1 or 2 of the trimmed callsign
per the WSPR encoding rules. Skip candidates whose sync correlation
score falls below a minimum threshold before attempting Fano decode.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
2026-03-17 22:57:13 +01:00
sjg b533d704a1 [style](trx-rs): reformat codebase
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
2026-03-17 22:36:11 +01:00
sjg 7044747ade [fix](trx-wspr): remove spurious power field offset that rejected all decodes
The WSPR 7-bit power field contains the raw dBm value (0-60) with no
offset. The decoder was subtracting 64, turning valid power values into
negative numbers that always failed the range check, causing
unpack_message to return None for every real signal. Also fix callsign
trimming to strip leading spaces from space-padded callsigns.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
2026-03-17 22:26:55 +01:00
sjg bcd3255ad7 [fix](trx-wspr): fix reversed deinterleaving that prevented all decodes
The deinterleave function had its indices swapped: it wrote
out[j] = symbols[p] instead of out[p] = symbols[j]. This fed
completely scrambled data to the Fano decoder, making convergence
impossible. Matched against the reference implementation in
raptor/lib/wsprd/wsprd_utils.c which does tmp[p] = sym[j].

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
2026-03-17 21:48:06 +01:00
sjg 46415fa307 [fix](trx-ft8): add hard-error verification to FT2 OSD decoder
The OSD-lite decoder was the source of FT2 false positives. It tries
685 CRC-14 checks across 5 passes (1 + 16 + 120 per pass), giving a
~4% chance of accepting random noise as a valid decode.

The reference implementation (decode174_91) verifies OSD results
against the received signal; the trx-rs OSD-lite only checked CRC.

Add ft2_count_hard_errors_vs_llr() which counts how many of the 174
coded bits in an OSD candidate disagree with the received hard
decisions. A legitimate correction disagrees in very few positions;
a false CRC match on noise disagrees in ~40-50 parity positions.
Reject OSD results with more than 36 hard errors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
2026-03-17 21:44:21 +01:00
sjg 8aa1884d2d [fix](trx-ft8): align FT2 decoder thresholds and LLR scaling with reference
The FT2 decoder was failing to decode valid signals due to thresholds
and LLR parameters that were significantly stricter than the reference
implementation (Decodium/raptor ft2_triggered_decode).

Thresholds aligned with reference at depth>=3:
- Peak detection: 1.08 -> 1.03 (reference uses 0.50 on normalized spectrum)
- Scan sync: 0.60 -> 0.50 (reference at depth>=3)
- Decode sync: 0.80 -> 0.65 (reference at depth>=3)
- Sync quality min: 13 -> 10 (reference at depth>=3)

LLR parameters aligned:
- Scale factor: 2.83 -> 3.2 (matches reference scalefac)
- Normalization: sqrt(24/var) -> 1/sigma (matches reference normalizebmet)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
2026-03-17 21:38:48 +01:00
sjg 7844cb65c8 [fix](trx-ft8): add missing encode.c to build
The ft8_wrapper.c references ft4_encode and ft8_encode from encode.c,
but encode.c was not included in build.rs, causing linker errors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
2026-03-17 21:29:42 +01:00
sjg c71fc58e3e [fix](trx-wspr): add sync vector correlation and multi-candidate decoding
The WSPR decoder was producing almost no valid decodes despite audible
signals. Three root causes:

- No sync vector: the 162-bit WSPR sync pattern was not used, so signal
  detection relied on raw peak power which is unreliable.
- Coarse frequency search: 4 Hz steps with 1.465 Hz tone spacing could
  miss signals entirely. Now uses 2 Hz coarse + 0.25 Hz fine refinement.
- Fixed timing: assumed signal starts exactly 1s into the slot. Now
  searches +/-2s in 0.5s steps to handle real-world timing jitter.

Also evaluates up to 8 frequency/timing candidates per slot and reports
the actual measured timing offset in dt_s.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
2026-03-17 21:24:50 +01:00
sjg 4464fa3735 [fix](trx-ft8): replace adjacent-bin SNR with post-decode estimation
The previous SNR formula (cand->score * 0.5 - 29.0) used the adjacent
tone bin as a noise reference. On a crowded FT8 band that bin is often
occupied by another station, inflating the apparent noise floor by
10-15 dB and capping reported SNR at around -10 dB even for strong
signals.

Replace with ftx_post_decode_snr(): re-encode the decoded message to
obtain the exact per-symbol tone sequence, compare each signal bin
against the minimum of the remaining (noise-only) bins, average over
all valid symbols, and apply the WSJT-X 2500 Hz bandwidth correction
dynamically per protocol. This produces accurate SNR estimates for both
FT8 and FT4 regardless of band occupancy.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
2026-03-17 21:06:43 +01:00
sjg 4c69273584 [feat](trx-wspr): implement WSPR protocol decoder
Replace the always-None stub with a full decode pipeline:
- Bit-reversal deinterleave of 4-FSK symbols (data_bit = symbol >> 1)
- Fano sequential decoder for K=32, rate-1/2 convolutional code
  (polynomials 0xF2D05351 / 0xE4613C47, 100k-cycle budget)
- Payload unpack: 28-bit callsign (mixed-radix N1), 15-bit Maidenhead
  grid (M1 formula), 7-bit power code (dBm + 64)
- Validity checks on callsign, grid, and power range
- Round-trip unit test for K1JT FN20 37

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
2026-03-17 01:04:38 +01:00
sjg 342adf476c [fix](trx-ft8): limit FT2 OSD-lite to prevent false decodes
The OSD-3 (triples) path over 5 LLR passes was doing ~11,600 CRC checks
per candidate. With a 14-bit CRC this gives ~0.7 expected false positives
per candidate — far too high.

Remove OSD-3 entirely. Cap max_candidates at 16 for OSD-1/OSD-2, giving
136 CRC checks per pass (680 total). Gate OSD-lite behind a check that
LDPC reached within 6 parity errors of converging, so it only fires when
the LLRs are already trustworthy. Combined false-positive rate drops to
~0.04 per near-miss candidate.

Also remove the now-unused ft2_osd_decode and ft2_codeword_distance
functions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-15 08:14:22 +01:00
sjg eac2efdb35 [fix](trx-ft8): increase FT2 LDPC iterations and improve OSD fallback
Increase BP/SP iteration count from 30 to 50 to match WSJT-X reference
and give belief propagation more opportunities to converge near-threshold
candidates.

Replace the parity-based OSD-1/OSD-2 fallback (which required LDPC to
have nearly converged) with ft2_osd_lite_decode applied to all five LLR
combination passes. The CRC-based decoder works directly from raw LLRs
without depending on LDPC convergence, searching the 24 least-reliable
systematic bits for up to three bit errors via OSD-3.

Also increase max_candidates in ft2_osd_lite_decode from 12 to 24 for
broader coverage of likely error positions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-15 08:06:19 +01:00
sjg 3b28281684 [fix](trx-ft8): add OSD-1/OSD-2 to FT2 LDPC decode path
Diagnostic logging showed the FT2 BP/SP decoders consistently reach
1-8 residual parity errors rather than zero — the LLRs are correct
in direction but LDPC belief propagation stalls just short of
convergence.

Add ft2_osd_decode() implementing Ordered Statistics Decoding orders
1 and 2: after the five-pass BP/SP loop fails, sort the 174 codeword
bits by |LLR| ascending and trial-flip single bits (OSD-1, always)
or all pairs of the 50 least-reliable bits (OSD-2, when the remaining
error count is <= 4).  Each trial costs one O(83) parity check;
worst-case overhead is ~1300 checks per candidate, negligible next to
the 5 x 30-iteration BP/SP passes already performed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-15 07:30:17 +01:00
sjg 0d2eb7adcd [fix](trx-ft8): log minimum LDPC parity errors per pass in FT2 window
Add err=N/N/N/N/N to the FT2 window diagnostic log line, showing the
minimum number of unsatisfied parity equations across all candidates
for each of the five LLR passes. This makes it possible to distinguish
between a signal-quality-limited failure (small error count) and a
systematic decoder bug (large error count), which is the key unknown
in diagnosing the current FT2 LDPC non-convergence.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-15 07:21:38 +01:00
sjg 188fa38f1b [fix](trx-ft8): improve FT2 decode fallback
Normalize FT2 log-likelihoods before LDPC and fall back to\nthe standard waterfall candidate decoder when the raw FT2\npath produces no decodes.\n\nCo-authored-by: OpenAI Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-14 22:39:07 +01:00
sjg 71bfc5fca1 [fix](trx-rs): route FT2 decode through shared LDPC path 2026-03-14 22:24:16 +01:00
sjg 5dd8f4112a [fix](trx-rs): isolate FT2 OSD LDPC from shared ft8_lib 2026-03-14 22:10:49 +01:00
sjg cededd9c3f [fix](trx-rs): align FT2 downsample path with reference
Reuse a shared FT2 downsample FFT context per decode window and\nfix filter shift/bin handling to match the reference implementation.\n\nCo-authored-by: OpenAI Codex <codex@openai.com>

Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
2026-03-14 21:45:35 +01:00
sjg 4efb0dc5ef [fix](trx-rs): correct FT2 symbol bin indexing 2026-03-14 21:29:26 +01:00
sjg 2ad555efd1 [debug](trx-rs): trace FT2 decode pass outcomes 2026-03-14 21:22:29 +01:00
sjg f43f3a27fd [fix](trx-rs): correct FT2 OSD generator setup 2026-03-14 21:18:13 +01:00
sjg e6a78d0ec0 [feat](trx-rs): port FT2 hybrid LDPC decoder 2026-03-14 21:15:20 +01:00
sjg 0b97329f63 [fix](trx-rs): normalize FT2 bitmetrics before LDPC 2026-03-14 21:05:55 +01:00
sjg 5b168fd6d5 [debug](trx-rs): add FT2 decode stage logging 2026-03-14 21:02:02 +01:00
sjg 3c538d5712 [fix](trx-rs): correct FT2 sync phase progression 2026-03-14 20:46:42 +01:00
sjg d3abce9ab0 [fix](trx-rs): align FT2 async window geometry 2026-03-14 20:44:25 +01:00
sjg 2ab05f5001 [fix](trx-rs): move FT2 decoding onto raw complex path 2026-03-14 20:40:11 +01:00
sjg 6d430a4300 [fix](trx-rs): add FT2 raw-window candidate search
Use an FT2-specific raw sample window and candidate acquisition path.
Keep the build clean by removing the stale monitor warning.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
2026-03-14 20:32:21 +01:00
sjg 27de75cf79 [fix](trx-rs): improve FT2 coherent decoding
Add coherent FT2 sync and likelihood extraction.
Align FT2 frequency and DT reporting with the reference decoder.
Fix vendored monitor phase-mode type mismatches.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
2026-03-14 20:25:59 +01:00