kopia lustrzana https://github.com/piotr022/UV_K5_playground
refactor, feat: 100KHz to track satellite doppler shift, better smaller steps, better defaults
rodzic
1e533bc6b8
commit
1d65b2e798
|
@ -26,7 +26,7 @@ Features:
|
||||||
|
|
||||||
* no scan sound
|
* no scan sound
|
||||||
* squelch by user input level
|
* squelch by user input level
|
||||||
* 0.2 .. 3.2MHz frequency ranges
|
* 0.1 .. 3.2MHz frequency ranges
|
||||||
* ticks by frequency (100,500,1000KHz)
|
* ticks by frequency (100,500,1000KHz)
|
||||||
* catch signal peak frequency
|
* catch signal peak frequency
|
||||||
* automatic frequency change step
|
* automatic frequency change step
|
||||||
|
@ -41,8 +41,11 @@ How to start:
|
||||||
|
|
||||||
How to operate:
|
How to operate:
|
||||||
|
|
||||||
* press **8** / **2** for zoom in / zoom out
|
* press **UP** / **DOWN** key to change frequency
|
||||||
* press and hold **3** / **9** to set squelch level
|
* press **1** / **7** to control measurement time (increasing "sensitivity")
|
||||||
|
* press **2** / **8** to to set frequency change step
|
||||||
|
* press **9** / **3** for zoom in / zoom out
|
||||||
|
* press and hold **\*** / **F** to set squelch level
|
||||||
* press **5** to toggle backlight
|
* press **5** to toggle backlight
|
||||||
* press **0** to remove frequency from sspectrum to scan
|
* press **0** to remove frequency from sspectrum to scan
|
||||||
* press **EXIT** to disable spectrum view
|
* press **EXIT** to disable spectrum view
|
||||||
|
|
|
@ -270,10 +270,9 @@ public:
|
||||||
const char dot[1] = {64};
|
const char dot[1] = {64};
|
||||||
for (unsigned char i = 0; i < len; i++) {
|
for (unsigned char i = 0; i < len; i++) {
|
||||||
if (pointAt == len - i) {
|
if (pointAt == len - i) {
|
||||||
u16CoursorPosition++;
|
auto *pCoursorPosition = Bitmap.GetCoursorData(u16CoursorPosition + 1);
|
||||||
auto *pCoursorPosition = Bitmap.GetCoursorData(u16CoursorPosition);
|
|
||||||
memcpy(pCoursorPosition, dot, 1);
|
memcpy(pCoursorPosition, dot, 1);
|
||||||
u16CoursorPosition++;
|
u16CoursorPosition += 2;
|
||||||
}
|
}
|
||||||
PrintCharacter(str[i]);
|
PrintCharacter(str[i]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
enum Keys {
|
||||||
|
NUM0,
|
||||||
|
NUM1,
|
||||||
|
NUM2,
|
||||||
|
NUM3,
|
||||||
|
NUM4,
|
||||||
|
NUM5,
|
||||||
|
NUM6,
|
||||||
|
NUM7,
|
||||||
|
NUM8,
|
||||||
|
NUM9,
|
||||||
|
MENU, // 10
|
||||||
|
UP, // 11
|
||||||
|
DOWN, // 12
|
||||||
|
EXIT, // 13
|
||||||
|
ASTERISK, // 14
|
||||||
|
FUNCTION, // 15
|
||||||
|
_NA16,
|
||||||
|
_NA17,
|
||||||
|
_NA18,
|
||||||
|
_NA19,
|
||||||
|
_NA20,
|
||||||
|
_NA21,
|
||||||
|
FN2, // 22
|
||||||
|
FN1, // 23
|
||||||
|
};
|
|
@ -1,4 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include "keys.hpp"
|
||||||
#include "radio.hpp"
|
#include "radio.hpp"
|
||||||
#include "system.hpp"
|
#include "system.hpp"
|
||||||
#include "types.hpp"
|
#include "types.hpp"
|
||||||
|
@ -6,10 +7,15 @@
|
||||||
|
|
||||||
template <Radio::CBK4819 &RadioDriver> class CSpectrum {
|
template <Radio::CBK4819 &RadioDriver> class CSpectrum {
|
||||||
public:
|
public:
|
||||||
static constexpr auto ExitKey = 13;
|
|
||||||
static constexpr auto DrawingEndY = 42;
|
static constexpr auto DrawingEndY = 42;
|
||||||
static constexpr auto BarPos = 5 * 128;
|
static constexpr auto BarPos = 5 * 128;
|
||||||
|
|
||||||
|
static constexpr u32 modeHalfSpectrumBW[6] = {50_KHz, 100_KHz, 200_KHz,
|
||||||
|
400_KHz, 800_KHz, 1600_KHz};
|
||||||
|
static constexpr u16 modeScanStep[6] = {1562_Hz, 6250_Hz, 12500_Hz,
|
||||||
|
25_KHz, 25_KHz, 25_KHz};
|
||||||
|
static constexpr u8 modeXdiv[6] = {1, 2, 2, 2, 1, 0};
|
||||||
|
|
||||||
u8 rssiHistory[128] = {};
|
u8 rssiHistory[128] = {};
|
||||||
u32 fMeasure;
|
u32 fMeasure;
|
||||||
|
|
||||||
|
@ -18,16 +24,16 @@ public:
|
||||||
u8 peakI = 0;
|
u8 peakI = 0;
|
||||||
u32 peakF = 0;
|
u32 peakF = 0;
|
||||||
u8 rssiMin = 255;
|
u8 rssiMin = 255;
|
||||||
|
u8 btnCounter = 0;
|
||||||
u16 scanDelay = 1200;
|
|
||||||
|
|
||||||
bool resetBlacklist = false;
|
bool resetBlacklist = false;
|
||||||
|
|
||||||
CSpectrum()
|
CSpectrum()
|
||||||
: DisplayBuff(gDisplayBuffer), Display(DisplayBuff),
|
: DisplayBuff(gDisplayBuffer), Display(DisplayBuff),
|
||||||
FontSmallNr(gSmallDigs), frequencyChangeStep(400_KHz), bwMul(2),
|
FontSmallNr(gSmallDigs), scanDelay(1600), mode(4),
|
||||||
rssiTriggerLevel(60) {
|
rssiTriggerLevel(60) {
|
||||||
Display.SetFont(&FontSmallNr);
|
Display.SetFont(&FontSmallNr);
|
||||||
|
frequencyChangeStep = modeHalfSpectrumBW[mode];
|
||||||
};
|
};
|
||||||
|
|
||||||
void Scan() {
|
void Scan() {
|
||||||
|
@ -73,7 +79,7 @@ public:
|
||||||
|
|
||||||
void DrawSpectrum() {
|
void DrawSpectrum() {
|
||||||
for (u8 x = 0; x < 128; ++x) {
|
for (u8 x = 0; x < 128; ++x) {
|
||||||
auto v = rssiHistory[x >> BWMul2XDiv()];
|
auto v = rssiHistory[x >> modeXdiv[mode]];
|
||||||
if (v != 255) {
|
if (v != 255) {
|
||||||
Display.DrawHLine(Rssi2Y(v), DrawingEndY, x);
|
Display.DrawHLine(Rssi2Y(v), DrawingEndY, x);
|
||||||
}
|
}
|
||||||
|
@ -87,9 +93,6 @@ public:
|
||||||
Display.SetCoursorXY(112, 0);
|
Display.SetCoursorXY(112, 0);
|
||||||
Display.PrintFixedDigitsNumber3(GetBW(), 4, 2, 1);
|
Display.PrintFixedDigitsNumber3(GetBW(), 4, 2, 1);
|
||||||
|
|
||||||
/* Display.SetCoursorXY(0, 0);
|
|
||||||
Display.PrintFixedDigitsNumber2(rssiMinV, 0); */
|
|
||||||
|
|
||||||
Display.SetCoursorXY(44, 0);
|
Display.SetCoursorXY(44, 0);
|
||||||
Display.PrintFixedDigitsNumber3(peakF, 2, 6, 3);
|
Display.PrintFixedDigitsNumber3(peakF, 2, 6, 3);
|
||||||
|
|
||||||
|
@ -101,9 +104,6 @@ public:
|
||||||
|
|
||||||
Display.SetCoursorXY(57, 48);
|
Display.SetCoursorXY(57, 48);
|
||||||
Display.PrintFixedDigitsNumber3(frequencyChangeStep, 4, 2, 1);
|
Display.PrintFixedDigitsNumber3(frequencyChangeStep, 4, 2, 1);
|
||||||
|
|
||||||
/* Display.SetCoursorXY(0, 8);
|
|
||||||
Display.PrintFixedDigitsNumber2(rssiMaxV, 0); */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawRssiTriggerLevel() {
|
void DrawRssiTriggerLevel() {
|
||||||
|
@ -127,61 +127,56 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnKey(u8 key) {
|
|
||||||
switch (key) {
|
|
||||||
case 14:
|
|
||||||
UpdateRssiTriggerLevel(1);
|
|
||||||
DelayMs(90);
|
|
||||||
break;
|
|
||||||
case 15:
|
|
||||||
UpdateRssiTriggerLevel(-1);
|
|
||||||
DelayMs(90);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnKeyDown(u8 key) {
|
void OnKeyDown(u8 key) {
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 1:
|
case Keys::NUM1:
|
||||||
if (scanDelay < 8000) {
|
if (scanDelay < 8000) {
|
||||||
scanDelay += 200;
|
scanDelay += 200;
|
||||||
rssiMin = 255;
|
rssiMin = 255;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 7:
|
case Keys::NUM7:
|
||||||
if (scanDelay > 800) {
|
if (scanDelay > 800) {
|
||||||
scanDelay -= 200;
|
scanDelay -= 200;
|
||||||
rssiMin = 255;
|
rssiMin = 255;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3:
|
case Keys::NUM3:
|
||||||
UpdateBWMul(1);
|
UpdateBWMul(1);
|
||||||
resetBlacklist = true;
|
resetBlacklist = true;
|
||||||
break;
|
break;
|
||||||
case 9:
|
case Keys::NUM9:
|
||||||
UpdateBWMul(-1);
|
UpdateBWMul(-1);
|
||||||
resetBlacklist = true;
|
resetBlacklist = true;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case Keys::NUM2:
|
||||||
UpdateFreqChangeStep(100_KHz);
|
UpdateFreqChangeStep(100_KHz);
|
||||||
break;
|
break;
|
||||||
case 8:
|
case Keys::NUM8:
|
||||||
UpdateFreqChangeStep(-100_KHz);
|
UpdateFreqChangeStep(-100_KHz);
|
||||||
break;
|
break;
|
||||||
case 11: // up
|
case Keys::UP:
|
||||||
UpdateCurrentFreq(frequencyChangeStep);
|
UpdateCurrentFreq(frequencyChangeStep);
|
||||||
resetBlacklist = true;
|
resetBlacklist = true;
|
||||||
break;
|
break;
|
||||||
case 12: // down
|
case Keys::DOWN:
|
||||||
UpdateCurrentFreq(-frequencyChangeStep);
|
UpdateCurrentFreq(-frequencyChangeStep);
|
||||||
resetBlacklist = true;
|
resetBlacklist = true;
|
||||||
break;
|
break;
|
||||||
case 5:
|
case Keys::NUM5:
|
||||||
ToggleBacklight();
|
ToggleBacklight();
|
||||||
break;
|
break;
|
||||||
case 0:
|
case Keys::NUM0:
|
||||||
Blacklist();
|
Blacklist();
|
||||||
break;
|
break;
|
||||||
|
case Keys::ASTERISK:
|
||||||
|
UpdateRssiTriggerLevel(1);
|
||||||
|
DelayMs(90);
|
||||||
|
break;
|
||||||
|
case Keys::FUNCTION:
|
||||||
|
UpdateRssiTriggerLevel(-1);
|
||||||
|
DelayMs(90);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
ResetPeak();
|
ResetPeak();
|
||||||
}
|
}
|
||||||
|
@ -189,12 +184,16 @@ public:
|
||||||
bool HandleUserInput() {
|
bool HandleUserInput() {
|
||||||
btnPrev = btn;
|
btnPrev = btn;
|
||||||
btn = PollKeyboard();
|
btn = PollKeyboard();
|
||||||
if (btn == ExitKey) {
|
if (btn == Keys::EXIT) {
|
||||||
DeInit();
|
DeInit();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
OnKey(btn);
|
if (btn != 255 && btn == btnPrev) {
|
||||||
if (btn != 255 && btnPrev == 255) {
|
btnCounter = clamp(btnCounter + 1, 0, 255);
|
||||||
|
} else {
|
||||||
|
btnCounter = 0;
|
||||||
|
}
|
||||||
|
if ((btn != 255 && btnPrev == 255) || btnCounter > 16) {
|
||||||
OnKeyDown(btn);
|
OnKeyDown(btn);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -203,7 +202,7 @@ public:
|
||||||
void Render() {
|
void Render() {
|
||||||
DisplayBuff.ClearAll();
|
DisplayBuff.ClearAll();
|
||||||
DrawTicks();
|
DrawTicks();
|
||||||
DrawArrow(peakI << BWMul2XDiv());
|
DrawArrow(peakI << modeXdiv[mode]);
|
||||||
DrawSpectrum();
|
DrawSpectrum();
|
||||||
DrawRssiTriggerLevel();
|
DrawRssiTriggerLevel();
|
||||||
DrawNums();
|
DrawNums();
|
||||||
|
@ -212,24 +211,22 @@ public:
|
||||||
|
|
||||||
void Update() {
|
void Update() {
|
||||||
if (peakRssi >= rssiTriggerLevel) {
|
if (peakRssi >= rssiTriggerLevel) {
|
||||||
Listen(1600);
|
Listen();
|
||||||
return;
|
}
|
||||||
|
if (peakRssi < rssiTriggerLevel) {
|
||||||
|
Scan();
|
||||||
}
|
}
|
||||||
Scan();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateRssiTriggerLevel(i32 diff) {
|
void UpdateRssiTriggerLevel(i32 diff) { rssiTriggerLevel += diff; }
|
||||||
if ((diff > 0 && rssiTriggerLevel < 255) ||
|
|
||||||
(diff < 0 && rssiTriggerLevel > 0)) {
|
|
||||||
rssiTriggerLevel += diff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateBWMul(i32 diff) {
|
void UpdateBWMul(i32 diff) {
|
||||||
if ((diff > 0 && bwMul < 4) || (diff < 0 && bwMul > 0)) {
|
if ((diff > 0 && mode < 5) || (diff < 0 && mode > 0)) {
|
||||||
bwMul += diff;
|
mode += diff;
|
||||||
|
SetBW();
|
||||||
|
rssiMin = 255;
|
||||||
|
frequencyChangeStep = modeHalfSpectrumBW[mode];
|
||||||
}
|
}
|
||||||
frequencyChangeStep = 100_KHz << bwMul;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateCurrentFreq(i64 diff) {
|
void UpdateCurrentFreq(i64 diff) {
|
||||||
|
@ -267,7 +264,9 @@ private:
|
||||||
oldAFSettings = BK4819Read(0x47);
|
oldAFSettings = BK4819Read(0x47);
|
||||||
oldBWSettings = BK4819Read(0x43);
|
oldBWSettings = BK4819Read(0x43);
|
||||||
MuteAF();
|
MuteAF();
|
||||||
SetWideBW();
|
SetBW();
|
||||||
|
ResetPeak();
|
||||||
|
resetBlacklist = true;
|
||||||
isInitialized = true;
|
isInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,19 +281,21 @@ private:
|
||||||
|
|
||||||
void ResetPeak() {
|
void ResetPeak() {
|
||||||
peakRssi = 0;
|
peakRssi = 0;
|
||||||
peakF = currentFreq;
|
// peakF = currentFreq;
|
||||||
peakT = 0;
|
peakT = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetWideBW() {
|
void SetBW() {
|
||||||
auto Reg = BK4819Read(0x43);
|
auto Reg = BK4819Read(0x43);
|
||||||
Reg &= ~(0b11 << 4);
|
Reg &= ~(0b11 << 4);
|
||||||
BK4819Write(0x43, Reg | (0b11 << 4));
|
if (mode >= 3)
|
||||||
|
Reg |= 0b11 << 4;
|
||||||
|
BK4819Write(0x43, Reg);
|
||||||
}
|
}
|
||||||
void MuteAF() { BK4819Write(0x47, 0); }
|
void MuteAF() { BK4819Write(0x47, 0); }
|
||||||
void RestoreOldAFSettings() { BK4819Write(0x47, oldAFSettings); }
|
void RestoreOldAFSettings() { BK4819Write(0x47, oldAFSettings); }
|
||||||
|
|
||||||
void Listen(u16 durationMs) {
|
void Listen() {
|
||||||
if (fMeasure != peakF) {
|
if (fMeasure != peakF) {
|
||||||
fMeasure = peakF;
|
fMeasure = peakF;
|
||||||
RadioDriver.SetFrequency(fMeasure);
|
RadioDriver.SetFrequency(fMeasure);
|
||||||
|
@ -302,26 +303,17 @@ private:
|
||||||
RadioDriver.ToggleAFDAC(true);
|
RadioDriver.ToggleAFDAC(true);
|
||||||
}
|
}
|
||||||
for (u8 i = 0; i < 16 && PollKeyboard() == 255; ++i) {
|
for (u8 i = 0; i < 16 && PollKeyboard() == 255; ++i) {
|
||||||
DelayMs(durationMs >> 4);
|
DelayMs(64);
|
||||||
}
|
}
|
||||||
peakRssi = rssiHistory[peakI] = GetRssi();
|
peakRssi = rssiHistory[peakI] = GetRssi();
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 GetScanStep() { return 25_KHz >> (2 >> bwMul); }
|
u16 GetScanStep() { return modeScanStep[mode]; }
|
||||||
u32 GetBW() { return 200_KHz << bwMul; }
|
u32 GetBW() { return modeHalfSpectrumBW[mode] << 1; }
|
||||||
u32 GetFStart() { return currentFreq - (100_KHz << bwMul); }
|
u32 GetFStart() { return currentFreq - modeHalfSpectrumBW[mode]; }
|
||||||
u32 GetFEnd() { return currentFreq + (100_KHz << bwMul); }
|
u32 GetFEnd() { return currentFreq + modeHalfSpectrumBW[mode]; }
|
||||||
|
|
||||||
u8 BWMul2XDiv() { return clamp(4 - bwMul, 0, 2); }
|
u8 GetMeasurementsCount() { return 128 >> modeXdiv[mode]; }
|
||||||
u8 GetMeasurementsCount() {
|
|
||||||
if (bwMul == 3) {
|
|
||||||
return 64;
|
|
||||||
}
|
|
||||||
if (bwMul > 3) {
|
|
||||||
return 128;
|
|
||||||
}
|
|
||||||
return 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ResetRSSI() {
|
void ResetRSSI() {
|
||||||
RadioDriver.ToggleRXDSP(false);
|
RadioDriver.ToggleRXDSP(false);
|
||||||
|
@ -331,7 +323,7 @@ private:
|
||||||
u8 GetRssi() {
|
u8 GetRssi() {
|
||||||
ResetRSSI();
|
ResetRSSI();
|
||||||
|
|
||||||
DelayUs(scanDelay);
|
DelayUs(scanDelay << (mode < 3));
|
||||||
return (BK4819Read(0x67) & 0x1FF) >> 1;
|
return (BK4819Read(0x67) & 0x1FF) >> 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -355,25 +347,20 @@ private:
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 modulo(u32 num, u32 div) {
|
|
||||||
while (num >= div)
|
|
||||||
num -= div;
|
|
||||||
return num;
|
|
||||||
}
|
|
||||||
|
|
||||||
TUV_K5Display DisplayBuff;
|
TUV_K5Display DisplayBuff;
|
||||||
CDisplay<const TUV_K5Display> Display;
|
CDisplay<const TUV_K5Display> Display;
|
||||||
const TUV_K5SmallNumbers FontSmallNr;
|
const TUV_K5SmallNumbers FontSmallNr;
|
||||||
|
|
||||||
u32 frequencyChangeStep;
|
u16 scanDelay;
|
||||||
u8 bwMul;
|
u8 mode;
|
||||||
u8 rssiTriggerLevel;
|
u8 rssiTriggerLevel;
|
||||||
|
|
||||||
u8 btn = 255;
|
u8 btn;
|
||||||
u8 btnPrev = 255;
|
u8 btnPrev;
|
||||||
u32 currentFreq;
|
u32 currentFreq;
|
||||||
u16 oldAFSettings;
|
u16 oldAFSettings;
|
||||||
u16 oldBWSettings;
|
u16 oldBWSettings;
|
||||||
|
u32 frequencyChangeStep;
|
||||||
|
|
||||||
bool isInitialized = false;
|
bool isInitialized = false;
|
||||||
};
|
};
|
||||||
|
|
Ładowanie…
Reference in New Issue