refactor, feat: 100KHz to track satellite doppler shift, better smaller steps, better defaults

pull/70/head
Mikhail Yudin 2023-08-12 22:30:43 +07:00
rodzic 1e533bc6b8
commit 1d65b2e798
4 zmienionych plików z 102 dodań i 87 usunięć

Wyświetl plik

@ -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

Wyświetl plik

@ -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]);
} }

Wyświetl plik

@ -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
};

Wyświetl plik

@ -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;
}; };