#include "app/app.h" #include "app/chFrScanner.h" #include "functions.h" #include "misc.h" #include "settings.h" int8_t gScanStateDir; bool gScanKeepResult; bool gScanPauseMode; #ifdef ENABLE_SCAN_RANGES uint32_t gScanRangeStart; #endif typedef enum { SCAN_NEXT_CHAN_SCANLIST1 = 0, SCAN_NEXT_CHAN_SCANLIST2, SCAN_NEXT_CHAN_DUAL_WATCH, SCAN_NEXT_CHAN_MR, SCAN_NEXT_NUM } scan_next_chan_t; scan_next_chan_t currentScanList; uint32_t initialFrqOrChan; uint8_t initialCROSS_BAND_RX_TX; uint32_t lastFoundFrqOrChan; static void NextFreqChannel(void); static void NextMemChannel(void); void CHFRSCANNER_Start(const bool storeBackupSettings, const int8_t scan_direction) { if (storeBackupSettings) { initialCROSS_BAND_RX_TX = gEeprom.CROSS_BAND_RX_TX; gEeprom.CROSS_BAND_RX_TX = CROSS_BAND_OFF; gScanKeepResult = false; } RADIO_SelectVfos(); gNextMrChannel = gRxVfo->CHANNEL_SAVE; currentScanList = SCAN_NEXT_CHAN_SCANLIST1; gScanStateDir = scan_direction; if (IS_MR_CHANNEL(gNextMrChannel)) { // channel mode if (storeBackupSettings) { initialFrqOrChan = gRxVfo->CHANNEL_SAVE; lastFoundFrqOrChan = initialFrqOrChan; } NextMemChannel(); } else { // frequency mode if (storeBackupSettings) { initialFrqOrChan = gRxVfo->freq_config_RX.Frequency; lastFoundFrqOrChan = initialFrqOrChan; } NextFreqChannel(); } gScanPauseDelayIn_10ms = scan_pause_delay_in_2_10ms; gScheduleScanListen = false; gRxReceptionMode = RX_MODE_NONE; gScanPauseMode = false; } void CHFRSCANNER_ContinueScanning(void) { if (IS_FREQ_CHANNEL(gNextMrChannel)) { if (gCurrentFunction == FUNCTION_INCOMING) APP_StartListening(gMonitor ? FUNCTION_MONITOR : FUNCTION_RECEIVE); else NextFreqChannel(); // switch to next frequency } else { if (gCurrentCodeType == CODE_TYPE_OFF && gCurrentFunction == FUNCTION_INCOMING) APP_StartListening(gMonitor ? FUNCTION_MONITOR : FUNCTION_RECEIVE); else NextMemChannel(); // switch to next channel } gScanPauseMode = false; gRxReceptionMode = RX_MODE_NONE; gScheduleScanListen = false; } void CHFRSCANNER_Found(void) { switch (gEeprom.SCAN_RESUME_MODE) { case SCAN_RESUME_TO: if (!gScanPauseMode) { gScanPauseDelayIn_10ms = scan_pause_delay_in_1_10ms; gScheduleScanListen = false; gScanPauseMode = true; } break; case SCAN_RESUME_CO: case SCAN_RESUME_SE: gScanPauseDelayIn_10ms = 0; gScheduleScanListen = false; break; } if (IS_MR_CHANNEL(gRxVfo->CHANNEL_SAVE)) { //memory scan lastFoundFrqOrChan = gRxVfo->CHANNEL_SAVE; } else { // frequency scan lastFoundFrqOrChan = gRxVfo->freq_config_RX.Frequency; } gScanKeepResult = true; } void CHFRSCANNER_Stop(void) { if(initialCROSS_BAND_RX_TX != CROSS_BAND_OFF) { gEeprom.CROSS_BAND_RX_TX = initialCROSS_BAND_RX_TX; initialCROSS_BAND_RX_TX = CROSS_BAND_OFF; } gScanStateDir = SCAN_OFF; const uint32_t chFr = gScanKeepResult ? lastFoundFrqOrChan : initialFrqOrChan; const bool channelChanged = chFr != initialFrqOrChan; if (IS_MR_CHANNEL(gNextMrChannel)) { gEeprom.MrChannel[gEeprom.RX_VFO] = chFr; gEeprom.ScreenChannel[gEeprom.RX_VFO] = chFr; RADIO_ConfigureChannel(gEeprom.RX_VFO, VFO_CONFIGURE_RELOAD); if(channelChanged) { SETTINGS_SaveVfoIndices(); gUpdateStatus = true; } } else { gRxVfo->freq_config_RX.Frequency = chFr; RADIO_ApplyOffset(gRxVfo); RADIO_ConfigureSquelchAndOutputPower(gRxVfo); if(channelChanged) { SETTINGS_SaveChannel(gRxVfo->CHANNEL_SAVE, gEeprom.RX_VFO, gRxVfo, 1); } } RADIO_SetupRegisters(true); gUpdateDisplay = true; } static void NextFreqChannel(void) { #ifdef ENABLE_SCAN_RANGES if(gScanRangeStart) { uint32_t start = gScanRangeStart; uint32_t end = gEeprom.VfoInfo[(gEeprom.TX_VFO+1)%2].freq_config_RX.Frequency; gRxVfo->freq_config_RX.Frequency = APP_SetFreqByStepAndLimits(gRxVfo, gScanStateDir, MIN(start, end), MAX(start, end)); } else #endif gRxVfo->freq_config_RX.Frequency = APP_SetFrequencyByStep(gRxVfo, gScanStateDir); RADIO_ApplyOffset(gRxVfo); RADIO_ConfigureSquelchAndOutputPower(gRxVfo); RADIO_SetupRegisters(true); #ifdef ENABLE_FASTER_CHANNEL_SCAN gScanPauseDelayIn_10ms = 9; // 90ms #else gScanPauseDelayIn_10ms = scan_pause_delay_in_6_10ms; #endif gUpdateDisplay = true; } static void NextMemChannel(void) { static unsigned int prev_mr_chan = 0; const bool enabled = (gEeprom.SCAN_LIST_DEFAULT < 2) ? gEeprom.SCAN_LIST_ENABLED[gEeprom.SCAN_LIST_DEFAULT] : true; const int chan1 = (gEeprom.SCAN_LIST_DEFAULT < 2) ? gEeprom.SCANLIST_PRIORITY_CH1[gEeprom.SCAN_LIST_DEFAULT] : -1; const int chan2 = (gEeprom.SCAN_LIST_DEFAULT < 2) ? gEeprom.SCANLIST_PRIORITY_CH2[gEeprom.SCAN_LIST_DEFAULT] : -1; const unsigned int prev_chan = gNextMrChannel; unsigned int chan = 0; if (enabled) { switch (currentScanList) { case SCAN_NEXT_CHAN_SCANLIST1: prev_mr_chan = gNextMrChannel; if (chan1 >= 0) { if (RADIO_CheckValidChannel(chan1, false, 0)) { currentScanList = SCAN_NEXT_CHAN_SCANLIST1; gNextMrChannel = chan1; break; } } [[fallthrough]]; case SCAN_NEXT_CHAN_SCANLIST2: if (chan2 >= 0) { if (RADIO_CheckValidChannel(chan2, false, 0)) { currentScanList = SCAN_NEXT_CHAN_SCANLIST2; gNextMrChannel = chan2; break; } } [[fallthrough]]; // this bit doesn't yet work if the other VFO is a frequency case SCAN_NEXT_CHAN_DUAL_WATCH: // dual watch is enabled - include the other VFO in the scan // if (gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) // { // chan = (gEeprom.RX_VFO + 1) & 1u; // chan = gEeprom.ScreenChannel[chan]; // if (IS_MR_CHANNEL(chan)) // { // currentScanList = SCAN_NEXT_CHAN_DUAL_WATCH; // gNextMrChannel = chan; // break; // } // } default: case SCAN_NEXT_CHAN_MR: currentScanList = SCAN_NEXT_CHAN_MR; gNextMrChannel = prev_mr_chan; chan = 0xff; break; } } if (!enabled || chan == 0xff) { chan = RADIO_FindNextChannel(gNextMrChannel + gScanStateDir, gScanStateDir, (gEeprom.SCAN_LIST_DEFAULT < 2) ? true : false, gEeprom.SCAN_LIST_DEFAULT); if (chan == 0xFF) { // no valid channel found chan = MR_CHANNEL_FIRST; } gNextMrChannel = chan; } if (gNextMrChannel != prev_chan) { gEeprom.MrChannel[ gEeprom.RX_VFO] = gNextMrChannel; gEeprom.ScreenChannel[gEeprom.RX_VFO] = gNextMrChannel; RADIO_ConfigureChannel(gEeprom.RX_VFO, VFO_CONFIGURE_RELOAD); RADIO_SetupRegisters(true); gUpdateDisplay = true; } #ifdef ENABLE_FASTER_CHANNEL_SCAN gScanPauseDelayIn_10ms = 9; // 90ms .. <= ~60ms it misses signals (squelch response and/or PLL lock time) ? #else gScanPauseDelayIn_10ms = scan_pause_delay_in_3_10ms; #endif if (enabled) if (++currentScanList >= SCAN_NEXT_NUM) currentScanList = SCAN_NEXT_CHAN_SCANLIST1; // back round we go }