mirror of
https://github.com/armel/uv-k1-k5v3-firmware-custom.git
synced 2026-10-02 03:15:37 +00:00
Improve fast scan detection and display metadata
This commit is contained in:
1 parent
ec4ea28325
commit
3e6b169b7b
6 files changed
+264
-21
No files matched your search
+133
-16
@@ -1,4 +1,6 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "app/app.h"
|
||||
#include "app/chFrScanner.h"
|
||||
#include "audio.h"
|
||||
@@ -61,6 +63,8 @@ static void CHFRSCANNER_AbortActiveReception(void)
|
||||
#define SCAN_FAST_PRECHECK_STEPS 6
|
||||
#define SCAN_FAST_RSSI_MARGIN 16
|
||||
#define SCAN_FAST_SQUELCH_MARGIN 8
|
||||
#define SCAN_FAST_WEAK_MARGIN 8
|
||||
#define SCAN_FAST_RECHECK_DELAY_US 350
|
||||
#define SCAN_FAST_FINE_STEP_LIMIT 250
|
||||
#define SCAN_FAST_FINE_REFINE_SPAN 1000
|
||||
#define SCAN_FAST_FINE_REFINE_MAX 80
|
||||
@@ -86,6 +90,8 @@ static uint16_t scanFastReg30;
|
||||
static uint16_t scanFastNoiseFloor = SCAN_FAST_RSSI_MAX;
|
||||
static uint32_t scanFastPrevFrequency;
|
||||
static bool scanFastLastFullTuneCandidate;
|
||||
static VFO_Info_t scanFastDisplayVfo;
|
||||
static bool scanFastDisplayVfoValid;
|
||||
|
||||
static void ScanFastResetState(void)
|
||||
{
|
||||
@@ -96,6 +102,7 @@ static void ScanFastResetState(void)
|
||||
scanFastNoiseFloor = SCAN_FAST_RSSI_MAX;
|
||||
scanFastPrevFrequency = 0;
|
||||
scanFastLastFullTuneCandidate = false;
|
||||
scanFastDisplayVfoValid = false;
|
||||
}
|
||||
|
||||
static void ScanFastResetNoiseFloor(void)
|
||||
@@ -131,25 +138,133 @@ static void ScanFastTune(uint32_t frequency)
|
||||
BK4819_WriteRegister(BK4819_REG_30, scanFastReg30);
|
||||
}
|
||||
|
||||
static bool ScanFastIsCandidate(uint16_t rssi)
|
||||
const VFO_Info_t *CHFRSCANNER_GetScanDisplayVfo(void)
|
||||
{
|
||||
if (scanFastNoiseFloor == SCAN_FAST_RSSI_MAX)
|
||||
if (!scanFastDisplayVfoValid || gScanStateDir == SCAN_OFF || FUNCTION_IsRx())
|
||||
return NULL;
|
||||
|
||||
return &scanFastDisplayVfo;
|
||||
}
|
||||
|
||||
static bool ScanFastUpdateDisplayVfo(uint16_t channel, uint32_t *frequency, ModulationMode_t *modulation)
|
||||
{
|
||||
ChannelScanDisplayInfo_t info;
|
||||
|
||||
if (!SETTINGS_FetchChannelScanDisplayInfo(channel, &info))
|
||||
{
|
||||
scanFastNoiseFloor = rssi;
|
||||
scanFastDisplayVfoValid = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
const uint16_t noiseTrigger =
|
||||
(scanFastNoiseFloor > SCAN_FAST_RSSI_MAX - SCAN_FAST_RSSI_MARGIN)
|
||||
? SCAN_FAST_RSSI_MAX
|
||||
: (uint16_t)(scanFastNoiseFloor + SCAN_FAST_RSSI_MARGIN);
|
||||
const uint16_t squelchTrigger =
|
||||
(gRxVfo->SquelchOpenRSSIThresh > SCAN_FAST_SQUELCH_MARGIN)
|
||||
? (uint16_t)(gRxVfo->SquelchOpenRSSIThresh - SCAN_FAST_SQUELCH_MARGIN)
|
||||
: 0;
|
||||
scanFastDisplayVfo = gEeprom.VfoInfo[gEeprom.RX_VFO];
|
||||
|
||||
scanFastDisplayVfo.CHANNEL_SAVE = channel;
|
||||
scanFastDisplayVfo.freq_config_RX = info.rx;
|
||||
scanFastDisplayVfo.freq_config_TX = info.tx;
|
||||
scanFastDisplayVfo.TX_OFFSET_FREQUENCY = info.offset;
|
||||
scanFastDisplayVfo.StepFrequency = info.stepFrequency;
|
||||
scanFastDisplayVfo.STEP_SETTING = info.stepSetting;
|
||||
scanFastDisplayVfo.Modulation = info.modulation;
|
||||
scanFastDisplayVfo.TX_OFFSET_FREQUENCY_DIRECTION = info.txOffsetFrequencyDirection;
|
||||
scanFastDisplayVfo.OUTPUT_POWER = info.outputPower;
|
||||
scanFastDisplayVfo.FrequencyReverse = info.frequencyReverse;
|
||||
scanFastDisplayVfo.CHANNEL_BANDWIDTH = info.channelBandwidth;
|
||||
scanFastDisplayVfo.BUSY_CHANNEL_LOCK = info.busyChannelLock;
|
||||
scanFastDisplayVfo.TX_LOCK = info.txLock;
|
||||
#ifdef ENABLE_DTMF_CALLING
|
||||
scanFastDisplayVfo.DTMF_DECODING_ENABLE = info.dtmfDecodingEnable;
|
||||
#endif
|
||||
scanFastDisplayVfo.DTMF_PTT_ID_TX_MODE = info.dtmfPttIdTxMode;
|
||||
|
||||
if (!scanFastDisplayVfo.FrequencyReverse)
|
||||
{
|
||||
scanFastDisplayVfo.pRX = &scanFastDisplayVfo.freq_config_RX;
|
||||
scanFastDisplayVfo.pTX = &scanFastDisplayVfo.freq_config_TX;
|
||||
}
|
||||
else
|
||||
{
|
||||
scanFastDisplayVfo.pRX = &scanFastDisplayVfo.freq_config_TX;
|
||||
scanFastDisplayVfo.pTX = &scanFastDisplayVfo.freq_config_RX;
|
||||
}
|
||||
|
||||
scanFastDisplayVfoValid = true;
|
||||
|
||||
if (frequency)
|
||||
*frequency = info.rx.Frequency;
|
||||
if (modulation)
|
||||
*modulation = info.modulation;
|
||||
|
||||
if (rssi >= noiseTrigger && rssi >= squelchTrigger)
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint16_t ScanFastSaturatingAdd(uint16_t value, uint16_t add)
|
||||
{
|
||||
return (value > SCAN_FAST_RSSI_MAX - add) ? SCAN_FAST_RSSI_MAX : (uint16_t)(value + add);
|
||||
}
|
||||
|
||||
static uint16_t ScanFastSaturatingSub(uint16_t value, uint16_t sub)
|
||||
{
|
||||
return (value > sub) ? (uint16_t)(value - sub) : 0;
|
||||
}
|
||||
|
||||
static uint16_t ScanFastGetNoiseTrigger(void)
|
||||
{
|
||||
return ScanFastSaturatingAdd(scanFastNoiseFloor, SCAN_FAST_RSSI_MARGIN);
|
||||
}
|
||||
|
||||
static uint16_t ScanFastGetSquelchTrigger(void)
|
||||
{
|
||||
return ScanFastSaturatingSub(gRxVfo->SquelchOpenRSSIThresh, SCAN_FAST_SQUELCH_MARGIN);
|
||||
}
|
||||
|
||||
static bool ScanFastIsNearCandidate(uint16_t rssi)
|
||||
{
|
||||
const uint16_t rssiWithMargin = ScanFastSaturatingAdd(rssi, SCAN_FAST_WEAK_MARGIN);
|
||||
const uint16_t squelchTrigger = ScanFastGetSquelchTrigger();
|
||||
|
||||
if (scanFastNoiseFloor == SCAN_FAST_RSSI_MAX)
|
||||
return gRxVfo->SquelchOpenRSSIThresh > 0 &&
|
||||
rssiWithMargin >= gRxVfo->SquelchOpenRSSIThresh;
|
||||
|
||||
return rssiWithMargin >= ScanFastGetNoiseTrigger() &&
|
||||
rssiWithMargin >= squelchTrigger;
|
||||
}
|
||||
|
||||
static uint16_t ScanFastReadCandidateRssi(void)
|
||||
{
|
||||
uint16_t rssi = ScanFastReadRssi();
|
||||
|
||||
if (ScanFastIsNearCandidate(rssi))
|
||||
{
|
||||
SYSTICK_DelayUs(SCAN_FAST_RECHECK_DELAY_US);
|
||||
|
||||
const uint16_t retryRssi = ScanFastReadRssi();
|
||||
if (retryRssi > rssi)
|
||||
rssi = retryRssi;
|
||||
}
|
||||
|
||||
return rssi;
|
||||
}
|
||||
|
||||
static bool ScanFastIsCandidate(uint16_t rssi)
|
||||
{
|
||||
const uint16_t squelchTrigger = ScanFastGetSquelchTrigger();
|
||||
|
||||
if (scanFastNoiseFloor == SCAN_FAST_RSSI_MAX)
|
||||
{
|
||||
scanFastNoiseFloor = rssi;
|
||||
return gRxVfo->SquelchOpenRSSIThresh > 0 &&
|
||||
rssi >= gRxVfo->SquelchOpenRSSIThresh;
|
||||
}
|
||||
|
||||
const uint16_t noiseTrigger = ScanFastGetNoiseTrigger();
|
||||
const uint16_t rssiWithMargin = ScanFastSaturatingAdd(rssi, SCAN_FAST_WEAK_MARGIN);
|
||||
|
||||
if ((rssi >= noiseTrigger && rssi >= squelchTrigger) ||
|
||||
(rssiWithMargin >= noiseTrigger && rssiWithMargin >= squelchTrigger))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (rssi < scanFastNoiseFloor)
|
||||
scanFastNoiseFloor = rssi;
|
||||
@@ -284,7 +399,7 @@ static scan_fast_result_t ScanRangeFastPrecheck(void)
|
||||
|
||||
ScanFastTune(freq);
|
||||
|
||||
const uint16_t rssi = ScanFastReadRssi();
|
||||
const uint16_t rssi = ScanFastReadCandidateRssi();
|
||||
if (ScanFastIsCandidate(rssi))
|
||||
{
|
||||
ScanRangeFastRefineCandidate(rssi);
|
||||
@@ -308,7 +423,7 @@ static bool MemChannelFastPrecheck(uint16_t channel)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!SETTINGS_FetchChannelScanInfo(channel, &frequency, &modulation))
|
||||
if (!ScanFastUpdateDisplayVfo(channel, &frequency, &modulation))
|
||||
{
|
||||
scanFastLastFullTuneCandidate = false;
|
||||
return true;
|
||||
@@ -320,7 +435,7 @@ static bool MemChannelFastPrecheck(uint16_t channel)
|
||||
scanFastReg30 = BK4819_ReadRegister(BK4819_REG_30) & ~BK4819_REG_30_MASK_ENABLE_AF_DAC;
|
||||
ScanFastTune(frequency);
|
||||
|
||||
if (ScanFastIsCandidate(ScanFastReadRssi()))
|
||||
if (ScanFastIsCandidate(ScanFastReadCandidateRssi()))
|
||||
{
|
||||
scanFastLastFullTuneCandidate = true;
|
||||
return true; // signal detected: let the full tune path follow
|
||||
@@ -419,7 +534,9 @@ void CHFRSCANNER_ManualResume(const int8_t scan_direction)
|
||||
{
|
||||
CHFRSCANNER_Start(false, scan_direction);
|
||||
|
||||
gScanPauseDelayIn_10ms = 1;
|
||||
gScanPauseDelayIn_10ms = (gRxVfo->SquelchOpenRSSIThresh == 0)
|
||||
? scan_pause_delay_in_3_10ms
|
||||
: 1;
|
||||
gScheduleScanListen = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "radio.h"
|
||||
|
||||
// scan direction, if not equal SCAN_OFF indicates
|
||||
// that we are in a process of scanning channels/frequencies
|
||||
extern int8_t gScanStateDir;
|
||||
@@ -20,6 +22,9 @@ void CHFRSCANNER_Stop(void);
|
||||
void CHFRSCANNER_Start(const bool storeBackupSettings, const int8_t scan_direction);
|
||||
void CHFRSCANNER_ManualResume(const int8_t scan_direction);
|
||||
void CHFRSCANNER_ContinueScanning(void);
|
||||
#ifdef ENABLE_FEAT_F4HWN_SCAN_FASTER
|
||||
const VFO_Info_t *CHFRSCANNER_GetScanDisplayVfo(void);
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_FEAT_F4HWN_RESUME_STATE) || defined(ENABLE_SCAN_RANGES)
|
||||
void CHFRSCANNER_ScanRange(void);
|
||||
|
||||
@@ -156,6 +156,7 @@ uint16_t RADIO_FindNextChannel(uint16_t ChNum, int8_t Direction, bool bCheckScan
|
||||
void RADIO_InitInfo(VFO_Info_t *pInfo, const uint16_t ChannelSave, const uint32_t Frequency);
|
||||
void RADIO_ConfigureChannel(const unsigned int VFO, const unsigned int configure);
|
||||
void RADIO_ConfigureSquelchAndOutputPower(VFO_Info_t *pInfo);
|
||||
void RADIO_ValidateAndSetCode(FREQ_Config_t *pFreq_Config, uint8_t tmp);
|
||||
void RADIO_ApplyOffset(VFO_Info_t *pInfo);
|
||||
void RADIO_SelectVfos(void);
|
||||
void RADIO_SetupRegisters(bool switchToForeground);
|
||||
|
||||
@@ -604,6 +604,99 @@ bool SETTINGS_FetchChannelScanInfo(const uint16_t channel, uint32_t *frequency,
|
||||
return info.frequency != 0 && info.frequency != 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
bool SETTINGS_FetchChannelScanDisplayInfo(const uint16_t channel, ChannelScanDisplayInfo_t *info)
|
||||
{
|
||||
if (info == NULL)
|
||||
return false;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t frequency;
|
||||
uint32_t offset;
|
||||
uint8_t data[8];
|
||||
} __attribute__((packed)) raw;
|
||||
|
||||
PY25Q16_ReadBuffer(channel * 16, &raw, sizeof(raw));
|
||||
|
||||
if (raw.frequency == 0 || raw.frequency == 0xFFFFFFFF)
|
||||
return false;
|
||||
|
||||
memset(info, 0, sizeof(*info));
|
||||
|
||||
info->rx.Frequency = raw.frequency;
|
||||
info->tx.Frequency = raw.frequency;
|
||||
info->offset = (raw.offset >= _1GHz_in_KHz) ? (_1GHz_in_KHz / 100) : raw.offset;
|
||||
|
||||
info->rx.CodeType = (raw.data[2] >> 0) & 0x0F;
|
||||
info->tx.CodeType = (raw.data[2] >> 4) & 0x0F;
|
||||
RADIO_ValidateAndSetCode(&info->rx, raw.data[0]);
|
||||
RADIO_ValidateAndSetCode(&info->tx, raw.data[1]);
|
||||
|
||||
uint8_t tmp = raw.data[3] & 0x0F;
|
||||
if (tmp > TX_OFFSET_FREQUENCY_DIRECTION_SUB)
|
||||
tmp = TX_OFFSET_FREQUENCY_DIRECTION_OFF;
|
||||
info->txOffsetFrequencyDirection = tmp;
|
||||
|
||||
tmp = raw.data[3] >> 4;
|
||||
if (tmp >= MODULATION_UKNOWN)
|
||||
tmp = MODULATION_FM;
|
||||
info->modulation = (ModulationMode_t)tmp;
|
||||
|
||||
tmp = raw.data[6];
|
||||
if (tmp >= STEP_N_ELEM)
|
||||
tmp = STEP_12_5kHz;
|
||||
info->stepSetting = (STEP_Setting_t)tmp;
|
||||
info->stepFrequency = gStepFrequencyTable[tmp];
|
||||
|
||||
if (raw.data[4] == 0xFF)
|
||||
{
|
||||
info->frequencyReverse = false;
|
||||
info->channelBandwidth = BANDWIDTH_WIDE;
|
||||
info->outputPower = OUTPUT_POWER_LOW1;
|
||||
info->busyChannelLock = false;
|
||||
info->txLock = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint8_t d4 = raw.data[4];
|
||||
info->frequencyReverse = !!((d4 >> 0) & 1u);
|
||||
info->channelBandwidth = !!((d4 >> 1) & 1u);
|
||||
info->outputPower = ((d4 >> 2) & 7u);
|
||||
info->busyChannelLock = !!((d4 >> 5) & 1u);
|
||||
info->txLock = !!((d4 >> 6) & 1u);
|
||||
}
|
||||
|
||||
switch (info->txOffsetFrequencyDirection)
|
||||
{
|
||||
case TX_OFFSET_FREQUENCY_DIRECTION_ADD:
|
||||
info->tx.Frequency = raw.frequency + info->offset;
|
||||
break;
|
||||
case TX_OFFSET_FREQUENCY_DIRECTION_SUB:
|
||||
info->tx.Frequency = raw.frequency - info->offset;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (raw.data[5] == 0xFF)
|
||||
{
|
||||
#ifdef ENABLE_DTMF_CALLING
|
||||
info->dtmfDecodingEnable = false;
|
||||
#endif
|
||||
info->dtmfPttIdTxMode = PTT_ID_OFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef ENABLE_DTMF_CALLING
|
||||
info->dtmfDecodingEnable = (raw.data[5] >> 0) & 1u;
|
||||
#endif
|
||||
const uint8_t pttId = (raw.data[5] >> 1) & 7u;
|
||||
info->dtmfPttIdTxMode = pttId < ARRAY_SIZE(gSubMenu_PTT_ID) ? pttId : PTT_ID_OFF;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SETTINGS_FetchChannelName(char *s, const uint16_t channel)
|
||||
{
|
||||
if (s == NULL)
|
||||
|
||||
@@ -307,10 +307,30 @@ typedef struct {
|
||||
|
||||
extern EEPROM_Config_t gEeprom;
|
||||
|
||||
typedef struct {
|
||||
FREQ_Config_t rx;
|
||||
FREQ_Config_t tx;
|
||||
uint32_t offset;
|
||||
uint16_t stepFrequency;
|
||||
STEP_Setting_t stepSetting;
|
||||
ModulationMode_t modulation;
|
||||
uint8_t txOffsetFrequencyDirection;
|
||||
uint8_t outputPower;
|
||||
bool frequencyReverse;
|
||||
uint8_t channelBandwidth;
|
||||
uint8_t busyChannelLock;
|
||||
uint8_t txLock;
|
||||
#ifdef ENABLE_DTMF_CALLING
|
||||
uint8_t dtmfDecodingEnable;
|
||||
#endif
|
||||
PTT_ID_t dtmfPttIdTxMode;
|
||||
} ChannelScanDisplayInfo_t;
|
||||
|
||||
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);
|
||||
bool SETTINGS_FetchChannelScanDisplayInfo(const uint16_t channel, ChannelScanDisplayInfo_t *info);
|
||||
void SETTINGS_FetchChannelName(char *s, const uint16_t channel);
|
||||
void SETTINGS_FactoryReset(bool bIsAll);
|
||||
#ifdef ENABLE_FMRADIO
|
||||
|
||||
+12
-5
@@ -1748,6 +1748,11 @@ void UI_DisplayMain(void)
|
||||
|
||||
String[0] = '\0';
|
||||
const VFO_Info_t *vfoInfo = &gEeprom.VfoInfo[vfo_num];
|
||||
#ifdef ENABLE_FEAT_F4HWN_SCAN_FASTER
|
||||
const VFO_Info_t *scanDisplayVfo = CHFRSCANNER_GetScanDisplayVfo();
|
||||
if (vfo_num == gEeprom.RX_VFO && scanDisplayVfo != NULL)
|
||||
vfoInfo = scanDisplayVfo;
|
||||
#endif
|
||||
|
||||
// show the modulation symbol
|
||||
const char * s = "";
|
||||
@@ -1937,10 +1942,12 @@ void UI_DisplayMain(void)
|
||||
#endif
|
||||
|
||||
#if ENABLE_FEAT_F4HWN
|
||||
const uint8_t displayBandwidth = vfoInfo->CHANNEL_BANDWIDTH;
|
||||
|
||||
#ifdef ENABLE_FEAT_F4HWN_NARROWER
|
||||
bool narrower = 0;
|
||||
|
||||
if(vfoInfo->CHANNEL_BANDWIDTH == BANDWIDTH_NARROW && gSetting_set_nfm == 1)
|
||||
if(displayBandwidth == BANDWIDTH_NARROW && gSetting_set_nfm == 1)
|
||||
{
|
||||
narrower = 1;
|
||||
}
|
||||
@@ -1948,23 +1955,23 @@ void UI_DisplayMain(void)
|
||||
if (gSetting_set_gui)
|
||||
{
|
||||
const char *bandWidthNames[] = {"W", "N", "N+"};
|
||||
UI_PrintStringSmallNormal(bandWidthNames[vfoInfo->CHANNEL_BANDWIDTH + narrower], LCD_WIDTH + 80, 0, line + 1);
|
||||
UI_PrintStringSmallNormal(bandWidthNames[displayBandwidth + narrower], LCD_WIDTH + 80, 0, line + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *bandWidthNames[] = {"WIDE", "NAR", "NAR+"};
|
||||
GUI_DisplaySmallest(bandWidthNames[vfoInfo->CHANNEL_BANDWIDTH + narrower], 91, line == 0 ? 17 : 49, false, true);
|
||||
GUI_DisplaySmallest(bandWidthNames[displayBandwidth + narrower], 91, line == 0 ? 17 : 49, false, true);
|
||||
}
|
||||
#else
|
||||
if (gSetting_set_gui)
|
||||
{
|
||||
const char *bandWidthNames[] = {"W", "N"};
|
||||
UI_PrintStringSmallNormal(bandWidthNames[vfoInfo->CHANNEL_BANDWIDTH], LCD_WIDTH + 80, 0, line + 1);
|
||||
UI_PrintStringSmallNormal(bandWidthNames[displayBandwidth], LCD_WIDTH + 80, 0, line + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *bandWidthNames[] = {"WIDE", "NAR"};
|
||||
GUI_DisplaySmallest(bandWidthNames[vfoInfo->CHANNEL_BANDWIDTH], 91, line == 0 ? 17 : 49, false, true);
|
||||
GUI_DisplaySmallest(bandWidthNames[displayBandwidth], 91, line == 0 ? 17 : 49, false, true);
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
|
||||
Reference in new issue
Block a user