From 5157dc573b825e603019b4d581d502a2668ce7ef Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Sun, 3 May 2026 14:39:13 +0200 Subject: [PATCH] Fix scan resume, AM/FM precheck and list refresh --- App/app/action.c | 3 ++ App/app/chFrScanner.c | 79 +++++++++++++++++++++++++++++++++++-------- App/app/main.c | 6 ++++ App/settings.c | 25 ++++++++++++++ App/settings.h | 1 + 5 files changed, 100 insertions(+), 14 deletions(-) diff --git a/App/app/action.c b/App/app/action.c index f441940d..1b925bf9 100644 --- a/App/app/action.c +++ b/App/app/action.c @@ -40,6 +40,7 @@ #include "misc.h" #include "settings.h" #include "ui/inputbox.h" +#include "ui/main.h" #include "ui/ui.h" #ifdef ENABLE_REGA #include "app/rega.h" @@ -237,6 +238,8 @@ void ACTION_Scan(bool bRestart) // channel mode. Keep scanning but toggle between scan lists RADIO_NextValidList(1); + UI_MAIN_NotifyScanProgressDataChanged(); + gUpdateStatus = true; #ifdef ENABLE_FEAT_F4HWN_RESUME_STATE SETTINGS_WriteCurrentState(); diff --git a/App/app/chFrScanner.c b/App/app/chFrScanner.c index 7efd2c9b..3c755fc1 100644 --- a/App/app/chFrScanner.c +++ b/App/app/chFrScanner.c @@ -1,12 +1,14 @@ #include "app/app.h" #include "app/chFrScanner.h" +#include "audio.h" #ifdef ENABLE_FEAT_F4HWN_SCAN_FASTER #include "driver/systick.h" #endif #include "functions.h" #include "misc.h" #include "settings.h" +#include "ui/main.h" //#include "debugging.h" int8_t gScanStateDir; @@ -40,6 +42,21 @@ uint8_t initialCROSS_BAND_RX_TX; static void NextFreqChannel(void); static void NextMemChannel(void); +static void CHFRSCANNER_AbortActiveReception(void) +{ + if (!FUNCTION_IsRx()) + return; + + AUDIO_AudioPathOff(); + gEnableSpeaker = false; + gMonitor = false; + gRxReceptionMode = RX_MODE_NONE; + gScanPauseMode = false; + + FUNCTION_Init(); + FUNCTION_Select(FUNCTION_FOREGROUND); +} + #ifdef ENABLE_FEAT_F4HWN_SCAN_FASTER #define SCAN_FAST_PRECHECK_STEPS 6 #define SCAN_FAST_RSSI_MARGIN 16 @@ -136,6 +153,34 @@ static bool ScanFastIsCandidate(uint16_t rssi) return false; } + +static void ScanFastApplyChannelShape(ModulationMode_t modulation) +{ + const bool modulationChanged = gRxVfo->Modulation != modulation; + const bool bandwidthChanged = gRxVfo->CHANNEL_BANDWIDTH != BANDWIDTH_WIDE; + + if (!modulationChanged && !bandwidthChanged) + return; + + gRxVfo->Modulation = modulation; + gRxVfo->CHANNEL_BANDWIDTH = BANDWIDTH_WIDE; + + if (modulationChanged) + RADIO_SetModulation(modulation); + + if (modulation == MODULATION_AM) + { + BK4819_SetFilterBandwidth(RADIO_GetAMFilterBandwidth(gRxVfo), true); + } + else + { +#ifdef ENABLE_AM_FIX + BK4819_SetFilterBandwidth(BK4819_FILTER_BW_WIDE, true); +#else + BK4819_SetFilterBandwidth(BK4819_FILTER_BW_WIDE, false); +#endif + } +} #endif #if defined(ENABLE_FEAT_F4HWN_SCAN_FASTER) && defined(ENABLE_SCAN_RANGES) @@ -240,19 +285,23 @@ static scan_fast_result_t ScanRangeFastPrecheck(void) #ifdef ENABLE_FEAT_F4HWN_SCAN_FASTER static bool MemChannelFastPrecheck(uint16_t channel) { + uint32_t frequency; + ModulationMode_t modulation; + if (gRxVfo->SquelchOpenRSSIThresh == 0) { scanFastLastFullTuneCandidate = false; return true; } - const uint32_t frequency = SETTINGS_FetchChannelFrequency(channel); - if (frequency == 0 || frequency == 0xFFFFFFFF) + if (!SETTINGS_FetchChannelScanInfo(channel, &frequency, &modulation)) { scanFastLastFullTuneCandidate = false; return true; } + ScanFastApplyChannelShape(modulation); + // Mute AF DAC for the same reason as in ScanRangeFastPrecheck(). scanFastReg30 = BK4819_ReadRegister(BK4819_REG_30) & ~BK4819_REG_30_MASK_ENABLE_AF_DAC; ScanFastTune(frequency); @@ -308,6 +357,7 @@ void CHFRSCANNER_Start(const bool storeBackupSettings, const int8_t scan_directi } RADIO_SelectVfos(); + CHFRSCANNER_AbortActiveReception(); gNextMrChannel = gRxVfo->CHANNEL_SAVE; currentScanList = SCAN_NEXT_CHAN_SCANLIST1; @@ -321,6 +371,8 @@ void CHFRSCANNER_Start(const bool storeBackupSettings, const int8_t scan_directi if(!RADIO_CheckValidList(gEeprom.SCAN_LIST_DEFAULT)) { RADIO_NextValidList(1); + UI_MAIN_NotifyScanProgressDataChanged(); + gUpdateStatus = true; } // channel mode @@ -351,18 +403,6 @@ void CHFRSCANNER_Start(const bool storeBackupSettings, const int8_t scan_directi void CHFRSCANNER_ManualResume(const int8_t scan_direction) { - if (FUNCTION_IsRx()) - { - // Abort the current reception before a user-forced scan step, otherwise - // HandleReceive() can re-apply the carrier resume delay on the next tick. - gMonitor = false; - gRxReceptionMode = RX_MODE_NONE; - gScanPauseMode = false; - - FUNCTION_Init(); - FUNCTION_Select(FUNCTION_FOREGROUND); - } - CHFRSCANNER_Start(false, scan_direction); gScanPauseDelayIn_10ms = 1; @@ -673,6 +713,7 @@ static void NextMemChannel(void) if (!enabled || chan == 0xFFFF) { + const uint16_t searchStart = gNextMrChannel; chan = RADIO_FindNextChannel(gNextMrChannel + gScanStateDir, gScanStateDir, true, gEeprom.SCAN_LIST_DEFAULT); if (chan == 0xFFFF) { // no valid channel found -> wrapping back to the first channel @@ -684,6 +725,16 @@ static void NextMemChannel(void) ScanFastResetState(); #endif } +#ifdef ENABLE_FEAT_F4HWN_SCAN_FASTER + else if ((gScanStateDir > 0 && chan < searchStart) || + (gScanStateDir < 0 && chan > searchStart)) + { + // RADIO_FindNextChannel() wraps internally, so 0xFFFF is not + // returned on a normal full-sweep wrap. Detect that transition + // here and restart the RSSI floor learning for the new pass. + ScanFastResetState(); + } +#endif gNextMrChannel = chan; diff --git a/App/app/main.c b/App/app/main.c index 1708a477..525112d9 100644 --- a/App/app/main.c +++ b/App/app/main.c @@ -300,6 +300,8 @@ static void processFKeyFunction(const KEY_Code_t Key, const bool beep) if (gScanStateDir != SCAN_OFF) { RADIO_NextValidList(isKeyUp ? 1 : -1); + UI_MAIN_NotifyScanProgressDataChanged(); + gUpdateStatus = true; } else { // Adjust squelch: UP increments, DOWN decrements if (gSquelchLevelOriginal == 10) @@ -482,6 +484,8 @@ static void MAIN_Key_DIGITS(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld) if (value == 0) { gEeprom.SCAN_LIST_DEFAULT = MR_CHANNELS_LIST + 1; + UI_MAIN_NotifyScanProgressDataChanged(); + gUpdateStatus = true; #ifdef ENABLE_FEAT_F4HWN_RESUME_STATE SETTINGS_WriteCurrentState(); #endif @@ -500,6 +504,8 @@ static void MAIN_Key_DIGITS(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld) gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; RADIO_NextValidList(1); } + UI_MAIN_NotifyScanProgressDataChanged(); + gUpdateStatus = true; #ifdef ENABLE_FEAT_F4HWN_RESUME_STATE SETTINGS_WriteCurrentState(); diff --git a/App/settings.c b/App/settings.c index 66eb4688..ecbf9e9e 100644 --- a/App/settings.c +++ b/App/settings.c @@ -579,6 +579,31 @@ uint32_t SETTINGS_FetchChannelFrequency(const uint16_t channel) return info.frequency; } +bool SETTINGS_FetchChannelScanInfo(const uint16_t channel, uint32_t *frequency, ModulationMode_t *modulation) +{ + struct + { + uint32_t frequency; + uint32_t offset; + uint8_t settings[4]; + } __attribute__((packed)) info; + + PY25Q16_ReadBuffer(channel * 16, &info, sizeof(info)); + + if (frequency) + *frequency = info.frequency; + + if (modulation) + { + uint8_t mode = info.settings[3] >> 4; + if (mode >= MODULATION_UKNOWN) + mode = MODULATION_FM; + *modulation = (ModulationMode_t)mode; + } + + return info.frequency != 0 && info.frequency != 0xFFFFFFFF; +} + void SETTINGS_FetchChannelName(char *s, const uint16_t channel) { if (s == NULL) diff --git a/App/settings.h b/App/settings.h index 77e22463..5ea7efcb 100644 --- a/App/settings.h +++ b/App/settings.h @@ -310,6 +310,7 @@ extern EEPROM_Config_t gEeprom; void SETTINGS_InitEEPROM(void); void SETTINGS_LoadCalibration(void); uint32_t SETTINGS_FetchChannelFrequency(const uint16_t channel); +bool SETTINGS_FetchChannelScanInfo(const uint16_t channel, uint32_t *frequency, ModulationMode_t *modulation); void SETTINGS_FetchChannelName(char *s, const uint16_t channel); void SETTINGS_FactoryReset(bool bIsAll); #ifdef ENABLE_FMRADIO