diff --git a/static/js/modes/morse.js b/static/js/modes/morse.js index a28ed9e..a1a5817 100644 --- a/static/js/modes/morse.js +++ b/static/js/modes/morse.js @@ -7,7 +7,7 @@ var MorseMode = (function () { var SETTINGS_KEY = 'intercept.morse.settings.v3'; var STATUS_POLL_MS = 5000; - var LOCAL_STOP_TIMEOUT_MS = 2200; + var LOCAL_STOP_TIMEOUT_MS = 5000; var START_TIMEOUT_MS = 60000; var state = { @@ -87,7 +87,7 @@ var MorseMode = (function () { }); }).catch(function (err) { if (err && err.name === 'AbortError') { - throw new Error('Request timed out while waiting for decoder startup'); + throw new Error('Request timed out'); } throw err; }).finally(function () { diff --git a/utils/morse.py b/utils/morse.py index 3f910f7..b920ceb 100644 --- a/utils/morse.py +++ b/utils/morse.py @@ -165,12 +165,12 @@ class MorseDecoder: self._detector = GoertzelFilter(self._active_tone_freq, self.sample_rate, self._block_size) self._noise_detector_low = GoertzelFilter( - _clamp(self._active_tone_freq - max(60.0, self.bandwidth_hz * 0.5), 150.0, 2000.0), + _clamp(self._active_tone_freq - max(150.0, self.bandwidth_hz), 150.0, 2000.0), self.sample_rate, self._block_size, ) self._noise_detector_high = GoertzelFilter( - _clamp(self._active_tone_freq + max(60.0, self.bandwidth_hz * 0.5), 150.0, 2000.0), + _clamp(self._active_tone_freq + max(150.0, self.bandwidth_hz), 150.0, 2000.0), self.sample_rate, self._block_size, ) @@ -249,7 +249,7 @@ class MorseDecoder: def _rebuild_detectors(self) -> None: """Rebuild target/noise Goertzel filters after tone updates.""" self._detector = GoertzelFilter(self._active_tone_freq, self.sample_rate, self._block_size) - ref_offset = max(60.0, self.bandwidth_hz * 0.5) + ref_offset = max(150.0, self.bandwidth_hz) self._noise_detector_low = GoertzelFilter( _clamp(self._active_tone_freq - ref_offset, 150.0, 2000.0), self.sample_rate, @@ -457,8 +457,9 @@ class MorseDecoder: # gain-invariant — fixes stuck-ON tone when AGC amplifies # inter-element silence above the raw magnitude threshold. snr = level / max(noise_ref, 1e-6) - snr_on = self.threshold_multiplier * (1.0 + self._hysteresis) - snr_off = self.threshold_multiplier * (1.0 - self._hysteresis) + snr_mult = max(1.3, self.threshold_multiplier * 0.55) + snr_on = snr_mult * (1.0 + self._hysteresis) + snr_off = snr_mult * (1.0 - self._hysteresis) if self._tone_on: tone_detected = gate_ok and snr >= snr_off