From 69e00a82451569bad22a7759c938e11ba8d3e929 Mon Sep 17 00:00:00 2001 From: Stan Grams Date: Sat, 4 Apr 2026 07:54:31 +0200 Subject: [PATCH] [fix](trx-wefax): remove idle phasing fallback detection Phasing-only signals (no APT start tone) should not trigger image decoding. Only APT start tones and signal-level variance detection can start reception. Co-Authored-By: Claude Opus 4.6 Signed-off-by: Stan Grams --- src/decoders/trx-wefax/src/decoder.rs | 36 +-------------------------- 1 file changed, 1 insertion(+), 35 deletions(-) diff --git a/src/decoders/trx-wefax/src/decoder.rs b/src/decoders/trx-wefax/src/decoder.rs index 69e3634..79a3d8b 100644 --- a/src/decoders/trx-wefax/src/decoder.rs +++ b/src/decoders/trx-wefax/src/decoder.rs @@ -65,9 +65,6 @@ pub struct WefaxDecoder { demodulator: FmDiscriminator, tone_detector: ToneDetector, phasing: Option, - /// Fallback phasing detector that runs in Idle state to catch ongoing - /// transmissions when the APT start tone was missed. - idle_phasing: Option, slicer: Option, image: Option, /// Total sample counter for timestamps. @@ -87,7 +84,6 @@ pub struct WefaxDecoder { impl WefaxDecoder { pub fn new(input_sample_rate: u32, config: WefaxConfig) -> Self { - let default_lpm = config.lpm.unwrap_or(120); Self { resampler: Resampler::new(input_sample_rate), demodulator: FmDiscriminator::new( @@ -96,7 +92,6 @@ impl WefaxDecoder { config.deviation_hz, ), tone_detector: ToneDetector::new(INTERNAL_RATE), - idle_phasing: Some(PhasingDetector::new(default_lpm, INTERNAL_RATE)), config, state: State::Idle, phasing: None, @@ -155,20 +150,15 @@ impl WefaxDecoder { match self.state.clone() { State::Idle => { // Look for APT start tone first. - let mut got_start = false; for result in &tone_results { if let Some(tone) = result.tone { match tone { AptTone::Start576 => { - self.idle_phasing = None; events.push(self.transition_to_start_detected(576)); - got_start = true; break; } AptTone::Start288 => { - self.idle_phasing = None; events.push(self.transition_to_start_detected(288)); - got_start = true; break; } AptTone::Stop => {} // Ignore stop in idle. @@ -176,26 +166,7 @@ impl WefaxDecoder { } } - // Fallback 1: try phasing detection on luminance to catch - // ongoing transmissions where the start tone was missed. - if !got_start { - if let Some(ref mut idle_ph) = self.idle_phasing { - if let Some(offset) = idle_ph.process(&luminance) { - let ioc = self.config.ioc.unwrap_or(576); - let lpm = self.config.lpm.unwrap_or(120); - self.reception_start_ms = Some( - std::time::SystemTime::now() - .duration_since(std::time::UNIX_EPOCH) - .unwrap_or_default() - .as_millis() as i64, - ); - self.idle_phasing = None; - events.push(self.transition_to_receiving(ioc, lpm, offset)); - } - } - } - - // Fallback 2: detect active WEFAX signal by luminance variance. + // Fallback: detect active WEFAX signal by luminance variance. // Like fldigi's "strong image signal" detection — if we see // sustained modulated signal, auto-start receiving with defaults. if self.state == State::Idle { @@ -230,7 +201,6 @@ impl WefaxDecoder { .unwrap_or_default() .as_millis() as i64, ); - self.idle_phasing = None; self.signal_detect_buf.clear(); events.push(self.transition_to_receiving(ioc, lpm, 0)); break; @@ -334,13 +304,11 @@ impl WefaxDecoder { } _ => Vec::new(), }; - let default_lpm = self.config.lpm.unwrap_or(120); self.state = State::Idle; self.resampler.reset(); self.demodulator.reset(); self.tone_detector.reset(); self.phasing = None; - self.idle_phasing = Some(PhasingDetector::new(default_lpm, INTERNAL_RATE)); self.slicer = None; self.image = None; self.sample_count = 0; @@ -409,13 +377,11 @@ impl WefaxDecoder { } fn transition_to_idle(&mut self) { - let default_lpm = self.config.lpm.unwrap_or(120); self.state = State::Idle; self.phasing = None; self.slicer = None; // image is kept until finalize_image is called or next reception starts. self.tone_detector.reset(); - self.idle_phasing = Some(PhasingDetector::new(default_lpm, INTERNAL_RATE)); self.signal_detect_count = 0; self.signal_detect_buf.clear(); }