diff --git a/README.md b/README.md index cf23dd5..e2ddf5c 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ Features: * no scan sound * squelch by user input level -* 0.2 .. 3.2MHz frequency ranges +* 0.1 .. 3.2MHz frequency ranges * ticks by frequency (100,500,1000KHz) * catch signal peak frequency * automatic frequency change step @@ -41,8 +41,11 @@ How to start: How to operate: -* press **8** / **2** for zoom in / zoom out -* press and hold **3** / **9** to set squelch level +* press **UP** / **DOWN** key to change frequency +* 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 **0** to remove frequency from sspectrum to scan * press **EXIT** to disable spectrum view diff --git a/libs/lcd/lcd.hpp b/libs/lcd/lcd.hpp index 22ef78f..31c4d19 100644 --- a/libs/lcd/lcd.hpp +++ b/libs/lcd/lcd.hpp @@ -270,10 +270,9 @@ public: const char dot[1] = {64}; for (unsigned char i = 0; i < len; i++) { if (pointAt == len - i) { - u16CoursorPosition++; - auto *pCoursorPosition = Bitmap.GetCoursorData(u16CoursorPosition); + auto *pCoursorPosition = Bitmap.GetCoursorData(u16CoursorPosition + 1); memcpy(pCoursorPosition, dot, 1); - u16CoursorPosition++; + u16CoursorPosition += 2; } PrintCharacter(str[i]); } diff --git a/src/spectrum_fagci/keys.hpp b/src/spectrum_fagci/keys.hpp new file mode 100644 index 0000000..82396bf --- /dev/null +++ b/src/spectrum_fagci/keys.hpp @@ -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 +}; diff --git a/src/spectrum_fagci/spectrum.hpp b/src/spectrum_fagci/spectrum.hpp index 508e35b..a58f092 100644 --- a/src/spectrum_fagci/spectrum.hpp +++ b/src/spectrum_fagci/spectrum.hpp @@ -1,4 +1,5 @@ #pragma once +#include "keys.hpp" #include "radio.hpp" #include "system.hpp" #include "types.hpp" @@ -6,10 +7,15 @@ template class CSpectrum { public: - static constexpr auto ExitKey = 13; static constexpr auto DrawingEndY = 42; 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] = {}; u32 fMeasure; @@ -18,16 +24,16 @@ public: u8 peakI = 0; u32 peakF = 0; u8 rssiMin = 255; - - u16 scanDelay = 1200; + u8 btnCounter = 0; bool resetBlacklist = false; CSpectrum() : DisplayBuff(gDisplayBuffer), Display(DisplayBuff), - FontSmallNr(gSmallDigs), frequencyChangeStep(400_KHz), bwMul(2), + FontSmallNr(gSmallDigs), scanDelay(1600), mode(4), rssiTriggerLevel(60) { Display.SetFont(&FontSmallNr); + frequencyChangeStep = modeHalfSpectrumBW[mode]; }; void Scan() { @@ -73,7 +79,7 @@ public: void DrawSpectrum() { for (u8 x = 0; x < 128; ++x) { - auto v = rssiHistory[x >> BWMul2XDiv()]; + auto v = rssiHistory[x >> modeXdiv[mode]]; if (v != 255) { Display.DrawHLine(Rssi2Y(v), DrawingEndY, x); } @@ -87,9 +93,6 @@ public: Display.SetCoursorXY(112, 0); Display.PrintFixedDigitsNumber3(GetBW(), 4, 2, 1); - /* Display.SetCoursorXY(0, 0); - Display.PrintFixedDigitsNumber2(rssiMinV, 0); */ - Display.SetCoursorXY(44, 0); Display.PrintFixedDigitsNumber3(peakF, 2, 6, 3); @@ -101,9 +104,6 @@ public: Display.SetCoursorXY(57, 48); Display.PrintFixedDigitsNumber3(frequencyChangeStep, 4, 2, 1); - - /* Display.SetCoursorXY(0, 8); - Display.PrintFixedDigitsNumber2(rssiMaxV, 0); */ } 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) { switch (key) { - case 1: + case Keys::NUM1: if (scanDelay < 8000) { scanDelay += 200; rssiMin = 255; } break; - case 7: + case Keys::NUM7: if (scanDelay > 800) { scanDelay -= 200; rssiMin = 255; } break; - case 3: + case Keys::NUM3: UpdateBWMul(1); resetBlacklist = true; break; - case 9: + case Keys::NUM9: UpdateBWMul(-1); resetBlacklist = true; break; - case 2: + case Keys::NUM2: UpdateFreqChangeStep(100_KHz); break; - case 8: + case Keys::NUM8: UpdateFreqChangeStep(-100_KHz); break; - case 11: // up + case Keys::UP: UpdateCurrentFreq(frequencyChangeStep); resetBlacklist = true; break; - case 12: // down + case Keys::DOWN: UpdateCurrentFreq(-frequencyChangeStep); resetBlacklist = true; break; - case 5: + case Keys::NUM5: ToggleBacklight(); break; - case 0: + case Keys::NUM0: Blacklist(); break; + case Keys::ASTERISK: + UpdateRssiTriggerLevel(1); + DelayMs(90); + break; + case Keys::FUNCTION: + UpdateRssiTriggerLevel(-1); + DelayMs(90); + break; } ResetPeak(); } @@ -189,12 +184,16 @@ public: bool HandleUserInput() { btnPrev = btn; btn = PollKeyboard(); - if (btn == ExitKey) { + if (btn == Keys::EXIT) { DeInit(); return false; } - OnKey(btn); - if (btn != 255 && btnPrev == 255) { + if (btn != 255 && btn == btnPrev) { + btnCounter = clamp(btnCounter + 1, 0, 255); + } else { + btnCounter = 0; + } + if ((btn != 255 && btnPrev == 255) || btnCounter > 16) { OnKeyDown(btn); } return true; @@ -203,7 +202,7 @@ public: void Render() { DisplayBuff.ClearAll(); DrawTicks(); - DrawArrow(peakI << BWMul2XDiv()); + DrawArrow(peakI << modeXdiv[mode]); DrawSpectrum(); DrawRssiTriggerLevel(); DrawNums(); @@ -212,24 +211,22 @@ public: void Update() { if (peakRssi >= rssiTriggerLevel) { - Listen(1600); - return; + Listen(); + } + if (peakRssi < rssiTriggerLevel) { + Scan(); } - Scan(); } - void UpdateRssiTriggerLevel(i32 diff) { - if ((diff > 0 && rssiTriggerLevel < 255) || - (diff < 0 && rssiTriggerLevel > 0)) { - rssiTriggerLevel += diff; - } - } + void UpdateRssiTriggerLevel(i32 diff) { rssiTriggerLevel += diff; } void UpdateBWMul(i32 diff) { - if ((diff > 0 && bwMul < 4) || (diff < 0 && bwMul > 0)) { - bwMul += diff; + if ((diff > 0 && mode < 5) || (diff < 0 && mode > 0)) { + mode += diff; + SetBW(); + rssiMin = 255; + frequencyChangeStep = modeHalfSpectrumBW[mode]; } - frequencyChangeStep = 100_KHz << bwMul; } void UpdateCurrentFreq(i64 diff) { @@ -267,7 +264,9 @@ private: oldAFSettings = BK4819Read(0x47); oldBWSettings = BK4819Read(0x43); MuteAF(); - SetWideBW(); + SetBW(); + ResetPeak(); + resetBlacklist = true; isInitialized = true; } @@ -282,19 +281,21 @@ private: void ResetPeak() { peakRssi = 0; - peakF = currentFreq; + // peakF = currentFreq; peakT = 0; } - void SetWideBW() { + void SetBW() { auto Reg = BK4819Read(0x43); Reg &= ~(0b11 << 4); - BK4819Write(0x43, Reg | (0b11 << 4)); + if (mode >= 3) + Reg |= 0b11 << 4; + BK4819Write(0x43, Reg); } void MuteAF() { BK4819Write(0x47, 0); } void RestoreOldAFSettings() { BK4819Write(0x47, oldAFSettings); } - void Listen(u16 durationMs) { + void Listen() { if (fMeasure != peakF) { fMeasure = peakF; RadioDriver.SetFrequency(fMeasure); @@ -302,26 +303,17 @@ private: RadioDriver.ToggleAFDAC(true); } for (u8 i = 0; i < 16 && PollKeyboard() == 255; ++i) { - DelayMs(durationMs >> 4); + DelayMs(64); } peakRssi = rssiHistory[peakI] = GetRssi(); } - u16 GetScanStep() { return 25_KHz >> (2 >> bwMul); } - u32 GetBW() { return 200_KHz << bwMul; } - u32 GetFStart() { return currentFreq - (100_KHz << bwMul); } - u32 GetFEnd() { return currentFreq + (100_KHz << bwMul); } + u16 GetScanStep() { return modeScanStep[mode]; } + u32 GetBW() { return modeHalfSpectrumBW[mode] << 1; } + u32 GetFStart() { return currentFreq - modeHalfSpectrumBW[mode]; } + u32 GetFEnd() { return currentFreq + modeHalfSpectrumBW[mode]; } - u8 BWMul2XDiv() { return clamp(4 - bwMul, 0, 2); } - u8 GetMeasurementsCount() { - if (bwMul == 3) { - return 64; - } - if (bwMul > 3) { - return 128; - } - return 32; - } + u8 GetMeasurementsCount() { return 128 >> modeXdiv[mode]; } void ResetRSSI() { RadioDriver.ToggleRXDSP(false); @@ -331,7 +323,7 @@ private: u8 GetRssi() { ResetRSSI(); - DelayUs(scanDelay); + DelayUs(scanDelay << (mode < 3)); return (BK4819Read(0x67) & 0x1FF) >> 1; } @@ -355,25 +347,20 @@ private: return v; } - u32 modulo(u32 num, u32 div) { - while (num >= div) - num -= div; - return num; - } - TUV_K5Display DisplayBuff; CDisplay Display; const TUV_K5SmallNumbers FontSmallNr; - u32 frequencyChangeStep; - u8 bwMul; + u16 scanDelay; + u8 mode; u8 rssiTriggerLevel; - u8 btn = 255; - u8 btnPrev = 255; + u8 btn; + u8 btnPrev; u32 currentFreq; u16 oldAFSettings; u16 oldBWSettings; + u32 frequencyChangeStep; bool isInitialized = false; };