[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>
This commit is contained in:
@@ -521,32 +521,6 @@ fn ft2_extract_logl_seq(
|
||||
}
|
||||
}
|
||||
|
||||
/// Normalize LLR array by dividing by standard deviation, then optionally
|
||||
/// scaling to a target variance.
|
||||
///
|
||||
/// If `target_variance` is `Some(v)`, the output has variance ≈ v.
|
||||
/// If `None`, the output has unit variance (σ = 1).
|
||||
pub(crate) fn normalize_llr(log174: &mut [f32; FTX_LDPC_N], target_variance: Option<f32>) {
|
||||
let mut sum = 0.0f32;
|
||||
let mut sum2 = 0.0f32;
|
||||
for &v in log174.iter() {
|
||||
sum += v;
|
||||
sum2 += v * v;
|
||||
}
|
||||
let inv_n = 1.0 / FTX_LDPC_N as f32;
|
||||
let variance = (sum2 - sum * sum * inv_n) * inv_n;
|
||||
if variance <= 1e-12 {
|
||||
return;
|
||||
}
|
||||
let scale = match target_variance {
|
||||
Some(tv) => (tv / variance).sqrt(),
|
||||
None => 1.0 / variance.sqrt(),
|
||||
};
|
||||
for v in log174.iter_mut() {
|
||||
*v *= scale;
|
||||
}
|
||||
}
|
||||
|
||||
/// Verify CRC of a 174-bit plaintext and build an FtxMessage.
|
||||
///
|
||||
/// `plain174`: decoded LDPC codeword (174 bits, each 0 or 1).
|
||||
|
||||
@@ -134,7 +134,7 @@ impl BitMetricsWorkspace {
|
||||
}
|
||||
_ => Complex32::new(0.0, 0.0),
|
||||
};
|
||||
let coherent = sum.norm_sqr();
|
||||
let coherent = sum.norm();
|
||||
|
||||
for ib in 0..=ibmax {
|
||||
if ((i >> (ibmax - ib)) & 1) != 0 {
|
||||
|
||||
@@ -16,7 +16,7 @@ pub mod sync;
|
||||
use num_complex::Complex32;
|
||||
use realfft::RealFftPlanner;
|
||||
|
||||
use crate::decode::{normalize_llr, verify_crc_and_build_message, FtxMessage};
|
||||
use crate::decode::{verify_crc_and_build_message, FtxMessage};
|
||||
use crate::protocol::*;
|
||||
|
||||
use bitmetrics::BitMetricsWorkspace;
|
||||
@@ -428,7 +428,7 @@ impl Ft2Pipeline {
|
||||
idf += 3;
|
||||
}
|
||||
|
||||
if best_score < 0.50 {
|
||||
if best_score < 0.40 {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -452,7 +452,7 @@ impl Ft2Pipeline {
|
||||
}
|
||||
}
|
||||
|
||||
if best_score < 0.50 {
|
||||
if best_score < 0.40 {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -516,7 +516,7 @@ impl Ft2Pipeline {
|
||||
}
|
||||
}
|
||||
|
||||
if best_score < 0.65 {
|
||||
if best_score < 0.55 {
|
||||
return None;
|
||||
}
|
||||
|
||||
@@ -575,7 +575,7 @@ impl Ft2Pipeline {
|
||||
0
|
||||
};
|
||||
}
|
||||
if sync_qual < 10 {
|
||||
if sync_qual < 9 {
|
||||
return None;
|
||||
}
|
||||
|
||||
@@ -628,7 +628,6 @@ impl Ft2Pipeline {
|
||||
break;
|
||||
}
|
||||
let mut log174 = llr_passes[pass];
|
||||
normalize_llr(&mut log174, None);
|
||||
|
||||
let mut message91 = [0u8; FTX_LDPC_K];
|
||||
let mut cw = [0u8; FTX_LDPC_N];
|
||||
@@ -639,7 +638,7 @@ impl Ft2Pipeline {
|
||||
osd::ft2_decode174_91_osd(
|
||||
&mut log174,
|
||||
FTX_LDPC_K,
|
||||
3,
|
||||
4,
|
||||
3,
|
||||
&mut apmask,
|
||||
&mut message91,
|
||||
|
||||
Reference in New Issue
Block a user