kopia lustrzana https://github.com/piotr022/UV_K5_playground
performance tuning, cleanup, use of radio library, static methods for less ram usage, user-friendly SetCursorXY
rodzic
26726b344b
commit
d68ec04a16
|
@ -49,6 +49,11 @@ public:
|
||||||
u16CoursorPosition = (u8Line * Bitmap.SizeX) + u8X;
|
u16CoursorPosition = (u8Line * Bitmap.SizeX) + u8X;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetCoursorXY(unsigned char x, unsigned char y) const
|
||||||
|
{
|
||||||
|
u16CoursorPosition = x + (y << 4);
|
||||||
|
}
|
||||||
|
|
||||||
void SetFont(const IFont *pFont) const
|
void SetFont(const IFont *pFont) const
|
||||||
{
|
{
|
||||||
pCurrentFont = pFont;
|
pCurrentFont = pFont;
|
||||||
|
|
|
@ -74,12 +74,12 @@ namespace Radio
|
||||||
// Fw.BK4819WriteFrequency(u32FrequencyD10);
|
// Fw.BK4819WriteFrequency(u32FrequencyD10);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
unsigned int GetFrequency()
|
static unsigned int GetFrequency()
|
||||||
{
|
{
|
||||||
return (Fw.BK4819Read(0x39) << 16) | Fw.BK4819Read(0x38);
|
return (Fw.BK4819Read(0x39) << 16) | Fw.BK4819Read(0x38);
|
||||||
}
|
}
|
||||||
|
|
||||||
signed short GetRssi()
|
static signed short GetRssi()
|
||||||
{
|
{
|
||||||
short s16Rssi = ((Fw.BK4819Read(0x67) >> 1) & 0xFF);
|
short s16Rssi = ((Fw.BK4819Read(0x67) >> 1) & 0xFF);
|
||||||
return s16Rssi - 160;
|
return s16Rssi - 160;
|
||||||
|
@ -95,7 +95,7 @@ namespace Radio
|
||||||
return Fw.BK4819Read(0x0C) & 0b10;
|
return Fw.BK4819Read(0x0C) & 0b10;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetFrequency(unsigned int u32Freq)
|
static void SetFrequency(unsigned int u32Freq)
|
||||||
{
|
{
|
||||||
Fw.BK4819Write(0x39, ((u32Freq >> 16) & 0xFFFF));
|
Fw.BK4819Write(0x39, ((u32Freq >> 16) & 0xFFFF));
|
||||||
Fw.BK4819Write(0x38, (u32Freq & 0xFFFF));
|
Fw.BK4819Write(0x38, (u32Freq & 0xFFFF));
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include "radio.hpp"
|
||||||
#include "system.hpp"
|
#include "system.hpp"
|
||||||
#include "uv_k5_display.hpp"
|
#include "uv_k5_display.hpp"
|
||||||
#include "radio.hpp"
|
|
||||||
|
|
||||||
typedef unsigned char u8;
|
typedef unsigned char u8;
|
||||||
typedef signed short i16;
|
typedef signed short i16;
|
||||||
|
@ -11,82 +11,71 @@ typedef unsigned int u32;
|
||||||
typedef signed long long i64;
|
typedef signed long long i64;
|
||||||
typedef unsigned long long u64;
|
typedef unsigned long long u64;
|
||||||
|
|
||||||
static constexpr auto operator""_Hz(u64 Hz) { return Hz / 10; }
|
template <const System::TOrgFunctions &Fw, const System::TOrgData &FwData,
|
||||||
static constexpr auto operator""_KHz(u64 KHz) { return KHz * 1000_Hz; }
|
Radio::CBK4819<Fw> &RadioDriver>
|
||||||
static constexpr auto operator""_MHz(u64 KHz) { return KHz * 1000_KHz; }
|
|
||||||
static constexpr auto operator""_ms(u64 us) { return us * 1000; }
|
|
||||||
static constexpr auto operator""_s(u64 us) { return us * 1000_ms; }
|
|
||||||
|
|
||||||
template <const System::TOrgFunctions &Fw, const System::TOrgData &FwData, Radio::CBK4819<Fw> &RadioDriver>
|
|
||||||
class CSpectrum {
|
class CSpectrum {
|
||||||
public:
|
public:
|
||||||
static constexpr auto ExitKey = 13;
|
static constexpr auto ExitKey = 13;
|
||||||
static constexpr auto DrawingSizeY = 16 + 6 * 8;
|
|
||||||
static constexpr auto DrawingEndY = 42;
|
static constexpr auto DrawingEndY = 42;
|
||||||
static constexpr auto BarPos = 5 * 128;
|
static constexpr auto BarPos = 5 * 128;
|
||||||
|
|
||||||
u8 rssiHistory[128] = {};
|
u8 rssiHistory[128] = {};
|
||||||
u8 measurementsCount = 32;
|
u8 measurementsCount = 32;
|
||||||
u8 rssiMin = 255, rssiMax = 0;
|
u8 rssiMin = 255;
|
||||||
u8 highestPeakX = 0;
|
u8 highestPeakX = 0;
|
||||||
u8 highestPeakT = 0;
|
u8 highestPeakT = 0;
|
||||||
u8 highestPeakRssi = 0;
|
u8 highestPeakRssi = 0;
|
||||||
u32 highestPeakF = 0;
|
u32 highestPeakF = 0;
|
||||||
u32 FStart, FEnd, fMeasure;
|
u32 FStart;
|
||||||
|
|
||||||
CSpectrum()
|
CSpectrum()
|
||||||
: DisplayBuff(FwData.pDisplayBuffer), FontSmallNr(FwData.pSmallDigs),
|
: DisplayBuff(FwData.pDisplayBuffer), FontSmallNr(FwData.pSmallDigs),
|
||||||
Display(DisplayBuff), scanDelay(800), sampleZoom(2), scanStep(25_KHz),
|
Display(DisplayBuff), scanDelay(800), sampleZoom(2), scanStep(25_KHz),
|
||||||
rssiTriggerLevel(65) {
|
frequencyChangeStep(100_KHz), rssiTriggerLevel(65) {
|
||||||
Display.SetFont(&FontSmallNr);
|
Display.SetFont(&FontSmallNr);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void Measure() {
|
inline bool ListenPeak() {
|
||||||
if (highestPeakRssi >= rssiTriggerLevel) {
|
if (highestPeakRssi < rssiTriggerLevel) {
|
||||||
// listen
|
return false;
|
||||||
if (fMeasure != highestPeakF) {
|
|
||||||
fMeasure = highestPeakF;
|
|
||||||
SetFrequency(fMeasure);
|
|
||||||
}
|
}
|
||||||
Fw.BK4819Write(0x47, u16OldAfSettings);
|
|
||||||
Fw.DelayUs(1_s);
|
|
||||||
|
|
||||||
// check signal level
|
|
||||||
Fw.BK4819Write(0x47, 0); // AF
|
|
||||||
|
|
||||||
highestPeakRssi = GetRssi(fMeasure, scanDelay);
|
|
||||||
|
|
||||||
|
// measure peak for this moment
|
||||||
|
highestPeakRssi = GetRssi(highestPeakF); // also sets freq for us
|
||||||
rssiHistory[highestPeakX >> sampleZoom] = highestPeakRssi;
|
rssiHistory[highestPeakX >> sampleZoom] = highestPeakRssi;
|
||||||
return;
|
|
||||||
|
if (highestPeakRssi >= rssiTriggerLevel) {
|
||||||
|
Listen(1000000);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 rssi = 0;
|
return false;
|
||||||
u8 xPeak = 64;
|
}
|
||||||
u32 fPeak = currentFreq;
|
|
||||||
|
|
||||||
Fw.BK4819Write(0x47, 0);
|
inline void Scan() {
|
||||||
|
u8 rssi = 0, rssiMax = 0;
|
||||||
|
u8 iPeak = 0;
|
||||||
|
u32 fPeak = currentFreq, fMeasure = FStart;
|
||||||
|
|
||||||
rssiMin = 255;
|
rssiMin = 255;
|
||||||
rssiMax = 0;
|
|
||||||
fMeasure = FStart;
|
|
||||||
|
|
||||||
for (u8 i = 0; i < measurementsCount; ++i, fMeasure += scanStep) {
|
for (u8 i = 0; i < measurementsCount; ++i, fMeasure += scanStep) {
|
||||||
rssi = rssiHistory[i] = GetRssi(fMeasure, scanDelay);
|
rssi = rssiHistory[i] = GetRssi(fMeasure);
|
||||||
if (rssi < rssiMin) {
|
if (rssi < rssiMin) {
|
||||||
rssiMin = rssi;
|
rssiMin = rssi;
|
||||||
}
|
}
|
||||||
if (rssi > rssiMax) {
|
if (rssi > rssiMax) {
|
||||||
rssiMax = rssi;
|
rssiMax = rssi;
|
||||||
fPeak = fMeasure;
|
fPeak = fMeasure;
|
||||||
xPeak = i << sampleZoom;
|
iPeak = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
++highestPeakT;
|
++highestPeakT;
|
||||||
if (highestPeakT >= 8 || rssiMax > highestPeakRssi) {
|
if (rssiMax > highestPeakRssi || highestPeakT >= (8 << sampleZoom)) {
|
||||||
highestPeakT = 0;
|
highestPeakT = 0;
|
||||||
highestPeakRssi = rssiMax;
|
highestPeakRssi = rssiMax;
|
||||||
highestPeakX = xPeak;
|
highestPeakX = iPeak << sampleZoom;
|
||||||
highestPeakF = fPeak;
|
highestPeakF = fPeak;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,25 +87,28 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void DrawNums() {
|
inline void DrawNums() {
|
||||||
Display.SetCoursor(0, 0);
|
Display.SetCoursorXY(0, 0);
|
||||||
Display.PrintFixedDigitsNumber2(scanDelay, 0);
|
Display.PrintFixedDigitsNumber2(scanDelay, 0);
|
||||||
|
|
||||||
Display.SetCoursor(0, 8 * 2 + 5 * 7);
|
Display.SetCoursorXY(51, 0);
|
||||||
Display.PrintFixedDigitsNumber2(scanStep << (7 - sampleZoom));
|
Display.PrintFixedDigitsNumber2(scanStep << (7 - sampleZoom));
|
||||||
|
|
||||||
Display.SetCoursor(1, 8 * 2 + 6 * 7);
|
Display.SetCoursorXY(58, 8);
|
||||||
Display.PrintFixedDigitsNumber2(scanStep);
|
Display.PrintFixedDigitsNumber2(scanStep);
|
||||||
|
|
||||||
Display.SetCoursor(1, 8 * 2 + 13 * 7);
|
Display.SetCoursorXY(107, 8);
|
||||||
Display.PrintFixedDigitsNumber2(highestPeakRssi, 0);
|
Display.PrintFixedDigitsNumber2(highestPeakRssi, 0);
|
||||||
|
|
||||||
Display.SetCoursor(0, 8 * 2 + 10 * 7);
|
Display.SetCoursorXY(86, 0);
|
||||||
Display.PrintFixedDigitsNumber2(highestPeakF);
|
Display.PrintFixedDigitsNumber2(highestPeakF);
|
||||||
|
|
||||||
Display.SetCoursor(6, 8 * 2 + 4 * 7);
|
Display.SetCoursorXY(44, 48);
|
||||||
Display.PrintFixedDigitsNumber2(currentFreq);
|
Display.PrintFixedDigitsNumber2(currentFreq);
|
||||||
|
|
||||||
Display.SetCoursor(1, 0);
|
Display.SetCoursorXY(100, 48);
|
||||||
|
Display.PrintFixedDigitsNumber2(frequencyChangeStep);
|
||||||
|
|
||||||
|
Display.SetCoursorXY(0, 8);
|
||||||
Display.PrintFixedDigitsNumber2(rssiTriggerLevel, 0);
|
Display.PrintFixedDigitsNumber2(rssiTriggerLevel, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +142,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleUserInput() {
|
void HandleUserInput() {
|
||||||
switch (u8LastBtnPressed) {
|
switch (lastButtonPressed) {
|
||||||
case 1:
|
case 1:
|
||||||
UpdateScanDelay(200);
|
UpdateScanDelay(200);
|
||||||
break;
|
break;
|
||||||
|
@ -176,10 +168,16 @@ public:
|
||||||
UpdateScanStep(1);
|
UpdateScanStep(1);
|
||||||
break;
|
break;
|
||||||
case 11: // up
|
case 11: // up
|
||||||
UpdateCurrentFreq(100_KHz);
|
UpdateCurrentFreq(frequencyChangeStep);
|
||||||
break;
|
break;
|
||||||
case 12: // down
|
case 12: // down
|
||||||
UpdateCurrentFreq(-100_KHz);
|
UpdateCurrentFreq(-frequencyChangeStep);
|
||||||
|
break;
|
||||||
|
case 14:
|
||||||
|
UpdateFreqChangeStep(100_KHz);
|
||||||
|
break;
|
||||||
|
case 15:
|
||||||
|
UpdateFreqChangeStep(-100_KHz);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
isUserInput = false;
|
isUserInput = false;
|
||||||
|
@ -198,7 +196,7 @@ public:
|
||||||
|
|
||||||
void Update() {
|
void Update() {
|
||||||
if (bDisplayCleared) {
|
if (bDisplayCleared) {
|
||||||
currentFreq = GetFrequency();
|
currentFreq = RadioDriver.GetFrequency();
|
||||||
OnUserInput();
|
OnUserInput();
|
||||||
u16OldAfSettings = Fw.BK4819Read(0x47);
|
u16OldAfSettings = Fw.BK4819Read(0x47);
|
||||||
Fw.BK4819Write(0x47, 0); // mute AF during scan
|
Fw.BK4819Write(0x47, 0); // mute AF during scan
|
||||||
|
@ -207,7 +205,8 @@ public:
|
||||||
|
|
||||||
HandleUserInput();
|
HandleUserInput();
|
||||||
|
|
||||||
Measure();
|
if (!ListenPeak())
|
||||||
|
Scan();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateRssiTriggerLevel(i32 diff) {
|
void UpdateRssiTriggerLevel(i32 diff) {
|
||||||
|
@ -241,11 +240,15 @@ public:
|
||||||
OnUserInput();
|
OnUserInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UpdateFreqChangeStep(i64 diff) {
|
||||||
|
frequencyChangeStep = clamp(frequencyChangeStep + diff, 100_KHz, 2_MHz);
|
||||||
|
OnUserInput();
|
||||||
|
}
|
||||||
|
|
||||||
inline void OnUserInput() {
|
inline void OnUserInput() {
|
||||||
isUserInput = true;
|
isUserInput = true;
|
||||||
u32 halfOfScanRange = scanStep << (6 - sampleZoom);
|
u32 halfOfScanRange = scanStep << (6 - sampleZoom);
|
||||||
FStart = currentFreq - halfOfScanRange;
|
FStart = currentFreq - halfOfScanRange;
|
||||||
FEnd = currentFreq + halfOfScanRange;
|
|
||||||
|
|
||||||
// reset peak
|
// reset peak
|
||||||
highestPeakT = 0;
|
highestPeakT = 0;
|
||||||
|
@ -253,7 +256,7 @@ public:
|
||||||
highestPeakX = 64;
|
highestPeakX = 64;
|
||||||
highestPeakF = currentFreq;
|
highestPeakF = currentFreq;
|
||||||
|
|
||||||
Fw.DelayUs(90_ms);
|
Fw.DelayUs(90000);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Handle() {
|
void Handle() {
|
||||||
|
@ -269,8 +272,8 @@ public:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8LastBtnPressed = Fw.PollKeyboard();
|
lastButtonPressed = Fw.PollKeyboard();
|
||||||
if (u8LastBtnPressed == ExitKey) {
|
if (lastButtonPressed == ExitKey) {
|
||||||
working = false;
|
working = false;
|
||||||
RestoreParams();
|
RestoreParams();
|
||||||
return;
|
return;
|
||||||
|
@ -285,28 +288,26 @@ private:
|
||||||
bDisplayCleared = true;
|
bDisplayCleared = true;
|
||||||
DisplayBuff.ClearAll();
|
DisplayBuff.ClearAll();
|
||||||
Fw.FlushFramebufferToScreen();
|
Fw.FlushFramebufferToScreen();
|
||||||
SetFrequency(currentFreq);
|
RadioDriver.SetFrequency(currentFreq);
|
||||||
Fw.BK4819Write(0x47, u16OldAfSettings); // set previous AF settings
|
Fw.BK4819Write(0x47, u16OldAfSettings); // set previous AF settings
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetFrequency(u32 f) {
|
inline void Listen(u32 duration) {
|
||||||
Fw.BK4819Write(0x39, (f >> 16) & 0xFFFF);
|
Fw.BK4819Write(0x47, u16OldAfSettings);
|
||||||
Fw.BK4819Write(0x38, f & 0xFFFF);
|
for (u8 i = 0; i < 16 && lastButtonPressed == 255; ++i) {
|
||||||
Fw.BK4819Write(0x30, 0);
|
lastButtonPressed = Fw.PollKeyboard();
|
||||||
Fw.BK4819Write(0x30, 0xbff1);
|
Fw.DelayUs(duration >> 4);
|
||||||
|
}
|
||||||
|
Fw.BK4819Write(0x47, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 GetRssi(u32 f, u32 delay = 800) {
|
u8 GetRssi(u32 f) {
|
||||||
SetFrequency(f);
|
RadioDriver.SetFrequency(f);
|
||||||
Fw.DelayUs(delay);
|
Fw.DelayUs(scanDelay);
|
||||||
return Fw.BK4819Read(0x67);
|
return Fw.BK4819Read(0x67);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 GetFrequency() {
|
|
||||||
return (Fw.BK4819Read(0x39) << 16) | Fw.BK4819Read(0x38);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool IsFlashLightOn() { return GPIOC->DATA & GPIO_PIN_3; }
|
inline bool IsFlashLightOn() { return GPIOC->DATA & GPIO_PIN_3; }
|
||||||
inline void TurnOffFlashLight() {
|
inline void TurnOffFlashLight() {
|
||||||
GPIOC->DATA &= ~GPIO_PIN_3;
|
GPIOC->DATA &= ~GPIO_PIN_3;
|
||||||
|
@ -335,13 +336,14 @@ private:
|
||||||
const TUV_K5SmallNumbers FontSmallNr;
|
const TUV_K5SmallNumbers FontSmallNr;
|
||||||
CDisplay<const TUV_K5Display> Display;
|
CDisplay<const TUV_K5Display> Display;
|
||||||
|
|
||||||
u8 u8LastBtnPressed;
|
u8 lastButtonPressed;
|
||||||
u32 currentFreq;
|
u32 currentFreq;
|
||||||
u16 u16OldAfSettings;
|
u16 u16OldAfSettings;
|
||||||
|
|
||||||
u16 scanDelay;
|
u16 scanDelay;
|
||||||
u8 sampleZoom;
|
u8 sampleZoom;
|
||||||
u32 scanStep;
|
u32 scanStep;
|
||||||
|
u32 frequencyChangeStep;
|
||||||
u8 rssiTriggerLevel;
|
u8 rssiTriggerLevel;
|
||||||
|
|
||||||
bool working = false;
|
bool working = false;
|
||||||
|
|
Ładowanie…
Reference in New Issue