Scan range in spectrum
This commit is contained in:
@@ -11,6 +11,7 @@ bool gScanPauseMode;
|
|||||||
|
|
||||||
#ifdef ENABLE_SCAN_RANGES
|
#ifdef ENABLE_SCAN_RANGES
|
||||||
uint32_t gScanRangeStart;
|
uint32_t gScanRangeStart;
|
||||||
|
uint32_t gScanRangeStop;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -157,9 +158,7 @@ static void NextFreqChannel(void)
|
|||||||
{
|
{
|
||||||
#ifdef ENABLE_SCAN_RANGES
|
#ifdef ENABLE_SCAN_RANGES
|
||||||
if(gScanRangeStart) {
|
if(gScanRangeStart) {
|
||||||
uint32_t start = gScanRangeStart;
|
gRxVfo->freq_config_RX.Frequency = APP_SetFreqByStepAndLimits(gRxVfo, gScanStateDir, gScanRangeStart, gScanRangeStop);
|
||||||
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
|
else
|
||||||
#endif
|
#endif
|
||||||
|
@@ -12,6 +12,7 @@ extern bool gScanPauseMode;
|
|||||||
|
|
||||||
#ifdef ENABLE_SCAN_RANGES
|
#ifdef ENABLE_SCAN_RANGES
|
||||||
extern uint32_t gScanRangeStart;
|
extern uint32_t gScanRangeStart;
|
||||||
|
extern uint32_t gScanRangeStop;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void CHFRSCANNER_Found(void);
|
void CHFRSCANNER_Found(void);
|
||||||
|
@@ -52,6 +52,9 @@ void toggle_chan_scanlist(void)
|
|||||||
if(!IS_MR_CHANNEL(gTxVfo->CHANNEL_SAVE)) {
|
if(!IS_MR_CHANNEL(gTxVfo->CHANNEL_SAVE)) {
|
||||||
#ifdef ENABLE_SCAN_RANGES
|
#ifdef ENABLE_SCAN_RANGES
|
||||||
gScanRangeStart = gScanRangeStart ? 0 : gTxVfo->pRX->Frequency;
|
gScanRangeStart = gScanRangeStart ? 0 : gTxVfo->pRX->Frequency;
|
||||||
|
gScanRangeStop = gEeprom.VfoInfo[!gEeprom.TX_VFO].freq_config_RX.Frequency;
|
||||||
|
if(gScanRangeStart > gScanRangeStop)
|
||||||
|
SWAP(gScanRangeStart, gScanRangeStop);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
143
app/spectrum.c
143
app/spectrum.c
@@ -13,10 +13,14 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "app/spectrum.h"
|
#include "app/spectrum.h"
|
||||||
#include "am_fix.h"
|
#include "am_fix.h"
|
||||||
#include "audio.h"
|
#include "audio.h"
|
||||||
|
|
||||||
|
#ifdef ENABLE_SCAN_RANGES
|
||||||
|
#include "chFrScanner.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "driver/backlight.h"
|
#include "driver/backlight.h"
|
||||||
#include "frequencies.h"
|
#include "frequencies.h"
|
||||||
#include "ui/helper.h"
|
#include "ui/helper.h"
|
||||||
@@ -53,6 +57,11 @@ PeakInfo peak;
|
|||||||
ScanInfo scanInfo;
|
ScanInfo scanInfo;
|
||||||
KeyboardState kbd = {KEY_INVALID, KEY_INVALID, 0};
|
KeyboardState kbd = {KEY_INVALID, KEY_INVALID, 0};
|
||||||
|
|
||||||
|
#ifdef ENABLE_SCAN_RANGES
|
||||||
|
static uint16_t blacklistFreqs[15];
|
||||||
|
static uint8_t blacklistFreqsIdx;
|
||||||
|
#endif
|
||||||
|
|
||||||
const char *bwOptions[] = {" 25k", "12.5k", "6.25k"};
|
const char *bwOptions[] = {" 25k", "12.5k", "6.25k"};
|
||||||
const uint8_t modulationTypeTuneSteps[] = {100, 50, 10};
|
const uint8_t modulationTypeTuneSteps[] = {100, 50, 10};
|
||||||
const uint8_t modTypeReg47Values[] = {1, 7, 5};
|
const uint8_t modTypeReg47Values[] = {1, 7, 5};
|
||||||
@@ -260,12 +269,24 @@ static void ResetPeak() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool IsCenterMode() { return settings.scanStepIndex < S_STEP_2_5kHz; }
|
bool IsCenterMode() { return settings.scanStepIndex < S_STEP_2_5kHz; }
|
||||||
uint8_t GetStepsCount() { return 128 >> settings.stepsCount; }
|
// scan step in 0.01khz
|
||||||
uint16_t GetScanStep() { return scanStepValues[settings.scanStepIndex]; }
|
uint16_t GetScanStep() { return scanStepValues[settings.scanStepIndex]; }
|
||||||
|
|
||||||
|
uint16_t GetStepsCount()
|
||||||
|
{
|
||||||
|
#ifdef ENABLE_SCAN_RANGES
|
||||||
|
if(gScanRangeStart) {
|
||||||
|
return (gScanRangeStop - gScanRangeStart) / GetScanStep();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 128 >> settings.stepsCount;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t GetBW() { return GetStepsCount() * GetScanStep(); }
|
uint32_t GetBW() { return GetStepsCount() * GetScanStep(); }
|
||||||
uint32_t GetFStart() {
|
uint32_t GetFStart() {
|
||||||
return IsCenterMode() ? currentFreq - (GetBW() >> 1) : currentFreq;
|
return IsCenterMode() ? currentFreq - (GetBW() >> 1) : currentFreq;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t GetFEnd() { return currentFreq + GetBW(); }
|
uint32_t GetFEnd() { return currentFreq + GetBW(); }
|
||||||
|
|
||||||
static void TuneToPeak() {
|
static void TuneToPeak() {
|
||||||
@@ -352,6 +373,10 @@ static void ResetBlacklist() {
|
|||||||
if (rssiHistory[i] == RSSI_MAX_VALUE)
|
if (rssiHistory[i] == RSSI_MAX_VALUE)
|
||||||
rssiHistory[i] = 0;
|
rssiHistory[i] = 0;
|
||||||
}
|
}
|
||||||
|
#ifdef ENABLE_SCAN_RANGES
|
||||||
|
memset(blacklistFreqs, 0, sizeof(blacklistFreqs));
|
||||||
|
blacklistFreqsIdx = 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void RelaunchScan() {
|
static void RelaunchScan() {
|
||||||
@@ -398,7 +423,20 @@ static void UpdatePeakInfo() {
|
|||||||
UpdatePeakInfoForce();
|
UpdatePeakInfoForce();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Measure() { rssiHistory[scanInfo.i] = scanInfo.rssi = GetRssi(); }
|
static void Measure()
|
||||||
|
{
|
||||||
|
uint16_t rssi = scanInfo.rssi = GetRssi();
|
||||||
|
#ifdef ENABLE_SCAN_RANGES
|
||||||
|
if(scanInfo.measurementsCount > 128) {
|
||||||
|
uint8_t idx = (uint32_t)ARRAY_SIZE(rssiHistory) * 1000 / scanInfo.measurementsCount * scanInfo.i / 1000;
|
||||||
|
if(rssiHistory[idx] < rssi || isListening)
|
||||||
|
rssiHistory[idx] = rssi;
|
||||||
|
rssiHistory[(idx+1)%128] = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
rssiHistory[scanInfo.i] = rssi;
|
||||||
|
}
|
||||||
|
|
||||||
// Update things by keypress
|
// Update things by keypress
|
||||||
|
|
||||||
@@ -595,12 +633,25 @@ static void UpdateFreqInput(KEY_Code_t key) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void Blacklist() {
|
static void Blacklist() {
|
||||||
|
#ifdef ENABLE_SCAN_RANGES
|
||||||
|
blacklistFreqs[blacklistFreqsIdx++ % ARRAY_SIZE(blacklistFreqs)] = peak.i;
|
||||||
|
#endif
|
||||||
rssiHistory[peak.i] = RSSI_MAX_VALUE;
|
rssiHistory[peak.i] = RSSI_MAX_VALUE;
|
||||||
ResetPeak();
|
ResetPeak();
|
||||||
ToggleRX(false);
|
ToggleRX(false);
|
||||||
newScanStart = true;
|
ResetScanStats();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_SCAN_RANGES
|
||||||
|
static bool IsBlacklisted(uint16_t idx)
|
||||||
|
{
|
||||||
|
for(uint8_t i = 0; i < ARRAY_SIZE(blacklistFreqs); i++)
|
||||||
|
if(blacklistFreqs[i] == idx)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Draw things
|
// Draw things
|
||||||
|
|
||||||
// applied x2 to prevent initial rounding
|
// applied x2 to prevent initial rounding
|
||||||
@@ -710,9 +761,11 @@ static void DrawRssiTriggerLevel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void DrawTicks() {
|
static void DrawTicks() {
|
||||||
uint32_t f = GetFStart() % 100000;
|
uint32_t f = GetFStart();
|
||||||
uint32_t step = GetScanStep();
|
uint32_t span = GetFEnd() - GetFStart();
|
||||||
for (uint8_t i = 0; i < 128; i += (1 << settings.stepsCount), f += step) {
|
uint32_t step = span / 128;
|
||||||
|
for (uint8_t i = 0; i < 128; i += (1 << settings.stepsCount)) {
|
||||||
|
f = GetFStart() + span * i / 128;
|
||||||
uint8_t barValue = 0b00000001;
|
uint8_t barValue = 0b00000001;
|
||||||
(f % 10000) < step && (barValue |= 0b00000010);
|
(f % 10000) < step && (barValue |= 0b00000010);
|
||||||
(f % 50000) < step && (barValue |= 0b00000100);
|
(f % 50000) < step && (barValue |= 0b00000100);
|
||||||
@@ -764,10 +817,16 @@ static void OnKeyDown(uint8_t key) {
|
|||||||
UpdateFreqChangeStep(false);
|
UpdateFreqChangeStep(false);
|
||||||
break;
|
break;
|
||||||
case KEY_UP:
|
case KEY_UP:
|
||||||
UpdateCurrentFreq(true);
|
#ifdef ENABLE_SCAN_RANGES
|
||||||
|
if(!gScanRangeStart)
|
||||||
|
#endif
|
||||||
|
UpdateCurrentFreq(true);
|
||||||
break;
|
break;
|
||||||
case KEY_DOWN:
|
case KEY_DOWN:
|
||||||
UpdateCurrentFreq(false);
|
#ifdef ENABLE_SCAN_RANGES
|
||||||
|
if(!gScanRangeStart)
|
||||||
|
#endif
|
||||||
|
UpdateCurrentFreq(false);
|
||||||
break;
|
break;
|
||||||
case KEY_SIDE1:
|
case KEY_SIDE1:
|
||||||
Blacklist();
|
Blacklist();
|
||||||
@@ -779,7 +838,10 @@ static void OnKeyDown(uint8_t key) {
|
|||||||
UpdateRssiTriggerLevel(false);
|
UpdateRssiTriggerLevel(false);
|
||||||
break;
|
break;
|
||||||
case KEY_5:
|
case KEY_5:
|
||||||
FreqInput();
|
#ifdef ENABLE_SCAN_RANGES
|
||||||
|
if(!gScanRangeStart)
|
||||||
|
#endif
|
||||||
|
FreqInput();
|
||||||
break;
|
break;
|
||||||
case KEY_0:
|
case KEY_0:
|
||||||
ToggleModulation();
|
ToggleModulation();
|
||||||
@@ -788,7 +850,10 @@ static void OnKeyDown(uint8_t key) {
|
|||||||
ToggleListeningBW();
|
ToggleListeningBW();
|
||||||
break;
|
break;
|
||||||
case KEY_4:
|
case KEY_4:
|
||||||
ToggleStepsCount();
|
#ifdef ENABLE_SCAN_RANGES
|
||||||
|
if(!gScanRangeStart)
|
||||||
|
#endif
|
||||||
|
ToggleStepsCount();
|
||||||
break;
|
break;
|
||||||
case KEY_SIDE2:
|
case KEY_SIDE2:
|
||||||
ToggleBacklight();
|
ToggleBacklight();
|
||||||
@@ -932,7 +997,7 @@ static void RenderStatus() {
|
|||||||
|
|
||||||
static void RenderSpectrum() {
|
static void RenderSpectrum() {
|
||||||
DrawTicks();
|
DrawTicks();
|
||||||
DrawArrow(peak.i << settings.stepsCount);
|
DrawArrow(128u * peak.i / GetStepsCount());
|
||||||
DrawSpectrum();
|
DrawSpectrum();
|
||||||
DrawRssiTriggerLevel();
|
DrawRssiTriggerLevel();
|
||||||
DrawF(peak.f);
|
DrawF(peak.f);
|
||||||
@@ -1049,7 +1114,11 @@ bool HandleUserInput() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void Scan() {
|
static void Scan() {
|
||||||
if (rssiHistory[scanInfo.i] != RSSI_MAX_VALUE) {
|
if (rssiHistory[scanInfo.i] != RSSI_MAX_VALUE
|
||||||
|
#ifdef ENABLE_SCAN_RANGES
|
||||||
|
&& !IsBlacklisted(scanInfo.i)
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
SetF(scanInfo.f);
|
SetF(scanInfo.f);
|
||||||
Measure();
|
Measure();
|
||||||
UpdateScanInfo();
|
UpdateScanInfo();
|
||||||
@@ -1070,6 +1139,10 @@ static void UpdateScan() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(scanInfo.measurementsCount < 128)
|
||||||
|
memset(&rssiHistory[scanInfo.measurementsCount], 0,
|
||||||
|
sizeof(rssiHistory) - scanInfo.measurementsCount*sizeof(rssiHistory[0]));
|
||||||
|
|
||||||
redrawScreen = true;
|
redrawScreen = true;
|
||||||
preventKeypress = false;
|
preventKeypress = false;
|
||||||
|
|
||||||
@@ -1122,7 +1195,7 @@ static void UpdateListening() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ToggleRX(false);
|
ToggleRX(false);
|
||||||
newScanStart = true;
|
ResetScanStats();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Tick() {
|
static void Tick() {
|
||||||
@@ -1135,6 +1208,26 @@ static void Tick() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_SCAN_RANGES
|
||||||
|
if (gNextTimeslice_500ms) {
|
||||||
|
gNextTimeslice_500ms = false;
|
||||||
|
|
||||||
|
// if a lot of steps then it takes long time
|
||||||
|
// we don't want to wait for whole scan
|
||||||
|
// listening has it's own timer
|
||||||
|
if(GetStepsCount()>128 && !isListening) {
|
||||||
|
UpdatePeakInfo();
|
||||||
|
if (IsPeakOverLevel()) {
|
||||||
|
ToggleRX(true);
|
||||||
|
TuneToPeak();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
redrawScreen = true;
|
||||||
|
preventKeypress = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!preventKeypress) {
|
if (!preventKeypress) {
|
||||||
HandleUserInput();
|
HandleUserInput();
|
||||||
}
|
}
|
||||||
@@ -1166,18 +1259,32 @@ void APP_RunSpectrum() {
|
|||||||
// TX here coz it always? set to active VFO
|
// TX here coz it always? set to active VFO
|
||||||
vfo = gEeprom.TX_VFO;
|
vfo = gEeprom.TX_VFO;
|
||||||
// set the current frequency in the middle of the display
|
// set the current frequency in the middle of the display
|
||||||
currentFreq = initialFreq = gEeprom.VfoInfo[vfo].pRX->Frequency -
|
#ifdef ENABLE_SCAN_RANGES
|
||||||
((GetStepsCount() / 2) * GetScanStep());
|
if(gScanRangeStart) {
|
||||||
|
currentFreq = initialFreq = gScanRangeStart;
|
||||||
|
for(uint8_t i = 0; i < ARRAY_SIZE(scanStepValues); i++) {
|
||||||
|
if(scanStepValues[i] >= gTxVfo->StepFrequency) {
|
||||||
|
settings.scanStepIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
settings.stepsCount = STEPS_128;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
currentFreq = initialFreq = gTxVfo->pRX->Frequency -
|
||||||
|
((GetStepsCount() / 2) * GetScanStep());
|
||||||
|
|
||||||
BackupRegisters();
|
BackupRegisters();
|
||||||
|
|
||||||
isListening = true; // to turn off RX later
|
isListening = true; // to turn off RX later
|
||||||
redrawStatus = true;
|
redrawStatus = true;
|
||||||
redrawScreen = false; // we will wait until scan done
|
redrawScreen = true;
|
||||||
newScanStart = true;
|
newScanStart = true;
|
||||||
|
|
||||||
|
|
||||||
ToggleRX(true), ToggleRX(false); // hack to prevent noise when squelch off
|
ToggleRX(true), ToggleRX(false); // hack to prevent noise when squelch off
|
||||||
RADIO_SetModulation(settings.modulationType = gRxVfo->Modulation);
|
RADIO_SetModulation(settings.modulationType = gTxVfo->Modulation);
|
||||||
|
|
||||||
BK4819_SetFilterBandwidth(settings.listenBw = BK4819_FILTER_BW_WIDE, false);
|
BK4819_SetFilterBandwidth(settings.listenBw = BK4819_FILTER_BW_WIDE, false);
|
||||||
|
|
||||||
|
@@ -138,17 +138,17 @@ typedef struct KeyboardState {
|
|||||||
|
|
||||||
typedef struct ScanInfo {
|
typedef struct ScanInfo {
|
||||||
uint16_t rssi, rssiMin, rssiMax;
|
uint16_t rssi, rssiMin, rssiMax;
|
||||||
uint8_t i, iPeak;
|
uint16_t i, iPeak;
|
||||||
uint32_t f, fPeak;
|
uint32_t f, fPeak;
|
||||||
uint16_t scanStep;
|
uint16_t scanStep;
|
||||||
uint8_t measurementsCount;
|
uint16_t measurementsCount;
|
||||||
} ScanInfo;
|
} ScanInfo;
|
||||||
|
|
||||||
typedef struct PeakInfo {
|
typedef struct PeakInfo {
|
||||||
uint16_t t;
|
uint16_t t;
|
||||||
uint16_t rssi;
|
uint16_t rssi;
|
||||||
uint32_t f;
|
uint32_t f;
|
||||||
uint8_t i;
|
uint16_t i;
|
||||||
} PeakInfo;
|
} PeakInfo;
|
||||||
|
|
||||||
void APP_RunSpectrum(void);
|
void APP_RunSpectrum(void);
|
||||||
|
4
misc.h
4
misc.h
@@ -32,6 +32,10 @@
|
|||||||
#define MIN(a, b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a < _b ? _a : _b; })
|
#define MIN(a, b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a < _b ? _a : _b; })
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef SWAP
|
||||||
|
#define SWAP(a, b) ({ __typeof__ (a) _c = (a); a = b; b = _c; })
|
||||||
|
#endif
|
||||||
|
|
||||||
#define IS_MR_CHANNEL(x) ((x) <= MR_CHANNEL_LAST)
|
#define IS_MR_CHANNEL(x) ((x) <= MR_CHANNEL_LAST)
|
||||||
#define IS_FREQ_CHANNEL(x) ((x) >= FREQ_CHANNEL_FIRST && (x) <= FREQ_CHANNEL_LAST)
|
#define IS_FREQ_CHANNEL(x) ((x) >= FREQ_CHANNEL_FIRST && (x) <= FREQ_CHANNEL_LAST)
|
||||||
#define IS_VALID_CHANNEL(x) ((x) < LAST_CHANNEL)
|
#define IS_VALID_CHANNEL(x) ((x) < LAST_CHANNEL)
|
||||||
|
@@ -348,8 +348,7 @@ void UI_DisplayMain(void)
|
|||||||
UI_PrintString("ScnRng", 5, 0, line, 8);
|
UI_PrintString("ScnRng", 5, 0, line, 8);
|
||||||
sprintf(String, "%3u.%05u", gScanRangeStart / 100000, gScanRangeStart % 100000);
|
sprintf(String, "%3u.%05u", gScanRangeStart / 100000, gScanRangeStart % 100000);
|
||||||
UI_PrintStringSmall(String, 56, 0, line);
|
UI_PrintStringSmall(String, 56, 0, line);
|
||||||
uint32_t frq = gEeprom.VfoInfo[vfo_num].pRX->Frequency;
|
sprintf(String, "%3u.%05u", gScanRangeStop / 100000, gScanRangeStop % 100000);
|
||||||
sprintf(String, "%3u.%05u", frq / 100000, frq % 100000);
|
|
||||||
UI_PrintStringSmall(String, 56, 0, line + 1);
|
UI_PrintStringSmall(String, 56, 0, line + 1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user