From 21fd8d00eccedd5dc6b3538dd5b644e660cf3fff Mon Sep 17 00:00:00 2001 From: KubaPro010 Date: Wed, 18 Feb 2026 10:38:19 +0100 Subject: [PATCH] move some things around --- include/comms.h | 1 + include/constants.h | 2 +- include/core.h | 12 +- include/graphics.h | 9 + include/gui.h | 6 + include/language.h | 2 +- include/main.h | 21 +- include/rds.h | 1 + src/core.cpp | 1576 +++++-------------------------------------- src/globals.cpp | 4 +- src/graphics.cpp | 107 +++ src/gui.cpp | 78 +++ src/main.cpp | 983 +++++++++++++++++++++++++++ 13 files changed, 1391 insertions(+), 1411 deletions(-) create mode 100644 include/graphics.h create mode 100644 src/graphics.cpp diff --git a/include/comms.h b/include/comms.h index 84723a8..4ce78d7 100644 --- a/include/comms.h +++ b/include/comms.h @@ -4,6 +4,7 @@ #include "nonvolatile.h" #include #include "core.h" +#include "gui.h" void Communication(); void XDRGTKRoutine(); diff --git a/include/constants.h b/include/constants.h index 48e8b56..139287c 100644 --- a/include/constants.h +++ b/include/constants.h @@ -51,7 +51,7 @@ #define DELAY_BUTTON_DEBOUNCE_MS 50 #define DELAY_BUTTON_DEBOUNCE_EXTRA_MS 75 #define DELAY_KEYPAD_TIMEOUT_MS 2000 -#define DELAY_RDS_READ_MS 50 +#define DELAY_RDS_READ_MS 60 #define DELAY_TOUCH_REPEAT_MS 500 #define TOT_MULTIPLIER_MS 60000 #define NTP_UPDATE_INTERVAL_MS 1800000 diff --git a/include/core.h b/include/core.h index d0c94d4..1373ee7 100644 --- a/include/core.h +++ b/include/core.h @@ -1,21 +1,15 @@ #pragma once #include #include +#include "graphics.h" -void tftPrint(int8_t offset, const String & text, int16_t x, int16_t y, int color, int smoothcolor, uint8_t fontsize); -void tftPrint16(int8_t offset, const String & text, int16_t x, int16_t y, int color, int smoothcolor, bool force_font = true, bool font = false); -void tftReplace(int8_t offset, const String & textold, const String & text, int16_t x, int16_t y, int color, int smoothcolor, int background, uint8_t fontsize); -void tftReplace16(int8_t offset, const String & textold, const String & text, int16_t x, int16_t y, int color, int smoothcolor, int background, bool force_font = true, bool font = false); const char* textUI(uint16_t number); uint8_t doAutoMemory(uint16_t startfreq, uint16_t stopfreq, uint8_t startmem, uint8_t stopmem, bool rdsonly, uint8_t doublepi); -void showAutoSquelch(bool mode); -void UpdateFonts(); void setAutoSpeedSPI(); void DoMemoryPosTune(); void startFMDXScan(); void endMenu(); void TuneUp(); -void ShowStepSize(); void ShowFreq(int mode); void ShowMemoryPos(); void TuneDown(); @@ -23,12 +17,8 @@ void ShowTuneMode(); void SelectBand(); void doBW(); void ModeButtonPress(); -void updateEQ(); -void updateiMS(); void Seek(bool mode); void MuteScreen(bool setting); void cancelDXScan(); void doStereoToggle(); -void updateBW(); -void ShowRDSLogo(bool RDSstatus); void DataPrint(String string); diff --git a/include/graphics.h b/include/graphics.h new file mode 100644 index 0000000..221431f --- /dev/null +++ b/include/graphics.h @@ -0,0 +1,9 @@ +#pragma once + +#include "globals.h" + +void tftPrint(int8_t offset, const String & text, int16_t x, int16_t y, int color, int smoothcolor, uint8_t fontsize); +void tftPrint16(int8_t offset, const String & text, int16_t x, int16_t y, int color, int smoothcolor, bool force_font = true, bool font = false); +void tftReplace(int8_t offset, const String & textold, const String & text, int16_t x, int16_t y, int color, int smoothcolor, int background, uint8_t fontsize); +void tftReplace16(int8_t offset, const String & textold, const String & text, int16_t x, int16_t y, int color, int smoothcolor, int background, bool force_font = true, bool font = false); +void UpdateFonts(); diff --git a/include/gui.h b/include/gui.h index 97a6956..a19e8d0 100644 --- a/include/gui.h +++ b/include/gui.h @@ -25,6 +25,12 @@ void drawButton(const char* text, byte button_number, bool active, bool selected String shortLine(String text); void showMenuOpenTouchButtons(); void showBWSelector(); +void ShowRDSLogo(bool RDSstatus); +void showAutoSquelch(bool mode); +void updateEQ(); +void updateiMS(); +void updateBW(); +void ShowStepSize(); extern void ShowBandSelectionFM(bool notglanceview, bool normaldisplay); extern void ShowBandSelectionAM(bool notglanceview, bool normaldisplay); diff --git a/include/language.h b/include/language.h index ff1bb95..5b8c83d 100644 --- a/include/language.h +++ b/include/language.h @@ -24,7 +24,7 @@ Process: } */ -static const char* const myLanguage[22][297] PROGMEM = { +static const char* const Languages[22][297] PROGMEM = { { "English", // English "Rotary direction changed", // 1 "Please release button", // 2 diff --git a/include/main.h b/include/main.h index d9d8637..7c1da66 100644 --- a/include/main.h +++ b/include/main.h @@ -8,9 +8,28 @@ extern RTC_DATA_ATTR bool gpio_chip; extern RTC_DATA_ATTR bool tef_found; template -void panic(Args... args); +void panic(Args... args) { + radio.power(true); + tft.fillScreen(TFT_RED); + console.reset(); + + (console.print(args), ...); + while (true); +} void Round30K(unsigned int freq); void Round50K(unsigned int freq); void Round100K(unsigned int freq); void Round200K(unsigned int freq); +void WakeToSleep(bool yes); +void BANDBUTTONPress(); +void BWButtonPress(); +void doBandToggle(); +int GetNum(); +void NumpadProcess(int num); + +bool isSignalQualityGood(int usn, int wam, int ostatus, int threshold_multiplier = SCAN_SIGNAL_THRESHOLD_USN_MULTIPLIER, int ostatus_threshold = SCAN_SIGNAL_THRESHOLD_OSTATUS); +void deepSleep(); +inline bool IsStationEmpty() { + return presets[memorypos].band == BAND_FM && presets[memorypos].frequency == EE_PRESETS_FREQUENCY; +} diff --git a/include/rds.h b/include/rds.h index 0250f3d..8257132 100644 --- a/include/rds.h +++ b/include/rds.h @@ -9,6 +9,7 @@ #include "NTPupdate.h" #include "rtc.hpp" #include "core.h" +#include "gui.h" void ShowAdvancedRDS(); void readRds(); diff --git a/src/core.cpp b/src/core.cpp index 3444d2f..5fed322 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -10,32 +10,20 @@ using fs::FS; #include "gui.h" #include "comms.h" #include "rds.h" -#include "touch.h" #include "nonvolatile.h" #include "utils.h" #include "system_console.h" #include "core.h" +#include "main.h" Console console(&tft); RTC_DATA_ATTR bool gpio_chip = false; RTC_DATA_ATTR bool tef_found = false; -template -void panic(Args... args) { - radio.power(1); - tft.fillScreen(TFT_RED); - console.reset(); - - (console.print(args), ...); - while (true); -} - #pragma region helpers -inline bool isSignalQualityGood(int usn, int wam, int ostatus, int threshold_multiplier = SCAN_SIGNAL_THRESHOLD_USN_MULTIPLIER, int ostatus_threshold = SCAN_SIGNAL_THRESHOLD_OSTATUS) { - return (usn < fmscansens * threshold_multiplier) && - (wam < SCAN_SIGNAL_THRESHOLD_WAM) && - (ostatus < ostatus_threshold) && - (ostatus > -ostatus_threshold); +bool isSignalQualityGood(int usn, int wam, int ostatus, int threshold_multiplier, int ostatus_threshold) { + return (usn < fmscansens * threshold_multiplier) && (wam < SCAN_SIGNAL_THRESHOLD_WAM) && + (ostatus < ostatus_threshold) && (ostatus > -ostatus_threshold); } void Round30K(unsigned int freq) { @@ -69,145 +57,22 @@ void Round5K(unsigned int freqAM) { else if (freqAM % 10 > 7) frequency_AM = (freqAM - (freqAM % 10) + 10); } -inline void deepSleep() { - MuteScreen(1); +void deepSleep() { + MuteScreen(true); StoreFrequency(); - radio.power(1); + radio.power(true); esp_sleep_enable_ext0_wakeup((gpio_num_t)ROTARY_PIN_A, LOW); esp_deep_sleep_start(); } -inline bool IsStationEmpty() { - return presets[memorypos].band == BAND_FM && presets[memorypos].frequency == EE_PRESETS_FREQUENCY; -} - -void ShowFreq(int mode); -void doLog() { - if (!autologged && RDSstatus && radio.rds.correctPI != 0) { - if (autolog) { - switch (addRowToCSV()) { - case 0: ShowFreq(2); break; - case 1: ShowFreq(3); break; - case 2: ShowFreq(4); break; - } - - delay(DELAY_UI_UPDATE_MS); - ShowFreq(0); - } - autologged = true; - } -} - -inline void EdgeBeeper() { +inline __attribute__((always_inline)) void EdgeBeeper() { if(!edgebeep) return; - radio.tone(50, -5, 2000); + radio.tone(50, -6, 2000); } const char* textUI(uint16_t number) { - if (number >= language_entrynumber) return "Overflow"; - else return (const char*)pgm_read_ptr(&(myLanguage[language][number])); -} - -inline bool shouldHighlightBWButton(byte temp, byte set) { - return (set == temp) || (temp == 17 && set == 0) || (temp == 18 && !iMSset) || (temp == 19 && !EQset); -} - -inline const char* getBWButtonLabel(byte temp, bool isFM) { - constexpr byte BW_OK_BUTTON = 20; - if (temp == BW_OK_BUTTON) return "OK"; - return isFM ? BWButtonLabelsFM[temp - 1] : BWButtonLabelsAM[temp - 1]; -} - -void doBWtuneUp() { - rotary = 0; - constexpr byte BW_OK_BUTTON = 20; - constexpr byte BW_AM_MAX = 4; - - if (band < BAND_GAP) { - // FM band - drawButton(getBWButtonLabel(BWsettemp, true), BWsettemp - 1, shouldHighlightBWButton(BWsettemp, BWset), false); - BWsettemp++; - if (BWsettemp > BW_OK_BUTTON) BWsettemp = 1; - drawButton(getBWButtonLabel(BWsettemp, true), BWsettemp - 1, shouldHighlightBWButton(BWsettemp, BWset), true); - } else { - // AM band - drawButton(getBWButtonLabel(BWsettemp, false), BWsettemp - 1, (BWset == BWsettemp), false); - BWsettemp++; - if (BWsettemp > BW_AM_MAX && BWsettemp < BW_OK_BUTTON) BWsettemp = BW_OK_BUTTON; - else if (BWsettemp > BW_OK_BUTTON) BWsettemp = 1; - drawButton(getBWButtonLabel(BWsettemp, false), BWsettemp - 1, (BWset == BWsettemp), true); - } -} - -void doBWtuneDown() { - rotary = 0; - constexpr byte BW_OK_BUTTON = 20; - constexpr byte BW_AM_MAX = 4; - - if (band < BAND_GAP) { - // FM band - drawButton(getBWButtonLabel(BWsettemp, true), BWsettemp - 1, shouldHighlightBWButton(BWsettemp, BWset), false); - BWsettemp--; - if (BWsettemp > BW_OK_BUTTON || BWsettemp == 0) BWsettemp = BW_OK_BUTTON; - drawButton(getBWButtonLabel(BWsettemp, true), BWsettemp - 1, shouldHighlightBWButton(BWsettemp, BWset), true); - } else { - // AM band - drawButton(getBWButtonLabel(BWsettemp, false), BWsettemp - 1, (BWset == BWsettemp), false); - BWsettemp--; - if (BWsettemp > BW_AM_MAX && BWsettemp < BW_OK_BUTTON) BWsettemp = BW_AM_MAX; - else if (BWsettemp == 0) BWsettemp = BW_OK_BUTTON; - drawButton(getBWButtonLabel(BWsettemp, false), BWsettemp - 1, (BWset == BWsettemp), true); - } -} - -void ShowStereoStatus() { - if (StereoToggle) { - if (band < BAND_GAP) Stereostatus = radio.getStereoStatus(); else Stereostatus = false; - if (Stereostatus != Stereostatusold) { - if (Stereostatus && !screenmute) tft.drawBitmap(STEREO_ICON_X, STEREO_ICON_Y, Stereo, 32, 22, StereoColor); - else if (!screenmute) tft.drawBitmap(STEREO_ICON_X, STEREO_ICON_Y, Stereo, 32, 22, GreyoutColor); - Stereostatusold = Stereostatus; - } - } -} - -void ShowRSSI() { - if (wifi) rssi = WiFi.RSSI(); else rssi = 0; - if (rssiold != rssi) { - if (!wifi && batterydetect) tft.drawBitmap(WIFI_ICON_X, WIFI_ICON_Y, WiFi4, WIFI_ICON_WIDTH, WIFI_ICON_HEIGHT, BackgroundColor); - else if (rssi == 0) tft.drawBitmap(WIFI_ICON_X, WIFI_ICON_Y, WiFi4, WIFI_ICON_WIDTH, WIFI_ICON_HEIGHT, GreyoutColor); - else if (rssi > -50 && rssi < 0) tft.drawBitmap(WIFI_ICON_X, WIFI_ICON_Y, WiFi4, WIFI_ICON_WIDTH, WIFI_ICON_HEIGHT, WifiColorHigh); - else if (rssi > -60) { - tft.drawBitmap(WIFI_ICON_X, WIFI_ICON_Y, WiFi4, WIFI_ICON_WIDTH, WIFI_ICON_HEIGHT, GreyoutColor); - tft.drawBitmap(WIFI_ICON_X, WIFI_ICON_Y, WiFi3, WIFI_ICON_WIDTH, WIFI_ICON_HEIGHT, WifiColorHigh); - } else if (rssi > -70) { - tft.drawBitmap(WIFI_ICON_X, WIFI_ICON_Y, WiFi4, WIFI_ICON_WIDTH, WIFI_ICON_HEIGHT, GreyoutColor); - tft.drawBitmap(WIFI_ICON_X, WIFI_ICON_Y, WiFi2, WIFI_ICON_WIDTH, WIFI_ICON_HEIGHT, WifiColorLow); - } else if (rssi < -70) { - tft.drawBitmap(WIFI_ICON_X, WIFI_ICON_Y, WiFi4, WIFI_ICON_WIDTH, WIFI_ICON_HEIGHT, GreyoutColor); - tft.drawBitmap(WIFI_ICON_X, WIFI_ICON_Y, WiFi1, WIFI_ICON_WIDTH, WIFI_ICON_HEIGHT, WifiColorLow); - } - rssiold = rssi; - } -} - -void ShowBW() { - if (!BWtune && millis() >= bwupdatetimer + TIMER_BW_TIMER) bwupdatetimer = millis(); - else if(!BWtune) return; - - if (BW != BWOld || BWreset) { - if(BW == 0) panic("BW is 0"); - else if(BW > 311) panic("BW larger than 311"); - - if(BWset == 0) tftReplace(ARIGHT, String(BWOld, DEC), String(BW, DEC), 203, 4, BWAutoColor, BWAutoColorSmooth, BackgroundColor, 28); else tftReplace(ARIGHT, String (BWOld, DEC), String(BW, DEC), 203, 4, PrimaryColor, PrimaryColorSmooth, BackgroundColor, 28); - BWOld = BW; - BWreset = false; - if (wifi) { - Udp.beginPacket(remoteip, 9030); - Udp.print("from=TEF_tuner_" + String(stationlistid, DEC) + ";bandwidth=" + String(BW * 1000)); - Udp.endPacket(); - } - } + if (number >= language_entrynumber) return "[OVERFLOW]"; + else return (const char*)pgm_read_ptr(&(Languages[language][number])); } void updateSWMIBand() { @@ -245,51 +110,12 @@ void updateSWMIBand() { } } -inline void updateCodetect() { - if (band > BAND_GAP) { - if (WAM) tftPrint16(ALEFT, "CO", 50, 61, PrimaryColor, PrimaryColorSmooth); - else tftPrint16(ALEFT, "CO", 50, 61, BackgroundColor, BackgroundColor); - } -} - -void ShowSignalLevel(); -void ShowOffset(); -void ShowBattery(); -void GetData() { - if (!afscreen && !rdsstatscreen) ShowSignalLevel(); - if (!BWtune && !menu && !rdsstatscreen) showPS(); - - if (band < BAND_GAP && !BWtune && !menu) { - if (advancedRDS && !afscreen && !rdsstatscreen && !screenmute) ShowAdvancedRDS(); - if (!advancedRDS && !afscreen && rdsstatscreen && !screenmute) ShowRDSStatistics(); - if (afscreen && !screenmute) ShowAFEON(); - if (!afscreen && !rdsstatscreen) { - if (!screenmute) ShowErrors(); - showPTY(); - showRadioText(); - if (millis() >= tuningtimer + 200) doAF(); - } - showPI(); - } - - ShowStereoStatus(); - - if (!screenmute) { - showCT(); - ShowRSSI(); - ShowOffset(); - ShowBW(); - updateCodetect(); - if (millis() >= tuningtimer + 200 && !wifi) ShowBattery(); - } -} - void WakeToSleep(bool yes) { if (yes) { screensavertriggered = true; switch (poweroptions) { case LCD_OFF: - MuteScreen(1); + MuteScreen(true); break; case LCD_BRIGHTNESS_1_PERCENT: analogWrite(CONTRASTPIN, map(ContrastSet / 100, 0, 100, 0, 255)); @@ -304,14 +130,14 @@ void WakeToSleep(bool yes) { } else { switch (poweroptions) { case LCD_OFF: - MuteScreen(0); + MuteScreen(false); screensavertriggered = false; screensavertimer = millis(); break; case LCD_BRIGHTNESS_1_PERCENT: case LCD_BRIGHTNESS_A_QUARTER: case LCD_BRIGHTNESS_HALF: - MuteScreen(0); + MuteScreen(false); screensavertriggered = false; screensavertimer = millis(); break; @@ -414,8 +240,7 @@ void doBandSelectionFM() { } else if (frequency_OIRT < FREQ_FM_OIRT_START) { frequency_OIRT = FREQ_FM_OIRT_END; EdgeBeeper(); - } - SelectBand(); + } SelectBand(); } break; case FM_BAND_FM: @@ -480,7 +305,7 @@ void doBandSelectionAM() { } void BANDBUTTONPress() { - if(seek)radio.setUnMute(); + if(seek) radio.setUnMute(); seek = false; if (scandxmode) { ShowFreq(5); @@ -571,7 +396,7 @@ void BWButtonPress() { else { if (scandxmode) { unsigned long counterold = millis(); - unsigned long counter = millis(); + unsigned long counter = counterold; while (digitalRead(BWBUTTON) == LOW && counter - counterold <= 1000) counter = millis(); if (counter - counterold < 1000) { @@ -629,101 +454,15 @@ void doStereoToggle() { EEPROM.commit(); } -void ShowStepSize() { - if (!advancedRDS) { - tft.fillRect(191, 38, 15, 4, GreyoutColor); - tft.fillRect(222, 38, 15, 4, GreyoutColor); - if (band < BAND_GAP) tft.fillRect(113, 38, 15, 4, GreyoutColor); else if (band != BAND_LW && band != BAND_MW) tft.fillRect(129, 38, 15, 4, GreyoutColor); - if (band < BAND_GAP) tft.fillRect(144, 38, 15, 4, GreyoutColor); else tft.fillRect(159, 38, 15, 4, GreyoutColor); - if (stepsize == 1) tft.fillRect(222, 38, 15, 4, InsignificantColor); - if (stepsize == 2) tft.fillRect(191, 38, 15, 4, InsignificantColor); - if (stepsize == 3) { - if (band < BAND_GAP) tft.fillRect(144, 38, 15, 4, InsignificantColor); else tft.fillRect(159, 38, 15, 4, InsignificantColor); - } - if (stepsize == 4) { - if (band < BAND_GAP) tft.fillRect(113, 38, 15, 4, InsignificantColor); else tft.fillRect(129, 38, 15, 4, InsignificantColor); - } - } -} - bool IsFrequencyUsed(unsigned int freq) { - bool result = false; for (byte x = scanstart; x <= scanstop; x++) { - if ((presets[x].band == BAND_FM || presets[x].band == BAND_OIRT) && presets[x].frequency == freq) { - result = true; - break; - } - } - return result; + if ((presets[x].band == BAND_FM || presets[x].band == BAND_OIRT) && presets[x].frequency == freq) return true; + } return false; } -void ShowRDSLogo(bool RDSstatus) { - if (screenmute) return; - if (RDSstatus != RDSstatusold) { - if (RDSstatus) tft.drawBitmap(68, 5, RDSLogo, 35, 22, RDSColor); - else tft.drawBitmap(68, 5, RDSLogo, 35, 22, GreyoutColor); - } - RDSstatusold = RDSstatus; -} - -void showAutoSquelch(bool mode) { - if (screenmute) return; - if (mode) tft.drawBitmap(223, 147, AutoSQ, 18, 18, PrimaryColor); - else tft.drawBitmap(223, 147, AutoSQ, 18, 18, BackgroundColor); -} - -void updateBW() { - if (BWset == 0) { - if (!BWtune && !screenmute && !advancedRDS && !afscreen && !rdsstatscreen) { - tft.fillRoundRect(248, 36, 69, 18, 2, SecondaryColor); - tftPrint16(ACENTER, "AUTO BW", 282, 38, BackgroundColor, SecondaryColor); - } - radio.setFMABandw(); - } else { - if (!BWtune && !screenmute && !advancedRDS && !afscreen && !rdsstatscreen) { - tft.fillRoundRect(248, 36, 69, 18, 2, GreyoutColor); - tftPrint16(ACENTER, "AUTO BW", 282, 38, BackgroundColor, GreyoutColor); - } - } -} - -void updateiMS() { - if (band < BAND_GAP) { - if (iMSset == 0) { - if (!screenmute && !advancedRDS && !afscreen && !rdsstatscreen && !BWtune) { - tft.fillRoundRect(249, 57, 30, 18, 2, SecondaryColor); - tftPrint16(ACENTER, "iMS", 265, 59, BackgroundColor, SecondaryColor); - } - radio.setiMS(1); - } else { - if (!screenmute && !advancedRDS && !afscreen && !rdsstatscreen && !BWtune) { - tft.fillRoundRect(249, 57, 30, 18, 2, GreyoutColor); - tftPrint16(ACENTER, "iMS", 265, 59, BackgroundColor, GreyoutColor); - } - radio.setiMS(0); - } - } -} - -void updateEQ() { - if (band < BAND_GAP) { - if (EQset == 0) { - if (!screenmute && !advancedRDS && !afscreen && !rdsstatscreen && !BWtune) { - tft.fillRoundRect(287, 57, 30, 18, 2, SecondaryColor); - tftPrint16(ACENTER, "EQ", 301, 59, BackgroundColor, SecondaryColor); - } radio.setEQ(1); - } else { - if (!screenmute && !advancedRDS && !afscreen && !rdsstatscreen && !BWtune) { - tft.fillRoundRect(287, 57, 30, 18, 2, GreyoutColor); - tftPrint16(ACENTER, "EQ", 301, 59, BackgroundColor, GreyoutColor); - } radio.setEQ(0); - } - } -} - -inline void DataPrint(String string) { - if (XDRGTKUSB) Serial.print(string); - if (XDRGTKTCP) RemoteClient.print(string); +void DataPrint(String string) { + if(XDRGTKUSB) Serial.print(string); + if(XDRGTKTCP) RemoteClient.print(string); } void toggleiMSEQ() { @@ -774,7 +513,6 @@ void TuneFreq(int temp) { if (newfreq == frequency) return; frequency = newfreq; radio.SetFreq(frequency); - } else if (band == BAND_OIRT) { while (newfreq < (LowEdgeOIRTSet * 10)) newfreq *= 10; if (newfreq > HighEdgeOIRTSet) { @@ -784,7 +522,6 @@ void TuneFreq(int temp) { if (newfreq == frequency_OIRT) return; frequency_OIRT = newfreq; radio.SetFreq(frequency_OIRT); - } else if (band == BAND_LW) { while (newfreq < LWLowEdgeSet) newfreq *= 10; if (newfreq > LWHighEdgeSet) { @@ -833,7 +570,7 @@ void ShowNum(int val) { FrequencySprite.pushSprite(46, 46); } -byte numval[16] = {2, 3, 127, 5, 6, 0, 9, 13, 8, 7, 4, 1, 0, 0, 0, 0}; +constexpr byte numval[16] = {2, 3, 127, 5, 6, 0, 9, 13, 8, 7, 4, 1, 0, 0, 0, 0}; int GetNum() { if(!gpio_chip) return -1; // Get input port 0 and 1 @@ -867,7 +604,7 @@ int GetNum() { temp = Wire.read() & 0xFF; temp |= (Wire.read() & 0xFF) << 8; for (int i = 0; i < 16; i++) { - if ((temp & 0x01) == 0) { + if ((temp & 1) == 0) { num = numval[i]; cnt++; } @@ -940,8 +677,7 @@ void startFMDXScan() { if (band != presets[memorypos].band) { band = presets[memorypos].band; SelectBand(); - } - DoMemoryPosTune(); + } DoMemoryPosTune(); } else { tunemode = TUNE_MAN; if (band != presets[memorypos].band) { @@ -950,8 +686,7 @@ void startFMDXScan() { } TuneUp(); ShowFreq(0); - } - if (scanmute) { + } if (scanmute) { radio.setMute(); tft.drawBitmap(249, 4, Speaker, 28, 24, PrimaryColor); SQ = true; @@ -978,8 +713,7 @@ void doBandToggle() { scanmodeold = tunemode; startFMDXScan(); return; - } - screensavertimer = millis(); + } screensavertimer = millis(); } void NumpadProcess(int num) { @@ -1005,16 +739,13 @@ void NumpadProcess(int num) { FrequencySprite.setTextDatum(TR_DATUM); FrequencySprite.fillSprite(BackgroundColor); FrequencySprite.setTextColor(SignificantColor, SignificantColorSmooth, false); - FrequencySprite.drawString(String(freq_in) + " ", 218, -6); + FrequencySprite.drawString(String(freq_in) + " ", 218, -6, freqfont); FrequencySprite.pushSprite(46, 46); - delay(500); + delay(505); memorypos = oldmemorypos; ShowFreq(0); - ShowMemoryPos(); - } else { - DoMemoryPosTune(); - ShowMemoryPos(); - } + } else DoMemoryPosTune(); + ShowMemoryPos(); } else ShowFreq(0); freq_in = 0; } else { @@ -1072,7 +803,7 @@ void setAutoSpeedSPI() { case 940 ... 941: tft.setSPISpeed(12); break; case 942: tft.setSPISpeed(17); break; case 943 ... 949: tft.setSPISpeed(15); break; - case 950: tft.setSPISpeed(19); break; + case 950: tft.setSPISpeed(20); break; case 951: tft.setSPISpeed(15); break; case 952 ... 960: tft.setSPISpeed(22); break; case 961 ... 965: tft.setSPISpeed(15); break; @@ -1117,6 +848,8 @@ void endMenu() { if (af == 2) radio.rds.afreg = true; else radio.rds.afreg = false; Serial.end(); if (wifi) remoteip = IPAddress(WiFi.localIP()[0], WiFi.localIP()[1], WiFi.localIP()[2], subnetclient); + + Serial.flush(); if (USBmode) Serial.updateBaudRate(19200); else Serial.updateBaudRate(115200); leave = true; @@ -1183,491 +916,71 @@ void MuteScreen(bool setting) { } #pragma endregion -void ShowAudioLevel(); -void doSquelch(); -void handleWiFi() { - if (wifi && !menu) { - webserver.handleClient(); - - if (millis() >= udplogtimer + UDP_LOG_INTERVAL_MS) { - sendUDPlog(); - udplogtimer = millis(); - } - - if (millis() >= NTPtimer + NTP_UPDATE_INTERVAL_MS) { - NTPupdate(); - NTPtimer = millis(); - } - } -} - -void handleTouch() { - if (hardwaremodel == PORTABLE_TOUCH_ILI9341 && touch_detect) { - if (tft.getTouchRawZ() > TOUCH_RAW_Z_THRESHOLD) { - uint16_t x, y; - tft.getTouch(&x, &y); - if (x > 0 || y > 0) { - if (!firstTouchHandled) { - doTouchEvent(x, y); - firstTouchHandled = true; - lastTouchTime = millis(); - } else if (touchrepeat && millis() - lastTouchTime >= DELAY_TOUCH_REPEAT_MS) doTouchEvent(x, y); - } - } else { - firstTouchHandled = false; - touch_detect = false; - } - } -} - -void handleTimers() { - // tottimer is like the time of the last interaction - if (tot != 0 && millis() >= tottimer + (tot * TOT_MULTIPLIER_MS)) deepSleep(); - - if (freq_in != 0 && millis() >= keypadtimer + DELAY_KEYPAD_TIMEOUT_MS) { - freq_in = 0; - ShowFreq(0); - if (tunemode == TUNE_MEM) ShowMemoryPos(); - } -} - -void loop() { - if(i2c_pc_control) { - total_pc_control(); - if(i2c_pc_control) return; - } - - handleWiFi(); - handleTouch(); - Communication(); - handleTimers(); - - if (scandxmode) { - unsigned long waitTime = (scanhold == 0) ? SCAN_HOLD_DEFAULT_MS : (scanhold * 1000); - if (!scanholdflag) scanholdflag = isSignalQualityGood(USN, WAM, OStatus); - bool bypassMillisCheck = scanholdonsignal && !scanholdflag; - bool shouldScan = bypassMillisCheck || (!bypassMillisCheck && (millis() >= scantimer + waitTime)); - - if (shouldScan) { - if (scanmute && scanholdonsignal) { - radio.setMute(); - if (!screenmute) tft.drawBitmap(SPEAKER_ICON_X, SPEAKER_ICON_Y, Speaker, SPEAKER_ICON_WIDTH, SPEAKER_ICON_HEIGHT, PrimaryColor); - SQ = true; - } - scanholdflag = false; - if (scanmem) { - memorypos++; - if (memorypos > scanstop) memorypos = scanstart; - while (IsStationEmpty() || (presets[memorypos].band != BAND_FM && presets[memorypos].band != BAND_OIRT)) { - memorypos++; - if (memorypos > scanstop) { - memorypos = scanstart; - break; - } - } - doLog(); - DoMemoryPosTune(); - radio.clearRDS(); - autologged = false; - ShowMemoryPos(); - } else { - doLog(); - TuneUp(); - autologged = false; - ShowFreq(0); - if (XDRGTKUSB || XDRGTKTCP) DataPrint("T" + String((frequency + ConverterSet * 100) * 10) + "\n"); - } - scantimer = millis(); - initdxscan = false; - } else { - if (scanmute && scanholdonsignal) { - radio.setUnMute(); - SQ = false; - if (!screenmute) tft.drawBitmap(249, 4, Speaker, 28, 24, GreyoutColor); - } - } - - if (millis() >= flashingtimer + 500) { - flashing = !flashing; - if (flashing) { - tft.fillRoundRect(2, 80, 40, 18, 2, SecondaryColor); - tftPrint16(ACENTER, "MEM", 22, 82, BackgroundColor, SecondaryColor); - } else { - tft.fillRoundRect(2, 80, 40, 18, 2, GreyoutColor); - tftPrint16(ACENTER, "MEM", 22, 82, BackgroundColor, GreyoutColor); - } - flashingtimer = millis(); - } - - if (!scanholdflag) delay(75); - radio.getStatus(&SStatus, &USN, &WAM, &OStatus, &BW, &MStatus, &CN); - - if (!initdxscan) { - switch (scancancel) { - case CORRECTPI: - if (RDSstatus && radio.rds.correctPI != 0) cancelDXScan(); - break; - case SIGNAL: - if (isSignalQualityGood(USN, WAM, OStatus) && (Squelch < SStatus || Squelch == SQUELCH_MAX_VALUE)) cancelDXScan(); - break; - } - } - } - - if (millis() >= tuningtimer + 200) rdsflagreset = false; - - if (millis() >= tuningtimer + 2000) { - if (store) { - StoreFrequency(); - store = false; - } - } - - if (!BWtune && !menu && !afscreen && !rdsstatscreen && !scandxmode) { - if (af != 0 && dropout && millis() >= aftimer + 1000) { - aftimer = millis(); - if (radio.af_counter == 0) { - if (findMemoryAF && radio.rds.correctPI != 0 && tunemode == TUNE_MEM && (USN > 250 || WAM > 250)) { - radio.setMute(); - tft.drawBitmap(249, 4, Speaker, 28, 24, PrimaryColor); - SQ = true; - if (!screenmute) { - if (advancedRDS) { - tft.drawRoundRect(10, 30, 300, 170, 2, ActiveColor); - tft.fillRoundRect(12, 32, 296, 166, 2, BackgroundColor); - tftPrint(ACENTER, textUI(31), 160, 100, ActiveColor, ActiveColorSmooth, 28); - } else ShowFreq(1); - } - - bool foundmemaf = false; - for (int x = 8750; x <= 10800; x += 10) { - if (rotary != 0 || digitalRead(BANDBUTTON) == LOW || digitalRead(MODEBUTTON) == LOW || digitalRead(BWBUTTON) == LOW || digitalRead(ROTARY_BUTTON) == LOW) break; - radio.SetFreq(x); - unsigned long millisold = millis(); - while (millis() - millisold < 187) { - if (!screenmute && !advancedRDS) ShowAudioLevel(); - } - if (radio.rds.correctPI == radio.getBlockA()) { - frequency = x; - foundmemaf = true; - break; - } - } - - if (!foundmemaf) { - frequency = freqold; - radio.SetFreq(frequency); - } - - if (!screenmute) { - if (advancedRDS) { - leave = true; - BuildAdvancedRDS(); - freq_in = 0; - } else ShowFreq(0); - } - - radio.setUnMute(); - SQ = false; - tft.drawBitmap(249, 4, Speaker, 28, 24, GreyoutColor); - } - findMemoryAF = false; - } else frequency = radio.TestAF(); - if (freqold != frequency) { - ShowFreq(0); - dropout = true; - if (radio.afmethodB) { - afmethodBold = true; - radio.clearRDS(); - } - } - if (XDRGTKUSB || XDRGTKTCP) DataPrint("T" + String((frequency + ConverterSet * 100) * 10) + "\n"); - if (screenmute) { - freqold = frequency; - dropout = false; - } - store = true; - } - - if (band == BAND_FM && af != 0 && radio.rds.correctPI != 0) { - if ((aftest && millis() >= aftimer + 3000) || ((USN > 250 || WAM > 250) && millis() >= aftimer + 1000)) { - aftimer = millis(); - aftest = false; - frequency = radio.TestAF(); - if (freqold != frequency) { - ShowFreq(0); - dropout = true; - if (radio.afmethodB) { - afmethodBold = true; - radio.clearRDS(); - } - if (XDRGTKUSB || XDRGTKTCP) DataPrint("T" + String((frequency + ConverterSet * 100) * 10) + "\n"); - if (screenmute) { - freqold = frequency; - dropout = false; - } - store = true; - } - } - - if (band == BAND_FM && millis() >= aftimer + 10000) { - aftimer = millis(); - if (USN > 150 || WAM > 150) { - frequency = radio.TestAF(); - if (freqold != frequency) { - ShowFreq(0); - dropout = true; - if (radio.afmethodB) { - afmethodBold = true; - radio.clearRDS(); - } - if (XDRGTKUSB || XDRGTKTCP) DataPrint("T" + String((frequency + ConverterSet * 100) * 10) + "\n"); - store = true; - if (screenmute) { - freqold = frequency; - dropout = false; - } - } - } - } - } - } - - if(seek) Seek(direction); - - if ((SStatus / 10 > LowLevelSet) && !LowLevelInit && !BWtune && !menu && band < BAND_GAP) { - if (!screenmute && !advancedRDS && !rdsstatscreen && !afscreen) { - if (showaudio) { - tftPrint16(ALEFT, "10", 24, 144, ActiveColor, ActiveColorSmooth); - tftPrint16(ALEFT, "30", 54, 144, ActiveColor, ActiveColorSmooth); - tftPrint16(ALEFT, "50", 84, 144, ActiveColor, ActiveColorSmooth); - tftPrint16(ALEFT, "70", 114, 144, ActiveColor, ActiveColorSmooth); - tftPrint16(ALEFT, "100", 160, 144, ActiveColor, ActiveColorSmooth); - tftPrint16(ACENTER, "A", 7, 128, ActiveColor, ActiveColorSmooth); - for (byte segments = 0; segments < 93; segments++) { - if (segments > 54) { - if (((segments - 53) % 10) == 0) tft.fillRect(22 + (2 * segments), 141, 2, 2, BarSignificantColor); - } else { - if (((segments + 1) % 6) == 0) tft.fillRect(22 + (2 * segments), 141, 2, 2, BarInsignificantColor); - } - } - } - if (radio.rds.region == 0) tftPrint16(ALEFT, "PI", 212, 193, ActiveColor, ActiveColorSmooth); - else { - tftPrint16(ALEFT, "PI", 212, 184, ActiveColor, ActiveColorSmooth); - tftPrint16(ALEFT, "ID", 212, 201, ActiveColor, ActiveColorSmooth); - } - tftPrint16(ALEFT, "PS", 3, 193, ActiveColor, ActiveColorSmooth); - tftPrint16(ALEFT, "RT", 3, 221, ActiveColor, ActiveColorSmooth); - tftPrint16(ALEFT, "PTY", 3, 163, ActiveColor, ActiveColorSmooth); - if (!showaudio) tft.drawLine(16, 143, 189, 143, GreyoutColor); else tft.drawLine(16, 143, 189, 143, ActiveColor); - } - LowLevelInit = true; - } - - if ((SStatus / 10 <= LowLevelSet) && band < BAND_GAP) { - if (LowLevelInit && !BWtune && !menu) { - if (!screenmute && !rdsstatscreen && !afscreen && !advancedRDS) { - if(showaudio) { - tftPrint16(ALEFT, "10", 24, 144, GreyoutColor, BackgroundColor); - tftPrint16(ALEFT, "30", 54, 144, GreyoutColor, BackgroundColor); - tftPrint16(ALEFT, "50", 84, 144, GreyoutColor, BackgroundColor); - tftPrint16(ALEFT, "70", 114, 144, GreyoutColor, BackgroundColor); - tftPrint16(ALEFT, "100", 160, 144, GreyoutColor, BackgroundColor); - tftPrint16(ACENTER, "A", 7, 128, GreyoutColor, BackgroundColor); - tft.fillRect(16, 133, 174, 6, GreyoutColor); - for (byte segments = 0; segments < 93; segments++) { - if (segments > 54) { - if (((segments - 53) % 10) == 0) tft.fillRect(22 + (2 * segments), 141, 2, 2, GreyoutColor); - } else { - if (((segments + 1) % 6) == 0) tft.fillRect(22 + (2 * segments), 141, 2, 2, GreyoutColor); - } - } - } - if (radio.rds.region == 0) tftPrint16(ALEFT, "PI", 212, 193, GreyoutColor, BackgroundColor); - else { - tftPrint16(ALEFT, "PI", 212, 184, GreyoutColor, BackgroundColor); - tftPrint16(ALEFT, "ID", 212, 201, GreyoutColor, BackgroundColor); - } - tftPrint16(ALEFT, "PS", 3, 193, GreyoutColor, BackgroundColor); - tftPrint16(ALEFT, "RT", 3, 221, GreyoutColor, BackgroundColor); - tftPrint16(ALEFT, "PTY", 3, 163, GreyoutColor, BackgroundColor); - tft.drawLine(16, 143, 189, 143, GreyoutColor); - tft.drawBitmap(68, 5, RDSLogo, 35, 22, GreyoutColor); - } - LowLevelInit = false; - } - - if (!BWtune && !menu && (screenmute || radio.rds.correctPI != 0)) readRds(); - if (millis() >= lowsignaltimer + 300) { - lowsignaltimer = millis(); - if (af || (!screenmute || (screenmute && (XDRGTKTCP || XDRGTKUSB)))) { - if (band < BAND_GAP) radio.getStatus(&SStatus, &USN, &WAM, &OStatus, &BW, &MStatus, &CN); - else radio.getStatusAM(&SStatus, &USN, &WAM, &OStatus, &BW, &MStatus, &CN); - } - if (!BWtune && !menu) { - doSquelch(); - GetData(); - } - } - - } else { - if (af || (!screenmute || (screenmute && (XDRGTKTCP || XDRGTKUSB)))) { - if (band < BAND_GAP) radio.getStatus(&SStatus, &USN, &WAM, &OStatus, &BW, &MStatus, &CN); - else radio.getStatusAM(&SStatus, &USN, &WAM, &OStatus, &BW, &MStatus, &CN); - } - if (!BWtune && !menu) { - doSquelch(); - if (millis() >= tuningtimer + 200) readRds(); - GetData(); - if (!screenmute && !rdsstatscreen && !afscreen && !advancedRDS) ShowAudioLevel(); - } - } - - if (rotary == -1) { - tottimer = millis(); - if (screensavertriggered) { - if (!touchrotating) { - rotary = 0; - WakeToSleep(REVERSE); - } else { - if (BWtune) doBWtuneUp(); else KeyUp(); - } - } else { - if (BWtune) doBWtuneUp(); else KeyUp(); - if (rotaryaccelerate && rotarycounter > 2 && !BWtune && !menu) { - for (int i = 0; i < rotarycounteraccelerator; i++) KeyUp(); - rotarycounter = 0; - } - if (screensaverset > 0 && !BWtune && !menu && !screensavertriggered) screensavertimer = millis(); - } - } - - if (rotary == 1) { - tottimer = millis(); - if (screensavertriggered) { - if (!touchrotating) { - rotary = 0; - WakeToSleep(REVERSE); - } else { - if (BWtune) doBWtuneDown(); else KeyDown(); - } - } else { - if (BWtune) doBWtuneDown(); else KeyDown(); - if (rotaryaccelerate && rotarycounter > 2 && !BWtune && !menu) { - for (int i = 0; i < rotarycounteraccelerator; i++) KeyDown(); - rotarycounter = 0; - } - if (screensaverset > 0 && !BWtune && !menu && !screensavertriggered) screensavertimer = millis(); - } - } - - if (digitalRead(BANDBUTTON) == LOW) { - tottimer = millis(); - if (screensavertriggered) { - WakeToSleep(REVERSE); - while (digitalRead(BANDBUTTON) == LOW); - } else BANDBUTTONPress(); - } - - if (digitalRead(ROTARY_BUTTON) == LOW) { - tottimer = millis(); - if (screensavertriggered) { - WakeToSleep(REVERSE); - while (digitalRead(ROTARY_BUTTON) == LOW); - } else if (!afscreen && !rdsstatscreen) ButtonPress(); - } - - if (digitalRead(MODEBUTTON) == LOW) { - tottimer = millis(); - if (screensavertriggered) { - WakeToSleep(REVERSE); - while (digitalRead(MODEBUTTON) == LOW); - } else if(!screenmute) ModeButtonPress(); - } - - if (digitalRead(BWBUTTON) == LOW && !BWtune) { - tottimer = millis(); - if (screensavertriggered) { - WakeToSleep(REVERSE); - while (digitalRead(BWBUTTON) == LOW); - } else if(!screenmute) BWButtonPress(); - } - - if (digitalRead(EXT_IRQ) == LOW) { - if (screensavertriggered) WakeToSleep(REVERSE); - int num = GetNum(); - if (!screenmute && !BWtune && !menu && !advancedRDS && !rdsstatscreen && !afscreen && num != -1) NumpadProcess(num); - } - - if (screensaverset > 0 && !screensavertriggered && !BWtune && !menu && millis() >= screensavertimer + 1000 * screensaverOptions[screensaverset]) WakeToSleep(true); -} - void DivdeSWMIBand() { if (frequency_AM >= FREQ_SW_160M_START && frequency_AM <= FREQ_SW_160M_END) { SWMIBandPos = SW_MI_BAND_160M; frequency_MIBand_160M = frequency_AM; - SWMIBandstring = (String) "" + SWMIBandPos + " m"; + SWMIBandstring = (String)"" + SWMIBandPos + " m"; } else if (frequency_AM >= FREQ_SW_120M_START && frequency_AM <= FREQ_SW_120M_END) { SWMIBandPos = SW_MI_BAND_120M; frequency_MIBand_120M = frequency_AM; - SWMIBandstring = (String) "" + SWMIBandPos + " m"; + SWMIBandstring = (String)"" + SWMIBandPos + " m"; } else if (frequency_AM >= FREQ_SW_90M_START && frequency_AM <= FREQ_SW_90M_END) { SWMIBandPos = SW_MI_BAND_90M; frequency_MIBand_90M = frequency_AM; - SWMIBandstring = (String) "" + SWMIBandPos + " m"; + SWMIBandstring = (String)"" + SWMIBandPos + " m"; } else if (frequency_AM >= FREQ_SW_75M_START && frequency_AM <= FREQ_SW_75M_END) { SWMIBandPos = SW_MI_BAND_75M; frequency_MIBand_75M = frequency_AM; - SWMIBandstring = (String) "" + SWMIBandPos + " m"; + SWMIBandstring = (String)"" + SWMIBandPos + " m"; } else if (frequency_AM >= FREQ_SW_60M_START && frequency_AM <= FREQ_SW_60M_END) { SWMIBandPos = SW_MI_BAND_60M; frequency_MIBand_60M = frequency_AM; - SWMIBandstring = (String) "" + SWMIBandPos + " m"; + SWMIBandstring = (String)"" + SWMIBandPos + " m"; } else if (frequency_AM >= FREQ_SW_49M_START && frequency_AM <= FREQ_SW_49M_END) { SWMIBandPos = SW_MI_BAND_49M; frequency_MIBand_49M = frequency_AM; - SWMIBandstring = (String) "" + SWMIBandPos + " m"; + SWMIBandstring = (String)"" + SWMIBandPos + " m"; } else if (frequency_AM >= FREQ_SW_41M_START && frequency_AM <= FREQ_SW_41M_END) { SWMIBandPos = SW_MI_BAND_41M; frequency_MIBand_41M = frequency_AM; - SWMIBandstring = (String) "" + SWMIBandPos + " m"; + SWMIBandstring = (String)"" + SWMIBandPos + " m"; } else if (frequency_AM >= FREQ_SW_31M_START && frequency_AM <= FREQ_SW_31M_END) { SWMIBandPos = SW_MI_BAND_31M; frequency_MIBand_31M = frequency_AM; - SWMIBandstring = (String) "" + SWMIBandPos + " m"; + SWMIBandstring = (String)"" + SWMIBandPos + " m"; } else if (frequency_AM >= FREQ_SW_25M_START && frequency_AM <= FREQ_SW_25M_END) { SWMIBandPos = SW_MI_BAND_25M; frequency_MIBand_25M = frequency_AM; - SWMIBandstring = (String) "" + SWMIBandPos + " m"; + SWMIBandstring = (String)"" + SWMIBandPos + " m"; } else if (frequency_AM >= FREQ_SW_22M_START && frequency_AM <= FREQ_SW_22M_END) { SWMIBandPos = SW_MI_BAND_22M; frequency_MIBand_22M = frequency_AM; - SWMIBandstring = (String) "" + SWMIBandPos + " m"; + SWMIBandstring = (String)"" + SWMIBandPos + " m"; } else if (frequency_AM >= FREQ_SW_19M_START && frequency_AM <= FREQ_SW_19M_END) { SWMIBandPos = SW_MI_BAND_19M; frequency_MIBand_19M = frequency_AM; - SWMIBandstring = (String) "" + SWMIBandPos + " m"; + SWMIBandstring = (String)"" + SWMIBandPos + " m"; } else if (frequency_AM >= FREQ_SW_16M_START && frequency_AM <= FREQ_SW_16M_END) { SWMIBandPos = SW_MI_BAND_16M; frequency_MIBand_16M = frequency_AM; - SWMIBandstring = (String) "" + SWMIBandPos + " m"; + SWMIBandstring = (String)"" + SWMIBandPos + " m"; } else if (frequency_AM >= FREQ_SW_15M_START && frequency_AM <= FREQ_SW_15M_END) { SWMIBandPos = SW_MI_BAND_15M; frequency_MIBand_15M = frequency_AM; - SWMIBandstring = (String) "" + SWMIBandPos + " m"; + SWMIBandstring = (String)"" + SWMIBandPos + " m"; } else if (frequency_AM >= FREQ_SW_13M_START && frequency_AM <= FREQ_SW_13M_END) { SWMIBandPos = SW_MI_BAND_13M; frequency_MIBand_13M = frequency_AM; - SWMIBandstring = (String) "" + SWMIBandPos + " m"; + SWMIBandstring = (String)"" + SWMIBandPos + " m"; } else if (frequency_AM >= FREQ_SW_11M_START && frequency_AM <= FREQ_SW_11M_END) { SWMIBandPos = SW_MI_BAND_11M; frequency_MIBand_11M = frequency_AM; - SWMIBandstring = (String) "" + SWMIBandPos + " m"; + SWMIBandstring = (String)"" + SWMIBandPos + " m"; } else { if (SWMIBandPos > SW_MI_BAND_GAP) { SWMIBandPosold = SWMIBandPos; - SWMIBandstringold = (String) "" + SWMIBandPosold + " m"; + SWMIBandstringold = (String)"" + SWMIBandPosold + " m"; } SWMIBandPos = SW_MI_BAND_GAP; } } @@ -1689,16 +1002,16 @@ void ToggleSWMIBand(bool frequencyup) { break; case SW_MI_BAND_11M: if (frequencyup) { - SWMIBandstringold = (String) "" + SWMIBandPosold + " m"; + SWMIBandstringold = (String)"" + SWMIBandPosold + " m"; SWMIBandPos = SW_MI_BAND_160M; SWMIBandPosold = SWMIBandPos; - SWMIBandstring = (String) "" + SWMIBandPos + " m"; + SWMIBandstring = (String)"" + SWMIBandPos + " m"; frequency_AM = frequency_MIBand_160M == 0 ? FREQ_SW_160M_START : frequency_MIBand_160M; } else { - SWMIBandstringold = (String) "" + SWMIBandPosold + " m"; + SWMIBandstringold = (String)"" + SWMIBandPosold + " m"; SWMIBandPos = SW_MI_BAND_13M; SWMIBandPosold = SWMIBandPos; - SWMIBandstring = (String) "" + SWMIBandPos + " m"; + SWMIBandstring = (String)"" + SWMIBandPos + " m"; frequency_AM = frequency_MIBand_13M == 0 ? FREQ_SW_13M_END : frequency_MIBand_13M; } radio.SetFreqAM(frequency_AM); @@ -1706,16 +1019,16 @@ void ToggleSWMIBand(bool frequencyup) { break; case SW_MI_BAND_13M: if (frequencyup) { - SWMIBandstringold = (String) "" + SWMIBandPosold + " m"; + SWMIBandstringold = (String)"" + SWMIBandPosold + " m"; SWMIBandPos = SW_MI_BAND_11M; SWMIBandPosold = SWMIBandPos; - SWMIBandstring = (String) "" + SWMIBandPos + " m"; + SWMIBandstring = (String)"" + SWMIBandPos + " m"; frequency_AM = frequency_MIBand_11M == 0 ? FREQ_SW_11M_START : frequency_MIBand_11M; } else { - SWMIBandstringold = (String) "" + SWMIBandPosold + " m"; + SWMIBandstringold = (String)"" + SWMIBandPosold + " m"; SWMIBandPos = SW_MI_BAND_15M; SWMIBandPosold = SWMIBandPos; - SWMIBandstring = (String) "" + SWMIBandPos + " m"; + SWMIBandstring = (String)"" + SWMIBandPos + " m"; frequency_AM = frequency_MIBand_15M == 0 ? FREQ_SW_15M_END : frequency_MIBand_15M; } radio.SetFreqAM(frequency_AM); @@ -1774,16 +1087,16 @@ void ToggleSWMIBand(bool frequencyup) { break; case SW_MI_BAND_22M: if (frequencyup) { - SWMIBandstringold = (String) "" + SWMIBandPosold + " m"; + SWMIBandstringold = (String)"" + SWMIBandPosold + " m"; SWMIBandPos = SW_MI_BAND_19M; SWMIBandPosold = SWMIBandPos; - SWMIBandstring = (String) "" + SWMIBandPos + " m"; + SWMIBandstring = (String)"" + SWMIBandPos + " m"; frequency_AM = frequency_MIBand_19M == 0 ? FREQ_SW_19M_START : frequency_MIBand_19M; } else { - SWMIBandstringold = (String) "" + SWMIBandPosold + " m"; + SWMIBandstringold = (String)"" + SWMIBandPosold + " m"; SWMIBandPos = SW_MI_BAND_25M; SWMIBandPosold = SWMIBandPos; - SWMIBandstring = (String) "" + SWMIBandPos + " m"; + SWMIBandstring = (String)"" + SWMIBandPos + " m"; frequency_AM = frequency_MIBand_25M == 0 ? FREQ_SW_25M_END : frequency_MIBand_25M; } radio.SetFreqAM(frequency_AM); @@ -1791,16 +1104,16 @@ void ToggleSWMIBand(bool frequencyup) { break; case SW_MI_BAND_25M: if (frequencyup) { - SWMIBandstringold = (String) "" + SWMIBandPosold + " m"; + SWMIBandstringold = (String)"" + SWMIBandPosold + " m"; SWMIBandPos = SW_MI_BAND_22M; SWMIBandPosold = SWMIBandPos; - SWMIBandstring = (String) "" + SWMIBandPos + " m"; + SWMIBandstring = (String)"" + SWMIBandPos + " m"; frequency_AM = frequency_MIBand_22M == 0 ? FREQ_SW_22M_START : frequency_MIBand_22M; } else { - SWMIBandstringold = (String) "" + SWMIBandPosold + " m"; + SWMIBandstringold = (String)"" + SWMIBandPosold + " m"; SWMIBandPos = SW_MI_BAND_31M; SWMIBandPosold = SWMIBandPos; - SWMIBandstring = (String) "" + SWMIBandPos + " m"; + SWMIBandstring = (String)"" + SWMIBandPos + " m"; frequency_AM = frequency_MIBand_31M == 0 ? FREQ_SW_31M_END : frequency_MIBand_31M; } radio.SetFreqAM(frequency_AM); @@ -2040,92 +1353,26 @@ void SelectBand() { leave = false; } -void ModeButtonPress() { - if (seek) radio.setUnMute(); - seek = false; - if (scandxmode) { - ShowFreq(5); - ShowFreq(0); - } else { - if (!usesquelch) radio.setUnMute(); - if (advancedRDS) { - BuildDisplay(); - freq_in = 0; - SelectBand(); - screensavertimer = millis(); - } else if (afscreen) { - if (afpagenr == 1) afpagenr = 2; else if (afpagenr == 2 && afpage) afpagenr = 3; else afpagenr = 1; - BuildAFScreen(); - freq_in = 0; - } else if (rdsstatscreen) { - BuildAFScreen(); - freq_in = 0; - } else { - if (!BWtune && !menu) { - if (!screenmute) tft.drawBitmap(249, 4, Speaker, 28, 24, GreyoutColor); - memorystore = false; - unsigned long counterold = millis(); - unsigned long counter = millis(); - while (digitalRead(MODEBUTTON) == LOW && counter - counterold <= 1000) counter = millis(); - - if (counter - counterold <= 1000) { - doTuneMode(); - } else { - if (!BWtune && !menu) { - menuoption = ITEM1; - menupage = INDEX; - menuitem = 0; - if (language == LANGUAGE_CHS) PSSprite.setTextFont(1); else PSSprite.setTextFont(0); - BuildMenu(); - freq_in = 0; - menu = true; - } - } - } else { - if (menuopen && !submenu) { - ButtonPress(); - } else if (!submenu) { - OStatusold = 1000; - Stereostatusold = false; - SStatusold = 2000; - BWOld = 0; - if (frequency % 10 != 0) { - if (fmdefaultstepsize == 1) Round100K(frequency); else Round50K(frequency); - EEPROM.writeUInt(EE_UINT16_FREQUENCY_FM, frequency); - } - CheckBandForbiddenFM(); - CheckBandForbiddenAM(); - if (!usesquelch) radio.setUnMute(); - MWLowEdgeSet = mwstepsize == false ? FREQ_MW_LOW_EDGE_MIN_9K : FREQ_MW_LOW_EDGE_MIN_10K; - MWHighEdgeSet = mwstepsize == false ? FREQ_MW_HIGH_EDGE_MAX_9K : FREQ_MW_HIGH_EDGE_MAX_10K; - doBandSelectionFM(); - doBandSelectionAM(); - screensavertimer = millis(); - endMenu(); - } else { - if (submenu) { - if (menuopen) { - if (menupage == CONNECTIVITY && menuoption == ITEM2 && wifi) { - tryWiFi(); - delay(1750); - } - if (menupage == DISPLAYSETTINGS && menuoption == ITEM5) doTheme(); - menuopen = false; - } - submenu = false; - menuoption = ITEM1; - menupage = INDEX; - menuitem = 0; - if (language == LANGUAGE_CHS) PSSprite.setTextFont(1); else PSSprite.setTextFont(0); - BuildMenu(); - freq_in = 0; - } - } - } - } +void doTuneMode() { + switch (tunemode) { + case TUNE_MAN: + if (band == BAND_SW) { + if (showSWMIBand && nowToggleSWMIBand) tunemode = TUNE_MI_BAND; + else tunemode = TUNE_AUTO; + } else tunemode = TUNE_AUTO; + break; + case TUNE_MI_BAND: + case TUNE_AUTO: + tunemode = TUNE_MEM; + break; + case TUNE_MEM: + if (!bandforbidden) tunemode = TUNE_MAN; + break; } - while (digitalRead(MODEBUTTON) == LOW) delay(50); - delay(50); + ShowTuneMode(); + ShowMemoryPos(); + EEPROM.writeByte(EE_BYTE_TUNEMODE, tunemode); + EEPROM.commit(); } void RoundStep() { @@ -2157,7 +1404,6 @@ void RoundStep() { radio.SetFreqAM(frequency_AM); } } StoreFrequency(); - while (digitalRead(ROTARY_BUTTON) == LOW) delay(50); } @@ -2176,17 +1422,14 @@ void ButtonPress() { } if (!BWtune && !menu) { if (tunemode == TUNE_MEM) { + memorystore = !memorystore; if (!memorystore) { - memorystore = true; if (!IsStationEmpty()) memoryposstatus = MEM_EXIST; else memoryposstatus = MEM_NORMAL; ShowMemoryPos(); - ShowTuneMode(); } else { - memorystore = false; StoreMemoryPos(memorypos); - ShowTuneMode(); if (memoryposstatus == MEM_DARK || memoryposstatus == MEM_EXIST) { memoryposstatus = MEM_NORMAL; @@ -2196,7 +1439,7 @@ void ButtonPress() { } else { if (!screenmute) tft.drawBitmap(249, 4, Speaker, 28, 24, GreyoutColor); unsigned long counterold = millis(); - unsigned long counter = millis(); + unsigned long counter = counterold; while (digitalRead(ROTARY_BUTTON) == LOW && counter - counterold <= 1000) counter = millis(); if (counter - counterold < 1000) { @@ -2277,6 +1520,92 @@ void ButtonPress() { while (digitalRead(ROTARY_BUTTON) == LOW) delay(50); } +void ModeButtonPress() { + if (seek) radio.setUnMute(); + seek = false; + if (scandxmode) { + ShowFreq(5); + ShowFreq(0); + } else { + if (!usesquelch) radio.setUnMute(); + if (advancedRDS) { + BuildDisplay(); + freq_in = 0; + SelectBand(); + screensavertimer = millis(); + } else if (afscreen) { + if (afpagenr == 1) afpagenr = 2; else if (afpagenr == 2 && afpage) afpagenr = 3; else afpagenr = 1; + BuildAFScreen(); + freq_in = 0; + } else if (rdsstatscreen) { + BuildAFScreen(); + freq_in = 0; + } else { + if (!BWtune && !menu) { + if (!screenmute) tft.drawBitmap(249, 4, Speaker, 28, 24, GreyoutColor); + memorystore = false; + unsigned long counterold = millis(); + unsigned long counter = counterold; + while (digitalRead(MODEBUTTON) == LOW && counter - counterold <= 1000) counter = millis(); + + if (counter - counterold <= 1000) doTuneMode(); + else { + if (!BWtune && !menu) { + menuoption = ITEM1; + menupage = INDEX; + menuitem = 0; + if (language == LANGUAGE_CHS) PSSprite.setTextFont(1); else PSSprite.setTextFont(0); + BuildMenu(); + freq_in = 0; + menu = true; + } + } + } else { + if (menuopen && !submenu) ButtonPress(); + else if (!submenu) { + OStatusold = 1000; + Stereostatusold = false; + SStatusold = 2000; + BWOld = 0; + if (frequency % 10 != 0) { + if (fmdefaultstepsize == 1) Round100K(frequency); else Round50K(frequency); + EEPROM.writeUInt(EE_UINT16_FREQUENCY_FM, frequency); + } + CheckBandForbiddenFM(); + CheckBandForbiddenAM(); + if (!usesquelch) radio.setUnMute(); + MWLowEdgeSet = mwstepsize == false ? FREQ_MW_LOW_EDGE_MIN_9K : FREQ_MW_LOW_EDGE_MIN_10K; + MWHighEdgeSet = mwstepsize == false ? FREQ_MW_HIGH_EDGE_MAX_9K : FREQ_MW_HIGH_EDGE_MAX_10K; + doBandSelectionFM(); + doBandSelectionAM(); + screensavertimer = millis(); + endMenu(); + } else { + if (submenu) { + if (menuopen) { + if (menupage == CONNECTIVITY && menuoption == ITEM2 && wifi) { + tryWiFi(); + delay(1750); + } + if (menupage == DISPLAYSETTINGS && menuoption == ITEM5) doTheme(); + menuopen = false; + } + submenu = false; + menuoption = ITEM1; + menupage = INDEX; + menuitem = 0; + if (language == LANGUAGE_CHS) PSSprite.setTextFont(1); else PSSprite.setTextFont(0); + BuildMenu(); + freq_in = 0; + } + } + } + } + } + while (digitalRead(MODEBUTTON) == LOW) delay(50); + delay(50); +} + void KeyUp() { rotary = 0; if (scandxmode) { @@ -2378,8 +1707,7 @@ void KeyDown() { if (showSWMIBand) { if (displayflip) ToggleSWMIBand(REVERSE); else ToggleSWMIBand(true); - } - break; + } break; } if (XDRGTKUSB || XDRGTKTCP) { if (band == BAND_FM) DataPrint("M0\nT" + String(frequency * 10) + "\n"); else if (band == BAND_OIRT) DataPrint("M0\nT" + String(frequency_OIRT * 10) + "\n"); else DataPrint("M1\nT" + String(frequency_AM) + "\n"); @@ -2409,12 +1737,10 @@ void ShowMemoryPos() { memposcolor = InsignificantColor; memposcolorsmooth = InsignificantColorSmooth; break; - case MEM_NORMAL: memposcolor = PrimaryColor; memposcolorsmooth = PrimaryColorSmooth; break; - case MEM_EXIST: memposcolor = SignificantColor; memposcolorsmooth = SignificantColorSmooth; @@ -2615,376 +1941,6 @@ void ShowFreq(int mode) { } } -void ShowSignalLevel() { - SAvg = (((SAvg * 9) + 5) / 10) + SStatus; - SAvg2 = (((SAvg2 * 9) + 5) / 10) + CN; - SAvg4 = (((SAvg4 * 9) + 5) / 10) + WAM; - SAvg5 = (((SAvg5 * 9) + 5) / 10) + USN; - - SStatus = SAvg / 10; - CN = SAvg2 / 10; - MP = SAvg4 / 10; - US = SAvg5 / 10; - - if (!screenmute) { - if (millis() >= SNRupdatetimer + TIMER_SNR_TIMER) { - SNRupdatetimer = millis(); - if (!advancedRDS) { - if (CN > (CNold + 1) || CN < (CNold - 1)) { - if (CNold == 0) tftPrint16(ARIGHT, "--", 234, 165, BackgroundColor, BackgroundColor); else tftPrint16(ARIGHT, String(CNold), 234, 165, BackgroundColor, BackgroundColor); - if (tuned) { - if (CN == 0) tftPrint16(ARIGHT, "--", 234, 165, PrimaryColor, PrimaryColorSmooth); else tftPrint16(ARIGHT, String(CN), 234, 165, PrimaryColor, PrimaryColorSmooth); - CNold = CN; - } else { - tftPrint16(ARIGHT, "--", 234, 165, PrimaryColor, PrimaryColorSmooth); - CNold = 0; - } - } - - byte MPprint = constrain(map(MP, 0, 1000, 0, 100), 0, 100); - if (MPprint != MPold) { - tftReplace(ARIGHT, String(MPold), (band < BAND_GAP ? String(MPprint) : "--"), 299, 165, PrimaryColor, PrimaryColorSmooth, BackgroundColor, 16); - MPold = MPprint; - } - - byte USprint = constrain(map(US, 0, 1000, 0, 100), 0, 100); - if (USprint != USold) { - tftReplace(ARIGHT, String(USold), (band < BAND_GAP ? String(USprint) : "--"), 299, 147, PrimaryColor, PrimaryColorSmooth, BackgroundColor, 16); - USold = USprint; - } - } - } - - int SStatusprint = 0; - if (unit == 0) SStatusprint = SStatus; - if (unit == 1) SStatusprint = ((SStatus * 100) + 10875) / 100; - if (unit == 2) SStatusprint = round((float(SStatus) / 10.0 - 10.0 * log10(75) - 90.0) * 10.0); - - static int DisplayedSignalSegments = 0; - if (SStatusprint > (SStatusold + 3) || SStatusprint < (SStatusold - 3)) { - if (advancedRDS) tftReplace(ARIGHT, String(SStatusold / 10) + "." + String(abs(SStatusold % 10)), String(SStatusprint / 10) + "." + String(abs(SStatusprint % 10)), 273, 51, PrimaryColor, PrimaryColorSmooth, BackgroundColor, 16); - else { - if (SStatusold / 10 != SStatusprint / 10) tftReplace(ARIGHT, String(SStatusold / 10), String(SStatusprint / 10), 280, 104, FreqColor, FreqColorSmooth, BackgroundColor, 48); - tftReplace(ALEFT, "." + String(abs(SStatusold % 10)), "." + String(abs(SStatusprint % 10)), 285, 102, FreqColor, FreqColorSmooth, BackgroundColor, 28); - - // Calculate segments for signal meter - if (band < BAND_GAP) DisplayedSignalSegments = constrain(map(SStatus / 10, 0, 70, 0, 100), 0, 87); - else DisplayedSignalSegments = constrain((SStatus + 200) / 10, 0, 87); - - HSV hsv1 = RGB565toHSV(BarInsignificantColor); - HSV hsv2 = RGB565toHSV(BarSignificantColor); - - int gradientStart = (87 * 25) / 100; - int gradientEnd = (87 * 60) / 100; - - // Draw solid color for first 25% - for (int i = 0; i < min(DisplayedSignalSegments, gradientStart); i++) tft.fillRect(16 + 2 * i, 105, 2, 6, BarInsignificantColor); - - if (DisplayedSignalSegments > gradientStart) { - for (int i = gradientStart; i < min(DisplayedSignalSegments, gradientEnd); i++) { - float h = map(i, gradientStart, gradientEnd, hsv1.h, hsv2.h); - float s = map(i, gradientStart, gradientEnd, hsv1.s * 100, hsv2.s * 100) / 100.0; - float v = map(i, gradientStart, gradientEnd, hsv1.v * 100, hsv2.v * 100) / 100.0; - tft.fillRect(16 + 2 * i, 105, 2, 6, HSVtoRGB565(h, s, v)); - } - } - - if (DisplayedSignalSegments > gradientEnd) { - for (int i = gradientEnd; i < DisplayedSignalSegments; i++) tft.fillRect(16 + 2 * i, 105, 2, 6, BarSignificantColor); - } - - int greyStart = 16 + 2 * DisplayedSignalSegments; - int greyWidth = 2 * (87 - DisplayedSignalSegments); - tft.fillRect(greyStart, 105, greyWidth, 6, GreyoutColor); - } - - SStatusold = SStatusprint; - } - } - - if (!seek) { - if (tuned && CN > 15 && SStatus > 300) { - if (!setextendbw) { - setextendbw = true; - radio.extendBW(true); - } - } else { - if (setextendbw) { - setextendbw = false; - radio.extendBW(false); - } - } - } - - if (wifi && millis() >= udptimer + 2000) { - udptimer = millis(); - Udp.beginPacket(remoteip, 9030); - Udp.print("from=TEF_tuner_" + String(stationlistid, DEC) + ";RcvLevel=" + String(SStatus / 10)); - Udp.endPacket(); - } -} - -void ShowOffset() { - if (OStatus != OStatusold) { - if (millis() >= offsetupdatetimer + TIMER_OFFSET_TIMER) offsetupdatetimer = millis(); - else return; - - int baseX = 13; // Left boundary - int baseY = 2; // Top boundary - int width = 4; // Max width - int height = 26; // Max height - - int centerX = baseX + width / 2; // Center dot X - int centerY = baseY + height / 2; // Center dot Y - - // **Move arrows 3px further from the dot** - int arrowGap = 3; // Space between dot and arrows - int arrowWidth = 9; // Arrow stretch size - int leftArrowBaseX = centerX - arrowWidth - arrowGap; // Shift left arrow further left - int rightArrowBaseX = centerX + arrowWidth + arrowGap; // Shift right arrow further right - - int arrowBaseYTop = baseY + 1; // Adjusted top Y position - int arrowBaseYBottom = baseY + height - 1; - - if (band < BAND_GAP) { - if (OStatus < -250) { - // Left arrow active (▶) - tft.fillTriangle(leftArrowBaseX, arrowBaseYTop, centerX - arrowGap, centerY, leftArrowBaseX, arrowBaseYBottom, GreyoutColor); - // Center dot - tft.fillCircle(centerX, centerY, 3, GreyoutColor); - // Right arrow dimmed (◀) - tft.fillTriangle(rightArrowBaseX, arrowBaseYTop, centerX + arrowGap, centerY, rightArrowBaseX, arrowBaseYBottom, SignificantColor); - tuned = false; - } else if (USN < 250 && WAM < 250 && OStatus > -250 && OStatus < 250 && !SQ) { - // Both arrows dimmed - tft.fillTriangle(leftArrowBaseX, arrowBaseYTop, centerX - arrowGap, centerY, leftArrowBaseX, arrowBaseYBottom, GreyoutColor); - tft.fillTriangle(rightArrowBaseX, arrowBaseYTop, centerX + arrowGap, centerY, rightArrowBaseX, arrowBaseYBottom, GreyoutColor); - // Center dot active - tft.fillCircle(centerX, centerY, 3, InsignificantColor); - tuned = true; - } else if (OStatus > 250) { - // Right arrow active (◀) - tft.fillTriangle(rightArrowBaseX, arrowBaseYTop, centerX + arrowGap, centerY, rightArrowBaseX, arrowBaseYBottom, GreyoutColor); - // Center dot dimmed - tft.fillCircle(centerX, centerY, 3, GreyoutColor); - // Left arrow dimmed (▶) - tft.fillTriangle(leftArrowBaseX, arrowBaseYTop, centerX - arrowGap, centerY, leftArrowBaseX, arrowBaseYBottom, SignificantColor); - tuned = false; - } else { - // Everything dimmed - tft.fillTriangle(leftArrowBaseX, arrowBaseYTop, centerX - arrowGap, centerY, leftArrowBaseX, arrowBaseYBottom, GreyoutColor); - tft.fillTriangle(rightArrowBaseX, arrowBaseYTop, centerX + arrowGap, centerY, rightArrowBaseX, arrowBaseYBottom, GreyoutColor); - tft.fillCircle(centerX, centerY, 3, GreyoutColor); - tuned = false; - } - } else { - if (OStatus < -2) { - // Left arrow active (▶) - tft.fillTriangle(leftArrowBaseX, arrowBaseYTop, centerX - arrowGap, centerY, leftArrowBaseX, arrowBaseYBottom, GreyoutColor); - tft.fillCircle(centerX, centerY, 3, GreyoutColor); - // Right arrow dimmed (◀) - tft.fillTriangle(rightArrowBaseX, arrowBaseYTop, centerX + arrowGap, centerY, rightArrowBaseX, arrowBaseYBottom, SignificantColor); - tuned = false; - } else if (OStatus >= -2 && OStatus <= 2 && !SQ) { - tft.fillTriangle(leftArrowBaseX, arrowBaseYTop, centerX - arrowGap, centerY, leftArrowBaseX, arrowBaseYBottom, GreyoutColor); - tft.fillTriangle(rightArrowBaseX, arrowBaseYTop, centerX + arrowGap, centerY, rightArrowBaseX, arrowBaseYBottom, GreyoutColor); - tft.fillCircle(centerX, centerY, 3, InsignificantColor); - tuned = true; - } else if (OStatus > 2) { - // Right arrow active (◀) - tft.fillTriangle(rightArrowBaseX, arrowBaseYTop, centerX + arrowGap, centerY, rightArrowBaseX, arrowBaseYBottom, GreyoutColor); - tft.fillCircle(centerX, centerY, 3, GreyoutColor); - // Left arrow dimmed (▶) - tft.fillTriangle(leftArrowBaseX, arrowBaseYTop, centerX - arrowGap, centerY, leftArrowBaseX, arrowBaseYBottom, SignificantColor); - tuned = false; - } else { - tft.fillTriangle(leftArrowBaseX, arrowBaseYTop, centerX - arrowGap, centerY, leftArrowBaseX, arrowBaseYBottom, GreyoutColor); - tft.fillTriangle(rightArrowBaseX, arrowBaseYTop, centerX + arrowGap, centerY, rightArrowBaseX, arrowBaseYBottom, GreyoutColor); - tft.fillCircle(centerX, centerY, 3, GreyoutColor); - tuned = false; - } - } - OStatusold = OStatus; - } -} - -void ShowAudioLevel() { - if(showaudio) { - int segments; - MStatus = (MStatus > 120) ? 120 : MStatus; - - if (seek || SQ) MStatus = 0; - - segments = constrain(map(MStatus, 0, 120, 0, 86), 0, 86); - - if (segments < DisplayedSegments && (millis() - AudiopreviousMillis >= 20)) { - DisplayedSegments = max(DisplayedSegments - 3, segments); - AudiopreviousMillis = millis(); - } else if (segments > DisplayedSegments) DisplayedSegments = segments; - - DisplayedSegments = constrain(DisplayedSegments, 0, 86); - - if (DisplayedSegments > peakholdold) { - peakholdold = DisplayedSegments; - peakholdmillis = millis(); - } - - if (millis() - peakholdmillis >= 1000) { - if (millis() - AudiopeakPreviousMillis >= 20) { - peakholdold = max(peakholdold - 3, DisplayedSegments); - AudiopeakPreviousMillis = millis(); - } - } - - peakholdold = constrain(peakholdold, 0, 86); - - HSV hsv1 = RGB565toHSV(ModBarInsignificantColor); - HSV hsv2 = RGB565toHSV(ModBarSignificantColor); - - int gradientStart = (86 * 25) / 100; - int gradientEnd = (86 * 60) / 100; - - for (int i = 0; i < min(DisplayedSegments, gradientStart); i++) tft.fillRect(16 + 2 * i, 133, 2, 6, ModBarInsignificantColor); - - if (DisplayedSegments > gradientStart) { - for (int i = gradientStart; i < min(DisplayedSegments, gradientEnd); i++) { - float h = map(i, gradientStart, gradientEnd, hsv1.h, hsv2.h); - float s = map(i, gradientStart, gradientEnd, hsv1.s * 100, hsv2.s * 100) / 100.0; - float v = map(i, gradientStart, gradientEnd, hsv1.v * 100, hsv2.v * 100) / 100.0; - tft.fillRect(16 + 2 * i, 133, 2, 6, HSVtoRGB565(h, s, v)); - } - } - - if (DisplayedSegments > gradientEnd) { - for (int i = gradientEnd; i < DisplayedSegments; i++) tft.fillRect(16 + 2 * i, 133, 2, 6, ModBarSignificantColor); - } - - int greyStart = 16 + 2 * DisplayedSegments; - int greyWidth = 2 * (87 - DisplayedSegments); - tft.fillRect(greyStart, 133, greyWidth, 6, GreyoutColor); - - int peakHoldPosition = 16 + 2 * peakholdold; - tft.fillRect(peakHoldPosition, 133, 2, 6, (MStatus > 80) ? ModBarSignificantColor : PrimaryColor); - - if (millis() - peakholdmillis >= 1000 && (peakholdold <= DisplayedSegments || peakholdold >= 86)) tft.fillRect(peakHoldPosition, 133, 2, 6, GreyoutColor); - } -} - -void doSquelch() { - if (!XDRGTKUSB && !XDRGTKTCP && usesquelch && !autosquelch) Squelch = map(analogRead(PIN_POT), 0, 4095, -100, 920); - if (Squelch < - 800) Squelch = -100; - if (Squelch > 900) Squelch = 920; - - if (unit == 0) SquelchShow = Squelch / 10; - if (unit == 1) SquelchShow = ((Squelch * 100) + 10875) / 1000; - if (unit == 2) SquelchShow = round(((float)Squelch / 10.0 - 10.0 * log10(75) - 90.0) * 10.0) / 10; - if (Squelch > 920) Squelch = 920; - - if (autosquelch) { - if (band < BAND_GAP) { - if (isSignalQualityGood(USN, WAM, OStatus, SCAN_SIGNAL_THRESHOLD_USN_MULTIPLIER, SCAN_SIGNAL_THRESHOLD_OSTATUS_WIDE) && (!scandxmode || (scandxmode && !scanmute))) { - if (SQ || BWreset) { - if (!seek) radio.setUnMute(); - if (!screenmute && !seek) tft.drawBitmap(249, 4, Speaker, 28, 24, GreyoutColor); - autosquelchtimer = millis(); - SQ = false; - } - } else { - if ((!SQ || BWreset) && (millis() >= autosquelchtimer + 1000)) { - radio.setMute(); - if (!screenmute && !seek) tft.drawBitmap(249, 4, Speaker, 28, 24, PrimaryColor); - autosquelchtimer = millis(); - SQ = true; - } - } - } else { - if ((USN < amscansens * 30) && (OStatus < 2 && OStatus > -2) && (!scandxmode || (scandxmode && !scanmute))) { - if (!seek) radio.setUnMute(); - if (!screenmute && !seek) tft.drawBitmap(249, 4, Speaker, 28, 24, GreyoutColor); - SQ = false; - } else { - radio.setMute(); - if (!screenmute && !seek) tft.drawBitmap(249, 4, Speaker, 28, 24, PrimaryColor); - SQ = true; - } - } - } else { - if (!XDRGTKUSB && !XDRGTKTCP && usesquelch && (!scandxmode || (scandxmode && !scanmute))) { - if (!screenmute && usesquelch && !advancedRDS && !afscreen && !rdsstatscreen) { - if (!BWtune && !menu && (Squelch > Squelchold + 2 || Squelch < Squelchold - 2)) { - SquelchSprite.setTextColor(PrimaryColor, PrimaryColorSmooth, false); - SquelchSprite.fillSprite(BackgroundColor); - if (Squelch == -100) SquelchSprite.drawString("--", 0, 0); - else if (Squelch == 920) SquelchSprite.drawString("ST", 0, 0); - else SquelchSprite.drawString(String(SquelchShow), 0, 0); - SquelchSprite.pushSprite(223, 147); - Squelchold = Squelch; - } - } - } - - if ((XDRGTKUSB || XDRGTKTCP) && (!scandxmode || (scandxmode && !scanmute))) { - if (!XDRMute) { - if (Squelch != -1) { - if (Squelch < SStatus || Squelch == -100 || Squelch == 0) { - if (!seek) radio.setUnMute(); - if (!screenmute && !seek) tft.drawBitmap(249, 4, Speaker, 28, 24, GreyoutColor); - SQ = false; - } else { - radio.setMute(); - if (!screenmute && !seek) tft.drawBitmap(249, 4, Speaker, 28, 24, PrimaryColor); - SQ = true; - } - } else { - if (Stereostatus) { - radio.setUnMute(); - if (!screenmute && !seek) tft.drawBitmap(249, 4, Speaker, 28, 24, GreyoutColor); - SQ = false; - } else { - radio.setMute(); - if (!screenmute && !seek) tft.drawBitmap(249, 4, Speaker, 28, 24, PrimaryColor); - SQ = true; - } - } - if (!screenmute && usesquelch && !advancedRDS && !afscreen && !rdsstatscreen) { - if (Squelch != Squelchold) { - SquelchSprite.setTextColor(PrimaryColor, PrimaryColorSmooth); - SquelchSprite.fillSprite(BackgroundColor); - - if (Squelch == -1) SquelchSprite.drawString("ST", 0, 0); - else if (Squelch == 0) SquelchSprite.drawString("--", 0, 0); - else SquelchSprite.drawString(String(SquelchShow), 0, 0); - if (Squelch != Squelchold) SquelchSprite.pushSprite(223, 147); - Squelchold = Squelch; - } - } - } - } else if (usesquelch && (!scandxmode || (scandxmode && !scanmute))) { - if (Squelch != 920) { - if (Squelch < SStatus || Squelch == -100 || Squelch == 0) { - if (!seek) radio.setUnMute(); - if (!screenmute && !seek) tft.drawBitmap(249, 4, Speaker, 28, 24, GreyoutColor); - SQ = false; - } else { - radio.setMute(); - if (!screenmute && !seek) tft.drawBitmap(249, 4, Speaker, 28, 24, PrimaryColor); - SQ = true; - } - } else { - if (Stereostatus) { - if (!seek) radio.setUnMute(); - if (!screenmute && !seek) tft.drawBitmap(249, 4, Speaker, 28, 24, GreyoutColor); - SQ = false; - } else { - radio.setMute(); - if (!screenmute && !seek) tft.drawBitmap(249, 4, Speaker, 28, 24, PrimaryColor); - SQ = true; - } - } - } - } -} - void doBW() { if (BWtune && !bwtouchtune) BWset = BWsettemp; @@ -3050,28 +2006,6 @@ void doBW() { EEPROM.commit(); } -void doTuneMode() { - switch (tunemode) { - case TUNE_MAN: - if (band == BAND_SW) { - if (showSWMIBand && nowToggleSWMIBand) tunemode = TUNE_MI_BAND; - else tunemode = TUNE_AUTO; - } else tunemode = TUNE_AUTO; - break; - case TUNE_MI_BAND: - case TUNE_AUTO: - tunemode = TUNE_MEM; - break; - case TUNE_MEM: - if (!bandforbidden) tunemode = TUNE_MAN; - break; - } - ShowTuneMode(); - ShowMemoryPos(); - EEPROM.writeByte(EE_BYTE_TUNEMODE, tunemode); - EEPROM.commit(); -} - void ShowTuneMode() { if (!screenmute) { switch (tunemode) { @@ -3143,45 +2077,6 @@ void ShowTuneMode() { } } -void ShowBattery() { - if (millis() >= batupdatetimer + TIMER_BAT_TIMER) batupdatetimer = millis(); - else return; - - float v = analogReadMilliVolts(BATTERY_PIN) * 0.002; // 0.002 converts to volts plus corrects the /2 voltage divider - byte battery = map(constrain(v, BATTERY_LOW_VALUE, BATTERY_FULL_VALUE), BATTERY_LOW_VALUE, BATTERY_FULL_VALUE, 0, BAT_LEVEL_STAGE); - byte batteryprobe = map(constrain(v, BATTERY_LOW_VALUE, BATTERY_FULL_VALUE), BATTERY_LOW_VALUE, BATTERY_FULL_VALUE, 0, 50); - if (batteryold != batteryprobe) { - if (batterydetect) { - if (battery == 0) { - tft.drawRoundRect(277, 6, 37, 20, 2, BarSignificantColor); - tft.fillRoundRect(313, 13, 4, 6, 2, BarSignificantColor); - } else { - tft.drawRoundRect(277, 6, 37, 20, 2, ActiveColor); - tft.fillRoundRect(313, 13, 4, 6, 2, ActiveColor); - } - - if (batteryoptions != BATTERY_VALUE && batteryoptions != BATTERY_PERCENT && battery != 0) { - if(v > BATTERY_FULL_VALUE) tft.fillRoundRect(279, 8, 32, 16, 2, ActiveColor); - else tft.fillRoundRect(279, 8, battery * 8, 16, 2, SecondaryColor); - } else tft.fillRoundRect(279, 8, 32, 16, 2, BackgroundColor); - } - batteryold = batteryprobe; - batteryVold = 0; - vPerold = 0; - - if (batterydetect) { - float vPer = constrain((v - BATTERY_LOW_VALUE) / (BATTERY_FULL_VALUE - BATTERY_LOW_VALUE), 0.0, 1.0) * 100.0; - if (abs(v - batteryVold) > 0.05 && batteryoptions == BATTERY_VALUE) { - tftPrint(ALEFT, String(v, 2) + "V", 279, 9, BatteryValueColor, BatteryValueColorSmooth, 16); - batteryVold = v; - } else if (int(vPer) != int(vPerold) && batteryoptions == BATTERY_PERCENT && abs(vPer - vPerold) > 0.5) { - tftPrint(ALEFT, String(vPer, 0) + "%", 279, 9, BatteryValueColor, BatteryValueColorSmooth, 16); - vPerold = vPer; - } - } - } -} - void TuneUp() { aftest = true; aftimer = millis(); @@ -3306,10 +2201,10 @@ void TuneDown() { } } } - if (stepsize == 1) temp = 1; - else if (stepsize == 2) temp = 10; - else if (stepsize == 3) temp = 100; - else if (stepsize == 4) temp = 1000; + if(stepsize == 1) temp = 1; + else if(stepsize == 2) temp = 10; + else if(stepsize == 3) temp = 100; + else if(stepsize == 4) temp = 1000; if (rotaryaccelerate && rotarycounter > 2) temp *= 2; if (band == BAND_FM) { @@ -3404,126 +2299,17 @@ void Seek(bool mode) { } } -void tftReplace(int8_t offset, const String & textold, const String & text, int16_t x, int16_t y, int color, int smoothcolor, int background, uint8_t fontsize) { - uint8_t selectedFont = 0 ? (language == LANGUAGE_CHS) : 2; - if(fontsize == 28) selectedFont = (language == LANGUAGE_CHS) ? 4 : 3; - else if(fontsize == 48) selectedFont = 1; - - switch (offset) { - case -1: tft.setTextDatum(TL_DATUM); break; - case 0: tft.setTextDatum(TC_DATUM); break; - case 1: tft.setTextDatum(TR_DATUM); break; - } - - tft.setTextColor(background, background, false); - tft.drawString(textold, x, y, selectedFont); - - String modifiedText = text; - modifiedText.replace("\n", " "); - - tft.setTextColor(color, smoothcolor, false); - tft.drawString(modifiedText, x, y, selectedFont); -} - -void tftReplace16(int8_t offset, const String & textold, const String & text, int16_t x, int16_t y, int color, int smoothcolor, int background, bool force_font, bool font) { - uint8_t selectedFont = (language == LANGUAGE_CHS) ? 0 : 2; - if(force_font) selectedFont = 0 ? font : 2; - - switch (offset) { - case -1: tft.setTextDatum(TL_DATUM); break; - case 0: tft.setTextDatum(TC_DATUM); break; - case 1: tft.setTextDatum(TR_DATUM); break; - } - - tft.setTextColor(background, background, false); - tft.drawString(textold, x, y, selectedFont); - - String modifiedText = text; - modifiedText.replace("\n", " "); - - tft.setTextColor(color, smoothcolor, false); - tft.drawString(modifiedText, x, y, selectedFont); -} - -void tftPrint(int8_t offset, const String & text, int16_t x, int16_t y, int color, int smoothcolor, uint8_t fontsize) { - uint8_t selectedFont = (language == LANGUAGE_CHS) ? 0 : 2; - if (fontsize == 28) selectedFont = (language == LANGUAGE_CHS) ? 4 : 3; - else if (fontsize == 48) selectedFont = 1; - - tft.setTextColor(color, smoothcolor); - - switch (offset) { - case -1: tft.setTextDatum(TL_DATUM); break; - case 0: tft.setTextDatum(TC_DATUM); break; - case 1: tft.setTextDatum(TR_DATUM); break; - } - - String modifiedText = text; - modifiedText.replace("\n", " "); - - tft.drawString(modifiedText, x, y, selectedFont); -} - -void tftPrint16(int8_t offset, const String & text, int16_t x, int16_t y, int color, int smoothcolor, bool force_font, bool font) { - uint8_t selectedFont = (language == LANGUAGE_CHS) ? 0 : 2; - if(force_font) selectedFont = 0 ? font : 2; - - tft.setTextColor(color, smoothcolor); - - switch (offset) { - case -1: tft.setTextDatum(TL_DATUM); break; - case 0: tft.setTextDatum(TC_DATUM); break; - case 1: tft.setTextDatum(TR_DATUM); break; - } - - String modifiedText = text; - modifiedText.replace("\n", " "); - - tft.drawString(modifiedText, x, y, selectedFont); -} - -void UpdateFonts() { - // This is at setup: - // tft.loadFont(FONT48, 1); - - // tft.loadFont(FONT16_CHS, 0); - // tft.loadFont(FONT16, 2); - // tft.loadFont(FONT28, 3); - // tft.loadFont(FONT28_CHS, 4); - - if (language == LANGUAGE_CHS) { - if (menu) PSSprite.setTextFont(1); else PSSprite.setTextFont(3); - OneBigLineSprite.copyFontFromTFT(4, 0); - FullLineSprite.copyFontFromTFT(0, 0); - GeneralTextSprite.copyFontFromTFT(0, 0); - GeneralTextSprite.copyFontFromTFT(4, 1); - FrequencySprite.copyFontFromTFT(0, 6); - SquelchSprite.copyFontFromTFT(0, 0); - } else { - if (menu) PSSprite.setTextFont(0); else PSSprite.setTextFont(2); - OneBigLineSprite.copyFontFromTFT(3, 0); - FullLineSprite.copyFontFromTFT(2, 0); - GeneralTextSprite.copyFontFromTFT(2, 0); - GeneralTextSprite.copyFontFromTFT(3, 1); - FrequencySprite.copyFontFromTFT(2, 6); - SquelchSprite.copyFontFromTFT(2, 0); - } -} - uint8_t doAutoMemory(uint16_t startfreq, uint16_t stopfreq, uint8_t startmem, uint8_t stopmem, bool rdsonly, uint8_t doublepi) { - uint8_t error = 0; - uint8_t counter = 0; + uint8_t error = 0, counter = 0, percent = 0, percentold = 0; uint8_t rangestart = startmem; uint16_t _current = frequency; uint16_t totalIterations = (stopfreq - startfreq) + 1; uint16_t currentIteration = 0; - uint8_t percent = 0; - uint8_t percentold = 0; bool stopScanning = false; bool dostore = false; radio.setMute(); - radio.power(0); + radio.power(false); band = BAND_FM; tunemode = TUNE_MAN; @@ -3531,7 +2317,7 @@ uint8_t doAutoMemory(uint16_t startfreq, uint16_t stopfreq, uint8_t startmem, ui tft.fillRect(60, 110, 200, 6, GreyoutColor); tftPrint(ARIGHT, textUI(268), 120, 155, ActiveColor, ActiveColorSmooth, 16); - for (frequency = startfreq * 10; frequency <= stopfreq * 10; frequency += 10) { + for(frequency = startfreq * 10; frequency <= stopfreq * 10; frequency += 10) { if (stopScanning) break; currentIteration++; diff --git a/src/globals.cpp b/src/globals.cpp index 1aee8bd..4c94d8e 100644 --- a/src/globals.cpp +++ b/src/globals.cpp @@ -321,8 +321,8 @@ unsigned long tuningtimer; unsigned long udplogtimer; unsigned long udptimer; bool rds_settings_changed; -const size_t language_totalnumber = sizeof(myLanguage) / sizeof(myLanguage[0]); -const size_t language_entrynumber = sizeof(myLanguage[0]) / sizeof(myLanguage[0][0]); +const size_t language_totalnumber = sizeof(Languages) / sizeof(Languages[0]); +const size_t language_entrynumber = sizeof(Languages[0]) / sizeof(Languages[0][0]); volatile bool i2c_pc_control = false; volatile bool i2c_pc_control_init = false; diff --git a/src/graphics.cpp b/src/graphics.cpp new file mode 100644 index 0000000..9d95862 --- /dev/null +++ b/src/graphics.cpp @@ -0,0 +1,107 @@ +#include "graphics.h" + +void tftPrint(int8_t offset, const String & text, int16_t x, int16_t y, int color, int smoothcolor, uint8_t fontsize) { + uint8_t selectedFont = (language == LANGUAGE_CHS) ? 0 : 2; + if (fontsize == 28) selectedFont = (language == LANGUAGE_CHS) ? 4 : 3; + else if (fontsize == 48) selectedFont = 1; + + tft.setTextColor(color, smoothcolor); + + switch (offset) { + case -1: tft.setTextDatum(TL_DATUM); break; + case 0: tft.setTextDatum(TC_DATUM); break; + case 1: tft.setTextDatum(TR_DATUM); break; + } + + String modifiedText = text; + modifiedText.replace("\n", " "); + + tft.drawString(modifiedText, x, y, selectedFont); +} + +void tftPrint16(int8_t offset, const String & text, int16_t x, int16_t y, int color, int smoothcolor, bool force_font, bool font) { + uint8_t selectedFont = (language == LANGUAGE_CHS) ? 0 : 2; + if(force_font) selectedFont = 0 ? font : 2; + + tft.setTextColor(color, smoothcolor); + + switch (offset) { + case -1: tft.setTextDatum(TL_DATUM); break; + case 0: tft.setTextDatum(TC_DATUM); break; + case 1: tft.setTextDatum(TR_DATUM); break; + } + + String modifiedText = text; + modifiedText.replace("\n", " "); + + tft.drawString(modifiedText, x, y, selectedFont); +} + +void tftReplace(int8_t offset, const String & textold, const String & text, int16_t x, int16_t y, int color, int smoothcolor, int background, uint8_t fontsize) { + uint8_t selectedFont = 0 ? (language == LANGUAGE_CHS) : 2; + if(fontsize == 28) selectedFont = (language == LANGUAGE_CHS) ? 4 : 3; + else if(fontsize == 48) selectedFont = 1; + + switch (offset) { + case -1: tft.setTextDatum(TL_DATUM); break; + case 0: tft.setTextDatum(TC_DATUM); break; + case 1: tft.setTextDatum(TR_DATUM); break; + } + + tft.setTextColor(background, background, false); + tft.drawString(textold, x, y, selectedFont); + + String modifiedText = text; + modifiedText.replace("\n", " "); + + tft.setTextColor(color, smoothcolor, false); + tft.drawString(modifiedText, x, y, selectedFont); +} + +void tftReplace16(int8_t offset, const String & textold, const String & text, int16_t x, int16_t y, int color, int smoothcolor, int background, bool force_font, bool font) { + uint8_t selectedFont = (language == LANGUAGE_CHS) ? 0 : 2; + if(force_font) selectedFont = 0 ? font : 2; + + switch (offset) { + case -1: tft.setTextDatum(TL_DATUM); break; + case 0: tft.setTextDatum(TC_DATUM); break; + case 1: tft.setTextDatum(TR_DATUM); break; + } + + tft.setTextColor(background, background, false); + tft.drawString(textold, x, y, selectedFont); + + String modifiedText = text; + modifiedText.replace("\n", " "); + + tft.setTextColor(color, smoothcolor, false); + tft.drawString(modifiedText, x, y, selectedFont); +} + +void UpdateFonts() { + // This is at setup: + // tft.loadFont(FONT48, 1); + + // tft.loadFont(FONT16_CHS, 0); + // tft.loadFont(FONT16, 2); + // tft.loadFont(FONT28, 3); + // tft.loadFont(FONT28_CHS, 4); + + if (language == LANGUAGE_CHS) { + if (menu) PSSprite.setTextFont(1); else PSSprite.setTextFont(3); + OneBigLineSprite.copyFontFromTFT(4, 0); + FullLineSprite.copyFontFromTFT(0, 0); + GeneralTextSprite.copyFontFromTFT(0, 0); + GeneralTextSprite.copyFontFromTFT(4, 1); + FrequencySprite.copyFontFromTFT(0, 6); + SquelchSprite.copyFontFromTFT(0, 0); + } else { + if (menu) PSSprite.setTextFont(0); else PSSprite.setTextFont(2); + OneBigLineSprite.copyFontFromTFT(3, 0); + FullLineSprite.copyFontFromTFT(2, 0); + GeneralTextSprite.copyFontFromTFT(2, 0); + GeneralTextSprite.copyFontFromTFT(3, 1); + FrequencySprite.copyFontFromTFT(2, 6); + SquelchSprite.copyFontFromTFT(2, 0); + } +} \ No newline at end of file diff --git a/src/gui.cpp b/src/gui.cpp index 999d28d..7a6cf17 100644 --- a/src/gui.cpp +++ b/src/gui.cpp @@ -5614,4 +5614,82 @@ String shortLine(String text) { text = tempText + "..."; } return text; +} + +void ShowRDSLogo(bool RDSstatus) { + if (screenmute) return; + if (RDSstatus != RDSstatusold) { + if (RDSstatus) tft.drawBitmap(68, 5, RDSLogo, 35, 22, RDSColor); + else tft.drawBitmap(68, 5, RDSLogo, 35, 22, GreyoutColor); + } + RDSstatusold = RDSstatus; +} + +void showAutoSquelch(bool mode) { + if (screenmute) return; + if (mode) tft.drawBitmap(223, 147, AutoSQ, 18, 18, PrimaryColor); + else tft.drawBitmap(223, 147, AutoSQ, 18, 18, BackgroundColor); +} + +void updateiMS() { + if (band < BAND_GAP) { + if (iMSset == 0) { + if (!screenmute && !advancedRDS && !afscreen && !rdsstatscreen && !BWtune) { + tft.fillRoundRect(249, 57, 30, 18, 2, SecondaryColor); + tftPrint16(ACENTER, "iMS", 265, 59, BackgroundColor, SecondaryColor); + } radio.setiMS(1); + } else { + if (!screenmute && !advancedRDS && !afscreen && !rdsstatscreen && !BWtune) { + tft.fillRoundRect(249, 57, 30, 18, 2, GreyoutColor); + tftPrint16(ACENTER, "iMS", 265, 59, BackgroundColor, GreyoutColor); + } radio.setiMS(0); + } + } +} + +void updateEQ() { + if (band < BAND_GAP) { + if (EQset == 0) { + if (!screenmute && !advancedRDS && !afscreen && !rdsstatscreen && !BWtune) { + tft.fillRoundRect(287, 57, 30, 18, 2, SecondaryColor); + tftPrint16(ACENTER, "EQ", 301, 59, BackgroundColor, SecondaryColor); + } radio.setEQ(1); + } else { + if (!screenmute && !advancedRDS && !afscreen && !rdsstatscreen && !BWtune) { + tft.fillRoundRect(287, 57, 30, 18, 2, GreyoutColor); + tftPrint16(ACENTER, "EQ", 301, 59, BackgroundColor, GreyoutColor); + } radio.setEQ(0); + } + } +} + +void updateBW() { + if (BWset == 0) { + if (!BWtune && !screenmute && !advancedRDS && !afscreen && !rdsstatscreen) { + tft.fillRoundRect(248, 36, 69, 18, 2, SecondaryColor); + tftPrint16(ACENTER, "AUTO BW", 282, 38, BackgroundColor, SecondaryColor); + } radio.setFMABandw(); + } else { + if (!BWtune && !screenmute && !advancedRDS && !afscreen && !rdsstatscreen) { + tft.fillRoundRect(248, 36, 69, 18, 2, GreyoutColor); + tftPrint16(ACENTER, "AUTO BW", 282, 38, BackgroundColor, GreyoutColor); + } + } +} + +void ShowStepSize() { + if (!advancedRDS) { + tft.fillRect(191, 38, 15, 4, GreyoutColor); + tft.fillRect(222, 38, 15, 4, GreyoutColor); + if (band < BAND_GAP) tft.fillRect(113, 38, 15, 4, GreyoutColor); else if (band != BAND_LW && band != BAND_MW) tft.fillRect(129, 38, 15, 4, GreyoutColor); + if (band < BAND_GAP) tft.fillRect(144, 38, 15, 4, GreyoutColor); else tft.fillRect(159, 38, 15, 4, GreyoutColor); + if (stepsize == 1) tft.fillRect(222, 38, 15, 4, InsignificantColor); + if (stepsize == 2) tft.fillRect(191, 38, 15, 4, InsignificantColor); + if (stepsize == 3) { + if (band < BAND_GAP) tft.fillRect(144, 38, 15, 4, InsignificantColor); else tft.fillRect(159, 38, 15, 4, InsignificantColor); + } + if (stepsize == 4) { + if (band < BAND_GAP) tft.fillRect(113, 38, 15, 4, InsignificantColor); else tft.fillRect(129, 38, 15, 4, InsignificantColor); + } + } } \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index db41d43..5ec971a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,6 +9,8 @@ #include "FONT28_CHS.h" #include "FONT48DEC.h" #include "FREQFONT.h" +#include "touch.h" +#include "rds.h" void Touch_IRQ_Handler() { touch_detect = true; @@ -448,4 +450,985 @@ void setup() { screensavertimer = millis(); tottimer = millis(); console.reset(); +} + +#include "comms.h" + +void handleWiFi() { + if (wifi && !menu) { + webserver.handleClient(); + + if (millis() >= udplogtimer + UDP_LOG_INTERVAL_MS) { + sendUDPlog(); + udplogtimer = millis(); + } + + if (millis() >= NTPtimer + NTP_UPDATE_INTERVAL_MS) { + NTPupdate(); + NTPtimer = millis(); + } + } +} + +void handleTouch() { + if (hardwaremodel == PORTABLE_TOUCH_ILI9341 && touch_detect) { + if (tft.getTouchRawZ() > TOUCH_RAW_Z_THRESHOLD) { + uint16_t x, y; + tft.getTouch(&x, &y); + if (x > 0 || y > 0) { + if (!firstTouchHandled) { + doTouchEvent(x, y); + firstTouchHandled = true; + lastTouchTime = millis(); + } else if (touchrepeat && millis() - lastTouchTime >= DELAY_TOUCH_REPEAT_MS) doTouchEvent(x, y); + } + } else { + firstTouchHandled = false; + touch_detect = false; + } + } +} + +void handleTimers() { + // tottimer is like the time of the last interaction + if (tot != 0 && millis() >= tottimer + (tot * TOT_MULTIPLIER_MS)) deepSleep(); + + if (freq_in != 0 && millis() >= keypadtimer + DELAY_KEYPAD_TIMEOUT_MS) { + freq_in = 0; + ShowFreq(0); + if (tunemode == TUNE_MEM) ShowMemoryPos(); + } +} + +void ShowAudioLevel() { + if(showaudio) { + int segments; + MStatus = (MStatus > 120) ? 120 : MStatus; + + if (seek || SQ) MStatus = 0; + + segments = constrain(map(MStatus, 0, 120, 0, 86), 0, 86); + + if (segments < DisplayedSegments && (millis() - AudiopreviousMillis >= 20)) { + DisplayedSegments = max(DisplayedSegments - 3, segments); + AudiopreviousMillis = millis(); + } else if (segments > DisplayedSegments) DisplayedSegments = segments; + + DisplayedSegments = constrain(DisplayedSegments, 0, 86); + + if (DisplayedSegments > peakholdold) { + peakholdold = DisplayedSegments; + peakholdmillis = millis(); + } + + if (millis() - peakholdmillis >= 1000) { + if (millis() - AudiopeakPreviousMillis >= 20) { + peakholdold = max(peakholdold - 3, DisplayedSegments); + AudiopeakPreviousMillis = millis(); + } + } + + peakholdold = constrain(peakholdold, 0, 86); + + HSV hsv1 = RGB565toHSV(ModBarInsignificantColor); + HSV hsv2 = RGB565toHSV(ModBarSignificantColor); + + int gradientStart = (86 * 25) / 100; + int gradientEnd = (86 * 60) / 100; + + for (int i = 0; i < min(DisplayedSegments, gradientStart); i++) tft.fillRect(16 + 2 * i, 133, 2, 6, ModBarInsignificantColor); + + if (DisplayedSegments > gradientStart) { + for (int i = gradientStart; i < min(DisplayedSegments, gradientEnd); i++) { + float h = map(i, gradientStart, gradientEnd, hsv1.h, hsv2.h); + float s = map(i, gradientStart, gradientEnd, hsv1.s * 100, hsv2.s * 100) / 100.0; + float v = map(i, gradientStart, gradientEnd, hsv1.v * 100, hsv2.v * 100) / 100.0; + tft.fillRect(16 + 2 * i, 133, 2, 6, HSVtoRGB565(h, s, v)); + } + } + + if (DisplayedSegments > gradientEnd) { + for (int i = gradientEnd; i < DisplayedSegments; i++) tft.fillRect(16 + 2 * i, 133, 2, 6, ModBarSignificantColor); + } + + int greyStart = 16 + 2 * DisplayedSegments; + int greyWidth = 2 * (87 - DisplayedSegments); + tft.fillRect(greyStart, 133, greyWidth, 6, GreyoutColor); + + int peakHoldPosition = 16 + 2 * peakholdold; + tft.fillRect(peakHoldPosition, 133, 2, 6, (MStatus > 80) ? ModBarSignificantColor : PrimaryColor); + + if (millis() - peakholdmillis >= 1000 && (peakholdold <= DisplayedSegments || peakholdold >= 86)) tft.fillRect(peakHoldPosition, 133, 2, 6, GreyoutColor); + } +} + +void doLog() { + if (!autologged && RDSstatus && radio.rds.correctPI != 0) { + if (autolog) { + switch (addRowToCSV()) { + case 0: ShowFreq(2); break; + case 1: ShowFreq(3); break; + case 2: ShowFreq(4); break; + } + + delay(DELAY_UI_UPDATE_MS); + ShowFreq(0); + } + autologged = true; + } +} + +void doSquelch() { + if (!XDRGTKUSB && !XDRGTKTCP && usesquelch && !autosquelch) Squelch = map(analogRead(PIN_POT), 0, 4095, -100, 920); + if (Squelch < - 800) Squelch = -100; + if (Squelch > 900) Squelch = 920; + + if (unit == 0) SquelchShow = Squelch / 10; + if (unit == 1) SquelchShow = ((Squelch * 100) + 10875) / 1000; + if (unit == 2) SquelchShow = round(((float)Squelch / 10.0 - 10.0 * log10(75) - 90.0) * 10.0) / 10; + if (Squelch > 920) Squelch = 920; + + if (autosquelch) { + if (band < BAND_GAP) { + if (isSignalQualityGood(USN, WAM, OStatus, SCAN_SIGNAL_THRESHOLD_USN_MULTIPLIER, SCAN_SIGNAL_THRESHOLD_OSTATUS_WIDE) && (!scandxmode || (scandxmode && !scanmute))) { + if (SQ || BWreset) { + if (!seek) radio.setUnMute(); + if (!screenmute && !seek) tft.drawBitmap(249, 4, Speaker, 28, 24, GreyoutColor); + autosquelchtimer = millis(); + SQ = false; + } + } else { + if ((!SQ || BWreset) && (millis() >= autosquelchtimer + 1000)) { + radio.setMute(); + if (!screenmute && !seek) tft.drawBitmap(249, 4, Speaker, 28, 24, PrimaryColor); + autosquelchtimer = millis(); + SQ = true; + } + } + } else { + if ((USN < amscansens * 30) && (OStatus < 2 && OStatus > -2) && (!scandxmode || (scandxmode && !scanmute))) { + if (!seek) radio.setUnMute(); + if (!screenmute && !seek) tft.drawBitmap(249, 4, Speaker, 28, 24, GreyoutColor); + SQ = false; + } else { + radio.setMute(); + if (!screenmute && !seek) tft.drawBitmap(249, 4, Speaker, 28, 24, PrimaryColor); + SQ = true; + } + } + } else { + if (!XDRGTKUSB && !XDRGTKTCP && usesquelch && (!scandxmode || (scandxmode && !scanmute))) { + if (!screenmute && usesquelch && !advancedRDS && !afscreen && !rdsstatscreen) { + if (!BWtune && !menu && (Squelch > Squelchold + 2 || Squelch < Squelchold - 2)) { + SquelchSprite.setTextColor(PrimaryColor, PrimaryColorSmooth, false); + SquelchSprite.fillSprite(BackgroundColor); + if (Squelch == -100) SquelchSprite.drawString("--", 0, 0); + else if (Squelch == 920) SquelchSprite.drawString("ST", 0, 0); + else SquelchSprite.drawString(String(SquelchShow), 0, 0); + SquelchSprite.pushSprite(223, 147); + Squelchold = Squelch; + } + } + } + + if ((XDRGTKUSB || XDRGTKTCP) && (!scandxmode || (scandxmode && !scanmute))) { + if (!XDRMute) { + if (Squelch != -1) { + if (Squelch < SStatus || Squelch == -100 || Squelch == 0) { + if (!seek) radio.setUnMute(); + if (!screenmute && !seek) tft.drawBitmap(249, 4, Speaker, 28, 24, GreyoutColor); + SQ = false; + } else { + radio.setMute(); + if (!screenmute && !seek) tft.drawBitmap(249, 4, Speaker, 28, 24, PrimaryColor); + SQ = true; + } + } else { + if (Stereostatus) { + radio.setUnMute(); + if (!screenmute && !seek) tft.drawBitmap(249, 4, Speaker, 28, 24, GreyoutColor); + SQ = false; + } else { + radio.setMute(); + if (!screenmute && !seek) tft.drawBitmap(249, 4, Speaker, 28, 24, PrimaryColor); + SQ = true; + } + } + if (!screenmute && usesquelch && !advancedRDS && !afscreen && !rdsstatscreen) { + if (Squelch != Squelchold) { + SquelchSprite.setTextColor(PrimaryColor, PrimaryColorSmooth); + SquelchSprite.fillSprite(BackgroundColor); + + if (Squelch == -1) SquelchSprite.drawString("ST", 0, 0); + else if (Squelch == 0) SquelchSprite.drawString("--", 0, 0); + else SquelchSprite.drawString(String(SquelchShow), 0, 0); + if (Squelch != Squelchold) SquelchSprite.pushSprite(223, 147); + Squelchold = Squelch; + } + } + } + } else if (usesquelch && (!scandxmode || (scandxmode && !scanmute))) { + if (Squelch != 920) { + if (Squelch < SStatus || Squelch == -100 || Squelch == 0) { + if (!seek) radio.setUnMute(); + if (!screenmute && !seek) tft.drawBitmap(249, 4, Speaker, 28, 24, GreyoutColor); + SQ = false; + } else { + radio.setMute(); + if (!screenmute && !seek) tft.drawBitmap(249, 4, Speaker, 28, 24, PrimaryColor); + SQ = true; + } + } else { + if (Stereostatus) { + if (!seek) radio.setUnMute(); + if (!screenmute && !seek) tft.drawBitmap(249, 4, Speaker, 28, 24, GreyoutColor); + SQ = false; + } else { + radio.setMute(); + if (!screenmute && !seek) tft.drawBitmap(249, 4, Speaker, 28, 24, PrimaryColor); + SQ = true; + } + } + } + } +} + +void ShowSignalLevel() { + SAvg = (((SAvg * 9) + 5) / 10) + SStatus; + SAvg2 = (((SAvg2 * 9) + 5) / 10) + CN; + SAvg4 = (((SAvg4 * 9) + 5) / 10) + WAM; + SAvg5 = (((SAvg5 * 9) + 5) / 10) + USN; + + SStatus = SAvg / 10; + CN = SAvg2 / 10; + MP = SAvg4 / 10; + US = SAvg5 / 10; + + if (!screenmute) { + if (millis() >= SNRupdatetimer + TIMER_SNR_TIMER) { + SNRupdatetimer = millis(); + if (!advancedRDS) { + if (CN > (CNold + 1) || CN < (CNold - 1)) { + if (CNold == 0) tftPrint16(ARIGHT, "--", 234, 165, BackgroundColor, BackgroundColor); else tftPrint16(ARIGHT, String(CNold), 234, 165, BackgroundColor, BackgroundColor); + if (tuned) { + if (CN == 0) tftPrint16(ARIGHT, "--", 234, 165, PrimaryColor, PrimaryColorSmooth); else tftPrint16(ARIGHT, String(CN), 234, 165, PrimaryColor, PrimaryColorSmooth); + CNold = CN; + } else { + tftPrint16(ARIGHT, "--", 234, 165, PrimaryColor, PrimaryColorSmooth); + CNold = 0; + } + } + + byte MPprint = constrain(map(MP, 0, 1000, 0, 100), 0, 100); + if (MPprint != MPold) { + tftReplace(ARIGHT, String(MPold), (band < BAND_GAP ? String(MPprint) : "--"), 299, 165, PrimaryColor, PrimaryColorSmooth, BackgroundColor, 16); + MPold = MPprint; + } + + byte USprint = constrain(map(US, 0, 1000, 0, 100), 0, 100); + if (USprint != USold) { + tftReplace(ARIGHT, String(USold), (band < BAND_GAP ? String(USprint) : "--"), 299, 147, PrimaryColor, PrimaryColorSmooth, BackgroundColor, 16); + USold = USprint; + } + } + } + + int SStatusprint = 0; + if (unit == 0) SStatusprint = SStatus; + if (unit == 1) SStatusprint = ((SStatus * 100) + 10875) / 100; + if (unit == 2) SStatusprint = round((float(SStatus) / 10.0 - 10.0 * log10(75) - 90.0) * 10.0); + + static int DisplayedSignalSegments = 0; + if (SStatusprint > (SStatusold + 3) || SStatusprint < (SStatusold - 3)) { + if (advancedRDS) tftReplace(ARIGHT, String(SStatusold / 10) + "." + String(abs(SStatusold % 10)), String(SStatusprint / 10) + "." + String(abs(SStatusprint % 10)), 273, 51, PrimaryColor, PrimaryColorSmooth, BackgroundColor, 16); + else { + if (SStatusold / 10 != SStatusprint / 10) tftReplace(ARIGHT, String(SStatusold / 10), String(SStatusprint / 10), 280, 104, FreqColor, FreqColorSmooth, BackgroundColor, 48); + tftReplace(ALEFT, "." + String(abs(SStatusold % 10)), "." + String(abs(SStatusprint % 10)), 285, 102, FreqColor, FreqColorSmooth, BackgroundColor, 28); + + // Calculate segments for signal meter + if (band < BAND_GAP) DisplayedSignalSegments = constrain(map(SStatus / 10, 0, 70, 0, 100), 0, 87); + else DisplayedSignalSegments = constrain((SStatus + 200) / 10, 0, 87); + + HSV hsv1 = RGB565toHSV(BarInsignificantColor); + HSV hsv2 = RGB565toHSV(BarSignificantColor); + + int gradientStart = (87 * 25) / 100; + int gradientEnd = (87 * 60) / 100; + + // Draw solid color for first 25% + for (int i = 0; i < min(DisplayedSignalSegments, gradientStart); i++) tft.fillRect(16 + 2 * i, 105, 2, 6, BarInsignificantColor); + + if (DisplayedSignalSegments > gradientStart) { + for (int i = gradientStart; i < min(DisplayedSignalSegments, gradientEnd); i++) { + float h = map(i, gradientStart, gradientEnd, hsv1.h, hsv2.h); + float s = map(i, gradientStart, gradientEnd, hsv1.s * 100, hsv2.s * 100) / 100.0; + float v = map(i, gradientStart, gradientEnd, hsv1.v * 100, hsv2.v * 100) / 100.0; + tft.fillRect(16 + 2 * i, 105, 2, 6, HSVtoRGB565(h, s, v)); + } + } + + if (DisplayedSignalSegments > gradientEnd) { + for (int i = gradientEnd; i < DisplayedSignalSegments; i++) tft.fillRect(16 + 2 * i, 105, 2, 6, BarSignificantColor); + } + + int greyStart = 16 + 2 * DisplayedSignalSegments; + int greyWidth = 2 * (87 - DisplayedSignalSegments); + tft.fillRect(greyStart, 105, greyWidth, 6, GreyoutColor); + } + + SStatusold = SStatusprint; + } + } + + if (!seek) { + if (tuned && CN > 15 && SStatus > 300) { + if (!setextendbw) { + setextendbw = true; + radio.extendBW(true); + } + } else { + if (setextendbw) { + setextendbw = false; + radio.extendBW(false); + } + } + } + + if (wifi && millis() >= udptimer + 2000) { + udptimer = millis(); + Udp.beginPacket(remoteip, 9030); + Udp.print("from=TEF_tuner_" + String(stationlistid, DEC) + ";RcvLevel=" + String(SStatus / 10)); + Udp.endPacket(); + } +} + +void ShowStereoStatus() { + if (StereoToggle) { + if (band < BAND_GAP) Stereostatus = radio.getStereoStatus(); else Stereostatus = false; + if (Stereostatus != Stereostatusold) { + if (Stereostatus && !screenmute) tft.drawBitmap(STEREO_ICON_X, STEREO_ICON_Y, Stereo, 32, 22, StereoColor); + else if (!screenmute) tft.drawBitmap(STEREO_ICON_X, STEREO_ICON_Y, Stereo, 32, 22, GreyoutColor); + Stereostatusold = Stereostatus; + } + } +} + +void ShowRSSI() { + if (wifi) rssi = WiFi.RSSI(); else rssi = 0; + if (rssiold != rssi) { + if (!wifi && batterydetect) tft.drawBitmap(WIFI_ICON_X, WIFI_ICON_Y, WiFi4, WIFI_ICON_WIDTH, WIFI_ICON_HEIGHT, BackgroundColor); + else if (rssi == 0) tft.drawBitmap(WIFI_ICON_X, WIFI_ICON_Y, WiFi4, WIFI_ICON_WIDTH, WIFI_ICON_HEIGHT, GreyoutColor); + else if (rssi > -50 && rssi < 0) tft.drawBitmap(WIFI_ICON_X, WIFI_ICON_Y, WiFi4, WIFI_ICON_WIDTH, WIFI_ICON_HEIGHT, WifiColorHigh); + else if (rssi > -60) { + tft.drawBitmap(WIFI_ICON_X, WIFI_ICON_Y, WiFi4, WIFI_ICON_WIDTH, WIFI_ICON_HEIGHT, GreyoutColor); + tft.drawBitmap(WIFI_ICON_X, WIFI_ICON_Y, WiFi3, WIFI_ICON_WIDTH, WIFI_ICON_HEIGHT, WifiColorHigh); + } else if (rssi > -70) { + tft.drawBitmap(WIFI_ICON_X, WIFI_ICON_Y, WiFi4, WIFI_ICON_WIDTH, WIFI_ICON_HEIGHT, GreyoutColor); + tft.drawBitmap(WIFI_ICON_X, WIFI_ICON_Y, WiFi2, WIFI_ICON_WIDTH, WIFI_ICON_HEIGHT, WifiColorLow); + } else if (rssi < -70) { + tft.drawBitmap(WIFI_ICON_X, WIFI_ICON_Y, WiFi4, WIFI_ICON_WIDTH, WIFI_ICON_HEIGHT, GreyoutColor); + tft.drawBitmap(WIFI_ICON_X, WIFI_ICON_Y, WiFi1, WIFI_ICON_WIDTH, WIFI_ICON_HEIGHT, WifiColorLow); + } + rssiold = rssi; + } +} + +void ShowBW() { + if (!BWtune && millis() >= bwupdatetimer + TIMER_BW_TIMER) bwupdatetimer = millis(); + else if(!BWtune) return; + + if (BW != BWOld || BWreset) { + if(BW == 0) panic("BW is 0"); + else if(BW > 311) panic("BW larger than 311"); + + if(BWset == 0) tftReplace(ARIGHT, String(BWOld, DEC), String(BW, DEC), 203, 4, BWAutoColor, BWAutoColorSmooth, BackgroundColor, 28); else tftReplace(ARIGHT, String (BWOld, DEC), String(BW, DEC), 203, 4, PrimaryColor, PrimaryColorSmooth, BackgroundColor, 28); + BWOld = BW; + BWreset = false; + if (wifi) { + Udp.beginPacket(remoteip, 9030); + Udp.print("from=TEF_tuner_" + String(stationlistid, DEC) + ";bandwidth=" + String(BW * 1000)); + Udp.endPacket(); + } + } +} + +void ShowOffset() { + if (OStatus != OStatusold) { + if (millis() >= offsetupdatetimer + TIMER_OFFSET_TIMER) offsetupdatetimer = millis(); + else return; + + int baseX = 13; // Left boundary + int baseY = 2; // Top boundary + int width = 4; // Max width + int height = 26; // Max height + + int centerX = baseX + width / 2; // Center dot X + int centerY = baseY + height / 2; // Center dot Y + + // **Move arrows 3px further from the dot** + int arrowGap = 3; // Space between dot and arrows + int arrowWidth = 9; // Arrow stretch size + int leftArrowBaseX = centerX - arrowWidth - arrowGap; // Shift left arrow further left + int rightArrowBaseX = centerX + arrowWidth + arrowGap; // Shift right arrow further right + + int arrowBaseYTop = baseY + 1; // Adjusted top Y position + int arrowBaseYBottom = baseY + height - 1; + + if (band < BAND_GAP) { + if (OStatus < -250) { + // Left arrow active (▶) + tft.fillTriangle(leftArrowBaseX, arrowBaseYTop, centerX - arrowGap, centerY, leftArrowBaseX, arrowBaseYBottom, GreyoutColor); + // Center dot + tft.fillCircle(centerX, centerY, 3, GreyoutColor); + // Right arrow dimmed (◀) + tft.fillTriangle(rightArrowBaseX, arrowBaseYTop, centerX + arrowGap, centerY, rightArrowBaseX, arrowBaseYBottom, SignificantColor); + tuned = false; + } else if (USN < 250 && WAM < 250 && OStatus > -250 && OStatus < 250 && !SQ) { + // Both arrows dimmed + tft.fillTriangle(leftArrowBaseX, arrowBaseYTop, centerX - arrowGap, centerY, leftArrowBaseX, arrowBaseYBottom, GreyoutColor); + tft.fillTriangle(rightArrowBaseX, arrowBaseYTop, centerX + arrowGap, centerY, rightArrowBaseX, arrowBaseYBottom, GreyoutColor); + // Center dot active + tft.fillCircle(centerX, centerY, 3, InsignificantColor); + tuned = true; + } else if (OStatus > 250) { + // Right arrow active (◀) + tft.fillTriangle(rightArrowBaseX, arrowBaseYTop, centerX + arrowGap, centerY, rightArrowBaseX, arrowBaseYBottom, GreyoutColor); + // Center dot dimmed + tft.fillCircle(centerX, centerY, 3, GreyoutColor); + // Left arrow dimmed (▶) + tft.fillTriangle(leftArrowBaseX, arrowBaseYTop, centerX - arrowGap, centerY, leftArrowBaseX, arrowBaseYBottom, SignificantColor); + tuned = false; + } else { + // Everything dimmed + tft.fillTriangle(leftArrowBaseX, arrowBaseYTop, centerX - arrowGap, centerY, leftArrowBaseX, arrowBaseYBottom, GreyoutColor); + tft.fillTriangle(rightArrowBaseX, arrowBaseYTop, centerX + arrowGap, centerY, rightArrowBaseX, arrowBaseYBottom, GreyoutColor); + tft.fillCircle(centerX, centerY, 3, GreyoutColor); + tuned = false; + } + } else { + if (OStatus < -2) { + // Left arrow active (▶) + tft.fillTriangle(leftArrowBaseX, arrowBaseYTop, centerX - arrowGap, centerY, leftArrowBaseX, arrowBaseYBottom, GreyoutColor); + tft.fillCircle(centerX, centerY, 3, GreyoutColor); + // Right arrow dimmed (◀) + tft.fillTriangle(rightArrowBaseX, arrowBaseYTop, centerX + arrowGap, centerY, rightArrowBaseX, arrowBaseYBottom, SignificantColor); + tuned = false; + } else if (OStatus >= -2 && OStatus <= 2 && !SQ) { + tft.fillTriangle(leftArrowBaseX, arrowBaseYTop, centerX - arrowGap, centerY, leftArrowBaseX, arrowBaseYBottom, GreyoutColor); + tft.fillTriangle(rightArrowBaseX, arrowBaseYTop, centerX + arrowGap, centerY, rightArrowBaseX, arrowBaseYBottom, GreyoutColor); + tft.fillCircle(centerX, centerY, 3, InsignificantColor); + tuned = true; + } else if (OStatus > 2) { + // Right arrow active (◀) + tft.fillTriangle(rightArrowBaseX, arrowBaseYTop, centerX + arrowGap, centerY, rightArrowBaseX, arrowBaseYBottom, GreyoutColor); + tft.fillCircle(centerX, centerY, 3, GreyoutColor); + // Left arrow dimmed (▶) + tft.fillTriangle(leftArrowBaseX, arrowBaseYTop, centerX - arrowGap, centerY, leftArrowBaseX, arrowBaseYBottom, SignificantColor); + tuned = false; + } else { + tft.fillTriangle(leftArrowBaseX, arrowBaseYTop, centerX - arrowGap, centerY, leftArrowBaseX, arrowBaseYBottom, GreyoutColor); + tft.fillTriangle(rightArrowBaseX, arrowBaseYTop, centerX + arrowGap, centerY, rightArrowBaseX, arrowBaseYBottom, GreyoutColor); + tft.fillCircle(centerX, centerY, 3, GreyoutColor); + tuned = false; + } + } + OStatusold = OStatus; + } +} + +inline __attribute__((always_inline)) void updateCodetect() { + if (band > BAND_GAP) { + if (WAM) tftPrint16(ALEFT, "CO", 50, 61, PrimaryColor, PrimaryColorSmooth); + else tftPrint16(ALEFT, "CO", 50, 61, BackgroundColor, BackgroundColor); + } +} + +void ShowBattery() { + if (millis() >= batupdatetimer + TIMER_BAT_TIMER) batupdatetimer = millis(); + else return; + + float v = analogReadMilliVolts(BATTERY_PIN) * 0.002; // 0.002 converts to volts plus corrects the /2 voltage divider + byte battery = map(constrain(v, BATTERY_LOW_VALUE, BATTERY_FULL_VALUE), BATTERY_LOW_VALUE, BATTERY_FULL_VALUE, 0, BAT_LEVEL_STAGE); + byte batteryprobe = map(constrain(v, BATTERY_LOW_VALUE, BATTERY_FULL_VALUE), BATTERY_LOW_VALUE, BATTERY_FULL_VALUE, 0, 50); + if (batteryold != batteryprobe) { + if (batterydetect) { + if (battery == 0) { + tft.drawRoundRect(277, 6, 37, 20, 2, BarSignificantColor); + tft.fillRoundRect(313, 13, 4, 6, 2, BarSignificantColor); + } else { + tft.drawRoundRect(277, 6, 37, 20, 2, ActiveColor); + tft.fillRoundRect(313, 13, 4, 6, 2, ActiveColor); + } + + if (batteryoptions != BATTERY_VALUE && batteryoptions != BATTERY_PERCENT && battery != 0) { + if(v > BATTERY_FULL_VALUE) tft.fillRoundRect(279, 8, 32, 16, 2, ActiveColor); + else tft.fillRoundRect(279, 8, battery * 8, 16, 2, SecondaryColor); + } else tft.fillRoundRect(279, 8, 32, 16, 2, BackgroundColor); + } + batteryold = batteryprobe; + batteryVold = 0; + vPerold = 0; + + if (batterydetect) { + float vPer = constrain((v - BATTERY_LOW_VALUE) / (BATTERY_FULL_VALUE - BATTERY_LOW_VALUE), 0.0, 1.0) * 100.0; + if (abs(v - batteryVold) > 0.05 && batteryoptions == BATTERY_VALUE) { + tftPrint(ALEFT, String(v, 2) + "V", 279, 9, BatteryValueColor, BatteryValueColorSmooth, 16); + batteryVold = v; + } else if (int(vPer) != int(vPerold) && batteryoptions == BATTERY_PERCENT && abs(vPer - vPerold) > 0.5) { + tftPrint(ALEFT, String(vPer, 0) + "%", 279, 9, BatteryValueColor, BatteryValueColorSmooth, 16); + vPerold = vPer; + } + } + } +} + +void GetData() { + if (!afscreen && !rdsstatscreen) ShowSignalLevel(); + if (!BWtune && !menu && !rdsstatscreen) showPS(); + + if (band < BAND_GAP && !BWtune && !menu) { + if (advancedRDS && !afscreen && !rdsstatscreen && !screenmute) ShowAdvancedRDS(); + if (!advancedRDS && !afscreen && rdsstatscreen && !screenmute) ShowRDSStatistics(); + if (afscreen && !screenmute) ShowAFEON(); + if (!afscreen && !rdsstatscreen) { + if (!screenmute) ShowErrors(); + showPTY(); + showRadioText(); + if (millis() >= tuningtimer + 200) doAF(); + } + showPI(); + } + + ShowStereoStatus(); + + if (!screenmute) { + showCT(); + ShowRSSI(); + ShowOffset(); + ShowBW(); + updateCodetect(); + if (millis() >= tuningtimer + 200 && !wifi) ShowBattery(); + } +} + +inline __attribute__((always_inline)) const char* getBWButtonLabel(byte temp, bool isFM) { + constexpr byte BW_OK_BUTTON = 20; + if (temp == BW_OK_BUTTON) return "OK"; + return isFM ? BWButtonLabelsFM[temp - 1] : BWButtonLabelsAM[temp - 1]; +} +inline __attribute__((always_inline)) bool shouldHighlightBWButton(byte temp, byte set) { + return (set == temp) || (temp == 17 && set == 0) || (temp == 18 && !iMSset) || (temp == 19 && !EQset); +} + +void doBWtuneUp() { + rotary = 0; + constexpr byte BW_OK_BUTTON = 20; + constexpr byte BW_AM_MAX = 4; + + if (band < BAND_GAP) { + // FM band + drawButton(getBWButtonLabel(BWsettemp, true), BWsettemp - 1, shouldHighlightBWButton(BWsettemp, BWset), false); + BWsettemp++; + if (BWsettemp > BW_OK_BUTTON) BWsettemp = 1; + drawButton(getBWButtonLabel(BWsettemp, true), BWsettemp - 1, shouldHighlightBWButton(BWsettemp, BWset), true); + } else { + // AM band + drawButton(getBWButtonLabel(BWsettemp, false), BWsettemp - 1, (BWset == BWsettemp), false); + BWsettemp++; + if (BWsettemp > BW_AM_MAX && BWsettemp < BW_OK_BUTTON) BWsettemp = BW_OK_BUTTON; + else if (BWsettemp > BW_OK_BUTTON) BWsettemp = 1; + drawButton(getBWButtonLabel(BWsettemp, false), BWsettemp - 1, (BWset == BWsettemp), true); + } +} + +void doBWtuneDown() { + rotary = 0; + constexpr byte BW_OK_BUTTON = 20; + constexpr byte BW_AM_MAX = 4; + + if (band < BAND_GAP) { + // FM band + drawButton(getBWButtonLabel(BWsettemp, true), BWsettemp - 1, shouldHighlightBWButton(BWsettemp, BWset), false); + BWsettemp--; + if (BWsettemp > BW_OK_BUTTON || BWsettemp == 0) BWsettemp = BW_OK_BUTTON; + drawButton(getBWButtonLabel(BWsettemp, true), BWsettemp - 1, shouldHighlightBWButton(BWsettemp, BWset), true); + } else { + // AM band + drawButton(getBWButtonLabel(BWsettemp, false), BWsettemp - 1, (BWset == BWsettemp), false); + BWsettemp--; + if (BWsettemp > BW_AM_MAX && BWsettemp < BW_OK_BUTTON) BWsettemp = BW_AM_MAX; + else if (BWsettemp == 0) BWsettemp = BW_OK_BUTTON; + drawButton(getBWButtonLabel(BWsettemp, false), BWsettemp - 1, (BWset == BWsettemp), true); + } +} + +void loop() { + if(i2c_pc_control) { + total_pc_control(); + if(i2c_pc_control) return; + } + + handleWiFi(); + handleTouch(); + Communication(); + handleTimers(); + + if (scandxmode) { + unsigned long waitTime = (scanhold == 0) ? SCAN_HOLD_DEFAULT_MS : (scanhold * 1000); + if (!scanholdflag) scanholdflag = isSignalQualityGood(USN, WAM, OStatus); + bool bypassMillisCheck = scanholdonsignal && !scanholdflag; + bool shouldScan = bypassMillisCheck || (!bypassMillisCheck && (millis() >= scantimer + waitTime)); + + if (shouldScan) { + if (scanmute && scanholdonsignal) { + radio.setMute(); + if (!screenmute) tft.drawBitmap(SPEAKER_ICON_X, SPEAKER_ICON_Y, Speaker, SPEAKER_ICON_WIDTH, SPEAKER_ICON_HEIGHT, PrimaryColor); + SQ = true; + } + scanholdflag = false; + if (scanmem) { + memorypos++; + if (memorypos > scanstop) memorypos = scanstart; + while (IsStationEmpty() || (presets[memorypos].band != BAND_FM && presets[memorypos].band != BAND_OIRT)) { + memorypos++; + if (memorypos > scanstop) { + memorypos = scanstart; + break; + } + } + doLog(); + DoMemoryPosTune(); + radio.clearRDS(); + autologged = false; + ShowMemoryPos(); + } else { + doLog(); + TuneUp(); + autologged = false; + ShowFreq(0); + if (XDRGTKUSB || XDRGTKTCP) DataPrint("T" + String((frequency + ConverterSet * 100) * 10) + "\n"); + } + scantimer = millis(); + initdxscan = false; + } else { + if (scanmute && scanholdonsignal) { + radio.setUnMute(); + SQ = false; + if (!screenmute) tft.drawBitmap(249, 4, Speaker, 28, 24, GreyoutColor); + } + } + + if (millis() >= flashingtimer + 500) { + flashing = !flashing; + if (flashing) { + tft.fillRoundRect(2, 80, 40, 18, 2, SecondaryColor); + tftPrint16(ACENTER, "MEM", 22, 82, BackgroundColor, SecondaryColor); + } else { + tft.fillRoundRect(2, 80, 40, 18, 2, GreyoutColor); + tftPrint16(ACENTER, "MEM", 22, 82, BackgroundColor, GreyoutColor); + } flashingtimer = millis(); + } + + if (!scanholdflag) delay(75); + radio.getStatus(&SStatus, &USN, &WAM, &OStatus, &BW, &MStatus, &CN); + + if (!initdxscan) { + switch (scancancel) { + case CORRECTPI: + if (RDSstatus && radio.rds.correctPI != 0) cancelDXScan(); + break; + case SIGNAL: + if (isSignalQualityGood(USN, WAM, OStatus) && (Squelch < SStatus || Squelch == SQUELCH_MAX_VALUE)) cancelDXScan(); + break; + } + } + } + + if (millis() >= tuningtimer + 200) rdsflagreset = false; + + if (millis() >= tuningtimer + 2000) { + if (store) { + StoreFrequency(); + store = false; + } + } + + if (!BWtune && !menu && !afscreen && !rdsstatscreen && !scandxmode) { + if (af != 0 && dropout && millis() >= aftimer + 1000) { + aftimer = millis(); + if (radio.af_counter == 0) { + if (findMemoryAF && radio.rds.correctPI != 0 && tunemode == TUNE_MEM && (USN > 250 || WAM > 250)) { + radio.setMute(); + tft.drawBitmap(249, 4, Speaker, 28, 24, PrimaryColor); + SQ = true; + if (!screenmute) { + if (advancedRDS) { + tft.drawRoundRect(10, 30, 300, 170, 2, ActiveColor); + tft.fillRoundRect(12, 32, 296, 166, 2, BackgroundColor); + tftPrint(ACENTER, textUI(31), 160, 100, ActiveColor, ActiveColorSmooth, 28); + } else ShowFreq(1); + } + + bool foundmemaf = false; + for (int x = 8750; x <= 10800; x += 10) { + if (rotary != 0 || digitalRead(BANDBUTTON) == LOW || digitalRead(MODEBUTTON) == LOW || digitalRead(BWBUTTON) == LOW || digitalRead(ROTARY_BUTTON) == LOW) break; + radio.SetFreq(x); + unsigned long millisold = millis(); + while (millis() - millisold < 187) { + if (!screenmute && !advancedRDS) ShowAudioLevel(); + } + if (radio.rds.correctPI == radio.getBlockA()) { + frequency = x; + foundmemaf = true; + break; + } + } + + if (!foundmemaf) { + frequency = freqold; + radio.SetFreq(frequency); + } + + if (!screenmute) { + if (advancedRDS) { + leave = true; + BuildAdvancedRDS(); + freq_in = 0; + } else ShowFreq(0); + } + + radio.setUnMute(); + SQ = false; + tft.drawBitmap(249, 4, Speaker, 28, 24, GreyoutColor); + } + findMemoryAF = false; + } else frequency = radio.TestAF(); + if (freqold != frequency) { + ShowFreq(0); + dropout = true; + if (radio.afmethodB) { + afmethodBold = true; + radio.clearRDS(); + } + } + if (XDRGTKUSB || XDRGTKTCP) DataPrint("T" + String((frequency + ConverterSet * 100) * 10) + "\n"); + if (screenmute) { + freqold = frequency; + dropout = false; + } + store = true; + } + + if (band == BAND_FM && af != 0 && radio.rds.correctPI != 0) { + if ((aftest && millis() >= aftimer + 3000) || ((USN > 250 || WAM > 250) && millis() >= aftimer + 1000)) { + aftimer = millis(); + aftest = false; + frequency = radio.TestAF(); + if (freqold != frequency) { + ShowFreq(0); + dropout = true; + if (radio.afmethodB) { + afmethodBold = true; + radio.clearRDS(); + } + if (XDRGTKUSB || XDRGTKTCP) DataPrint("T" + String((frequency + ConverterSet * 100) * 10) + "\n"); + if (screenmute) { + freqold = frequency; + dropout = false; + } + store = true; + } + } + + if (band == BAND_FM && millis() >= aftimer + 10000) { + aftimer = millis(); + if (USN > 150 || WAM > 150) { + frequency = radio.TestAF(); + if (freqold != frequency) { + ShowFreq(0); + dropout = true; + if (radio.afmethodB) { + afmethodBold = true; + radio.clearRDS(); + } + if (XDRGTKUSB || XDRGTKTCP) DataPrint("T" + String((frequency + ConverterSet * 100) * 10) + "\n"); + store = true; + if (screenmute) { + freqold = frequency; + dropout = false; + } + } + } + } + } + } + + if(seek) Seek(direction); + + if ((SStatus / 10 > LowLevelSet) && !LowLevelInit && !BWtune && !menu && band < BAND_GAP) { + if (!screenmute && !advancedRDS && !rdsstatscreen && !afscreen) { + if (showaudio) { + tftPrint16(ALEFT, "10", 24, 144, ActiveColor, ActiveColorSmooth); + tftPrint16(ALEFT, "30", 54, 144, ActiveColor, ActiveColorSmooth); + tftPrint16(ALEFT, "50", 84, 144, ActiveColor, ActiveColorSmooth); + tftPrint16(ALEFT, "70", 114, 144, ActiveColor, ActiveColorSmooth); + tftPrint16(ALEFT, "100", 160, 144, ActiveColor, ActiveColorSmooth); + tftPrint16(ACENTER, "A", 7, 128, ActiveColor, ActiveColorSmooth); + for (byte segments = 0; segments < 93; segments++) { + if (segments > 54) { + if (((segments - 53) % 10) == 0) tft.fillRect(22 + (2 * segments), 141, 2, 2, BarSignificantColor); + } else { + if (((segments + 1) % 6) == 0) tft.fillRect(22 + (2 * segments), 141, 2, 2, BarInsignificantColor); + } + } + } + if (radio.rds.region == 0) tftPrint16(ALEFT, "PI", 212, 193, ActiveColor, ActiveColorSmooth); + else { + tftPrint16(ALEFT, "PI", 212, 184, ActiveColor, ActiveColorSmooth); + tftPrint16(ALEFT, "ID", 212, 201, ActiveColor, ActiveColorSmooth); + } + tftPrint16(ALEFT, "PS", 3, 193, ActiveColor, ActiveColorSmooth); + tftPrint16(ALEFT, "RT", 3, 221, ActiveColor, ActiveColorSmooth); + tftPrint16(ALEFT, "PTY", 3, 163, ActiveColor, ActiveColorSmooth); + if (!showaudio) tft.drawLine(16, 143, 189, 143, GreyoutColor); else tft.drawLine(16, 143, 189, 143, ActiveColor); + } + LowLevelInit = true; + } + + if ((SStatus / 10 <= LowLevelSet) && band < BAND_GAP) { + if (LowLevelInit && !BWtune && !menu) { + if (!screenmute && !rdsstatscreen && !afscreen && !advancedRDS) { + if(showaudio) { + tftPrint16(ALEFT, "10", 24, 144, GreyoutColor, BackgroundColor); + tftPrint16(ALEFT, "30", 54, 144, GreyoutColor, BackgroundColor); + tftPrint16(ALEFT, "50", 84, 144, GreyoutColor, BackgroundColor); + tftPrint16(ALEFT, "70", 114, 144, GreyoutColor, BackgroundColor); + tftPrint16(ALEFT, "100", 160, 144, GreyoutColor, BackgroundColor); + tftPrint16(ACENTER, "A", 7, 128, GreyoutColor, BackgroundColor); + tft.fillRect(16, 133, 174, 6, GreyoutColor); + for (byte segments = 0; segments < 93; segments++) { + if (segments > 54) { + if (((segments - 53) % 10) == 0) tft.fillRect(22 + (2 * segments), 141, 2, 2, GreyoutColor); + } else { + if (((segments + 1) % 6) == 0) tft.fillRect(22 + (2 * segments), 141, 2, 2, GreyoutColor); + } + } + } + if (radio.rds.region == 0) tftPrint16(ALEFT, "PI", 212, 193, GreyoutColor, BackgroundColor); + else { + tftPrint16(ALEFT, "PI", 212, 184, GreyoutColor, BackgroundColor); + tftPrint16(ALEFT, "ID", 212, 201, GreyoutColor, BackgroundColor); + } + tftPrint16(ALEFT, "PS", 3, 193, GreyoutColor, BackgroundColor); + tftPrint16(ALEFT, "RT", 3, 221, GreyoutColor, BackgroundColor); + tftPrint16(ALEFT, "PTY", 3, 163, GreyoutColor, BackgroundColor); + tft.drawLine(16, 143, 189, 143, GreyoutColor); + tft.drawBitmap(68, 5, RDSLogo, 35, 22, GreyoutColor); + } + LowLevelInit = false; + } + + if (!BWtune && !menu && (screenmute || radio.rds.correctPI != 0)) readRds(); + if (millis() >= lowsignaltimer + 300) { + lowsignaltimer = millis(); + if (af || (!screenmute || (screenmute && (XDRGTKTCP || XDRGTKUSB)))) { + if (band < BAND_GAP) radio.getStatus(&SStatus, &USN, &WAM, &OStatus, &BW, &MStatus, &CN); + else radio.getStatusAM(&SStatus, &USN, &WAM, &OStatus, &BW, &MStatus, &CN); + } + if (!BWtune && !menu) { + doSquelch(); + GetData(); + } + } + + } else { + if (af || (!screenmute || (screenmute && (XDRGTKTCP || XDRGTKUSB)))) { + if (band < BAND_GAP) radio.getStatus(&SStatus, &USN, &WAM, &OStatus, &BW, &MStatus, &CN); + else radio.getStatusAM(&SStatus, &USN, &WAM, &OStatus, &BW, &MStatus, &CN); + } + if (!BWtune && !menu) { + doSquelch(); + if (millis() >= tuningtimer + 200) readRds(); + GetData(); + if (!screenmute && !rdsstatscreen && !afscreen && !advancedRDS) ShowAudioLevel(); + } + } + + if (rotary == -1) { + tottimer = millis(); + if (screensavertriggered) { + if (!touchrotating) { + rotary = 0; + WakeToSleep(REVERSE); + } else { + if (BWtune) doBWtuneUp(); else KeyUp(); + } + } else { + if (BWtune) doBWtuneUp(); else KeyUp(); + if (rotaryaccelerate && rotarycounter > 2 && !BWtune && !menu) { + for (int i = 0; i < rotarycounteraccelerator; i++) KeyUp(); + rotarycounter = 0; + } + if (screensaverset > 0 && !BWtune && !menu && !screensavertriggered) screensavertimer = millis(); + } + } + + if (rotary == 1) { + tottimer = millis(); + if (screensavertriggered) { + if (!touchrotating) { + rotary = 0; + WakeToSleep(REVERSE); + } else { + if (BWtune) doBWtuneDown(); else KeyDown(); + } + } else { + if (BWtune) doBWtuneDown(); else KeyDown(); + if (rotaryaccelerate && rotarycounter > 2 && !BWtune && !menu) { + for (int i = 0; i < rotarycounteraccelerator; i++) KeyDown(); + rotarycounter = 0; + } + if (screensaverset > 0 && !BWtune && !menu && !screensavertriggered) screensavertimer = millis(); + } + } + + if (digitalRead(BANDBUTTON) == LOW) { + tottimer = millis(); + if (screensavertriggered) { + WakeToSleep(REVERSE); + while (digitalRead(BANDBUTTON) == LOW); + } else BANDBUTTONPress(); + } + + if (digitalRead(ROTARY_BUTTON) == LOW) { + tottimer = millis(); + if (screensavertriggered) { + WakeToSleep(REVERSE); + while (digitalRead(ROTARY_BUTTON) == LOW); + } else if (!afscreen && !rdsstatscreen) ButtonPress(); + } + + if (digitalRead(MODEBUTTON) == LOW) { + tottimer = millis(); + if (screensavertriggered) { + WakeToSleep(REVERSE); + while (digitalRead(MODEBUTTON) == LOW); + } else if(!screenmute) ModeButtonPress(); + } + + if (digitalRead(BWBUTTON) == LOW && !BWtune) { + tottimer = millis(); + if (screensavertriggered) { + WakeToSleep(REVERSE); + while (digitalRead(BWBUTTON) == LOW); + } else if(!screenmute) BWButtonPress(); + } + + if (digitalRead(EXT_IRQ) == LOW) { + if (screensavertriggered) WakeToSleep(REVERSE); + int num = GetNum(); + if (!screenmute && !BWtune && !menu && !advancedRDS && !rdsstatscreen && !afscreen && num != -1) NumpadProcess(num); + } + + if (screensaverset > 0 && !screensavertriggered && !BWtune && !menu && millis() >= screensavertimer + 1000 * screensaverOptions[screensaverset]) WakeToSleep(true); } \ No newline at end of file