From d2a132f966b6420998d229c2f76caab6ac2a2408 Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Fri, 9 Aug 2024 00:04:26 +0200 Subject: [PATCH 01/30] Update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 54cdc409f..47c335544 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ Special thanks to Jean-Cyrille F6IWW, Fabrice 14RC123, David F4BPP, Olivier 14RC * add SetMet menu to set s-meter style (Classic or Tiny), * add SetLck menu to set what is locked (Keys or Keys + PTT), * add SetGui menu to set font size on the VFO baseline (Classic or Tiny), - * add TXLock menu to open TX on channel + * add TXLock menu to open TX on channel, * rename BatVol menu (52/63) to SysInf, which displays the firmware version in addition to the battery status, * improve PonMsg menu, * improve BackLt menu, From f42de8f7c34c9a8ff323deeb345fb0e1afb3d2da Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Sat, 10 Aug 2024 15:40:44 +0200 Subject: [PATCH 02/30] Let's go to v3.3 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index c797710c4..7f856ad07 100644 --- a/Makefile +++ b/Makefile @@ -217,7 +217,7 @@ ifeq ($(ENABLE_FEAT_F4HWN),1) VERSION_STRING_1 ?= v0.22 AUTHOR_STRING_2 ?= F4HWN - VERSION_STRING_2 ?= v3.2 + VERSION_STRING_2 ?= v3.3 AUTHOR_STRING ?= $(AUTHOR_STRING_1)+$(AUTHOR_STRING_2) VERSION_STRING ?= $(VERSION_STRING_2) From bf85a444d09054c47113207d5c071fc4a046adbd Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Sun, 11 Aug 2024 07:06:33 +0200 Subject: [PATCH 03/30] Air Copy UI refactoring --- Makefile | 2 +- helper/boot.c | 2 ++ ui/aircopy.c | 40 +++++++++++++++++++++++++++++++++++++--- 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 7f856ad07..cf77eb536 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ # ---- STOCK QUANSHENG FERATURES ---- ENABLE_FMRADIO ?= 0 ENABLE_UART ?= 1 -ENABLE_AIRCOPY ?= 0 +ENABLE_AIRCOPY ?= 1 ENABLE_NOAA ?= 0 ENABLE_VOICE ?= 0 ENABLE_VOX ?= 1 diff --git a/helper/boot.c b/helper/boot.c index ad5663109..4ac9d5ca9 100644 --- a/helper/boot.c +++ b/helper/boot.c @@ -101,6 +101,8 @@ void BOOT_ProcessMode(BOOT_Mode_t Mode) gAircopyState = AIRCOPY_READY; + gEeprom.BACKLIGHT_TIME = 61; + GUI_SelectNextDisplay(DISPLAY_AIRCOPY); } #endif diff --git a/ui/aircopy.c b/ui/aircopy.c index 37b278d0e..f2020bd9a 100644 --- a/ui/aircopy.c +++ b/ui/aircopy.c @@ -27,10 +27,16 @@ #include "ui/helper.h" #include "ui/inputbox.h" +static int8_t map(int8_t x, int8_t in_min, int8_t in_max, int8_t out_min, int8_t out_max) { + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; +} + void UI_DisplayAircopy(void) { char String[16] = { 0 }; char *pPrintStr = { 0 }; + static bool crc[120] = { 0 }; + static uint8_t lErrorsDuringAirCopy = 0; UI_DisplayClear(); @@ -60,11 +66,39 @@ void UI_DisplayAircopy(void) memset(String, 0, sizeof(String)); if (gAirCopyIsSendMode == 0) { - sprintf(String, "RCV:%u E:%u", gAirCopyBlockNumber, gErrorsDuringAirCopy); + sprintf(String, "RCV:%02d%% E:%02d", map(gAirCopyBlockNumber + gErrorsDuringAirCopy, 0, 120, 0, 100), gErrorsDuringAirCopy); } else if (gAirCopyIsSendMode == 1) { - sprintf(String, "SND:%u", gAirCopyBlockNumber); + sprintf(String, "SND:%02d%%", map(gAirCopyBlockNumber + gErrorsDuringAirCopy, 0, 120, 0, 100)); + } + UI_PrintString(String, 2, 127, 5, 8); + + // Draw gauge + gFrameBuffer[4][2] = 0xff; + + for(uint8_t i = 1; i <= 122; i++) + { + gFrameBuffer[4][2 + i] = 0x81; } - UI_PrintString(String, 2, 127, 4, 8); + + if(gAirCopyBlockNumber + gErrorsDuringAirCopy != 0) + { + // Check CRC + if(gErrorsDuringAirCopy != lErrorsDuringAirCopy) + { + crc[gAirCopyBlockNumber + gErrorsDuringAirCopy - 1] = 1; + lErrorsDuringAirCopy = gErrorsDuringAirCopy; + } + + for(uint8_t i = 0; i < (gAirCopyBlockNumber + gErrorsDuringAirCopy); i++) + { + if(crc[i] == 0) + { + gFrameBuffer[4][i + 4] = 0xbd; + } + } + } + + gFrameBuffer[4][125] = 0xff; ST7565_BlitFullScreen(); } From 1bd71fce2f6687b3e7c08a9a9a27de6c2179e60e Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Sun, 11 Aug 2024 15:39:27 +0200 Subject: [PATCH 04/30] Fix approximative percent --- ui/aircopy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/aircopy.c b/ui/aircopy.c index f2020bd9a..9ea7df33e 100644 --- a/ui/aircopy.c +++ b/ui/aircopy.c @@ -66,9 +66,9 @@ void UI_DisplayAircopy(void) memset(String, 0, sizeof(String)); if (gAirCopyIsSendMode == 0) { - sprintf(String, "RCV:%02d%% E:%02d", map(gAirCopyBlockNumber + gErrorsDuringAirCopy, 0, 120, 0, 100), gErrorsDuringAirCopy); + sprintf(String, "RCV:%02d%% E:%02d", map(gAirCopyBlockNumber, 0, 120, 0, 100), gErrorsDuringAirCopy); } else if (gAirCopyIsSendMode == 1) { - sprintf(String, "SND:%02d%%", map(gAirCopyBlockNumber + gErrorsDuringAirCopy, 0, 120, 0, 100)); + sprintf(String, "SND:%02d%%", map(gAirCopyBlockNumber, 0, 120, 0, 100)); } UI_PrintString(String, 2, 127, 5, 8); From f0aefd8e8fcdb1a436aae3f2aa699f2590bfebf0 Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Sun, 11 Aug 2024 18:09:21 +0200 Subject: [PATCH 05/30] Improve percent --- ui/aircopy.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/ui/aircopy.c b/ui/aircopy.c index 9ea7df33e..5aaf42c3d 100644 --- a/ui/aircopy.c +++ b/ui/aircopy.c @@ -27,7 +27,7 @@ #include "ui/helper.h" #include "ui/inputbox.h" -static int8_t map(int8_t x, int8_t in_min, int8_t in_max, int8_t out_min, int8_t out_max) { +static int16_t map(int16_t x, int16_t in_min, int16_t in_max, int16_t out_min, int16_t out_max) { return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } @@ -37,6 +37,7 @@ void UI_DisplayAircopy(void) char *pPrintStr = { 0 }; static bool crc[120] = { 0 }; static uint8_t lErrorsDuringAirCopy = 0; + uint16_t percent; UI_DisplayClear(); @@ -65,10 +66,13 @@ void UI_DisplayAircopy(void) } memset(String, 0, sizeof(String)); + + percent = map(gAirCopyBlockNumber * 100, 0, 120 * 100, 0, 100 * 100); + if (gAirCopyIsSendMode == 0) { - sprintf(String, "RCV:%02d%% E:%02d", map(gAirCopyBlockNumber, 0, 120, 0, 100), gErrorsDuringAirCopy); + sprintf(String, "RCV:%02u.%02u%% E:%d", percent / 100, percent % 100, gErrorsDuringAirCopy); } else if (gAirCopyIsSendMode == 1) { - sprintf(String, "SND:%02d%%", map(gAirCopyBlockNumber, 0, 120, 0, 100)); + sprintf(String, "SND:%02d%%", percent / 100); } UI_PrintString(String, 2, 127, 5, 8); From 99fbf9d3844c9f0fb1f72f977b44afa05e9a4a2a Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Sun, 11 Aug 2024 18:49:14 +0200 Subject: [PATCH 06/30] Improve percent --- ui/aircopy.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/ui/aircopy.c b/ui/aircopy.c index 5aaf42c3d..66bf38d7f 100644 --- a/ui/aircopy.c +++ b/ui/aircopy.c @@ -27,10 +27,6 @@ #include "ui/helper.h" #include "ui/inputbox.h" -static int16_t map(int16_t x, int16_t in_min, int16_t in_max, int16_t out_min, int16_t out_max) { - return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; -} - void UI_DisplayAircopy(void) { char String[16] = { 0 }; @@ -67,12 +63,12 @@ void UI_DisplayAircopy(void) memset(String, 0, sizeof(String)); - percent = map(gAirCopyBlockNumber * 100, 0, 120 * 100, 0, 100 * 100); + percent = (gAirCopyBlockNumber * 10000) / 120; if (gAirCopyIsSendMode == 0) { sprintf(String, "RCV:%02u.%02u%% E:%d", percent / 100, percent % 100, gErrorsDuringAirCopy); } else if (gAirCopyIsSendMode == 1) { - sprintf(String, "SND:%02d%%", percent / 100); + sprintf(String, "SND:%02u.%02u%%", percent / 100, percent % 100); } UI_PrintString(String, 2, 127, 5, 8); From d696720b74b569a2e57a7c676955c72238cc0f78 Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Mon, 12 Aug 2024 01:15:54 +0200 Subject: [PATCH 07/30] Save 48 bytes --- ui/aircopy.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/ui/aircopy.c b/ui/aircopy.c index 66bf38d7f..6697a6e82 100644 --- a/ui/aircopy.c +++ b/ui/aircopy.c @@ -27,11 +27,19 @@ #include "ui/helper.h" #include "ui/inputbox.h" +static void set_bit(uint8_t* array, int bit_index) { + array[bit_index / 8] |= (1 << (bit_index % 8)); +} + +int get_bit(uint8_t* array, int bit_index) { + return (array[bit_index / 8] >> (bit_index % 8)) & 1; +} + void UI_DisplayAircopy(void) { char String[16] = { 0 }; char *pPrintStr = { 0 }; - static bool crc[120] = { 0 }; + static uint8_t crc[15] = { 0 }; static uint8_t lErrorsDuringAirCopy = 0; uint16_t percent; @@ -85,13 +93,13 @@ void UI_DisplayAircopy(void) // Check CRC if(gErrorsDuringAirCopy != lErrorsDuringAirCopy) { - crc[gAirCopyBlockNumber + gErrorsDuringAirCopy - 1] = 1; + set_bit(crc, gAirCopyBlockNumber + gErrorsDuringAirCopy); lErrorsDuringAirCopy = gErrorsDuringAirCopy; } for(uint8_t i = 0; i < (gAirCopyBlockNumber + gErrorsDuringAirCopy); i++) { - if(crc[i] == 0) + if(get_bit(crc, i) == 0) { gFrameBuffer[4][i + 4] = 0xbd; } From f98480175e29a5f6d42e984945fb7f73e7864ac9 Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Mon, 12 Aug 2024 02:15:51 +0200 Subject: [PATCH 08/30] Refactoring --- app/aircopy.c | 5 +++++ ui/aircopy.c | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/app/aircopy.c b/app/aircopy.c index 57134b150..9e5532f4a 100644 --- a/app/aircopy.c +++ b/app/aircopy.c @@ -16,6 +16,10 @@ #ifdef ENABLE_AIRCOPY +//#if !defined(ENABLE_OVERLAY) +// #include "ARMCM0.h" +//#endif + #include "app/aircopy.h" #include "audio.h" #include "driver/bk4819.h" @@ -61,6 +65,7 @@ bool AIRCOPY_SendMessage(void) if (++gAirCopyBlockNumber >= 0x78) { gAircopyState = AIRCOPY_COMPLETE; + //NVIC_SystemReset(); } RADIO_SetTxParameters(); diff --git a/ui/aircopy.c b/ui/aircopy.c index 6697a6e82..26e4dc084 100644 --- a/ui/aircopy.c +++ b/ui/aircopy.c @@ -31,7 +31,7 @@ static void set_bit(uint8_t* array, int bit_index) { array[bit_index / 8] |= (1 << (bit_index % 8)); } -int get_bit(uint8_t* array, int bit_index) { +static int get_bit(uint8_t* array, int bit_index) { return (array[bit_index / 8] >> (bit_index % 8)) & 1; } @@ -88,6 +88,8 @@ void UI_DisplayAircopy(void) gFrameBuffer[4][2 + i] = 0x81; } + gFrameBuffer[4][125] = 0xff; + if(gAirCopyBlockNumber + gErrorsDuringAirCopy != 0) { // Check CRC @@ -106,8 +108,6 @@ void UI_DisplayAircopy(void) } } - gFrameBuffer[4][125] = 0xff; - ST7565_BlitFullScreen(); } From bf90961944291d332b81f29496ccb23bdd7c57c9 Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Mon, 12 Aug 2024 19:43:12 +0200 Subject: [PATCH 09/30] Save 88 bytes --- app/spectrum.c | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/app/spectrum.c b/app/spectrum.c index 2066c9978..0896c76a7 100644 --- a/app/spectrum.c +++ b/app/spectrum.c @@ -789,32 +789,19 @@ static void DrawStatus() { #ifdef ENABLE_FEAT_F4HWN_SPECTRUM static void ShowChannelName(uint32_t f) { unsigned int i; - char s[12]; memset(String, 0, sizeof(String)); if ( isListening ) { for (i = 0; IS_MR_CHANNEL(i); i++) { - if (RADIO_CheckValidChannel(i, false, 0)) { - if (SETTINGS_FetchChannelFrequency(i) == f) { - memset(s, 0, sizeof(s)); - SETTINGS_FetchChannelName(s, i); - if (s[0] != 0) { - if ( strlen(String) != 0 ) - strcat(String, "/"); // Add a space to result - strcat(String, s); - } - break; - } + if (RADIO_CheckValidChannel(i, false, 0)) { + if (SETTINGS_FetchChannelFrequency(i) == f) { + SETTINGS_FetchChannelName(String, i); + UI_PrintStringSmallBold(String[0] ? String : "--", 8, 127, 1); + break; } + } } } - - if (String[0] != 0) { - if ( strlen(String) > 19 ) { - String[19] = 0; - } - UI_PrintStringSmallBold(String, 8, 127, 1); - } } #endif From 9c0df1355c020904c042195c3688556bae8bd3ce Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Tue, 13 Aug 2024 02:38:13 +0200 Subject: [PATCH 10/30] Save 8 bytes --- ui/status.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/ui/status.c b/ui/status.c index 24f1721f9..528aa0a0f 100644 --- a/ui/status.c +++ b/ui/status.c @@ -37,26 +37,16 @@ #ifdef ENABLE_FEAT_F4HWN_RX_TX_TIMER static void convertTime(uint8_t *line, uint8_t type) { - char str[8] = ""; - - uint8_t m, s; // Declare variables for seconds, hours, minutes, and seconds - uint16_t t; - - if(type == 0) // Tx timer - t = (gTxTimerCountdown_500ms / 2); - //t = ((gEeprom.TX_TIMEOUT_TIMER + 1) * 5) - (gTxTimerCountdown_500ms / 2); - else // Rx timer - t = 3600 - (gRxTimerCountdown_500ms / 2); + uint16_t t = (type == 0) ? (gTxTimerCountdown_500ms / 2) : (3600 - gRxTimerCountdown_500ms / 2); - m = t / 60; - s = t - (m * 60); + uint8_t m = t / 60; + uint8_t s = t % 60; // Utilisation de l'opérateur modulo pour simplifier le calcul des secondes - gStatusLine[0] = 0x00; // Quick fix on display (on scanning I, II, etc.) - gStatusLine[7] = 0x00; // Quick fix on display (on scanning I, II, etc.) - gStatusLine[14] = 0x00; // Quick fix on display (on scanning I, II, etc.) + gStatusLine[0] = gStatusLine[7] = gStatusLine[14] = 0x00; // Quick fix on display (on scanning I, II, etc.) + char str[8]; sprintf(str, "%02d:%02d", m, s); - UI_PrintStringSmallBufferNormal(str, line + 0); + UI_PrintStringSmallBufferNormal(str, line); gUpdateStatus = true; } From efdea646b7290cc125cb37efba204a27e6d02929 Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Tue, 13 Aug 2024 04:37:44 +0200 Subject: [PATCH 11/30] Save 16 bytes --- app/dtmf.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/app/dtmf.c b/app/dtmf.c index c7635c0bc..7376b967c 100644 --- a/app/dtmf.c +++ b/app/dtmf.c @@ -171,18 +171,11 @@ bool DTMF_FindContact(const char *pContact, char *pResult) char DTMF_GetCharacter(const unsigned int code) { + if (code <= KEY_9) + return '0' + code; + switch (code) { - case KEY_0: return '0'; - case KEY_1: return '1'; - case KEY_2: return '2'; - case KEY_3: return '3'; - case KEY_4: return '4'; - case KEY_5: return '5'; - case KEY_6: return '6'; - case KEY_7: return '7'; - case KEY_8: return '8'; - case KEY_9: return '9'; case KEY_MENU: return 'A'; case KEY_UP: return 'B'; case KEY_DOWN: return 'C'; From 4a3b2770811f4024a2e20b91ff404c7c806e95fc Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Tue, 13 Aug 2024 04:49:41 +0200 Subject: [PATCH 12/30] Save 40 bytes --- app/main.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/app/main.c b/app/main.c index 554ccb866..231ec5ffa 100644 --- a/app/main.c +++ b/app/main.c @@ -405,23 +405,8 @@ static void MAIN_Key_DIGITS(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld) if (gScanStateDir != SCAN_OFF){ switch(Key) { - case KEY_0: - gEeprom.SCAN_LIST_DEFAULT = 0; - break; - case KEY_1: - gEeprom.SCAN_LIST_DEFAULT = 1; - break; - case KEY_2: - gEeprom.SCAN_LIST_DEFAULT = 2; - break; - case KEY_3: - gEeprom.SCAN_LIST_DEFAULT = 3; - break; - case KEY_4: - gEeprom.SCAN_LIST_DEFAULT = 4; - break; - case KEY_5: - gEeprom.SCAN_LIST_DEFAULT = 5; + case KEY_0...KEY_5: + gEeprom.SCAN_LIST_DEFAULT = Key; break; default: break; From b78115f8bfc680c88e64595dd80664d0580b6b4e Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Tue, 13 Aug 2024 18:50:32 +0200 Subject: [PATCH 13/30] UI gauge refactoring --- ui/aircopy.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ui/aircopy.c b/ui/aircopy.c index 26e4dc084..cb0f77177 100644 --- a/ui/aircopy.c +++ b/ui/aircopy.c @@ -81,14 +81,16 @@ void UI_DisplayAircopy(void) UI_PrintString(String, 2, 127, 5, 8); // Draw gauge - gFrameBuffer[4][2] = 0xff; + gFrameBuffer[4][1] = 0x3c; + gFrameBuffer[4][2] = 0x42; for(uint8_t i = 1; i <= 122; i++) { gFrameBuffer[4][2 + i] = 0x81; } - gFrameBuffer[4][125] = 0xff; + gFrameBuffer[4][125] = 0x42; + gFrameBuffer[4][126] = 0x3c; if(gAirCopyBlockNumber + gErrorsDuringAirCopy != 0) { From d2235c0bdb4d01349bc927cfc47866ece6f63279 Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Tue, 13 Aug 2024 20:15:45 +0200 Subject: [PATCH 14/30] Improve Air Copy and enable restart --- app/aircopy.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/aircopy.c b/app/aircopy.c index 9e5532f4a..8e5ee5202 100644 --- a/app/aircopy.c +++ b/app/aircopy.c @@ -64,7 +64,8 @@ bool AIRCOPY_SendMessage(void) } if (++gAirCopyBlockNumber >= 0x78) { - gAircopyState = AIRCOPY_COMPLETE; + gAircopyState = AIRCOPY_READY; + //gAircopyState = AIRCOPY_COMPLETE; //NVIC_SystemReset(); } @@ -122,7 +123,8 @@ void AIRCOPY_StorePacket(void) } if (Offset == 0x1E00) { - gAircopyState = AIRCOPY_COMPLETE; + gAircopyState = AIRCOPY_READY; + //gAircopyState = AIRCOPY_COMPLETE; } gAirCopyBlockNumber++; From 69362495b390b1f344b3b1908d272a48ff9a5f33 Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Tue, 13 Aug 2024 20:30:00 +0200 Subject: [PATCH 15/30] Improve Air Copy and enable restart --- ui/aircopy.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ui/aircopy.c b/ui/aircopy.c index cb0f77177..7a218dd3e 100644 --- a/ui/aircopy.c +++ b/ui/aircopy.c @@ -47,6 +47,10 @@ void UI_DisplayAircopy(void) if (gAircopyState == AIRCOPY_READY) { pPrintStr = "AIR COPY(RDY)"; + for(uint8_t i = 0; i < 15; i++) + { + crc[i] = 0; + } } else if (gAircopyState == AIRCOPY_TRANSFER) { pPrintStr = "AIR COPY"; } else { From 7340e6cdc5a89e11183995614129be2019a67f93 Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Tue, 13 Aug 2024 20:36:23 +0200 Subject: [PATCH 16/30] Improve Air Copy and enable restart --- ui/aircopy.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/aircopy.c b/ui/aircopy.c index 7a218dd3e..c0e1b8449 100644 --- a/ui/aircopy.c +++ b/ui/aircopy.c @@ -47,6 +47,7 @@ void UI_DisplayAircopy(void) if (gAircopyState == AIRCOPY_READY) { pPrintStr = "AIR COPY(RDY)"; + lErrorsDuringAirCopy = 0; for(uint8_t i = 0; i < 15; i++) { crc[i] = 0; From cb4b622a2a63732e555f46050ce87ed73ef0407f Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Wed, 14 Aug 2024 00:05:22 +0200 Subject: [PATCH 17/30] Revert last 3 commit --- app/aircopy.c | 6 ++---- ui/aircopy.c | 5 ----- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/app/aircopy.c b/app/aircopy.c index 8e5ee5202..9e5532f4a 100644 --- a/app/aircopy.c +++ b/app/aircopy.c @@ -64,8 +64,7 @@ bool AIRCOPY_SendMessage(void) } if (++gAirCopyBlockNumber >= 0x78) { - gAircopyState = AIRCOPY_READY; - //gAircopyState = AIRCOPY_COMPLETE; + gAircopyState = AIRCOPY_COMPLETE; //NVIC_SystemReset(); } @@ -123,8 +122,7 @@ void AIRCOPY_StorePacket(void) } if (Offset == 0x1E00) { - gAircopyState = AIRCOPY_READY; - //gAircopyState = AIRCOPY_COMPLETE; + gAircopyState = AIRCOPY_COMPLETE; } gAirCopyBlockNumber++; diff --git a/ui/aircopy.c b/ui/aircopy.c index c0e1b8449..cb0f77177 100644 --- a/ui/aircopy.c +++ b/ui/aircopy.c @@ -47,11 +47,6 @@ void UI_DisplayAircopy(void) if (gAircopyState == AIRCOPY_READY) { pPrintStr = "AIR COPY(RDY)"; - lErrorsDuringAirCopy = 0; - for(uint8_t i = 0; i < 15; i++) - { - crc[i] = 0; - } } else if (gAircopyState == AIRCOPY_TRANSFER) { pPrintStr = "AIR COPY"; } else { From 19c0c05aaee88f7ee43b79d70697fd94e4422db0 Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Wed, 14 Aug 2024 04:16:58 +0200 Subject: [PATCH 18/30] Air Copy UI refactoring --- misc.c | 2 ++ misc.h | 2 ++ ui/aircopy.c | 24 +++++++++++++----------- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/misc.c b/misc.c index 75d401cc0..6c99d51c3 100644 --- a/misc.c +++ b/misc.c @@ -119,6 +119,8 @@ enum BacklightOnRxTx_t gSetting_backlight_on_tx_rx; uint8_t gDW = 0; uint8_t gCB = 0; bool gSaveRxMode = false; + uint8_t crc[15] = { 0 }; + uint8_t lErrorsDuringAirCopy = 0; #endif #ifdef ENABLE_AUDIO_BAR diff --git a/misc.h b/misc.h index fb5b4e640..9fcc6d501 100644 --- a/misc.h +++ b/misc.h @@ -171,6 +171,8 @@ extern enum BacklightOnRxTx_t gSetting_backlight_on_tx_rx; extern uint8_t gDW; extern uint8_t gCB; extern bool gSaveRxMode; + extern uint8_t crc[15]; + extern uint8_t lErrorsDuringAirCopy; #endif #ifdef ENABLE_AUDIO_BAR diff --git a/ui/aircopy.c b/ui/aircopy.c index cb0f77177..88e7af0f1 100644 --- a/ui/aircopy.c +++ b/ui/aircopy.c @@ -39,8 +39,6 @@ void UI_DisplayAircopy(void) { char String[16] = { 0 }; char *pPrintStr = { 0 }; - static uint8_t crc[15] = { 0 }; - static uint8_t lErrorsDuringAirCopy = 0; uint16_t percent; UI_DisplayClear(); @@ -78,19 +76,23 @@ void UI_DisplayAircopy(void) } else if (gAirCopyIsSendMode == 1) { sprintf(String, "SND:%02u.%02u%%", percent / 100, percent % 100); } - UI_PrintString(String, 2, 127, 5, 8); // Draw gauge - gFrameBuffer[4][1] = 0x3c; - gFrameBuffer[4][2] = 0x42; - - for(uint8_t i = 1; i <= 122; i++) + if(gAircopyState != AIRCOPY_READY) { - gFrameBuffer[4][2 + i] = 0x81; - } + UI_PrintString(String, 2, 127, 5, 8); - gFrameBuffer[4][125] = 0x42; - gFrameBuffer[4][126] = 0x3c; + gFrameBuffer[4][1] = 0x3c; + gFrameBuffer[4][2] = 0x42; + + for(uint8_t i = 1; i <= 122; i++) + { + gFrameBuffer[4][2 + i] = 0x81; + } + + gFrameBuffer[4][125] = 0x42; + gFrameBuffer[4][126] = 0x3c; + } if(gAirCopyBlockNumber + gErrorsDuringAirCopy != 0) { From 75480cac100252894c8205f077ed9db911d6fe4b Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Thu, 15 Aug 2024 01:43:26 +0200 Subject: [PATCH 19/30] Improve Air Copy and enable restart --- app/aircopy.c | 16 +++++++++++++++- misc.c | 1 + misc.h | 1 + ui/aircopy.c | 3 ++- 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/app/aircopy.c b/app/aircopy.c index 9e5532f4a..cda195c4a 100644 --- a/app/aircopy.c +++ b/app/aircopy.c @@ -41,6 +41,14 @@ uint8_t gAirCopyIsSendMode; uint16_t g_FSK_Buffer[36]; +static void AIRCOPY_clear() +{ + for (uint8_t i = 0; i < 15; i++) + { + crc[i] = 0; + } +} + bool AIRCOPY_SendMessage(void) { static uint8_t gAircopySendCountdown = 1; @@ -183,12 +191,15 @@ static void AIRCOPY_Key_EXIT(bool bKeyPressed, bool bKeyHeld) } if (gInputBoxIndex == 0) { + gAircopyStep = 1; gFSKWriteIndex = 0; gAirCopyBlockNumber = 0; gInputBoxIndex = 0; - gErrorsDuringAirCopy = 0; + gErrorsDuringAirCopy = lErrorsDuringAirCopy = 0; gAirCopyIsSendMode = 0; + AIRCOPY_clear(); + BK4819_PrepareFSKReceive(); gAircopyState = AIRCOPY_TRANSFER; @@ -205,6 +216,7 @@ static void AIRCOPY_Key_MENU(bool bKeyPressed, bool bKeyHeld) return; } + gAircopyStep = 1; gFSKWriteIndex = 0; gAirCopyBlockNumber = 0; gInputBoxIndex = 0; @@ -213,6 +225,8 @@ static void AIRCOPY_Key_MENU(bool bKeyPressed, bool bKeyHeld) g_FSK_Buffer[1] = 0; g_FSK_Buffer[35] = 0xDCBA; + AIRCOPY_clear(); + GUI_DisplayScreen(); gAircopyState = AIRCOPY_TRANSFER; diff --git a/misc.c b/misc.c index 6c99d51c3..d8e3a8972 100644 --- a/misc.c +++ b/misc.c @@ -121,6 +121,7 @@ enum BacklightOnRxTx_t gSetting_backlight_on_tx_rx; bool gSaveRxMode = false; uint8_t crc[15] = { 0 }; uint8_t lErrorsDuringAirCopy = 0; + uint8_t gAircopyStep = 0; #endif #ifdef ENABLE_AUDIO_BAR diff --git a/misc.h b/misc.h index 9fcc6d501..bf28f1e82 100644 --- a/misc.h +++ b/misc.h @@ -173,6 +173,7 @@ extern enum BacklightOnRxTx_t gSetting_backlight_on_tx_rx; extern bool gSaveRxMode; extern uint8_t crc[15]; extern uint8_t lErrorsDuringAirCopy; + extern uint8_t gAircopyStep; #endif #ifdef ENABLE_AUDIO_BAR diff --git a/ui/aircopy.c b/ui/aircopy.c index 88e7af0f1..0c3da4c76 100644 --- a/ui/aircopy.c +++ b/ui/aircopy.c @@ -49,6 +49,7 @@ void UI_DisplayAircopy(void) pPrintStr = "AIR COPY"; } else { pPrintStr = "AIR COPY(CMP)"; + gAircopyState = AIRCOPY_READY; } UI_PrintString(pPrintStr, 2, 127, 0, 8); @@ -78,7 +79,7 @@ void UI_DisplayAircopy(void) } // Draw gauge - if(gAircopyState != AIRCOPY_READY) + if(gAircopyStep != 0) { UI_PrintString(String, 2, 127, 5, 8); From e0083131706ef57f22783e49f359ec4142997274 Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Thu, 15 Aug 2024 04:34:00 +0200 Subject: [PATCH 20/30] Add SetTmr --- app/menu.c | 11 ++++++++++- main.c | 4 ++-- misc.c | 1 + misc.h | 1 + settings.c | 32 ++++++++++++++++++++++++++++++++ ui/menu.c | 4 ++++ ui/menu.h | 1 + ui/status.c | 4 ++-- 8 files changed, 53 insertions(+), 5 deletions(-) diff --git a/app/menu.c b/app/menu.c index 1f7ca9b3f..bc07c3882 100644 --- a/app/menu.c +++ b/app/menu.c @@ -254,6 +254,9 @@ int MENU_GetLimits(uint8_t menu_id, int32_t *pMin, int32_t *pMax) case MENU_350EN: #ifndef ENABLE_FEAT_F4HWN case MENU_SCREN: +#endif +#ifdef ENABLE_FEAT_F4HWN + case MENU_SET_TMR: #endif //*pMin = 0; *pMax = ARRAY_SIZE(gSubMenu_OFF_ON) - 1; @@ -895,10 +898,13 @@ void MENU_AcceptSetting(void) case MENU_SET_GUI: gSetting_set_gui = gSubMenuSelection; break; + case MENU_SET_TMR: + gSetting_set_tmr = gSubMenuSelection; + break; case MENU_TX_LOCK: gTxVfo->TX_LOCK = gSubMenuSelection; gRequestSaveChannel = 1; - return; + return; #endif } @@ -1316,6 +1322,9 @@ void MENU_ShowCurrentSetting(void) case MENU_SET_GUI: gSubMenuSelection = gSetting_set_gui; break; + case MENU_SET_TMR: + gSubMenuSelection = gSetting_set_tmr; + break; case MENU_TX_LOCK: gSubMenuSelection = gTxVfo->TX_LOCK; break; diff --git a/main.c b/main.c index e6fedb632..7359658e4 100644 --- a/main.c +++ b/main.c @@ -129,9 +129,9 @@ void Main(void) gEeprom.KEY_LOCK = 0; SETTINGS_SaveSettings(); #ifndef ENABLE_VOX - gMenuCursor = 63; // move to hidden section, fix me if change... !!! Remove VOX and Mic Bar + gMenuCursor = 64; // move to hidden section, fix me if change... !!! Remove VOX and Mic Bar #else - gMenuCursor = 65; // move to hidden section, fix me if change... !!! + gMenuCursor = 66; // move to hidden section, fix me if change... !!! #endif gSubMenuSelection = gSetting_F_LOCK; #endif diff --git a/misc.c b/misc.c index d8e3a8972..811d1eb5d 100644 --- a/misc.c +++ b/misc.c @@ -114,6 +114,7 @@ enum BacklightOnRxTx_t gSetting_backlight_on_tx_rx; bool gSetting_set_lck = false; bool gSetting_set_met = 0; bool gSetting_set_gui = 0; + bool gSetting_set_tmr = 0; bool gSetting_set_ptt_session; uint8_t gDebug; uint8_t gDW = 0; diff --git a/misc.h b/misc.h index bf28f1e82..4fb8cb08d 100644 --- a/misc.h +++ b/misc.h @@ -166,6 +166,7 @@ extern enum BacklightOnRxTx_t gSetting_backlight_on_tx_rx; extern bool gSetting_set_lck; extern bool gSetting_set_met; extern bool gSetting_set_gui; + extern bool gSetting_set_tmr; extern bool gSetting_set_ptt_session; extern uint8_t gDebug; extern uint8_t gDW; diff --git a/settings.c b/settings.c index d4acb46d7..298ae4df1 100644 --- a/settings.c +++ b/settings.c @@ -324,6 +324,7 @@ void SETTINGS_InitEEPROM(void) gSetting_set_tot = (((Data[6] & 0xF0) >> 4) < 4) ? ((Data[6] & 0xF0) >> 4) : 0; gSetting_set_eot = (((Data[6] & 0x0F)) < 4) ? ((Data[6] & 0x0F)) : 0; + /* int tmp = ((Data[5] & 0xF0) >> 4); gSetting_set_inv = (((tmp >> 0) & 0x01) < 2) ? ((tmp >> 0) & 0x01): 0; @@ -332,6 +333,21 @@ void SETTINGS_InitEEPROM(void) gSetting_set_gui = (((tmp >> 3) & 0x01) < 2) ? ((tmp >> 3) & 0x01): 0; gSetting_set_ctr = (((Data[5] & 0x0F)) > 00 && ((Data[5] & 0x0F)) < 16) ? ((Data[5] & 0x0F)) : 10; + gSetting_set_tmr = ((Data[4] & 1) < 2) ? (Data[4] & 1): 0; + */ + + int tmp = (Data[5] & 0xF0) >> 4; + + gSetting_set_inv = (tmp >> 0) & 0x01; + gSetting_set_lck = (tmp >> 1) & 0x01; + gSetting_set_met = (tmp >> 2) & 0x01; + gSetting_set_gui = (tmp >> 3) & 0x01; + + int ctr_value = Data[5] & 0x0F; + gSetting_set_ctr = (ctr_value > 0 && ctr_value < 16) ? ctr_value : 10; + + gSetting_set_tmr = Data[4] & 1; + // And set special session settings for actions gSetting_set_ptt_session = gSetting_set_ptt; gEeprom.KEY_LOCK_PTT = gSetting_set_lck; @@ -700,6 +716,14 @@ void SETTINGS_SaveSettings(void) #ifdef ENABLE_FEAT_F4HWN memset(State, 0xFF, sizeof(State)); + /* + tmp = 0; + + if(gSetting_set_tmr == 1) + tmp = tmp | (1 << 0); + + State[4] = tmp; + tmp = 0; if(gSetting_set_inv == 1) @@ -710,6 +734,14 @@ void SETTINGS_SaveSettings(void) tmp = tmp | (1 << 2); if (gSetting_set_gui == 1) tmp = tmp | (1 << 3); + */ + + State[4] = gSetting_set_tmr ? (1 << 0) : 0; + + tmp = (gSetting_set_inv << 0) | + (gSetting_set_lck << 1) | + (gSetting_set_met << 2) | + (gSetting_set_gui << 3); State[5] = ((tmp << 4) | (gSetting_set_ctr & 0x0F)); State[6] = ((gSetting_set_tot << 4) | (gSetting_set_eot & 0x0F)); diff --git a/ui/menu.c b/ui/menu.c index a6a29da2d..6be784862 100644 --- a/ui/menu.c +++ b/ui/menu.c @@ -146,6 +146,7 @@ const t_menu_item MenuList[] = {"SetLck", MENU_SET_LCK }, {"SetMet", MENU_SET_MET }, {"SetGui", MENU_SET_GUI }, + {"SetTmr", MENU_SET_TMR }, #endif // hidden menu items from here on // enabled if pressing both the PTT and upper side button at power-on @@ -737,6 +738,9 @@ void UI_DisplayMenu(void) case MENU_350EN: #ifndef ENABLE_FEAT_F4HWN case MENU_SCREN: +#endif +#ifdef ENABLE_FEAT_F4HWN + case MENU_SET_TMR: #endif strcpy(String, gSubMenu_OFF_ON[gSubMenuSelection]); break; diff --git a/ui/menu.h b/ui/menu.h index 4f40530d5..2025cd9cd 100644 --- a/ui/menu.h +++ b/ui/menu.h @@ -135,6 +135,7 @@ enum MENU_SET_LCK, MENU_SET_MET, MENU_SET_GUI, + MENU_SET_TMR, #endif MENU_BATCAL, // battery voltage calibration MENU_F1SHRT, diff --git a/ui/status.c b/ui/status.c index 528aa0a0f..32d4e480b 100644 --- a/ui/status.c +++ b/ui/status.c @@ -143,11 +143,11 @@ void UI_DisplayStatus() if(!SCANNER_IsScanning()) { #ifdef ENABLE_FEAT_F4HWN_RX_TX_TIMER - if(gCurrentFunction == FUNCTION_TRANSMIT) + if(gCurrentFunction == FUNCTION_TRANSMIT && gSetting_set_tmr == true) { convertTime(line, 0); } - else if(FUNCTION_IsRx()) + else if(FUNCTION_IsRx() && gSetting_set_tmr == true) { convertTime(line, 1); } From 7c53df8d2b88ef769fac3ea46f16f9d4644402d1 Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Thu, 15 Aug 2024 05:07:20 +0200 Subject: [PATCH 21/30] Remove mysterious AES_Encrypt call --- app/uart.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/app/uart.c b/app/uart.c index 8d8feac5e..a1b1fc577 100644 --- a/app/uart.c +++ b/app/uart.c @@ -42,6 +42,7 @@ #include "sram-overlay.h" #endif +#define UNUSED(x) (void)(x) #define DMA_INDEX(x, y) (((x) + (y)) % sizeof(UART_DMA_Buffer)) @@ -211,20 +212,25 @@ static void SendVersion(void) static bool IsBadChallenge(const uint32_t *pKey, const uint32_t *pIn, const uint32_t *pResponse) { - unsigned int i; - uint32_t IV[4]; - - IV[0] = 0; - IV[1] = 0; - IV[2] = 0; - IV[3] = 0; + #ifdef ENABLE_FEAT_F4HWN + UNUSED(pKey); + UNUSED(pIn); + UNUSED(pResponse); + #else + unsigned int i; + uint32_t IV[4]; - AES_Encrypt(pKey, IV, pIn, IV, true); + IV[0] = 0; + IV[1] = 0; + IV[2] = 0; + IV[3] = 0; - for (i = 0; i < 4; i++) - if (IV[i] != pResponse[i]) - return true; + AES_Encrypt(pKey, IV, pIn, IV, true); + for (i = 0; i < 4; i++) + if (IV[i] != pResponse[i]) + return true; + #endif return false; } From 74862d1ac2af5acec5d135e4b7c3133d64d4d67c Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Fri, 16 Aug 2024 00:11:09 +0200 Subject: [PATCH 22/30] Check tab only... --- am_fix.c | 326 ++-- am_fix.h | 16 +- app/action.c | 644 ++++---- app/action.h | 18 +- app/aircopy.c | 316 ++-- app/aircopy.h | 6 +- app/app.c | 3328 ++++++++++++++++++++-------------------- app/chFrScanner.c | 478 +++--- app/chFrScanner.h | 4 +- app/common.c | 6 +- app/dtmf.c | 608 ++++---- app/dtmf.h | 40 +- app/flashlight.c | 128 +- app/fm.c | 840 +++++------ app/fm.h | 6 +- app/generic.c | 258 ++-- app/menu.c | 3434 +++++++++++++++++++++--------------------- app/menu.h | 2 +- app/scanner.c | 776 +++++----- app/scanner.h | 14 +- app/uart.c | 852 +++++------ audio.c | 664 ++++---- audio.h | 222 +-- bitmaps.c | 391 +++-- bitmaps.h | 4 +- board.c | 854 +++++------ dcs.c | 130 +- dcs.h | 12 +- debugging.h | 36 +- driver/adc.c | 194 +-- driver/adc.h | 66 +- driver/aes.c | 70 +- driver/backlight.c | 178 +-- driver/bk1080-regs.h | 40 +- driver/bk1080.c | 120 +- driver/bk4819-regs.h | 542 +++---- driver/bk4819.c | 2704 ++++++++++++++++----------------- driver/bk4819.h | 58 +- driver/crc.c | 38 +- driver/eeprom.c | 46 +- driver/flash.c | 6 +- driver/flash.h | 24 +- driver/gpio.h | 60 +- driver/i2c.c | 226 +-- driver/i2c.h | 4 +- driver/keyboard.c | 226 +-- driver/keyboard.h | 40 +- driver/spi.c | 140 +- driver/spi.h | 24 +- driver/st7565.c | 340 ++--- driver/st7565.h | 2 +- driver/system.c | 14 +- driver/systick.c | 30 +- driver/uart.c | 122 +- font.c | 1202 +++++++-------- font.h | 2 +- frequencies.c | 364 ++--- frequencies.h | 78 +- functions.c | 284 ++-- functions.h | 16 +- helper/battery.c | 324 ++-- helper/boot.c | 148 +- helper/boot.h | 10 +- init.c | 18 +- main.c | 300 ++-- misc.c | 150 +- misc.h | 152 +- radio.c | 1916 +++++++++++------------ radio.h | 130 +- scheduler.c | 98 +- screenshot.h | 50 +- settings.c | 1460 +++++++++--------- settings.h | 342 ++--- sram-overlay.c | 144 +- ui/aircopy.c | 154 +- ui/aircopy.h | 2 +- ui/battery.c | 32 +- ui/fmradio.c | 114 +- ui/fmradio.h | 2 +- ui/helper.c | 416 ++--- ui/helper.h | 8 +- ui/inputbox.c | 22 +- ui/lock.c | 230 +-- ui/lock.h | 2 +- ui/main.c | 2316 ++++++++++++++-------------- ui/main.h | 20 +- ui/menu.c | 1776 +++++++++++----------- ui/menu.h | 222 +-- ui/scanner.c | 92 +- ui/status.c | 344 ++--- ui/ui.c | 62 +- ui/ui.h | 14 +- ui/welcome.c | 196 +-- version.c | 12 +- version.h | 4 +- 95 files changed, 16477 insertions(+), 16478 deletions(-) diff --git a/am_fix.c b/am_fix.c index dade2397d..3c4c9e45b 100644 --- a/am_fix.c +++ b/am_fix.c @@ -38,8 +38,8 @@ typedef struct { - uint16_t reg_val; - int8_t gain_dB; + uint16_t reg_val; + int8_t gain_dB; } __attribute__((packed)) t_gain_table; // REG_10 AGC gain table @@ -85,11 +85,11 @@ typedef struct // // these 4 tables need a measuring/calibration update // -//// static const int16_t lna_short_dB[] = { -19, -16, -11, 0}; // was (but wrong) -// static const int16_t lna_short_dB[] = { (-28), (-24), (-19), 0}; // corrected'ish -// static const int16_t lna_dB[] = { (-24), (-19), (-14), ( -9), (-6), (-4), (-2), 0}; -// static const int16_t mixer_dB[] = { ( -8), ( -6), ( -3), 0}; -// static const int16_t pga_dB[] = { (-33), (-27), (-21), (-15), (-9), (-6), (-3), 0}; +//// static const int16_t lna_short_dB[] = { -19, -16, -11, 0}; // was (but wrong) +// static const int16_t lna_short_dB[] = { (-28), (-24), (-19), 0}; // corrected'ish +// static const int16_t lna_dB[] = { (-24), (-19), (-14), ( -9), (-6), (-4), (-2), 0}; +// static const int16_t mixer_dB[] = { ( -8), ( -6), ( -3), 0}; +// static const int16_t pga_dB[] = { (-33), (-27), (-21), (-15), (-9), (-6), (-3), 0}; // lookup table is hugely easier than writing code to do the same // @@ -99,50 +99,50 @@ typedef struct #if LOOKUP_TABLE static const t_gain_table gain_table[] = { - {0x03BE, -7}, // 0 .. 3 5 3 6 .. 0dB -4dB 0dB -3dB .. -7dB original - - {0x0000,-93}, // 1 .. 0 0 0 0 .. -28dB -24dB -8dB -33dB .. -93dB - {0x0008,-91}, // 2 .. 0 0 1 0 .. -28dB -24dB -6dB -33dB .. -91dB - {0x0010,-88}, // 3 .. 0 0 2 0 .. -28dB -24dB -3dB -33dB .. -88dB - {0x0001,-87}, // 4 .. 0 0 0 1 .. -28dB -24dB -8dB -27dB .. -87dB - {0x0009,-85}, // 5 .. 0 0 1 1 .. -28dB -24dB -6dB -27dB .. -85dB - {0x0011,-82}, // 6 .. 0 0 2 1 .. -28dB -24dB -3dB -27dB .. -82dB - {0x0002,-81}, // 7 .. 0 0 0 2 .. -28dB -24dB -8dB -21dB .. -81dB - {0x000A,-79}, // 8 .. 0 0 1 2 .. -28dB -24dB -6dB -21dB .. -79dB - {0x0012,-76}, // 9 .. 0 0 2 2 .. -28dB -24dB -3dB -21dB .. -76dB - {0x0003,-75}, // 10 .. 0 0 0 3 .. -28dB -24dB -8dB -15dB .. -75dB - {0x000B,-73}, // 11 .. 0 0 1 3 .. -28dB -24dB -6dB -15dB .. -73dB - {0x0013,-70}, // 12 .. 0 0 2 3 .. -28dB -24dB -3dB -15dB .. -70dB - {0x0004,-69}, // 13 .. 0 0 0 4 .. -28dB -24dB -8dB -9dB .. -69dB - {0x000C,-67}, // 14 .. 0 0 1 4 .. -28dB -24dB -6dB -9dB .. -67dB - {0x000D,-64}, // 15 .. 0 0 1 5 .. -28dB -24dB -6dB -6dB .. -64dB - {0x001C,-61}, // 16 .. 0 0 3 4 .. -28dB -24dB 0dB - 9dB .. -61dB - {0x001D,-58}, // 17 .. 0 0 3 5 .. -28dB -24dB 0dB -6dB .. -58dB - {0x001E,-55}, // 18 .. 0 0 3 6 .. -28dB -24dB 0dB -3dB .. -55dB - {0x001F,-52}, // 19 .. 0 0 3 7 .. -28dB -24dB 0dB 0dB .. -52dB - {0x003E,-50}, // 20 .. 0 1 3 6 .. -28dB -19dB 0dB -3dB .. -50dB - {0x003F,-47}, // 21 .. 0 1 3 7 .. -28dB -19dB 0dB 0dB .. -47dB - {0x005E,-45}, // 22 .. 0 2 3 6 .. -28dB -14dB 0dB -3dB .. -45dB - {0x005F,-42}, // 23 .. 0 2 3 7 .. -28dB -14dB 0dB 0dB .. -42dB - {0x007E,-40}, // 24 .. 0 3 3 6 .. -28dB -9dB 0dB -3dB .. -40dB - {0x007F,-37}, // 25 .. 0 3 3 7 .. -28dB -9dB 0dB 0dB .. -37dB - {0x009F,-34}, // 26 .. 0 4 3 7 .. -28dB -6dB 0dB 0dB .. -34dB - {0x00BF,-32}, // 27 .. 0 5 3 7 .. -28dB -4dB 0dB 0dB .. -32dB - {0x00DF,-30}, // 28 .. 0 6 3 7 .. -28dB -2dB 0dB 0dB .. -30dB - {0x00FF,-28}, // 29 .. 0 7 3 7 .. -28dB 0dB 0dB 0dB .. -28dB - {0x01DF,-26}, // 30 .. 1 6 3 7 .. -24dB -2dB 0dB 0dB .. -26dB - {0x01FF,-24}, // 31 .. 1 7 3 7 .. -24dB 0dB 0dB 0dB .. -24dB - {0x02BF,-23}, // 32 .. 2 5 3 7 .. -19dB -4dB 0dB 0dB .. -23dB - {0x02DF,-21}, // 33 .. 2 6 3 7 .. -19dB -2dB 0dB -0dB .. -21dB - {0x02FF,-19}, // 34 .. 2 7 3 7 .. -19dB 0dB 0dB 0dB .. -19dB - {0x035E,-17}, // 35 .. 3 2 3 6 .. 0dB -14dB 0dB -3dB .. -17dB - {0x035F,-14}, // 36 .. 3 2 3 7 .. 0dB -14dB 0dB 0dB .. -14dB - {0x037E,-12}, // 37 .. 3 3 3 6 .. 0dB -9dB 0dB -3dB .. -12dB - {0x037F,-9}, // 38 .. 3 3 3 7 .. 0dB -9dB 0dB 0dB .. -9dB - {0x038F,-6}, // 39 .. 3 4 3 7 .. 0dB - 6dB 0dB 0dB .. -6dB - {0x03BF,-4}, // 40 .. 3 5 3 7 .. 0dB -4dB 0dB 0dB .. -4dB - {0x03DF,-2}, // 41 .. 3 6 3 7 .. 0dB - 2dB 0dB 0dB .. -2dB - {0x03FF,0} // 42 .. 3 7 3 7 .. 0dB 0dB 0dB 0dB .. 0dB + {0x03BE, -7}, // 0 .. 3 5 3 6 .. 0dB -4dB 0dB -3dB .. -7dB original + + {0x0000,-93}, // 1 .. 0 0 0 0 .. -28dB -24dB -8dB -33dB .. -93dB + {0x0008,-91}, // 2 .. 0 0 1 0 .. -28dB -24dB -6dB -33dB .. -91dB + {0x0010,-88}, // 3 .. 0 0 2 0 .. -28dB -24dB -3dB -33dB .. -88dB + {0x0001,-87}, // 4 .. 0 0 0 1 .. -28dB -24dB -8dB -27dB .. -87dB + {0x0009,-85}, // 5 .. 0 0 1 1 .. -28dB -24dB -6dB -27dB .. -85dB + {0x0011,-82}, // 6 .. 0 0 2 1 .. -28dB -24dB -3dB -27dB .. -82dB + {0x0002,-81}, // 7 .. 0 0 0 2 .. -28dB -24dB -8dB -21dB .. -81dB + {0x000A,-79}, // 8 .. 0 0 1 2 .. -28dB -24dB -6dB -21dB .. -79dB + {0x0012,-76}, // 9 .. 0 0 2 2 .. -28dB -24dB -3dB -21dB .. -76dB + {0x0003,-75}, // 10 .. 0 0 0 3 .. -28dB -24dB -8dB -15dB .. -75dB + {0x000B,-73}, // 11 .. 0 0 1 3 .. -28dB -24dB -6dB -15dB .. -73dB + {0x0013,-70}, // 12 .. 0 0 2 3 .. -28dB -24dB -3dB -15dB .. -70dB + {0x0004,-69}, // 13 .. 0 0 0 4 .. -28dB -24dB -8dB -9dB .. -69dB + {0x000C,-67}, // 14 .. 0 0 1 4 .. -28dB -24dB -6dB -9dB .. -67dB + {0x000D,-64}, // 15 .. 0 0 1 5 .. -28dB -24dB -6dB -6dB .. -64dB + {0x001C,-61}, // 16 .. 0 0 3 4 .. -28dB -24dB 0dB - 9dB .. -61dB + {0x001D,-58}, // 17 .. 0 0 3 5 .. -28dB -24dB 0dB -6dB .. -58dB + {0x001E,-55}, // 18 .. 0 0 3 6 .. -28dB -24dB 0dB -3dB .. -55dB + {0x001F,-52}, // 19 .. 0 0 3 7 .. -28dB -24dB 0dB 0dB .. -52dB + {0x003E,-50}, // 20 .. 0 1 3 6 .. -28dB -19dB 0dB -3dB .. -50dB + {0x003F,-47}, // 21 .. 0 1 3 7 .. -28dB -19dB 0dB 0dB .. -47dB + {0x005E,-45}, // 22 .. 0 2 3 6 .. -28dB -14dB 0dB -3dB .. -45dB + {0x005F,-42}, // 23 .. 0 2 3 7 .. -28dB -14dB 0dB 0dB .. -42dB + {0x007E,-40}, // 24 .. 0 3 3 6 .. -28dB -9dB 0dB -3dB .. -40dB + {0x007F,-37}, // 25 .. 0 3 3 7 .. -28dB -9dB 0dB 0dB .. -37dB + {0x009F,-34}, // 26 .. 0 4 3 7 .. -28dB -6dB 0dB 0dB .. -34dB + {0x00BF,-32}, // 27 .. 0 5 3 7 .. -28dB -4dB 0dB 0dB .. -32dB + {0x00DF,-30}, // 28 .. 0 6 3 7 .. -28dB -2dB 0dB 0dB .. -30dB + {0x00FF,-28}, // 29 .. 0 7 3 7 .. -28dB 0dB 0dB 0dB .. -28dB + {0x01DF,-26}, // 30 .. 1 6 3 7 .. -24dB -2dB 0dB 0dB .. -26dB + {0x01FF,-24}, // 31 .. 1 7 3 7 .. -24dB 0dB 0dB 0dB .. -24dB + {0x02BF,-23}, // 32 .. 2 5 3 7 .. -19dB -4dB 0dB 0dB .. -23dB + {0x02DF,-21}, // 33 .. 2 6 3 7 .. -19dB -2dB 0dB -0dB .. -21dB + {0x02FF,-19}, // 34 .. 2 7 3 7 .. -19dB 0dB 0dB 0dB .. -19dB + {0x035E,-17}, // 35 .. 3 2 3 6 .. 0dB -14dB 0dB -3dB .. -17dB + {0x035F,-14}, // 36 .. 3 2 3 7 .. 0dB -14dB 0dB 0dB .. -14dB + {0x037E,-12}, // 37 .. 3 3 3 6 .. 0dB -9dB 0dB -3dB .. -12dB + {0x037F,-9}, // 38 .. 3 3 3 7 .. 0dB -9dB 0dB 0dB .. -9dB + {0x038F,-6}, // 39 .. 3 4 3 7 .. 0dB - 6dB 0dB 0dB .. -6dB + {0x03BF,-4}, // 40 .. 3 5 3 7 .. 0dB -4dB 0dB 0dB .. -4dB + {0x03DF,-2}, // 41 .. 3 6 3 7 .. 0dB - 2dB 0dB 0dB .. -2dB + {0x03FF,0} // 42 .. 3 7 3 7 .. 0dB 0dB 0dB 0dB .. 0dB }; const uint8_t gain_table_size = ARRAY_SIZE(gain_table); @@ -163,12 +163,12 @@ typedef union { uint16_t __raw; } GainData; - static const int8_t lna_short_dB[] = {-28, -24, -19, 0}; // corrected'ish - static const int8_t lna_dB[] = {-24, -19, -14, -9, -6, -4, -2, 0}; - static const int8_t mixer_dB[] = { -8, -6, -3, 0}; - static const int8_t pga_dB[] = {-33, -27, -21, -15, -9, -6, -3, 0}; + static const int8_t lna_short_dB[] = {-28, -24, -19, 0}; // corrected'ish + static const int8_t lna_dB[] = {-24, -19, -14, -9, -6, -4, -2, 0}; + static const int8_t mixer_dB[] = { -8, -6, -3, 0}; + static const int8_t pga_dB[] = {-33, -27, -21, -15, -9, -6, -3, 0}; - unsigned i; + unsigned i; for (uint8_t lnaSIdx = 0; lnaSIdx < ARRAY_SIZE(lna_short_dB); lnaSIdx++) { for (uint8_t lnaIdx = 0; lnaIdx < ARRAY_SIZE(lna_dB); lnaIdx++) { for (uint8_t mixerIdx = 0; mixerIdx < ARRAY_SIZE(mixer_dB); mixerIdx++) { @@ -209,9 +209,9 @@ typedef union { #ifdef ENABLE_AM_FIX_SHOW_DATA - // display update rate - static const unsigned int display_update_rate = 250 / 10; // max 250ms display update rate - unsigned int counter = 0; + // display update rate + static const unsigned int display_update_rate = 250 / 10; // max 250ms display update rate + unsigned int counter = 0; #endif unsigned int gain_table_index[2] = {0, 0}; @@ -228,27 +228,27 @@ int8_t currentGainDiff; bool enabled = true; void AM_fix_init(void) -{ // called at boot-up - for (int i = 0; i < 2; i++) { - gain_table_index[i] = 0; // re-start with original QS setting - } +{ // called at boot-up + for (int i = 0; i < 2; i++) { + gain_table_index[i] = 0; // re-start with original QS setting + } #if !LOOKUP_TABLE - CreateTable(); + CreateTable(); #endif } void AM_fix_reset(const unsigned vfo) -{ // reset the AM fixer upper - if (vfo > 1) - return; +{ // reset the AM fixer upper + if (vfo > 1) + return; - #ifdef ENABLE_AM_FIX_SHOW_DATA - counter = 0; - #endif + #ifdef ENABLE_AM_FIX_SHOW_DATA + counter = 0; + #endif - prev_rssi[vfo] = 0; - hold_counter[vfo] = 0; - gain_table_index_prev[vfo] = 0; + prev_rssi[vfo] = 0; + hold_counter[vfo] = 0; + gain_table_index_prev[vfo] = 0; } // adjust the RX gain to try and prevent the AM demodulator from @@ -260,138 +260,138 @@ void AM_fix_reset(const unsigned vfo) // void AM_fix_10ms(const unsigned vfo) { - if(!gSetting_AM_fix || !enabled || vfo > 1 ) - return; + if(!gSetting_AM_fix || !enabled || vfo > 1 ) + return; - if (gCurrentFunction != FUNCTION_FOREGROUND && !FUNCTION_IsRx()) { + if (gCurrentFunction != FUNCTION_FOREGROUND && !FUNCTION_IsRx()) { #ifdef ENABLE_AM_FIX_SHOW_DATA - counter = display_update_rate; // queue up a display update as soon as we switch to RX mode + counter = display_update_rate; // queue up a display update as soon as we switch to RX mode #endif - return; - } + return; + } #ifdef ENABLE_AM_FIX_SHOW_DATA - if (counter > 0) { - if (++counter >= display_update_rate) { // trigger a display update - counter = 0; - gUpdateDisplay = true; - } - } + if (counter > 0) { + if (++counter >= display_update_rate) { // trigger a display update + counter = 0; + gUpdateDisplay = true; + } + } #endif - static uint32_t lastFreq[2]; - if(gEeprom.VfoInfo[vfo].pRX->Frequency != lastFreq[vfo]) { - lastFreq[vfo] = gEeprom.VfoInfo[vfo].pRX->Frequency; - AM_fix_reset(vfo); - } + static uint32_t lastFreq[2]; + if(gEeprom.VfoInfo[vfo].pRX->Frequency != lastFreq[vfo]) { + lastFreq[vfo] = gEeprom.VfoInfo[vfo].pRX->Frequency; + AM_fix_reset(vfo); + } - int16_t rssi; - { // sample the current RSSI level - // average it with the previous rssi (a bit of noise/spike immunity) - const int16_t new_rssi = BK4819_GetRSSI(); - rssi = (prev_rssi[vfo] > 0) ? (prev_rssi[vfo] + new_rssi) / 2 : new_rssi; - prev_rssi[vfo] = new_rssi; - } + int16_t rssi; + { // sample the current RSSI level + // average it with the previous rssi (a bit of noise/spike immunity) + const int16_t new_rssi = BK4819_GetRSSI(); + rssi = (prev_rssi[vfo] > 0) ? (prev_rssi[vfo] + new_rssi) / 2 : new_rssi; + prev_rssi[vfo] = new_rssi; + } #ifdef ENABLE_AM_FIX_SHOW_DATA - { - static int16_t lastRssi; - - if (lastRssi != rssi) { // rssi changed - lastRssi = rssi; - - if (counter == 0) { - counter = 1; - gUpdateDisplay = true; // trigger a display update - } - } - } + { + static int16_t lastRssi; + + if (lastRssi != rssi) { // rssi changed + lastRssi = rssi; + + if (counter == 0) { + counter = 1; + gUpdateDisplay = true; // trigger a display update + } + } + } #endif - // automatically adjust the RF RX gain + // automatically adjust the RF RX gain - // update the gain hold counter - if (hold_counter[vfo] > 0) - hold_counter[vfo]--; + // update the gain hold counter + if (hold_counter[vfo] > 0) + hold_counter[vfo]--; - // dB difference between actual and desired RSSI level - int16_t diff_dB = (rssi - desired_rssi) / 2; + // dB difference between actual and desired RSSI level + int16_t diff_dB = (rssi - desired_rssi) / 2; - if (diff_dB > 0) { // decrease gain - unsigned int index = gain_table_index[vfo]; // current position we're at + if (diff_dB > 0) { // decrease gain + unsigned int index = gain_table_index[vfo]; // current position we're at - if (diff_dB >= 10) { // jump immediately to a new gain setting - // this greatly speeds up initial gain reduction (but reduces noise/spike immunity) + if (diff_dB >= 10) { // jump immediately to a new gain setting + // this greatly speeds up initial gain reduction (but reduces noise/spike immunity) - const int16_t desired_gain_dB = (int16_t)gain_table[index].gain_dB - diff_dB + 8; // get no closer than 8dB (bit of noise/spike immunity) + const int16_t desired_gain_dB = (int16_t)gain_table[index].gain_dB - diff_dB + 8; // get no closer than 8dB (bit of noise/spike immunity) - // scan the table to see what index to jump straight too - while (index > 1) - if (gain_table[--index].gain_dB <= desired_gain_dB) - break; - } - else - { // incrementally reduce the gain .. taking it slow improves noise/spike immunity - if (index > 1) - index--; // slow step-by-step gain reduction - } + // scan the table to see what index to jump straight too + while (index > 1) + if (gain_table[--index].gain_dB <= desired_gain_dB) + break; + } + else + { // incrementally reduce the gain .. taking it slow improves noise/spike immunity + if (index > 1) + index--; // slow step-by-step gain reduction + } - index = MAX(1u, index); + index = MAX(1u, index); - if (gain_table_index[vfo] != index) - { - gain_table_index[vfo] = index; - hold_counter[vfo] = 30; // 300ms hold - } - } + if (gain_table_index[vfo] != index) + { + gain_table_index[vfo] = index; + hold_counter[vfo] = 30; // 300ms hold + } + } - if (diff_dB >= -6) // 6dB hysterisis (help reduce gain hunting) - hold_counter[vfo] = 30; // 300ms hold + if (diff_dB >= -6) // 6dB hysterisis (help reduce gain hunting) + hold_counter[vfo] = 30; // 300ms hold - if (hold_counter[vfo] == 0) - { // hold has been released, we're free to increase gain - const unsigned int index = gain_table_index[vfo] + 1; // move up to next gain index - gain_table_index[vfo] = MIN(index, gain_table_size - 1u); - } + if (hold_counter[vfo] == 0) + { // hold has been released, we're free to increase gain + const unsigned int index = gain_table_index[vfo] + 1; // move up to next gain index + gain_table_index[vfo] = MIN(index, gain_table_size - 1u); + } - { // apply the new settings to the front end registers - const unsigned int index = gain_table_index[vfo]; + { // apply the new settings to the front end registers + const unsigned int index = gain_table_index[vfo]; - // remember the new table index - gain_table_index_prev[vfo] = index; - currentGainDiff = gain_table[0].gain_dB - gain_table[index].gain_dB; - BK4819_WriteRegister(BK4819_REG_13, gain_table[index].reg_val); + // remember the new table index + gain_table_index_prev[vfo] = index; + currentGainDiff = gain_table[0].gain_dB - gain_table[index].gain_dB; + BK4819_WriteRegister(BK4819_REG_13, gain_table[index].reg_val); #ifdef ENABLE_AGC_SHOW_DATA - UI_MAIN_PrintAGC(true); + UI_MAIN_PrintAGC(true); #endif - } + } #ifdef ENABLE_AM_FIX_SHOW_DATA - if (counter == 0) { - counter = 1; - gUpdateDisplay = true; - } + if (counter == 0) { + counter = 1; + gUpdateDisplay = true; + } #endif } #ifdef ENABLE_AM_FIX_SHOW_DATA void AM_fix_print_data(const unsigned vfo, char *s) { - if (s != NULL && vfo < ARRAY_SIZE(gain_table_index)) { - const unsigned int index = gain_table_index[vfo]; - sprintf(s, "%2u %4ddB %3u", index, gain_table[index].gain_dB, prev_rssi[vfo]); - counter = 0; - } + if (s != NULL && vfo < ARRAY_SIZE(gain_table_index)) { + const unsigned int index = gain_table_index[vfo]; + sprintf(s, "%2u %4ddB %3u", index, gain_table[index].gain_dB, prev_rssi[vfo]); + counter = 0; + } } #endif int8_t AM_fix_get_gain_diff() { - return currentGainDiff; + return currentGainDiff; } void AM_fix_enable(bool on) { - enabled = on; + enabled = on; } #endif diff --git a/am_fix.h b/am_fix.h index db8f31ed6..3667301fd 100644 --- a/am_fix.h +++ b/am_fix.h @@ -21,14 +21,14 @@ #include #ifdef ENABLE_AM_FIX - void AM_fix_init(void); - void AM_fix_reset(const unsigned vfo); - void AM_fix_10ms(const unsigned vfo); - #ifdef ENABLE_AM_FIX_SHOW_DATA - void AM_fix_print_data(const unsigned vfo, char *s); - #endif - int8_t AM_fix_get_gain_diff(); - void AM_fix_enable(bool on); + void AM_fix_init(void); + void AM_fix_reset(const unsigned vfo); + void AM_fix_10ms(const unsigned vfo); + #ifdef ENABLE_AM_FIX_SHOW_DATA + void AM_fix_print_data(const unsigned vfo, char *s); + #endif + int8_t AM_fix_get_gain_diff(); + void AM_fix_enable(bool on); #endif diff --git a/app/action.c b/app/action.c index 021c72fdc..73a2f0be5 100644 --- a/app/action.c +++ b/app/action.c @@ -23,16 +23,16 @@ #include "app/common.h" #include "app/dtmf.h" #ifdef ENABLE_FLASHLIGHT - #include "app/flashlight.h" + #include "app/flashlight.h" #endif #ifdef ENABLE_FMRADIO - #include "app/fm.h" + #include "app/fm.h" #endif #include "app/scanner.h" #include "audio.h" #include "bsp/dp32g030/gpio.h" #ifdef ENABLE_FMRADIO - #include "driver/bk1080.h" + #include "driver/bk1080.h" #endif #include "driver/bk4819.h" #include "driver/gpio.h" @@ -60,59 +60,59 @@ inline static void ACTION_1750() { ACTION_AlarmOr1750(true); }; inline static void ACTION_ScanRestart() { ACTION_Scan(true); }; void (*action_opt_table[])(void) = { - [ACTION_OPT_NONE] = &FUNCTION_NOP, - [ACTION_OPT_POWER] = &ACTION_Power, - [ACTION_OPT_MONITOR] = &ACTION_Monitor, - [ACTION_OPT_SCAN] = &ACTION_ScanRestart, - [ACTION_OPT_KEYLOCK] = &COMMON_KeypadLockToggle, - [ACTION_OPT_A_B] = &COMMON_SwitchVFOs, - [ACTION_OPT_VFO_MR] = &COMMON_SwitchVFOMode, - [ACTION_OPT_SWITCH_DEMODUL] = &ACTION_SwitchDemodul, + [ACTION_OPT_NONE] = &FUNCTION_NOP, + [ACTION_OPT_POWER] = &ACTION_Power, + [ACTION_OPT_MONITOR] = &ACTION_Monitor, + [ACTION_OPT_SCAN] = &ACTION_ScanRestart, + [ACTION_OPT_KEYLOCK] = &COMMON_KeypadLockToggle, + [ACTION_OPT_A_B] = &COMMON_SwitchVFOs, + [ACTION_OPT_VFO_MR] = &COMMON_SwitchVFOMode, + [ACTION_OPT_SWITCH_DEMODUL] = &ACTION_SwitchDemodul, #ifdef ENABLE_FLASHLIGHT - [ACTION_OPT_FLASHLIGHT] = &ACTION_FlashLight, + [ACTION_OPT_FLASHLIGHT] = &ACTION_FlashLight, #else - [ACTION_OPT_FLASHLIGHT] = &FUNCTION_NOP, + [ACTION_OPT_FLASHLIGHT] = &FUNCTION_NOP, #endif #ifdef ENABLE_VOX - [ACTION_OPT_VOX] = &ACTION_Vox, + [ACTION_OPT_VOX] = &ACTION_Vox, #else - [ACTION_OPT_VOX] = &FUNCTION_NOP, + [ACTION_OPT_VOX] = &FUNCTION_NOP, #endif #ifdef ENABLE_FMRADIO - [ACTION_OPT_FM] = &ACTION_FM, + [ACTION_OPT_FM] = &ACTION_FM, #else - [ACTION_OPT_FM] = &FUNCTION_NOP, + [ACTION_OPT_FM] = &FUNCTION_NOP, #endif #ifdef ENABLE_ALARM - [ACTION_OPT_ALARM] = &ACTION_Alarm, + [ACTION_OPT_ALARM] = &ACTION_Alarm, #else - [ACTION_OPT_ALARM] = &FUNCTION_NOP, + [ACTION_OPT_ALARM] = &FUNCTION_NOP, #endif #ifdef ENABLE_TX1750 - [ACTION_OPT_1750] = &ACTION_1750, + [ACTION_OPT_1750] = &ACTION_1750, #else - [ACTION_OPT_1750] = &FUNCTION_NOP, + [ACTION_OPT_1750] = &FUNCTION_NOP, #endif #ifdef ENABLE_BLMIN_TMP_OFF - [ACTION_OPT_BLMIN_TMP_OFF] = &ACTION_BlminTmpOff, + [ACTION_OPT_BLMIN_TMP_OFF] = &ACTION_BlminTmpOff, #else - [ACTION_OPT_BLMIN_TMP_OFF] = &FUNCTION_NOP, + [ACTION_OPT_BLMIN_TMP_OFF] = &FUNCTION_NOP, #endif #ifdef ENABLE_FEAT_F4HWN - [ACTION_OPT_RXMODE] = &ACTION_RxMode, - [ACTION_OPT_MAINONLY] = &ACTION_MainOnly, - [ACTION_OPT_PTT] = &ACTION_Ptt, - [ACTION_OPT_WN] = &ACTION_Wn, - [ACTION_OPT_BACKLIGHT] = &ACTION_BackLight, + [ACTION_OPT_RXMODE] = &ACTION_RxMode, + [ACTION_OPT_MAINONLY] = &ACTION_MainOnly, + [ACTION_OPT_PTT] = &ACTION_Ptt, + [ACTION_OPT_WN] = &ACTION_Wn, + [ACTION_OPT_BACKLIGHT] = &ACTION_BackLight, #else - [ACTION_OPT_RXMODE] = &FUNCTION_NOP, + [ACTION_OPT_RXMODE] = &FUNCTION_NOP, #endif }; @@ -120,285 +120,285 @@ static_assert(ARRAY_SIZE(action_opt_table) == ACTION_OPT_LEN); void ACTION_Power(void) { - if (++gTxVfo->OUTPUT_POWER > OUTPUT_POWER_HIGH) - gTxVfo->OUTPUT_POWER = OUTPUT_POWER_LOW1; + if (++gTxVfo->OUTPUT_POWER > OUTPUT_POWER_HIGH) + gTxVfo->OUTPUT_POWER = OUTPUT_POWER_LOW1; - gRequestSaveChannel = 1; + gRequestSaveChannel = 1; - gRequestDisplayScreen = gScreenToDisplay; + gRequestDisplayScreen = gScreenToDisplay; #ifdef ENABLE_VOICE - gAnotherVoiceID = VOICE_ID_POWER; + gAnotherVoiceID = VOICE_ID_POWER; #endif } void ACTION_Monitor(void) { - if (gCurrentFunction != FUNCTION_MONITOR) { // enable the monitor - RADIO_SelectVfos(); + if (gCurrentFunction != FUNCTION_MONITOR) { // enable the monitor + RADIO_SelectVfos(); #ifdef ENABLE_NOAA - if (IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE) && gIsNoaaMode) - gNoaaChannel = gRxVfo->CHANNEL_SAVE - NOAA_CHANNEL_FIRST; + if (IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE) && gIsNoaaMode) + gNoaaChannel = gRxVfo->CHANNEL_SAVE - NOAA_CHANNEL_FIRST; #endif - RADIO_SetupRegisters(true); - APP_StartListening(FUNCTION_MONITOR); - return; - } + RADIO_SetupRegisters(true); + APP_StartListening(FUNCTION_MONITOR); + return; + } - gMonitor = false; + gMonitor = false; - if (gScanStateDir != SCAN_OFF) { - gScanPauseDelayIn_10ms = scan_pause_delay_in_1_10ms; - gScheduleScanListen = false; - gScanPauseMode = true; - } + if (gScanStateDir != SCAN_OFF) { + gScanPauseDelayIn_10ms = scan_pause_delay_in_1_10ms; + gScheduleScanListen = false; + gScanPauseMode = true; + } #ifdef ENABLE_NOAA - if (gEeprom.DUAL_WATCH == DUAL_WATCH_OFF && gIsNoaaMode) { - gNOAA_Countdown_10ms = NOAA_countdown_10ms; - gScheduleNOAA = false; - } + if (gEeprom.DUAL_WATCH == DUAL_WATCH_OFF && gIsNoaaMode) { + gNOAA_Countdown_10ms = NOAA_countdown_10ms; + gScheduleNOAA = false; + } #endif - RADIO_SetupRegisters(true); + RADIO_SetupRegisters(true); #ifdef ENABLE_FMRADIO - if (gFmRadioMode) { - FM_Start(); - gRequestDisplayScreen = DISPLAY_FM; - } - else + if (gFmRadioMode) { + FM_Start(); + gRequestDisplayScreen = DISPLAY_FM; + } + else #endif - gRequestDisplayScreen = gScreenToDisplay; + gRequestDisplayScreen = gScreenToDisplay; } void ACTION_Scan(bool bRestart) { - (void)bRestart; + (void)bRestart; #ifdef ENABLE_FMRADIO - if (gFmRadioMode) { - ACTION_Scan_FM(bRestart); - return; - } + if (gFmRadioMode) { + ACTION_Scan_FM(bRestart); + return; + } #endif - if (SCANNER_IsScanning()) { - return; - } + if (SCANNER_IsScanning()) { + return; + } - // not scanning - gMonitor = false; + // not scanning + gMonitor = false; #ifdef ENABLE_DTMF_CALLING - DTMF_clear_RX(); + DTMF_clear_RX(); #endif - gDTMF_RX_live_timeout = 0; - memset(gDTMF_RX_live, 0, sizeof(gDTMF_RX_live)); + gDTMF_RX_live_timeout = 0; + memset(gDTMF_RX_live, 0, sizeof(gDTMF_RX_live)); - RADIO_SelectVfos(); + RADIO_SelectVfos(); #ifdef ENABLE_NOAA - if (IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE)) { - return; - } + if (IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE)) { + return; + } #endif - GUI_SelectNextDisplay(DISPLAY_MAIN); + GUI_SelectNextDisplay(DISPLAY_MAIN); - if (gScanStateDir != SCAN_OFF) { - // already scanning + if (gScanStateDir != SCAN_OFF) { + // already scanning - if (!IS_MR_CHANNEL(gNextMrChannel)) { - CHFRSCANNER_Stop(); + if (!IS_MR_CHANNEL(gNextMrChannel)) { + CHFRSCANNER_Stop(); #ifdef ENABLE_VOICE - gAnotherVoiceID = VOICE_ID_SCANNING_STOP; + gAnotherVoiceID = VOICE_ID_SCANNING_STOP; #endif - return; - } + return; + } - // channel mode. Keep scanning but toggle between scan lists - gEeprom.SCAN_LIST_DEFAULT = (gEeprom.SCAN_LIST_DEFAULT + 1) % 6; + // channel mode. Keep scanning but toggle between scan lists + gEeprom.SCAN_LIST_DEFAULT = (gEeprom.SCAN_LIST_DEFAULT + 1) % 6; - // jump to the next channel - CHFRSCANNER_Start(false, gScanStateDir); - gScanPauseDelayIn_10ms = 1; - gScheduleScanListen = false; - } else { - // start scanning - CHFRSCANNER_Start(true, SCAN_FWD); + // jump to the next channel + CHFRSCANNER_Start(false, gScanStateDir); + gScanPauseDelayIn_10ms = 1; + gScheduleScanListen = false; + } else { + // start scanning + CHFRSCANNER_Start(true, SCAN_FWD); #ifdef ENABLE_VOICE - AUDIO_SetVoiceID(0, VOICE_ID_SCANNING_BEGIN); - AUDIO_PlaySingleVoice(true); + AUDIO_SetVoiceID(0, VOICE_ID_SCANNING_BEGIN); + AUDIO_PlaySingleVoice(true); #endif - // clear the other vfo's rssi level (to hide the antenna symbol) - gVFO_RSSI_bar_level[(gEeprom.RX_VFO + 1) & 1U] = 0; + // clear the other vfo's rssi level (to hide the antenna symbol) + gVFO_RSSI_bar_level[(gEeprom.RX_VFO + 1) & 1U] = 0; - // let the user see DW is not active - gDualWatchActive = false; - } + // let the user see DW is not active + gDualWatchActive = false; + } - gUpdateStatus = true; + gUpdateStatus = true; } void ACTION_SwitchDemodul(void) { - gRequestSaveChannel = 1; + gRequestSaveChannel = 1; - gTxVfo->Modulation++; + gTxVfo->Modulation++; - if(gTxVfo->Modulation == MODULATION_UKNOWN) - gTxVfo->Modulation = MODULATION_FM; + if(gTxVfo->Modulation == MODULATION_UKNOWN) + gTxVfo->Modulation = MODULATION_FM; } void ACTION_Handle(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld) { - if (gScreenToDisplay == DISPLAY_MAIN && gDTMF_InputMode){ - // entering DTMF code + if (gScreenToDisplay == DISPLAY_MAIN && gDTMF_InputMode){ + // entering DTMF code - gPttWasReleased = true; + gPttWasReleased = true; - if (Key != KEY_SIDE1 || bKeyHeld || !bKeyPressed){ - return; - } + if (Key != KEY_SIDE1 || bKeyHeld || !bKeyPressed){ + return; + } - // side1 btn pressed + // side1 btn pressed - gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; - gRequestDisplayScreen = DISPLAY_MAIN; + gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; + gRequestDisplayScreen = DISPLAY_MAIN; - if (gDTMF_InputBox_Index <= 0) { - // turn off DTMF input box if no codes left - gDTMF_InputMode = false; - return; - } + if (gDTMF_InputBox_Index <= 0) { + // turn off DTMF input box if no codes left + gDTMF_InputMode = false; + return; + } - // DTMF codes are in the input box - gDTMF_InputBox[--gDTMF_InputBox_Index] = '-'; // delete one code + // DTMF codes are in the input box + gDTMF_InputBox[--gDTMF_InputBox_Index] = '-'; // delete one code #ifdef ENABLE_VOICE - gAnotherVoiceID = VOICE_ID_CANCEL; + gAnotherVoiceID = VOICE_ID_CANCEL; #endif - return; - } - - enum ACTION_OPT_t funcShort = ACTION_OPT_NONE; - enum ACTION_OPT_t funcLong = ACTION_OPT_NONE; - switch(Key) { - case KEY_SIDE1: - funcShort = gEeprom.KEY_1_SHORT_PRESS_ACTION; - funcLong = gEeprom.KEY_1_LONG_PRESS_ACTION; - break; - case KEY_SIDE2: - funcShort = gEeprom.KEY_2_SHORT_PRESS_ACTION; - funcLong = gEeprom.KEY_2_LONG_PRESS_ACTION; - break; - case KEY_MENU: - funcLong = gEeprom.KEY_M_LONG_PRESS_ACTION; - break; - default: - break; - } - - if (!bKeyHeld && bKeyPressed) // button pushed - { - return; - } - - // held or released beyond this point - - if(!(bKeyHeld && !bKeyPressed)) // don't beep on released after hold - gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; - - if (bKeyHeld || bKeyPressed) // held - { - funcShort = funcLong; - - // For screenshot - #ifdef ENABLE_FEAT_F4HWN_SCREENSHOT - getScreenShot(); - #endif - - if (!bKeyPressed) //ignore release if held - return; - } - - // held or released after short press beyond this point - - action_opt_table[funcShort](); + return; + } + + enum ACTION_OPT_t funcShort = ACTION_OPT_NONE; + enum ACTION_OPT_t funcLong = ACTION_OPT_NONE; + switch(Key) { + case KEY_SIDE1: + funcShort = gEeprom.KEY_1_SHORT_PRESS_ACTION; + funcLong = gEeprom.KEY_1_LONG_PRESS_ACTION; + break; + case KEY_SIDE2: + funcShort = gEeprom.KEY_2_SHORT_PRESS_ACTION; + funcLong = gEeprom.KEY_2_LONG_PRESS_ACTION; + break; + case KEY_MENU: + funcLong = gEeprom.KEY_M_LONG_PRESS_ACTION; + break; + default: + break; + } + + if (!bKeyHeld && bKeyPressed) // button pushed + { + return; + } + + // held or released beyond this point + + if(!(bKeyHeld && !bKeyPressed)) // don't beep on released after hold + gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; + + if (bKeyHeld || bKeyPressed) // held + { + funcShort = funcLong; + + // For screenshot + #ifdef ENABLE_FEAT_F4HWN_SCREENSHOT + getScreenShot(); + #endif + + if (!bKeyPressed) //ignore release if held + return; + } + + // held or released after short press beyond this point + + action_opt_table[funcShort](); } #ifdef ENABLE_FMRADIO void ACTION_FM(void) { - if (gCurrentFunction != FUNCTION_TRANSMIT && gCurrentFunction != FUNCTION_MONITOR) - { - gInputBoxIndex = 0; + if (gCurrentFunction != FUNCTION_TRANSMIT && gCurrentFunction != FUNCTION_MONITOR) + { + gInputBoxIndex = 0; - if (gFmRadioMode) { - FM_TurnOff(); - gFlagReconfigureVfos = true; - gRequestDisplayScreen = DISPLAY_MAIN; + if (gFmRadioMode) { + FM_TurnOff(); + gFlagReconfigureVfos = true; + gRequestDisplayScreen = DISPLAY_MAIN; #ifdef ENABLE_VOX - gVoxResumeCountdown = 80; + gVoxResumeCountdown = 80; #endif - return; - } + return; + } - gMonitor = false; + gMonitor = false; - RADIO_SelectVfos(); - RADIO_SetupRegisters(true); + RADIO_SelectVfos(); + RADIO_SetupRegisters(true); - FM_Start(); + FM_Start(); - gRequestDisplayScreen = DISPLAY_FM; - } + gRequestDisplayScreen = DISPLAY_FM; + } } static void ACTION_Scan_FM(bool bRestart) { - if (FUNCTION_IsRx()) - return; + if (FUNCTION_IsRx()) + return; - GUI_SelectNextDisplay(DISPLAY_FM); + GUI_SelectNextDisplay(DISPLAY_FM); - gMonitor = false; + gMonitor = false; - if (gFM_ScanState != FM_SCAN_OFF) { - FM_PlayAndUpdate(); + if (gFM_ScanState != FM_SCAN_OFF) { + FM_PlayAndUpdate(); #ifdef ENABLE_VOICE - gAnotherVoiceID = VOICE_ID_SCANNING_STOP; + gAnotherVoiceID = VOICE_ID_SCANNING_STOP; #endif - return; - } + return; + } - uint16_t freq; + uint16_t freq; - if (bRestart) { - gFM_AutoScan = true; - gFM_ChannelPosition = 0; - FM_EraseChannels(); - freq = BK1080_GetFreqLoLimit(gEeprom.FM_Band); - } else { - gFM_AutoScan = false; - gFM_ChannelPosition = 0; - freq = gEeprom.FM_FrequencyPlaying; - } + if (bRestart) { + gFM_AutoScan = true; + gFM_ChannelPosition = 0; + FM_EraseChannels(); + freq = BK1080_GetFreqLoLimit(gEeprom.FM_Band); + } else { + gFM_AutoScan = false; + gFM_ChannelPosition = 0; + freq = gEeprom.FM_FrequencyPlaying; + } - BK1080_GetFrequencyDeviation(freq); - FM_Tune(freq, 1, bRestart); + BK1080_GetFrequencyDeviation(freq); + FM_Tune(freq, 1, bRestart); #ifdef ENABLE_VOICE - gAnotherVoiceID = VOICE_ID_SCANNING_BEGIN; + gAnotherVoiceID = VOICE_ID_SCANNING_BEGIN; #endif } @@ -410,29 +410,29 @@ static void ACTION_Scan_FM(bool bRestart) static void ACTION_AlarmOr1750(const bool b1750) { - if(gEeprom.KEY_LOCK && gEeprom.KEY_LOCK_PTT) - return; + if(gEeprom.KEY_LOCK && gEeprom.KEY_LOCK_PTT) + return; - #if defined(ENABLE_ALARM) - const AlarmState_t alarm_mode = (gEeprom.ALARM_MODE == ALARM_MODE_TONE) ? ALARM_STATE_TXALARM : ALARM_STATE_SITE_ALARM; - gAlarmRunningCounter = 0; - #endif + #if defined(ENABLE_ALARM) + const AlarmState_t alarm_mode = (gEeprom.ALARM_MODE == ALARM_MODE_TONE) ? ALARM_STATE_TXALARM : ALARM_STATE_SITE_ALARM; + gAlarmRunningCounter = 0; + #endif - #if defined(ENABLE_ALARM) && defined(ENABLE_TX1750) - gAlarmState = b1750 ? ALARM_STATE_TX1750 : alarm_mode; - #elif defined(ENABLE_ALARM) - gAlarmState = alarm_mode; - #else - gAlarmState = ALARM_STATE_TX1750; - #endif + #if defined(ENABLE_ALARM) && defined(ENABLE_TX1750) + gAlarmState = b1750 ? ALARM_STATE_TX1750 : alarm_mode; + #elif defined(ENABLE_ALARM) + gAlarmState = alarm_mode; + #else + gAlarmState = ALARM_STATE_TX1750; + #endif - (void)b1750; - gInputBoxIndex = 0; + (void)b1750; + gInputBoxIndex = 0; - gFlagPrepareTX = gAlarmState != ALARM_STATE_OFF; + gFlagPrepareTX = gAlarmState != ALARM_STATE_OFF; - if (gScreenToDisplay != DISPLAY_MENU) // 1of11 .. don't close the menu - gRequestDisplayScreen = DISPLAY_MAIN; + if (gScreenToDisplay != DISPLAY_MENU) // 1of11 .. don't close the menu + gRequestDisplayScreen = DISPLAY_MAIN; } @@ -441,137 +441,137 @@ static void ACTION_AlarmOr1750(const bool b1750) #ifdef ENABLE_VOX void ACTION_Vox(void) { - gEeprom.VOX_SWITCH = !gEeprom.VOX_SWITCH; - gRequestSaveSettings = true; - gFlagReconfigureVfos = true; - gUpdateStatus = true; - - #ifdef ENABLE_VOICE - gAnotherVoiceID = VOICE_ID_VOX; - #endif + gEeprom.VOX_SWITCH = !gEeprom.VOX_SWITCH; + gRequestSaveSettings = true; + gFlagReconfigureVfos = true; + gUpdateStatus = true; + + #ifdef ENABLE_VOICE + gAnotherVoiceID = VOICE_ID_VOX; + #endif } #endif #ifdef ENABLE_BLMIN_TMP_OFF void ACTION_BlminTmpOff(void) { - if(++gEeprom.BACKLIGHT_MIN_STAT == BLMIN_STAT_UNKNOWN) { - gEeprom.BACKLIGHT_MIN_STAT = BLMIN_STAT_ON; - BACKLIGHT_SetBrightness(gEeprom.BACKLIGHT_MIN); - } else { - BACKLIGHT_SetBrightness(0); - } + if(++gEeprom.BACKLIGHT_MIN_STAT == BLMIN_STAT_UNKNOWN) { + gEeprom.BACKLIGHT_MIN_STAT = BLMIN_STAT_ON; + BACKLIGHT_SetBrightness(gEeprom.BACKLIGHT_MIN); + } else { + BACKLIGHT_SetBrightness(0); + } } #endif #ifdef ENABLE_FEAT_F4HWN void ACTION_Update(void) { - gSaveRxMode = false; - gFlagReconfigureVfos = true; - gUpdateStatus = true; + gSaveRxMode = false; + gFlagReconfigureVfos = true; + gUpdateStatus = true; } void ACTION_RxMode(void) { - static bool cycle = 0; - - switch(cycle) { - case 0: - gEeprom.DUAL_WATCH = !gEeprom.DUAL_WATCH; - cycle = 1; - break; - case 1: - gEeprom.CROSS_BAND_RX_TX = !gEeprom.CROSS_BAND_RX_TX; - cycle = 0; - break; - } - - ACTION_Update(); + static bool cycle = 0; + + switch(cycle) { + case 0: + gEeprom.DUAL_WATCH = !gEeprom.DUAL_WATCH; + cycle = 1; + break; + case 1: + gEeprom.CROSS_BAND_RX_TX = !gEeprom.CROSS_BAND_RX_TX; + cycle = 0; + break; + } + + ACTION_Update(); } void ACTION_MainOnly(void) { - static bool cycle = 0; - static uint8_t dw = 0; - static uint8_t cb = 0; - - switch(cycle) { - case 0: - dw = gEeprom.DUAL_WATCH; - cb = gEeprom.CROSS_BAND_RX_TX; - - gEeprom.DUAL_WATCH = 0; - gEeprom.CROSS_BAND_RX_TX = 0; - cycle = 1; - break; - case 1: - gEeprom.DUAL_WATCH = dw; - gEeprom.CROSS_BAND_RX_TX = cb; - cycle = 0; - break; - } - - ACTION_Update(); + static bool cycle = 0; + static uint8_t dw = 0; + static uint8_t cb = 0; + + switch(cycle) { + case 0: + dw = gEeprom.DUAL_WATCH; + cb = gEeprom.CROSS_BAND_RX_TX; + + gEeprom.DUAL_WATCH = 0; + gEeprom.CROSS_BAND_RX_TX = 0; + cycle = 1; + break; + case 1: + gEeprom.DUAL_WATCH = dw; + gEeprom.CROSS_BAND_RX_TX = cb; + cycle = 0; + break; + } + + ACTION_Update(); } void ACTION_Ptt(void) { - gSetting_set_ptt_session = (gSetting_set_ptt_session == 0) ? 1: 0; + gSetting_set_ptt_session = (gSetting_set_ptt_session == 0) ? 1: 0; } void ACTION_Wn(void) { - if (FUNCTION_IsRx()) - { - gRxVfo->CHANNEL_BANDWIDTH = (gRxVfo->CHANNEL_BANDWIDTH == 0) ? 1: 0; - #ifdef ENABLE_AM_FIX - BK4819_SetFilterBandwidth(gRxVfo->CHANNEL_BANDWIDTH, true); - #else - BK4819_SetFilterBandwidth(gRxVfo->CHANNEL_BANDWIDTH, false); - #endif - } - else - { - gTxVfo->CHANNEL_BANDWIDTH = (gTxVfo->CHANNEL_BANDWIDTH == 0) ? 1: 0; - #ifdef ENABLE_AM_FIX - BK4819_SetFilterBandwidth(gTxVfo->CHANNEL_BANDWIDTH, true); - #else - BK4819_SetFilterBandwidth(gTxVfo->CHANNEL_BANDWIDTH, false); - #endif - } + if (FUNCTION_IsRx()) + { + gRxVfo->CHANNEL_BANDWIDTH = (gRxVfo->CHANNEL_BANDWIDTH == 0) ? 1: 0; + #ifdef ENABLE_AM_FIX + BK4819_SetFilterBandwidth(gRxVfo->CHANNEL_BANDWIDTH, true); + #else + BK4819_SetFilterBandwidth(gRxVfo->CHANNEL_BANDWIDTH, false); + #endif + } + else + { + gTxVfo->CHANNEL_BANDWIDTH = (gTxVfo->CHANNEL_BANDWIDTH == 0) ? 1: 0; + #ifdef ENABLE_AM_FIX + BK4819_SetFilterBandwidth(gTxVfo->CHANNEL_BANDWIDTH, true); + #else + BK4819_SetFilterBandwidth(gTxVfo->CHANNEL_BANDWIDTH, false); + #endif + } } void ACTION_BackLight(void) { - if(gBackLight) - { - gEeprom.BACKLIGHT_TIME = gBacklightTimeOriginal; - } - gBackLight = false; - BACKLIGHT_TurnOn(); + if(gBackLight) + { + gEeprom.BACKLIGHT_TIME = gBacklightTimeOriginal; + } + gBackLight = false; + BACKLIGHT_TurnOn(); } void ACTION_BackLightOnDemand(void) { - if(gBackLight == false) - { - gBacklightTimeOriginal = gEeprom.BACKLIGHT_TIME; - gEeprom.BACKLIGHT_TIME = 61; - gBackLight = true; - } - else - { - if(gBacklightBrightnessOld == gEeprom.BACKLIGHT_MAX) - { - gEeprom.BACKLIGHT_TIME = 0; - } - else - { - gEeprom.BACKLIGHT_TIME = 61; - } - } - - BACKLIGHT_TurnOn(); + if(gBackLight == false) + { + gBacklightTimeOriginal = gEeprom.BACKLIGHT_TIME; + gEeprom.BACKLIGHT_TIME = 61; + gBackLight = true; + } + else + { + if(gBacklightBrightnessOld == gEeprom.BACKLIGHT_MAX) + { + gEeprom.BACKLIGHT_TIME = 0; + } + else + { + gEeprom.BACKLIGHT_TIME = 61; + } + } + + BACKLIGHT_TurnOn(); } #endif \ No newline at end of file diff --git a/app/action.h b/app/action.h index 6f9244098..311d3b462 100644 --- a/app/action.h +++ b/app/action.h @@ -23,25 +23,25 @@ void ACTION_Power(void); void ACTION_Monitor(void); void ACTION_Scan(bool bRestart); #ifdef ENABLE_VOX - void ACTION_Vox(void); + void ACTION_Vox(void); #endif #ifdef ENABLE_FMRADIO - void ACTION_FM(void); + void ACTION_FM(void); #endif void ACTION_SwitchDemodul(void); #ifdef ENABLE_BLMIN_TMP_OFF - void ACTION_BlminTmpOff(void); + void ACTION_BlminTmpOff(void); #endif #ifdef ENABLE_FEAT_F4HWN - void ACTION_RxMode(void); - void ACTION_MainOnly(void); - void ACTION_Ptt(void); - void ACTION_Wn(void); - void ACTION_BackLightOnDemand(void); - void ACTION_BackLight(void); + void ACTION_RxMode(void); + void ACTION_MainOnly(void); + void ACTION_Ptt(void); + void ACTION_Wn(void); + void ACTION_BackLightOnDemand(void); + void ACTION_BackLight(void); #endif void ACTION_Handle(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld); diff --git a/app/aircopy.c b/app/aircopy.c index cda195c4a..4f0607593 100644 --- a/app/aircopy.c +++ b/app/aircopy.c @@ -17,7 +17,7 @@ #ifdef ENABLE_AIRCOPY //#if !defined(ENABLE_OVERLAY) -// #include "ARMCM0.h" +// #include "ARMCM0.h" //#endif #include "app/aircopy.h" @@ -43,219 +43,219 @@ uint16_t g_FSK_Buffer[36]; static void AIRCOPY_clear() { - for (uint8_t i = 0; i < 15; i++) - { - crc[i] = 0; - } + for (uint8_t i = 0; i < 15; i++) + { + crc[i] = 0; + } } bool AIRCOPY_SendMessage(void) { - static uint8_t gAircopySendCountdown = 1; + static uint8_t gAircopySendCountdown = 1; - if (gAircopyState != AIRCOPY_TRANSFER) { - return 1; - } + if (gAircopyState != AIRCOPY_TRANSFER) { + return 1; + } - if (--gAircopySendCountdown) { - return 1; - } + if (--gAircopySendCountdown) { + return 1; + } - g_FSK_Buffer[1] = (gAirCopyBlockNumber & 0x3FF) << 6; + g_FSK_Buffer[1] = (gAirCopyBlockNumber & 0x3FF) << 6; - EEPROM_ReadBuffer(g_FSK_Buffer[1], &g_FSK_Buffer[2], 64); + EEPROM_ReadBuffer(g_FSK_Buffer[1], &g_FSK_Buffer[2], 64); - g_FSK_Buffer[34] = CRC_Calculate(&g_FSK_Buffer[1], 2 + 64); + g_FSK_Buffer[34] = CRC_Calculate(&g_FSK_Buffer[1], 2 + 64); - for (unsigned int i = 0; i < 34; i++) { - g_FSK_Buffer[i + 1] ^= Obfuscation[i % 8]; - } + for (unsigned int i = 0; i < 34; i++) { + g_FSK_Buffer[i + 1] ^= Obfuscation[i % 8]; + } - if (++gAirCopyBlockNumber >= 0x78) { - gAircopyState = AIRCOPY_COMPLETE; - //NVIC_SystemReset(); - } + if (++gAirCopyBlockNumber >= 0x78) { + gAircopyState = AIRCOPY_COMPLETE; + //NVIC_SystemReset(); + } - RADIO_SetTxParameters(); + RADIO_SetTxParameters(); - BK4819_SendFSKData(g_FSK_Buffer); - BK4819_SetupPowerAmplifier(0, 0); - BK4819_ToggleGpioOut(BK4819_GPIO1_PIN29_PA_ENABLE, false); + BK4819_SendFSKData(g_FSK_Buffer); + BK4819_SetupPowerAmplifier(0, 0); + BK4819_ToggleGpioOut(BK4819_GPIO1_PIN29_PA_ENABLE, false); - gAircopySendCountdown = 30; + gAircopySendCountdown = 30; - return 0; + return 0; } void AIRCOPY_StorePacket(void) { - if (gFSKWriteIndex < 36) { - return; - } - - gFSKWriteIndex = 0; - gUpdateDisplay = true; - uint16_t Status = BK4819_ReadRegister(BK4819_REG_0B); - BK4819_PrepareFSKReceive(); - - // Doc says bit 4 should be 1 = CRC OK, 0 = CRC FAIL, but original firmware checks for FAIL. - - if ((Status & 0x0010U) != 0 || g_FSK_Buffer[0] != 0xABCD || g_FSK_Buffer[35] != 0xDCBA) { - gErrorsDuringAirCopy++; - return; - } - - for (unsigned int i = 0; i < 34; i++) { - g_FSK_Buffer[i + 1] ^= Obfuscation[i % 8]; - } - - uint16_t CRC = CRC_Calculate(&g_FSK_Buffer[1], 2 + 64); - if (g_FSK_Buffer[34] != CRC) { - gErrorsDuringAirCopy++; - return; - } - - uint16_t Offset = g_FSK_Buffer[1]; - - if (Offset >= 0x1E00) { - gErrorsDuringAirCopy++; - return; - } - - const uint16_t *pData = &g_FSK_Buffer[2]; - for (unsigned int i = 0; i < 8; i++) { - EEPROM_WriteBuffer(Offset, pData); - pData += 4; - Offset += 8; - } - - if (Offset == 0x1E00) { - gAircopyState = AIRCOPY_COMPLETE; - } - - gAirCopyBlockNumber++; + if (gFSKWriteIndex < 36) { + return; + } + + gFSKWriteIndex = 0; + gUpdateDisplay = true; + uint16_t Status = BK4819_ReadRegister(BK4819_REG_0B); + BK4819_PrepareFSKReceive(); + + // Doc says bit 4 should be 1 = CRC OK, 0 = CRC FAIL, but original firmware checks for FAIL. + + if ((Status & 0x0010U) != 0 || g_FSK_Buffer[0] != 0xABCD || g_FSK_Buffer[35] != 0xDCBA) { + gErrorsDuringAirCopy++; + return; + } + + for (unsigned int i = 0; i < 34; i++) { + g_FSK_Buffer[i + 1] ^= Obfuscation[i % 8]; + } + + uint16_t CRC = CRC_Calculate(&g_FSK_Buffer[1], 2 + 64); + if (g_FSK_Buffer[34] != CRC) { + gErrorsDuringAirCopy++; + return; + } + + uint16_t Offset = g_FSK_Buffer[1]; + + if (Offset >= 0x1E00) { + gErrorsDuringAirCopy++; + return; + } + + const uint16_t *pData = &g_FSK_Buffer[2]; + for (unsigned int i = 0; i < 8; i++) { + EEPROM_WriteBuffer(Offset, pData); + pData += 4; + Offset += 8; + } + + if (Offset == 0x1E00) { + gAircopyState = AIRCOPY_COMPLETE; + } + + gAirCopyBlockNumber++; } static void AIRCOPY_Key_DIGITS(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld) { - if (bKeyHeld || !bKeyPressed) { - return; - } + if (bKeyHeld || !bKeyPressed) { + return; + } - INPUTBOX_Append(Key); + INPUTBOX_Append(Key); - gRequestDisplayScreen = DISPLAY_AIRCOPY; + gRequestDisplayScreen = DISPLAY_AIRCOPY; - if (gInputBoxIndex < 6) { + if (gInputBoxIndex < 6) { #ifdef ENABLE_VOICE - gAnotherVoiceID = (VOICE_ID_t)Key; + gAnotherVoiceID = (VOICE_ID_t)Key; #endif - return; - } + return; + } - gInputBoxIndex = 0; - uint32_t Frequency = StrToUL(INPUTBOX_GetAscii()) * 100; + gInputBoxIndex = 0; + uint32_t Frequency = StrToUL(INPUTBOX_GetAscii()) * 100; - for (unsigned int i = 0; i < BAND_N_ELEM; i++) { - if (Frequency < frequencyBandTable[i].lower || Frequency >= frequencyBandTable[i].upper) { - continue; - } + for (unsigned int i = 0; i < BAND_N_ELEM; i++) { + if (Frequency < frequencyBandTable[i].lower || Frequency >= frequencyBandTable[i].upper) { + continue; + } - if (TX_freq_check(Frequency)) { - continue; - } + if (TX_freq_check(Frequency)) { + continue; + } #ifdef ENABLE_VOICE - gAnotherVoiceID = (VOICE_ID_t)Key; + gAnotherVoiceID = (VOICE_ID_t)Key; #endif - Frequency = FREQUENCY_RoundToStep(Frequency, gRxVfo->StepFrequency); - gRxVfo->Band = i; - gRxVfo->freq_config_RX.Frequency = Frequency; - gRxVfo->freq_config_TX.Frequency = Frequency; - RADIO_ConfigureSquelchAndOutputPower(gRxVfo); - gCurrentVfo = gRxVfo; - RADIO_SetupRegisters(true); - BK4819_SetupAircopy(); - BK4819_ResetFSK(); - return; - } - - gRequestDisplayScreen = DISPLAY_AIRCOPY; + Frequency = FREQUENCY_RoundToStep(Frequency, gRxVfo->StepFrequency); + gRxVfo->Band = i; + gRxVfo->freq_config_RX.Frequency = Frequency; + gRxVfo->freq_config_TX.Frequency = Frequency; + RADIO_ConfigureSquelchAndOutputPower(gRxVfo); + gCurrentVfo = gRxVfo; + RADIO_SetupRegisters(true); + BK4819_SetupAircopy(); + BK4819_ResetFSK(); + return; + } + + gRequestDisplayScreen = DISPLAY_AIRCOPY; } static void AIRCOPY_Key_EXIT(bool bKeyPressed, bool bKeyHeld) { - if (bKeyHeld || !bKeyPressed) { - return; - } + if (bKeyHeld || !bKeyPressed) { + return; + } - if (gInputBoxIndex == 0) { - gAircopyStep = 1; - gFSKWriteIndex = 0; - gAirCopyBlockNumber = 0; - gInputBoxIndex = 0; - gErrorsDuringAirCopy = lErrorsDuringAirCopy = 0; - gAirCopyIsSendMode = 0; + if (gInputBoxIndex == 0) { + gAircopyStep = 1; + gFSKWriteIndex = 0; + gAirCopyBlockNumber = 0; + gInputBoxIndex = 0; + gErrorsDuringAirCopy = lErrorsDuringAirCopy = 0; + gAirCopyIsSendMode = 0; - AIRCOPY_clear(); + AIRCOPY_clear(); - BK4819_PrepareFSKReceive(); + BK4819_PrepareFSKReceive(); - gAircopyState = AIRCOPY_TRANSFER; - } else { - gInputBox[--gInputBoxIndex] = 10; - } + gAircopyState = AIRCOPY_TRANSFER; + } else { + gInputBox[--gInputBoxIndex] = 10; + } - gRequestDisplayScreen = DISPLAY_AIRCOPY; + gRequestDisplayScreen = DISPLAY_AIRCOPY; } static void AIRCOPY_Key_MENU(bool bKeyPressed, bool bKeyHeld) { - if (bKeyHeld || !bKeyPressed) { - return; - } + if (bKeyHeld || !bKeyPressed) { + return; + } - gAircopyStep = 1; - gFSKWriteIndex = 0; - gAirCopyBlockNumber = 0; - gInputBoxIndex = 0; - gAirCopyIsSendMode = 1; - g_FSK_Buffer[0] = 0xABCD; - g_FSK_Buffer[1] = 0; - g_FSK_Buffer[35] = 0xDCBA; + gAircopyStep = 1; + gFSKWriteIndex = 0; + gAirCopyBlockNumber = 0; + gInputBoxIndex = 0; + gAirCopyIsSendMode = 1; + g_FSK_Buffer[0] = 0xABCD; + g_FSK_Buffer[1] = 0; + g_FSK_Buffer[35] = 0xDCBA; - AIRCOPY_clear(); + AIRCOPY_clear(); - GUI_DisplayScreen(); + GUI_DisplayScreen(); - gAircopyState = AIRCOPY_TRANSFER; + gAircopyState = AIRCOPY_TRANSFER; } void AIRCOPY_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld) { - switch (Key) { - case KEY_0: - case KEY_1: - case KEY_2: - case KEY_3: - case KEY_4: - case KEY_5: - case KEY_6: - case KEY_7: - case KEY_8: - case KEY_9: - AIRCOPY_Key_DIGITS(Key, bKeyPressed, bKeyHeld); - break; - case KEY_MENU: - AIRCOPY_Key_MENU(bKeyPressed, bKeyHeld); - break; - case KEY_EXIT: - AIRCOPY_Key_EXIT(bKeyPressed, bKeyHeld); - break; - default: - break; - } + switch (Key) { + case KEY_0: + case KEY_1: + case KEY_2: + case KEY_3: + case KEY_4: + case KEY_5: + case KEY_6: + case KEY_7: + case KEY_8: + case KEY_9: + AIRCOPY_Key_DIGITS(Key, bKeyPressed, bKeyHeld); + break; + case KEY_MENU: + AIRCOPY_Key_MENU(bKeyPressed, bKeyHeld); + break; + case KEY_EXIT: + AIRCOPY_Key_EXIT(bKeyPressed, bKeyHeld); + break; + default: + break; + } } #endif diff --git a/app/aircopy.h b/app/aircopy.h index 4ea18f945..fe64115bc 100644 --- a/app/aircopy.h +++ b/app/aircopy.h @@ -23,9 +23,9 @@ enum AIRCOPY_State_t { - AIRCOPY_READY = 0, - AIRCOPY_TRANSFER, - AIRCOPY_COMPLETE + AIRCOPY_READY = 0, + AIRCOPY_TRANSFER, + AIRCOPY_COMPLETE }; typedef enum AIRCOPY_State_t AIRCOPY_State_t; diff --git a/app/app.c b/app/app.c index c34292556..277b88543 100644 --- a/app/app.c +++ b/app/app.c @@ -22,23 +22,23 @@ #include "app/action.h" #ifdef ENABLE_AIRCOPY - #include "app/aircopy.h" + #include "app/aircopy.h" #endif #include "app/app.h" #include "app/chFrScanner.h" #include "app/dtmf.h" #ifdef ENABLE_FLASHLIGHT - #include "app/flashlight.h" + #include "app/flashlight.h" #endif #ifdef ENABLE_FMRADIO - #include "app/fm.h" + #include "app/fm.h" #endif #include "app/generic.h" #include "app/main.h" #include "app/menu.h" #include "app/scanner.h" #ifdef ENABLE_UART - #include "app/uart.h" + #include "app/uart.h" #endif #include "ARMCM0.h" #include "audio.h" @@ -46,7 +46,7 @@ #include "bsp/dp32g030/gpio.h" #include "driver/backlight.h" #ifdef ENABLE_FMRADIO - #include "driver/bk1080.h" + #include "driver/bk1080.h" #endif #include "driver/bk4819.h" #include "driver/gpio.h" @@ -63,7 +63,7 @@ #include "settings.h" #if defined(ENABLE_OVERLAY) - #include "sram-overlay.h" + #include "sram-overlay.h" #endif #include "ui/battery.h" #include "ui/inputbox.h" @@ -80,16 +80,16 @@ static void ProcessKey(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld); void (*ProcessKeysFunctions[])(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld) = { - [DISPLAY_MAIN] = &MAIN_ProcessKeys, - [DISPLAY_MENU] = &MENU_ProcessKeys, - [DISPLAY_SCANNER] = &SCANNER_ProcessKeys, + [DISPLAY_MAIN] = &MAIN_ProcessKeys, + [DISPLAY_MENU] = &MENU_ProcessKeys, + [DISPLAY_SCANNER] = &SCANNER_ProcessKeys, #ifdef ENABLE_FMRADIO - [DISPLAY_FM] = &FM_ProcessKeys, + [DISPLAY_FM] = &FM_ProcessKeys, #endif #ifdef ENABLE_AIRCOPY - [DISPLAY_AIRCOPY] = &AIRCOPY_ProcessKeys, + [DISPLAY_AIRCOPY] = &AIRCOPY_ProcessKeys, #endif }; @@ -99,2021 +99,2021 @@ static_assert(ARRAY_SIZE(ProcessKeysFunctions) == DISPLAY_N_ELEM); static void CheckForIncoming(void) { - if (!g_SquelchLost) - return; // squelch is closed - - // squelch is open - - if (gScanStateDir == SCAN_OFF) - { // not RF scanning - if (gEeprom.DUAL_WATCH == DUAL_WATCH_OFF) - { // dual watch is disabled - - #ifdef ENABLE_NOAA - if (gIsNoaaMode) - { - gNOAA_Countdown_10ms = NOAA_countdown_3_10ms; - gScheduleNOAA = false; - } - #endif - - if (gCurrentFunction != FUNCTION_INCOMING) - { - FUNCTION_Select(FUNCTION_INCOMING); - //gUpdateDisplay = true; - } - - return; - } - - // dual watch is enabled and we're RX'ing a signal - - if (gRxReceptionMode != RX_MODE_NONE) - { - if (gCurrentFunction != FUNCTION_INCOMING) - { - FUNCTION_Select(FUNCTION_INCOMING); - //gUpdateDisplay = true; - } - return; - } - - gDualWatchCountdown_10ms = dual_watch_count_after_rx_10ms; - gScheduleDualWatch = false; - - // let the user see DW is not active - gDualWatchActive = false; - gUpdateStatus = true; - } - else - { // RF scanning - if (gRxReceptionMode != RX_MODE_NONE) - { - if (gCurrentFunction != FUNCTION_INCOMING) - { - FUNCTION_Select(FUNCTION_INCOMING); - //gUpdateDisplay = true; - } - return; - } - - gScanPauseDelayIn_10ms = scan_pause_delay_in_3_10ms; - gScheduleScanListen = false; - } - - gRxReceptionMode = RX_MODE_DETECTED; - - if (gCurrentFunction != FUNCTION_INCOMING) - { - FUNCTION_Select(FUNCTION_INCOMING); - //gUpdateDisplay = true; - } + if (!g_SquelchLost) + return; // squelch is closed + + // squelch is open + + if (gScanStateDir == SCAN_OFF) + { // not RF scanning + if (gEeprom.DUAL_WATCH == DUAL_WATCH_OFF) + { // dual watch is disabled + + #ifdef ENABLE_NOAA + if (gIsNoaaMode) + { + gNOAA_Countdown_10ms = NOAA_countdown_3_10ms; + gScheduleNOAA = false; + } + #endif + + if (gCurrentFunction != FUNCTION_INCOMING) + { + FUNCTION_Select(FUNCTION_INCOMING); + //gUpdateDisplay = true; + } + + return; + } + + // dual watch is enabled and we're RX'ing a signal + + if (gRxReceptionMode != RX_MODE_NONE) + { + if (gCurrentFunction != FUNCTION_INCOMING) + { + FUNCTION_Select(FUNCTION_INCOMING); + //gUpdateDisplay = true; + } + return; + } + + gDualWatchCountdown_10ms = dual_watch_count_after_rx_10ms; + gScheduleDualWatch = false; + + // let the user see DW is not active + gDualWatchActive = false; + gUpdateStatus = true; + } + else + { // RF scanning + if (gRxReceptionMode != RX_MODE_NONE) + { + if (gCurrentFunction != FUNCTION_INCOMING) + { + FUNCTION_Select(FUNCTION_INCOMING); + //gUpdateDisplay = true; + } + return; + } + + gScanPauseDelayIn_10ms = scan_pause_delay_in_3_10ms; + gScheduleScanListen = false; + } + + gRxReceptionMode = RX_MODE_DETECTED; + + if (gCurrentFunction != FUNCTION_INCOMING) + { + FUNCTION_Select(FUNCTION_INCOMING); + //gUpdateDisplay = true; + } } static void HandleIncoming(void) { - if (!g_SquelchLost) { // squelch is closed + if (!g_SquelchLost) { // squelch is closed #ifdef ENABLE_DTMF_CALLING - if (gDTMF_RX_index > 0) - DTMF_clear_RX(); + if (gDTMF_RX_index > 0) + DTMF_clear_RX(); #endif - if (gCurrentFunction != FUNCTION_FOREGROUND) { - FUNCTION_Select(FUNCTION_FOREGROUND); - gUpdateDisplay = true; - } - return; - } + if (gCurrentFunction != FUNCTION_FOREGROUND) { + FUNCTION_Select(FUNCTION_FOREGROUND); + gUpdateDisplay = true; + } + return; + } - bool bFlag = (gScanStateDir == SCAN_OFF && gCurrentCodeType == CODE_TYPE_OFF); + bool bFlag = (gScanStateDir == SCAN_OFF && gCurrentCodeType == CODE_TYPE_OFF); #ifdef ENABLE_NOAA - if (IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE) && gNOAACountdown_10ms > 0) { - gNOAACountdown_10ms = 0; - bFlag = true; - } + if (IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE) && gNOAACountdown_10ms > 0) { + gNOAACountdown_10ms = 0; + bFlag = true; + } #endif - if (g_CTCSS_Lost && gCurrentCodeType == CODE_TYPE_CONTINUOUS_TONE) { - bFlag = true; - gFoundCTCSS = false; - } + if (g_CTCSS_Lost && gCurrentCodeType == CODE_TYPE_CONTINUOUS_TONE) { + bFlag = true; + gFoundCTCSS = false; + } - if (g_CDCSS_Lost && gCDCSSCodeType == CDCSS_POSITIVE_CODE - && (gCurrentCodeType == CODE_TYPE_DIGITAL || gCurrentCodeType == CODE_TYPE_REVERSE_DIGITAL)) - { - gFoundCDCSS = false; - } - else if (!bFlag) - return; + if (g_CDCSS_Lost && gCDCSSCodeType == CDCSS_POSITIVE_CODE + && (gCurrentCodeType == CODE_TYPE_DIGITAL || gCurrentCodeType == CODE_TYPE_REVERSE_DIGITAL)) + { + gFoundCDCSS = false; + } + else if (!bFlag) + return; #ifdef ENABLE_DTMF_CALLING - if (gScanStateDir == SCAN_OFF && (gRxVfo->DTMF_DECODING_ENABLE || gSetting_KILLED)) { + if (gScanStateDir == SCAN_OFF && (gRxVfo->DTMF_DECODING_ENABLE || gSetting_KILLED)) { - // DTMF DCD is enabled - DTMF_HandleRequest(); - if (gDTMF_CallState == DTMF_CALL_STATE_NONE) { - if (gRxReceptionMode != RX_MODE_DETECTED) { - return; - } - gDualWatchCountdown_10ms = dual_watch_count_after_1_10ms; - gScheduleDualWatch = false; + // DTMF DCD is enabled + DTMF_HandleRequest(); + if (gDTMF_CallState == DTMF_CALL_STATE_NONE) { + if (gRxReceptionMode != RX_MODE_DETECTED) { + return; + } + gDualWatchCountdown_10ms = dual_watch_count_after_1_10ms; + gScheduleDualWatch = false; - gRxReceptionMode = RX_MODE_LISTENING; + gRxReceptionMode = RX_MODE_LISTENING; - // let the user see DW is not active - gDualWatchActive = false; - gUpdateStatus = true; + // let the user see DW is not active + gDualWatchActive = false; + gUpdateStatus = true; - gUpdateDisplay = true; - return; - } - } + gUpdateDisplay = true; + return; + } + } #endif - APP_StartListening(gMonitor ? FUNCTION_MONITOR : FUNCTION_RECEIVE); + APP_StartListening(gMonitor ? FUNCTION_MONITOR : FUNCTION_RECEIVE); } static void HandleReceive(void) { - #define END_OF_RX_MODE_SKIP 0 - #define END_OF_RX_MODE_END 1 - #define END_OF_RX_MODE_TTE 2 - - uint8_t Mode = END_OF_RX_MODE_SKIP; - - if (gFlagTailNoteEliminationComplete) - { - Mode = END_OF_RX_MODE_END; - goto Skip; - } - - if (gScanStateDir != SCAN_OFF && IS_FREQ_CHANNEL(gNextMrChannel)) - { // we are scanning in the frequency mode - if (g_SquelchLost) - return; - - Mode = END_OF_RX_MODE_END; - goto Skip; - } - - switch (gCurrentCodeType) - { - default: - case CODE_TYPE_OFF: - break; - - case CODE_TYPE_CONTINUOUS_TONE: - if (gFoundCTCSS && gFoundCTCSSCountdown_10ms == 0) - { - gFoundCTCSS = false; - gFoundCDCSS = false; - Mode = END_OF_RX_MODE_END; - goto Skip; - } - break; - - case CODE_TYPE_DIGITAL: - case CODE_TYPE_REVERSE_DIGITAL: - if (gFoundCDCSS && gFoundCDCSSCountdown_10ms == 0) - { - gFoundCTCSS = false; - gFoundCDCSS = false; - Mode = END_OF_RX_MODE_END; - goto Skip; - } - break; - } - - if (g_SquelchLost) - { - #ifdef ENABLE_NOAA - if (!gEndOfRxDetectedMaybe && !IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE)) - #else - if (!gEndOfRxDetectedMaybe) - #endif - { - switch (gCurrentCodeType) - { - case CODE_TYPE_OFF: - if (gEeprom.SQUELCH_LEVEL) - { - if (g_CxCSS_TAIL_Found) - { - Mode = END_OF_RX_MODE_TTE; - g_CxCSS_TAIL_Found = false; - } - } - break; - - case CODE_TYPE_CONTINUOUS_TONE: - if (g_CTCSS_Lost) - { - gFoundCTCSS = false; - } - else - if (!gFoundCTCSS) - { - gFoundCTCSS = true; - gFoundCTCSSCountdown_10ms = 100; // 1 sec - } - - if (g_CxCSS_TAIL_Found) - { - Mode = END_OF_RX_MODE_TTE; - g_CxCSS_TAIL_Found = false; - } - break; - - case CODE_TYPE_DIGITAL: - case CODE_TYPE_REVERSE_DIGITAL: - if (g_CDCSS_Lost && gCDCSSCodeType == CDCSS_POSITIVE_CODE) - { - gFoundCDCSS = false; - } - else - if (!gFoundCDCSS) - { - gFoundCDCSS = true; - gFoundCDCSSCountdown_10ms = 100; // 1 sec - } - - if (g_CxCSS_TAIL_Found) - { - if (BK4819_GetCTCType() == 1) - Mode = END_OF_RX_MODE_TTE; - - g_CxCSS_TAIL_Found = false; - } - - break; - } - } - } - else - Mode = END_OF_RX_MODE_END; - - if (!gEndOfRxDetectedMaybe && - Mode == END_OF_RX_MODE_SKIP && - gNextTimeslice40ms && - gEeprom.TAIL_TONE_ELIMINATION && - (gCurrentCodeType == CODE_TYPE_DIGITAL || gCurrentCodeType == CODE_TYPE_REVERSE_DIGITAL) && - BK4819_GetCTCType() == 1) - Mode = END_OF_RX_MODE_TTE; - else - gNextTimeslice40ms = false; + #define END_OF_RX_MODE_SKIP 0 + #define END_OF_RX_MODE_END 1 + #define END_OF_RX_MODE_TTE 2 + + uint8_t Mode = END_OF_RX_MODE_SKIP; + + if (gFlagTailNoteEliminationComplete) + { + Mode = END_OF_RX_MODE_END; + goto Skip; + } + + if (gScanStateDir != SCAN_OFF && IS_FREQ_CHANNEL(gNextMrChannel)) + { // we are scanning in the frequency mode + if (g_SquelchLost) + return; + + Mode = END_OF_RX_MODE_END; + goto Skip; + } + + switch (gCurrentCodeType) + { + default: + case CODE_TYPE_OFF: + break; + + case CODE_TYPE_CONTINUOUS_TONE: + if (gFoundCTCSS && gFoundCTCSSCountdown_10ms == 0) + { + gFoundCTCSS = false; + gFoundCDCSS = false; + Mode = END_OF_RX_MODE_END; + goto Skip; + } + break; + + case CODE_TYPE_DIGITAL: + case CODE_TYPE_REVERSE_DIGITAL: + if (gFoundCDCSS && gFoundCDCSSCountdown_10ms == 0) + { + gFoundCTCSS = false; + gFoundCDCSS = false; + Mode = END_OF_RX_MODE_END; + goto Skip; + } + break; + } + + if (g_SquelchLost) + { + #ifdef ENABLE_NOAA + if (!gEndOfRxDetectedMaybe && !IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE)) + #else + if (!gEndOfRxDetectedMaybe) + #endif + { + switch (gCurrentCodeType) + { + case CODE_TYPE_OFF: + if (gEeprom.SQUELCH_LEVEL) + { + if (g_CxCSS_TAIL_Found) + { + Mode = END_OF_RX_MODE_TTE; + g_CxCSS_TAIL_Found = false; + } + } + break; + + case CODE_TYPE_CONTINUOUS_TONE: + if (g_CTCSS_Lost) + { + gFoundCTCSS = false; + } + else + if (!gFoundCTCSS) + { + gFoundCTCSS = true; + gFoundCTCSSCountdown_10ms = 100; // 1 sec + } + + if (g_CxCSS_TAIL_Found) + { + Mode = END_OF_RX_MODE_TTE; + g_CxCSS_TAIL_Found = false; + } + break; + + case CODE_TYPE_DIGITAL: + case CODE_TYPE_REVERSE_DIGITAL: + if (g_CDCSS_Lost && gCDCSSCodeType == CDCSS_POSITIVE_CODE) + { + gFoundCDCSS = false; + } + else + if (!gFoundCDCSS) + { + gFoundCDCSS = true; + gFoundCDCSSCountdown_10ms = 100; // 1 sec + } + + if (g_CxCSS_TAIL_Found) + { + if (BK4819_GetCTCType() == 1) + Mode = END_OF_RX_MODE_TTE; + + g_CxCSS_TAIL_Found = false; + } + + break; + } + } + } + else + Mode = END_OF_RX_MODE_END; + + if (!gEndOfRxDetectedMaybe && + Mode == END_OF_RX_MODE_SKIP && + gNextTimeslice40ms && + gEeprom.TAIL_TONE_ELIMINATION && + (gCurrentCodeType == CODE_TYPE_DIGITAL || gCurrentCodeType == CODE_TYPE_REVERSE_DIGITAL) && + BK4819_GetCTCType() == 1) + Mode = END_OF_RX_MODE_TTE; + else + gNextTimeslice40ms = false; Skip: - switch (Mode) - { - case END_OF_RX_MODE_SKIP: - break; - - case END_OF_RX_MODE_END: - RADIO_SetupRegisters(true); - - #ifdef ENABLE_NOAA - if (IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE)) - gNOAACountdown_10ms = 300; // 3 sec - #endif - - gUpdateDisplay = true; - - if (gScanStateDir != SCAN_OFF) - { - switch (gEeprom.SCAN_RESUME_MODE) - { - case SCAN_RESUME_TO: - break; - - case SCAN_RESUME_CO: - gScanPauseDelayIn_10ms = scan_pause_delay_in_7_10ms; - gScheduleScanListen = false; - break; - - case SCAN_RESUME_SE: - CHFRSCANNER_Stop(); - break; - } - } - - break; - - case END_OF_RX_MODE_TTE: - if (gEeprom.TAIL_TONE_ELIMINATION) { - AUDIO_AudioPathOff(); - - gTailNoteEliminationCountdown_10ms = 20; - gFlagTailNoteEliminationComplete = false; - gEndOfRxDetectedMaybe = true; - gEnableSpeaker = false; - } - break; - } + switch (Mode) + { + case END_OF_RX_MODE_SKIP: + break; + + case END_OF_RX_MODE_END: + RADIO_SetupRegisters(true); + + #ifdef ENABLE_NOAA + if (IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE)) + gNOAACountdown_10ms = 300; // 3 sec + #endif + + gUpdateDisplay = true; + + if (gScanStateDir != SCAN_OFF) + { + switch (gEeprom.SCAN_RESUME_MODE) + { + case SCAN_RESUME_TO: + break; + + case SCAN_RESUME_CO: + gScanPauseDelayIn_10ms = scan_pause_delay_in_7_10ms; + gScheduleScanListen = false; + break; + + case SCAN_RESUME_SE: + CHFRSCANNER_Stop(); + break; + } + } + + break; + + case END_OF_RX_MODE_TTE: + if (gEeprom.TAIL_TONE_ELIMINATION) { + AUDIO_AudioPathOff(); + + gTailNoteEliminationCountdown_10ms = 20; + gFlagTailNoteEliminationComplete = false; + gEndOfRxDetectedMaybe = true; + gEnableSpeaker = false; + } + break; + } } static void HandlePowerSave() { - if (!gRxIdleMode) { - CheckForIncoming(); - } + if (!gRxIdleMode) { + CheckForIncoming(); + } } static void (*HandleFunction_fn_table[])(void) = { - [FUNCTION_FOREGROUND] = &CheckForIncoming, - [FUNCTION_TRANSMIT] = &FUNCTION_NOP, - [FUNCTION_MONITOR] = &FUNCTION_NOP, - [FUNCTION_INCOMING] = &HandleIncoming, - [FUNCTION_RECEIVE] = &HandleReceive, - [FUNCTION_POWER_SAVE] = &HandlePowerSave, - [FUNCTION_BAND_SCOPE] = &FUNCTION_NOP, + [FUNCTION_FOREGROUND] = &CheckForIncoming, + [FUNCTION_TRANSMIT] = &FUNCTION_NOP, + [FUNCTION_MONITOR] = &FUNCTION_NOP, + [FUNCTION_INCOMING] = &HandleIncoming, + [FUNCTION_RECEIVE] = &HandleReceive, + [FUNCTION_POWER_SAVE] = &HandlePowerSave, + [FUNCTION_BAND_SCOPE] = &FUNCTION_NOP, }; static_assert(ARRAY_SIZE(HandleFunction_fn_table) == FUNCTION_N_ELEM); static void HandleFunction(void) { - HandleFunction_fn_table[gCurrentFunction](); + HandleFunction_fn_table[gCurrentFunction](); } void APP_StartListening(FUNCTION_Type_t function) { - const unsigned int vfo = gEeprom.RX_VFO; + const unsigned int vfo = gEeprom.RX_VFO; #ifdef ENABLE_FEAT_F4HWN_RX_TX_TIMER gRxTimerCountdown_500ms = 7200; #endif #ifdef ENABLE_DTMF_CALLING - if (gSetting_KILLED) - return; + if (gSetting_KILLED) + return; #endif #ifdef ENABLE_FMRADIO - if (gFmRadioMode) - BK1080_Init0(); + if (gFmRadioMode) + BK1080_Init0(); #endif - // clear the other vfo's rssi level (to hide the antenna symbol) - gVFO_RSSI_bar_level[!vfo] = 0; + // clear the other vfo's rssi level (to hide the antenna symbol) + gVFO_RSSI_bar_level[!vfo] = 0; - AUDIO_AudioPathOn(); - gEnableSpeaker = true; + AUDIO_AudioPathOn(); + gEnableSpeaker = true; - if (gSetting_backlight_on_tx_rx & BACKLIGHT_ON_TR_RX) { - BACKLIGHT_TurnOn(); - } + if (gSetting_backlight_on_tx_rx & BACKLIGHT_ON_TR_RX) { + BACKLIGHT_TurnOn(); + } - if (gScanStateDir != SCAN_OFF) - CHFRSCANNER_Found(); + if (gScanStateDir != SCAN_OFF) + CHFRSCANNER_Found(); #ifdef ENABLE_NOAA - if (IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE) && gIsNoaaMode) { - gRxVfo->CHANNEL_SAVE = gNoaaChannel + NOAA_CHANNEL_FIRST; - gRxVfo->pRX->Frequency = NoaaFrequencyTable[gNoaaChannel]; - gRxVfo->pTX->Frequency = NoaaFrequencyTable[gNoaaChannel]; - gEeprom.ScreenChannel[vfo] = gRxVfo->CHANNEL_SAVE; + if (IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE) && gIsNoaaMode) { + gRxVfo->CHANNEL_SAVE = gNoaaChannel + NOAA_CHANNEL_FIRST; + gRxVfo->pRX->Frequency = NoaaFrequencyTable[gNoaaChannel]; + gRxVfo->pTX->Frequency = NoaaFrequencyTable[gNoaaChannel]; + gEeprom.ScreenChannel[vfo] = gRxVfo->CHANNEL_SAVE; - gNOAA_Countdown_10ms = 500; // 5 sec - gScheduleNOAA = false; - } + gNOAA_Countdown_10ms = 500; // 5 sec + gScheduleNOAA = false; + } #endif - if (gScanStateDir == SCAN_OFF && - gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) - { // not scanning, dual watch is enabled + if (gScanStateDir == SCAN_OFF && + gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) + { // not scanning, dual watch is enabled - gDualWatchCountdown_10ms = dual_watch_count_after_2_10ms; - gScheduleDualWatch = false; + gDualWatchCountdown_10ms = dual_watch_count_after_2_10ms; + gScheduleDualWatch = false; - // when crossband is active only the main VFO should be used for TX - if(gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF) - gRxVfoIsActive = true; + // when crossband is active only the main VFO should be used for TX + if(gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF) + gRxVfoIsActive = true; - // let the user see DW is not active - gDualWatchActive = false; - gUpdateStatus = true; - } + // let the user see DW is not active + gDualWatchActive = false; + gUpdateStatus = true; + } - BK4819_WriteRegister(BK4819_REG_48, - (11u << 12) | // ??? .. 0 to 15, doesn't seem to make any difference - ( 0u << 10) | // AF Rx Gain-1 - (gEeprom.VOLUME_GAIN << 4) | // AF Rx Gain-2 - (gEeprom.DAC_GAIN << 0)); // AF DAC Gain (after Gain-1 and Gain-2) + BK4819_WriteRegister(BK4819_REG_48, + (11u << 12) | // ??? .. 0 to 15, doesn't seem to make any difference + ( 0u << 10) | // AF Rx Gain-1 + (gEeprom.VOLUME_GAIN << 4) | // AF Rx Gain-2 + (gEeprom.DAC_GAIN << 0)); // AF DAC Gain (after Gain-1 and Gain-2) #ifdef ENABLE_VOICE - if (gVoiceWriteIndex == 0) // AM/FM RX mode will be set when the voice has finished + if (gVoiceWriteIndex == 0) // AM/FM RX mode will be set when the voice has finished #endif - RADIO_SetModulation(gRxVfo->Modulation); // no need, set it now + RADIO_SetModulation(gRxVfo->Modulation); // no need, set it now - FUNCTION_Select(function); + FUNCTION_Select(function); #ifdef ENABLE_FMRADIO - if (function == FUNCTION_MONITOR || gFmRadioMode) + if (function == FUNCTION_MONITOR || gFmRadioMode) #else - if (function == FUNCTION_MONITOR) + if (function == FUNCTION_MONITOR) #endif - { // squelch is disabled - if (gScreenToDisplay != DISPLAY_MENU) // 1of11 .. don't close the menu - GUI_SelectNextDisplay(DISPLAY_MAIN); - } - else - gUpdateDisplay = true; + { // squelch is disabled + if (gScreenToDisplay != DISPLAY_MENU) // 1of11 .. don't close the menu + GUI_SelectNextDisplay(DISPLAY_MAIN); + } + else + gUpdateDisplay = true; - gUpdateStatus = true; + gUpdateStatus = true; } uint32_t APP_SetFreqByStepAndLimits(VFO_Info_t *pInfo, int8_t direction, uint32_t lower, uint32_t upper) { - uint32_t Frequency = FREQUENCY_RoundToStep(pInfo->freq_config_RX.Frequency + (direction * pInfo->StepFrequency), pInfo->StepFrequency); + uint32_t Frequency = FREQUENCY_RoundToStep(pInfo->freq_config_RX.Frequency + (direction * pInfo->StepFrequency), pInfo->StepFrequency); #ifdef ENABLE_FEAT_F4HWN - if (Frequency > upper) + if (Frequency > upper) #else - if (Frequency >= upper) + if (Frequency >= upper) #endif - Frequency = lower; + Frequency = lower; - else if (Frequency < lower) - Frequency = FREQUENCY_RoundToStep(upper - pInfo->StepFrequency, pInfo->StepFrequency); + else if (Frequency < lower) + Frequency = FREQUENCY_RoundToStep(upper - pInfo->StepFrequency, pInfo->StepFrequency); - return Frequency; + return Frequency; } uint32_t APP_SetFrequencyByStep(VFO_Info_t *pInfo, int8_t direction) { - return APP_SetFreqByStepAndLimits(pInfo, direction, frequencyBandTable[pInfo->Band].lower, frequencyBandTable[pInfo->Band].upper); + return APP_SetFreqByStepAndLimits(pInfo, direction, frequencyBandTable[pInfo->Band].lower, frequencyBandTable[pInfo->Band].upper); } #ifdef ENABLE_NOAA - static void NOAA_IncreaseChannel(void) - { - if (++gNoaaChannel > 9) - gNoaaChannel = 0; - } + static void NOAA_IncreaseChannel(void) + { + if (++gNoaaChannel > 9) + gNoaaChannel = 0; + } #endif static void DualwatchAlternate(void) { - #ifdef ENABLE_NOAA - if (gIsNoaaMode) - { - if (!IS_NOAA_CHANNEL(gEeprom.ScreenChannel[0]) || !IS_NOAA_CHANNEL(gEeprom.ScreenChannel[1])) - gEeprom.RX_VFO = (gEeprom.RX_VFO + 1) & 1; - else - gEeprom.RX_VFO = 0; - - gRxVfo = &gEeprom.VfoInfo[gEeprom.RX_VFO]; - - if (IS_NOAA_CHANNEL(gEeprom.VfoInfo[0].CHANNEL_SAVE)) - NOAA_IncreaseChannel(); - } - else - #endif - { // toggle between VFO's - gEeprom.RX_VFO = !gEeprom.RX_VFO; - gRxVfo = &gEeprom.VfoInfo[gEeprom.RX_VFO]; - - if (!gDualWatchActive) - { // let the user see DW is active - gDualWatchActive = true; - gUpdateStatus = true; - } - } - - RADIO_SetupRegisters(false); - - #ifdef ENABLE_NOAA - gDualWatchCountdown_10ms = gIsNoaaMode ? dual_watch_count_noaa_10ms : dual_watch_count_toggle_10ms; - #else - gDualWatchCountdown_10ms = dual_watch_count_toggle_10ms; - #endif + #ifdef ENABLE_NOAA + if (gIsNoaaMode) + { + if (!IS_NOAA_CHANNEL(gEeprom.ScreenChannel[0]) || !IS_NOAA_CHANNEL(gEeprom.ScreenChannel[1])) + gEeprom.RX_VFO = (gEeprom.RX_VFO + 1) & 1; + else + gEeprom.RX_VFO = 0; + + gRxVfo = &gEeprom.VfoInfo[gEeprom.RX_VFO]; + + if (IS_NOAA_CHANNEL(gEeprom.VfoInfo[0].CHANNEL_SAVE)) + NOAA_IncreaseChannel(); + } + else + #endif + { // toggle between VFO's + gEeprom.RX_VFO = !gEeprom.RX_VFO; + gRxVfo = &gEeprom.VfoInfo[gEeprom.RX_VFO]; + + if (!gDualWatchActive) + { // let the user see DW is active + gDualWatchActive = true; + gUpdateStatus = true; + } + } + + RADIO_SetupRegisters(false); + + #ifdef ENABLE_NOAA + gDualWatchCountdown_10ms = gIsNoaaMode ? dual_watch_count_noaa_10ms : dual_watch_count_toggle_10ms; + #else + gDualWatchCountdown_10ms = dual_watch_count_toggle_10ms; + #endif } static void CheckRadioInterrupts(void) { - if (SCANNER_IsScanning()) - return; - - while (BK4819_ReadRegister(BK4819_REG_0C) & 1u) { // BK chip interrupt request - // clear interrupts - BK4819_WriteRegister(BK4819_REG_02, 0); - // fetch interrupt status bits - - union { - struct { - uint16_t __UNUSED : 1; - uint16_t fskRxSync : 1; - uint16_t sqlLost : 1; - uint16_t sqlFound : 1; - uint16_t voxLost : 1; - uint16_t voxFound : 1; - uint16_t ctcssLost : 1; - uint16_t ctcssFound : 1; - uint16_t cdcssLost : 1; - uint16_t cdcssFound : 1; - uint16_t cssTailFound : 1; - uint16_t dtmf5ToneFound : 1; - uint16_t fskFifoAlmostFull : 1; - uint16_t fskRxFinied : 1; - uint16_t fskFifoAlmostEmpty : 1; - uint16_t fskTxFinied : 1; - }; - uint16_t __raw; - } interrupts; - - interrupts.__raw = BK4819_ReadRegister(BK4819_REG_02); - - // 0 = no phase shift - // 1 = 120deg phase shift - // 2 = 180deg phase shift - // 3 = 240deg phase shift -// const uint8_t ctcss_shift = BK4819_GetCTCShift(); -// if (ctcss_shift > 0) -// g_CTCSS_Lost = true; - - if (interrupts.dtmf5ToneFound) { - const char c = DTMF_GetCharacter(BK4819_GetDTMF_5TONE_Code()); // save the RX'ed DTMF character - if (c != 0xff) { - if (gCurrentFunction != FUNCTION_TRANSMIT) { - if (gSetting_live_DTMF_decoder) { - size_t len = strlen(gDTMF_RX_live); - if (len >= sizeof(gDTMF_RX_live) - 1) { // make room - memmove(&gDTMF_RX_live[0], &gDTMF_RX_live[1], sizeof(gDTMF_RX_live) - 1); - len--; - } - gDTMF_RX_live[len++] = c; - gDTMF_RX_live[len] = 0; - gDTMF_RX_live_timeout = DTMF_RX_live_timeout_500ms; // time till we delete it - gUpdateDisplay = true; - } + if (SCANNER_IsScanning()) + return; + + while (BK4819_ReadRegister(BK4819_REG_0C) & 1u) { // BK chip interrupt request + // clear interrupts + BK4819_WriteRegister(BK4819_REG_02, 0); + // fetch interrupt status bits + + union { + struct { + uint16_t __UNUSED : 1; + uint16_t fskRxSync : 1; + uint16_t sqlLost : 1; + uint16_t sqlFound : 1; + uint16_t voxLost : 1; + uint16_t voxFound : 1; + uint16_t ctcssLost : 1; + uint16_t ctcssFound : 1; + uint16_t cdcssLost : 1; + uint16_t cdcssFound : 1; + uint16_t cssTailFound : 1; + uint16_t dtmf5ToneFound : 1; + uint16_t fskFifoAlmostFull : 1; + uint16_t fskRxFinied : 1; + uint16_t fskFifoAlmostEmpty : 1; + uint16_t fskTxFinied : 1; + }; + uint16_t __raw; + } interrupts; + + interrupts.__raw = BK4819_ReadRegister(BK4819_REG_02); + + // 0 = no phase shift + // 1 = 120deg phase shift + // 2 = 180deg phase shift + // 3 = 240deg phase shift +// const uint8_t ctcss_shift = BK4819_GetCTCShift(); +// if (ctcss_shift > 0) +// g_CTCSS_Lost = true; + + if (interrupts.dtmf5ToneFound) { + const char c = DTMF_GetCharacter(BK4819_GetDTMF_5TONE_Code()); // save the RX'ed DTMF character + if (c != 0xff) { + if (gCurrentFunction != FUNCTION_TRANSMIT) { + if (gSetting_live_DTMF_decoder) { + size_t len = strlen(gDTMF_RX_live); + if (len >= sizeof(gDTMF_RX_live) - 1) { // make room + memmove(&gDTMF_RX_live[0], &gDTMF_RX_live[1], sizeof(gDTMF_RX_live) - 1); + len--; + } + gDTMF_RX_live[len++] = c; + gDTMF_RX_live[len] = 0; + gDTMF_RX_live_timeout = DTMF_RX_live_timeout_500ms; // time till we delete it + gUpdateDisplay = true; + } #ifdef ENABLE_DTMF_CALLING - if (gRxVfo->DTMF_DECODING_ENABLE || gSetting_KILLED) { - if (gDTMF_RX_index >= sizeof(gDTMF_RX) - 1) { // make room - memmove(&gDTMF_RX[0], &gDTMF_RX[1], sizeof(gDTMF_RX) - 1); - gDTMF_RX_index--; - } - gDTMF_RX[gDTMF_RX_index++] = c; - gDTMF_RX[gDTMF_RX_index] = 0; - gDTMF_RX_timeout = DTMF_RX_timeout_500ms; // time till we delete it - gDTMF_RX_pending = true; - - SYSTEM_DelayMs(3);//fix DTMF not reply@Yurisu - DTMF_HandleRequest(); - } -#endif - } - } - } - - if (interrupts.cssTailFound) - g_CxCSS_TAIL_Found = true; - - if (interrupts.cdcssLost) { - g_CDCSS_Lost = true; - gCDCSSCodeType = BK4819_GetCDCSSCodeType(); - } - - if (interrupts.cdcssFound) - g_CDCSS_Lost = false; - - if (interrupts.ctcssLost) - g_CTCSS_Lost = true; - - if (interrupts.ctcssFound) - g_CTCSS_Lost = false; + if (gRxVfo->DTMF_DECODING_ENABLE || gSetting_KILLED) { + if (gDTMF_RX_index >= sizeof(gDTMF_RX) - 1) { // make room + memmove(&gDTMF_RX[0], &gDTMF_RX[1], sizeof(gDTMF_RX) - 1); + gDTMF_RX_index--; + } + gDTMF_RX[gDTMF_RX_index++] = c; + gDTMF_RX[gDTMF_RX_index] = 0; + gDTMF_RX_timeout = DTMF_RX_timeout_500ms; // time till we delete it + gDTMF_RX_pending = true; + + SYSTEM_DelayMs(3);//fix DTMF not reply@Yurisu + DTMF_HandleRequest(); + } +#endif + } + } + } + + if (interrupts.cssTailFound) + g_CxCSS_TAIL_Found = true; + + if (interrupts.cdcssLost) { + g_CDCSS_Lost = true; + gCDCSSCodeType = BK4819_GetCDCSSCodeType(); + } + + if (interrupts.cdcssFound) + g_CDCSS_Lost = false; + + if (interrupts.ctcssLost) + g_CTCSS_Lost = true; + + if (interrupts.ctcssFound) + g_CTCSS_Lost = false; #ifdef ENABLE_VOX - if (interrupts.voxLost) { - g_VOX_Lost = true; - gVoxPauseCountdown = 10; - - if (gEeprom.VOX_SWITCH) { - if (gCurrentFunction == FUNCTION_POWER_SAVE && !gRxIdleMode) { - gPowerSave_10ms = power_save2_10ms; - gPowerSaveCountdownExpired = 0; - } - - if (gEeprom.DUAL_WATCH != DUAL_WATCH_OFF && (gScheduleDualWatch || gDualWatchCountdown_10ms < dual_watch_count_after_vox_10ms)) { - gDualWatchCountdown_10ms = dual_watch_count_after_vox_10ms; - gScheduleDualWatch = false; - - // let the user see DW is not active - gDualWatchActive = false; - gUpdateStatus = true; - } - } - } - - if (interrupts.voxFound) { - g_VOX_Lost = false; - gVoxPauseCountdown = 0; - } -#endif - - if (interrupts.sqlLost) { - g_SquelchLost = true; - BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, true); - #ifdef ENABLE_FEAT_F4HWN_RX_TX_TIMER - gRxTimerCountdown_500ms = 7200; - #endif - } - - if (interrupts.sqlFound) { - g_SquelchLost = false; - BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, false); - } + if (interrupts.voxLost) { + g_VOX_Lost = true; + gVoxPauseCountdown = 10; + + if (gEeprom.VOX_SWITCH) { + if (gCurrentFunction == FUNCTION_POWER_SAVE && !gRxIdleMode) { + gPowerSave_10ms = power_save2_10ms; + gPowerSaveCountdownExpired = 0; + } + + if (gEeprom.DUAL_WATCH != DUAL_WATCH_OFF && (gScheduleDualWatch || gDualWatchCountdown_10ms < dual_watch_count_after_vox_10ms)) { + gDualWatchCountdown_10ms = dual_watch_count_after_vox_10ms; + gScheduleDualWatch = false; + + // let the user see DW is not active + gDualWatchActive = false; + gUpdateStatus = true; + } + } + } + + if (interrupts.voxFound) { + g_VOX_Lost = false; + gVoxPauseCountdown = 0; + } +#endif + + if (interrupts.sqlLost) { + g_SquelchLost = true; + BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, true); + #ifdef ENABLE_FEAT_F4HWN_RX_TX_TIMER + gRxTimerCountdown_500ms = 7200; + #endif + } + + if (interrupts.sqlFound) { + g_SquelchLost = false; + BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, false); + } #ifdef ENABLE_AIRCOPY - if (interrupts.fskFifoAlmostFull && - gScreenToDisplay == DISPLAY_AIRCOPY && - gAircopyState == AIRCOPY_TRANSFER && - gAirCopyIsSendMode == 0) - { - for (unsigned int i = 0; i < 4; i++) { - g_FSK_Buffer[gFSKWriteIndex++] = BK4819_ReadRegister(BK4819_REG_5F); - } - - AIRCOPY_StorePacket(); - } -#endif - } + if (interrupts.fskFifoAlmostFull && + gScreenToDisplay == DISPLAY_AIRCOPY && + gAircopyState == AIRCOPY_TRANSFER && + gAirCopyIsSendMode == 0) + { + for (unsigned int i = 0; i < 4; i++) { + g_FSK_Buffer[gFSKWriteIndex++] = BK4819_ReadRegister(BK4819_REG_5F); + } + + AIRCOPY_StorePacket(); + } +#endif + } } void APP_EndTransmission(void) { - // back to RX mode - RADIO_SendEndOfTransmission(); + // back to RX mode + RADIO_SendEndOfTransmission(); - gFlagEndTransmission = true; + gFlagEndTransmission = true; - if (gMonitor) { - //turn the monitor back on - gFlagReconfigureVfos = true; - } + if (gMonitor) { + //turn the monitor back on + gFlagReconfigureVfos = true; + } } #ifdef ENABLE_VOX static void HandleVox(void) { #ifdef ENABLE_DTMF_CALLING - if (gSetting_KILLED) - return; + if (gSetting_KILLED) + return; #endif - if (gVoxResumeCountdown == 0) { - if (gVoxPauseCountdown) - return; - } - else { - g_VOX_Lost = false; - gVoxPauseCountdown = 0; - } + if (gVoxResumeCountdown == 0) { + if (gVoxPauseCountdown) + return; + } + else { + g_VOX_Lost = false; + gVoxPauseCountdown = 0; + } #ifdef ENABLE_FMRADIO - if (gFmRadioMode) - return; -#endif - - if (gCurrentFunction == FUNCTION_RECEIVE || gCurrentFunction == FUNCTION_MONITOR) - return; - - if (gScanStateDir != SCAN_OFF) - return; - - if (gVOX_NoiseDetected) { - if (g_VOX_Lost) - gVoxStopCountdown_10ms = vox_stop_count_down_10ms; - else if (gVoxStopCountdown_10ms == 0) - gVOX_NoiseDetected = false; - - if (gCurrentFunction == FUNCTION_TRANSMIT && !gPttIsPressed && !gVOX_NoiseDetected) { - if (gFlagEndTransmission) { - //if (gCurrentFunction != FUNCTION_FOREGROUND) - FUNCTION_Select(FUNCTION_FOREGROUND); - } - else { - APP_EndTransmission(); - - if (gEeprom.REPEATER_TAIL_TONE_ELIMINATION == 0) { - //if (gCurrentFunction != FUNCTION_FOREGROUND) - FUNCTION_Select(FUNCTION_FOREGROUND); - } - else - gRTTECountdown_10ms = gEeprom.REPEATER_TAIL_TONE_ELIMINATION * 10; - } - - gUpdateStatus = true; - gUpdateDisplay = true; - gFlagEndTransmission = false; - } - return; - } - - if (g_VOX_Lost) { - gVOX_NoiseDetected = true; - - if (gCurrentFunction == FUNCTION_POWER_SAVE) - FUNCTION_Select(FUNCTION_FOREGROUND); - - if (gCurrentFunction != FUNCTION_TRANSMIT && !SerialConfigInProgress()) { + if (gFmRadioMode) + return; +#endif + + if (gCurrentFunction == FUNCTION_RECEIVE || gCurrentFunction == FUNCTION_MONITOR) + return; + + if (gScanStateDir != SCAN_OFF) + return; + + if (gVOX_NoiseDetected) { + if (g_VOX_Lost) + gVoxStopCountdown_10ms = vox_stop_count_down_10ms; + else if (gVoxStopCountdown_10ms == 0) + gVOX_NoiseDetected = false; + + if (gCurrentFunction == FUNCTION_TRANSMIT && !gPttIsPressed && !gVOX_NoiseDetected) { + if (gFlagEndTransmission) { + //if (gCurrentFunction != FUNCTION_FOREGROUND) + FUNCTION_Select(FUNCTION_FOREGROUND); + } + else { + APP_EndTransmission(); + + if (gEeprom.REPEATER_TAIL_TONE_ELIMINATION == 0) { + //if (gCurrentFunction != FUNCTION_FOREGROUND) + FUNCTION_Select(FUNCTION_FOREGROUND); + } + else + gRTTECountdown_10ms = gEeprom.REPEATER_TAIL_TONE_ELIMINATION * 10; + } + + gUpdateStatus = true; + gUpdateDisplay = true; + gFlagEndTransmission = false; + } + return; + } + + if (g_VOX_Lost) { + gVOX_NoiseDetected = true; + + if (gCurrentFunction == FUNCTION_POWER_SAVE) + FUNCTION_Select(FUNCTION_FOREGROUND); + + if (gCurrentFunction != FUNCTION_TRANSMIT && !SerialConfigInProgress()) { #ifdef ENABLE_DTMF_CALLING - gDTMF_ReplyState = DTMF_REPLY_NONE; + gDTMF_ReplyState = DTMF_REPLY_NONE; #endif - RADIO_PrepareTX(); - gUpdateDisplay = true; - } - } + RADIO_PrepareTX(); + gUpdateDisplay = true; + } + } } #endif void APP_Update(void) { #ifdef ENABLE_VOICE - if (gFlagPlayQueuedVoice) { - AUDIO_PlayQueuedVoice(); - gFlagPlayQueuedVoice = false; - } + if (gFlagPlayQueuedVoice) { + AUDIO_PlayQueuedVoice(); + gFlagPlayQueuedVoice = false; + } #endif #ifdef ENABLE_FEAT_F4HWN - if (gCurrentFunction == FUNCTION_TRANSMIT && (gTxTimeoutReachedAlert || SerialConfigInProgress())) - { - if(gSetting_set_tot >= 2) - { - if (gEeprom.BACKLIGHT_TIME == 0) { - if (gBlinkCounter == 0 || gBlinkCounter == 250) - { - GPIO_FlipBit(&GPIOC->DATA, GPIOC_PIN_FLASHLIGHT); - } - } - else - { - if (gBlinkCounter == 0) - { - //BACKLIGHT_TurnOn(); - BACKLIGHT_SetBrightness(gEeprom.BACKLIGHT_MAX); - } - else if(gBlinkCounter == 15000) - { - //BACKLIGHT_TurnOff(); - BACKLIGHT_SetBrightness(gEeprom.BACKLIGHT_MIN); - } - } - } - - gBlinkCounter++; - - if( - (gSetting_set_tot == 3 && gEeprom.BACKLIGHT_TIME != 0 && gBlinkCounter > 74000) || - (gSetting_set_tot == 3 && gEeprom.BACKLIGHT_TIME == 0 && gBlinkCounter > 79000) || - (gSetting_set_tot != 3 && gBlinkCounter > 76000) - ) // try to calibrate 10 times - { - gBlinkCounter = 0; - - if(gSetting_set_tot == 1 || gSetting_set_tot == 3) - { - BK4819_DisableScramble(); - BK4819_PlaySingleTone(gTxTimeoutToneAlert, 30, 1, true); - gTxTimeoutToneAlert += 100; - } - } - } -#endif - - if (gCurrentFunction == FUNCTION_TRANSMIT && (gTxTimeoutReached || SerialConfigInProgress())) - { // transmitter timed out or must de-key - gTxTimeoutReached = false; + if (gCurrentFunction == FUNCTION_TRANSMIT && (gTxTimeoutReachedAlert || SerialConfigInProgress())) + { + if(gSetting_set_tot >= 2) + { + if (gEeprom.BACKLIGHT_TIME == 0) { + if (gBlinkCounter == 0 || gBlinkCounter == 250) + { + GPIO_FlipBit(&GPIOC->DATA, GPIOC_PIN_FLASHLIGHT); + } + } + else + { + if (gBlinkCounter == 0) + { + //BACKLIGHT_TurnOn(); + BACKLIGHT_SetBrightness(gEeprom.BACKLIGHT_MAX); + } + else if(gBlinkCounter == 15000) + { + //BACKLIGHT_TurnOff(); + BACKLIGHT_SetBrightness(gEeprom.BACKLIGHT_MIN); + } + } + } + + gBlinkCounter++; + + if( + (gSetting_set_tot == 3 && gEeprom.BACKLIGHT_TIME != 0 && gBlinkCounter > 74000) || + (gSetting_set_tot == 3 && gEeprom.BACKLIGHT_TIME == 0 && gBlinkCounter > 79000) || + (gSetting_set_tot != 3 && gBlinkCounter > 76000) + ) // try to calibrate 10 times + { + gBlinkCounter = 0; + + if(gSetting_set_tot == 1 || gSetting_set_tot == 3) + { + BK4819_DisableScramble(); + BK4819_PlaySingleTone(gTxTimeoutToneAlert, 30, 1, true); + gTxTimeoutToneAlert += 100; + } + } + } +#endif + + if (gCurrentFunction == FUNCTION_TRANSMIT && (gTxTimeoutReached || SerialConfigInProgress())) + { // transmitter timed out or must de-key + gTxTimeoutReached = false; #ifdef ENABLE_FEAT_F4HWN - if(gBacklightCountdown_500ms > 0 || gEeprom.BACKLIGHT_TIME == 61) - { - //BACKLIGHT_TurnOn(); - BACKLIGHT_SetBrightness(gEeprom.BACKLIGHT_MAX); - } - - gTxTimeoutReachedAlert = false; - gTxTimeoutToneAlert = 800; - - if (gSetting_set_ptt_session) // Improve OnePush if TOT - { - if(gPttOnePushCounter == 1) - { - gPttOnePushCounter = 3; - } - else if(gPttOnePushCounter == 2) - { - ProcessKey(KEY_PTT, false, false); - gPttIsPressed = false; - gPttOnePushCounter = 0; - gPttWasReleased = true; - //if (gKeyReading1 != KEY_INVALID) - // gPttWasReleased = true; - } - ST7565_ContrastAndInv(); - } - /* - if (gSetting_set_ptt_session) // Improve OnePush if TOT - { - ProcessKey(KEY_PTT, false, false); - gPttIsPressed = false; - gPttOnePushCounter = 0; - if (gKeyReading1 != KEY_INVALID) - gPttWasReleased = true; - ST7565_ContrastAndInv(); - } - */ -#endif - - APP_EndTransmission(); - - AUDIO_PlayBeep(BEEP_880HZ_60MS_DOUBLE_BEEP); - - RADIO_SetVfoState(VFO_STATE_TIMEOUT); - - GUI_DisplayScreen(); - } - - if (gReducedService) - return; - - if (gCurrentFunction != FUNCTION_TRANSMIT) - HandleFunction(); + if(gBacklightCountdown_500ms > 0 || gEeprom.BACKLIGHT_TIME == 61) + { + //BACKLIGHT_TurnOn(); + BACKLIGHT_SetBrightness(gEeprom.BACKLIGHT_MAX); + } + + gTxTimeoutReachedAlert = false; + gTxTimeoutToneAlert = 800; + + if (gSetting_set_ptt_session) // Improve OnePush if TOT + { + if(gPttOnePushCounter == 1) + { + gPttOnePushCounter = 3; + } + else if(gPttOnePushCounter == 2) + { + ProcessKey(KEY_PTT, false, false); + gPttIsPressed = false; + gPttOnePushCounter = 0; + gPttWasReleased = true; + //if (gKeyReading1 != KEY_INVALID) + // gPttWasReleased = true; + } + ST7565_ContrastAndInv(); + } + /* + if (gSetting_set_ptt_session) // Improve OnePush if TOT + { + ProcessKey(KEY_PTT, false, false); + gPttIsPressed = false; + gPttOnePushCounter = 0; + if (gKeyReading1 != KEY_INVALID) + gPttWasReleased = true; + ST7565_ContrastAndInv(); + } + */ +#endif + + APP_EndTransmission(); + + AUDIO_PlayBeep(BEEP_880HZ_60MS_DOUBLE_BEEP); + + RADIO_SetVfoState(VFO_STATE_TIMEOUT); + + GUI_DisplayScreen(); + } + + if (gReducedService) + return; + + if (gCurrentFunction != FUNCTION_TRANSMIT) + HandleFunction(); #ifdef ENABLE_FMRADIO -// if (gFmRadioCountdown_500ms > 0) - if (gFmRadioMode && gFmRadioCountdown_500ms > 0) // 1of11 - return; +// if (gFmRadioCountdown_500ms > 0) + if (gFmRadioMode && gFmRadioCountdown_500ms > 0) // 1of11 + return; #endif #ifdef ENABLE_VOICE - if (!SCANNER_IsScanning() && gScanStateDir != SCAN_OFF && gScheduleScanListen && !gPttIsPressed && gVoiceWriteIndex == 0) + if (!SCANNER_IsScanning() && gScanStateDir != SCAN_OFF && gScheduleScanListen && !gPttIsPressed && gVoiceWriteIndex == 0) #else - if (!SCANNER_IsScanning() && gScanStateDir != SCAN_OFF && gScheduleScanListen && !gPttIsPressed) + if (!SCANNER_IsScanning() && gScanStateDir != SCAN_OFF && gScheduleScanListen && !gPttIsPressed) #endif - { // scanning - CHFRSCANNER_ContinueScanning(); - } + { // scanning + CHFRSCANNER_ContinueScanning(); + } #ifdef ENABLE_NOAA #ifdef ENABLE_VOICE - if (gEeprom.DUAL_WATCH == DUAL_WATCH_OFF && gIsNoaaMode && gScheduleNOAA && gVoiceWriteIndex == 0) + if (gEeprom.DUAL_WATCH == DUAL_WATCH_OFF && gIsNoaaMode && gScheduleNOAA && gVoiceWriteIndex == 0) #else - if (gEeprom.DUAL_WATCH == DUAL_WATCH_OFF && gIsNoaaMode && gScheduleNOAA) + if (gEeprom.DUAL_WATCH == DUAL_WATCH_OFF && gIsNoaaMode && gScheduleNOAA) #endif - { - NOAA_IncreaseChannel(); - RADIO_SetupRegisters(false); + { + NOAA_IncreaseChannel(); + RADIO_SetupRegisters(false); - gNOAA_Countdown_10ms = 7; // 70ms - gScheduleNOAA = false; - } + gNOAA_Countdown_10ms = 7; // 70ms + gScheduleNOAA = false; + } #endif - // toggle between the VFO's if dual watch is enabled - if (!SCANNER_IsScanning() - && gEeprom.DUAL_WATCH != DUAL_WATCH_OFF - && gScheduleDualWatch - && gScanStateDir == SCAN_OFF - && !gPttIsPressed - && gCurrentFunction != FUNCTION_POWER_SAVE + // toggle between the VFO's if dual watch is enabled + if (!SCANNER_IsScanning() + && gEeprom.DUAL_WATCH != DUAL_WATCH_OFF + && gScheduleDualWatch + && gScanStateDir == SCAN_OFF + && !gPttIsPressed + && gCurrentFunction != FUNCTION_POWER_SAVE #ifdef ENABLE_VOICE - && gVoiceWriteIndex == 0 + && gVoiceWriteIndex == 0 #endif #ifdef ENABLE_FMRADIO - && !gFmRadioMode + && !gFmRadioMode #endif #ifdef ENABLE_DTMF_CALLING - && gDTMF_CallState == DTMF_CALL_STATE_NONE + && gDTMF_CallState == DTMF_CALL_STATE_NONE #endif - ) { - DualwatchAlternate(); // toggle between the two VFO's + ) { + DualwatchAlternate(); // toggle between the two VFO's - if (gRxVfoIsActive && gScreenToDisplay == DISPLAY_MAIN) { - GUI_SelectNextDisplay(DISPLAY_MAIN); - } + if (gRxVfoIsActive && gScreenToDisplay == DISPLAY_MAIN) { + GUI_SelectNextDisplay(DISPLAY_MAIN); + } - gRxVfoIsActive = false; - gScanPauseMode = false; - gRxReceptionMode = RX_MODE_NONE; - gScheduleDualWatch = false; - } + gRxVfoIsActive = false; + gScanPauseMode = false; + gRxReceptionMode = RX_MODE_NONE; + gScheduleDualWatch = false; + } #ifdef ENABLE_FMRADIO - if (gScheduleFM && gFM_ScanState != FM_SCAN_OFF && !FUNCTION_IsRx()) { - // switch to FM radio mode - FM_Play(); - gScheduleFM = false; - } + if (gScheduleFM && gFM_ScanState != FM_SCAN_OFF && !FUNCTION_IsRx()) { + // switch to FM radio mode + FM_Play(); + gScheduleFM = false; + } #endif #ifdef ENABLE_VOX - if (gEeprom.VOX_SWITCH) - HandleVox(); + if (gEeprom.VOX_SWITCH) + HandleVox(); #endif - if (gSchedulePowerSave) { - if (gPttIsPressed - || gKeyBeingHeld - || gEeprom.BATTERY_SAVE == 0 - || gScanStateDir != SCAN_OFF - || gCssBackgroundScan - || gScreenToDisplay != DISPLAY_MAIN + if (gSchedulePowerSave) { + if (gPttIsPressed + || gKeyBeingHeld + || gEeprom.BATTERY_SAVE == 0 + || gScanStateDir != SCAN_OFF + || gCssBackgroundScan + || gScreenToDisplay != DISPLAY_MAIN #ifdef ENABLE_FMRADIO - || gFmRadioMode + || gFmRadioMode #endif #ifdef ENABLE_DTMF_CALLING - || gDTMF_CallState != DTMF_CALL_STATE_NONE + || gDTMF_CallState != DTMF_CALL_STATE_NONE #endif #ifdef ENABLE_NOAA - || (gIsNoaaMode && (IS_NOAA_CHANNEL(gEeprom.ScreenChannel[0]) || IS_NOAA_CHANNEL(gEeprom.ScreenChannel[1]))) + || (gIsNoaaMode && (IS_NOAA_CHANNEL(gEeprom.ScreenChannel[0]) || IS_NOAA_CHANNEL(gEeprom.ScreenChannel[1]))) #endif - ) { - gBatterySaveCountdown_10ms = battery_save_count_10ms; - } else { - FUNCTION_Select(FUNCTION_POWER_SAVE); - } + ) { + gBatterySaveCountdown_10ms = battery_save_count_10ms; + } else { + FUNCTION_Select(FUNCTION_POWER_SAVE); + } - gSchedulePowerSave = false; - } + gSchedulePowerSave = false; + } - if (gPowerSaveCountdownExpired && gCurrentFunction == FUNCTION_POWER_SAVE + if (gPowerSaveCountdownExpired && gCurrentFunction == FUNCTION_POWER_SAVE #ifdef ENABLE_VOICE - && gVoiceWriteIndex == 0 + && gVoiceWriteIndex == 0 #endif - ) { - static bool goToSleep; - // wake up, enable RX then go back to sleep - if (gRxIdleMode) - { - BK4819_Conditional_RX_TurnOn_and_GPIO6_Enable(); + ) { + static bool goToSleep; + // wake up, enable RX then go back to sleep + if (gRxIdleMode) + { + BK4819_Conditional_RX_TurnOn_and_GPIO6_Enable(); #ifdef ENABLE_VOX - if (gEeprom.VOX_SWITCH) - BK4819_EnableVox(gEeprom.VOX1_THRESHOLD, gEeprom.VOX0_THRESHOLD); -#endif - - if (gEeprom.DUAL_WATCH != DUAL_WATCH_OFF && - gScanStateDir == SCAN_OFF && - !gCssBackgroundScan) - { // dual watch mode, toggle between the two VFO's - DualwatchAlternate(); - goToSleep = false; - } - - FUNCTION_Init(); - - gPowerSave_10ms = power_save1_10ms; // come back here in a bit - gRxIdleMode = false; // RX is awake - } - else if (gEeprom.DUAL_WATCH == DUAL_WATCH_OFF || gScanStateDir != SCAN_OFF || gCssBackgroundScan || goToSleep) - { // dual watch mode off or scanning or rssi update request - // go back to sleep - - gPowerSave_10ms = gEeprom.BATTERY_SAVE * 10; - gRxIdleMode = true; - goToSleep = false; - - BK4819_DisableVox(); - BK4819_Sleep(); - BK4819_ToggleGpioOut(BK4819_GPIO0_PIN28_RX_ENABLE, false); - - // Authentic device checked removed - - } - else { - // toggle between the two VFO's - DualwatchAlternate(); - gPowerSave_10ms = power_save1_10ms; - goToSleep = true; - } - - gPowerSaveCountdownExpired = false; - } + if (gEeprom.VOX_SWITCH) + BK4819_EnableVox(gEeprom.VOX1_THRESHOLD, gEeprom.VOX0_THRESHOLD); +#endif + + if (gEeprom.DUAL_WATCH != DUAL_WATCH_OFF && + gScanStateDir == SCAN_OFF && + !gCssBackgroundScan) + { // dual watch mode, toggle between the two VFO's + DualwatchAlternate(); + goToSleep = false; + } + + FUNCTION_Init(); + + gPowerSave_10ms = power_save1_10ms; // come back here in a bit + gRxIdleMode = false; // RX is awake + } + else if (gEeprom.DUAL_WATCH == DUAL_WATCH_OFF || gScanStateDir != SCAN_OFF || gCssBackgroundScan || goToSleep) + { // dual watch mode off or scanning or rssi update request + // go back to sleep + + gPowerSave_10ms = gEeprom.BATTERY_SAVE * 10; + gRxIdleMode = true; + goToSleep = false; + + BK4819_DisableVox(); + BK4819_Sleep(); + BK4819_ToggleGpioOut(BK4819_GPIO0_PIN28_RX_ENABLE, false); + + // Authentic device checked removed + + } + else { + // toggle between the two VFO's + DualwatchAlternate(); + gPowerSave_10ms = power_save1_10ms; + goToSleep = true; + } + + gPowerSaveCountdownExpired = false; + } } // called every 10ms static void CheckKeys(void) { #ifdef ENABLE_DTMF_CALLING - if(gSetting_KILLED){ - return; - } + if(gSetting_KILLED){ + return; + } #endif #ifdef ENABLE_AIRCOPY - if (gScreenToDisplay == DISPLAY_AIRCOPY && gAircopyState != AIRCOPY_READY){ - return; - } + if (gScreenToDisplay == DISPLAY_AIRCOPY && gAircopyState != AIRCOPY_READY){ + return; + } #endif // -------------------- PTT ------------------------ #ifdef ENABLE_FEAT_F4HWN - if (gSetting_set_ptt_session) - { - if (!GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT) && !SerialConfigInProgress() && gPttOnePushCounter == 0) - { // PTT pressed - if (++gPttDebounceCounter >= 3) // 30ms - { // start transmitting - boot_counter_10ms = 0; - gPttDebounceCounter = 0; - gPttIsPressed = true; - gPttOnePushCounter = 1; - ProcessKey(KEY_PTT, true, false); - } - } - else if ((GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT) || SerialConfigInProgress()) && gPttOnePushCounter == 1) - { - // PTT released or serial comms config in progress - if (++gPttDebounceCounter >= 3 || SerialConfigInProgress()) // 30ms - { // stop transmitting - gPttOnePushCounter = 2; - } - } - else if (!GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT) && !SerialConfigInProgress() && gPttOnePushCounter == 2) - { // PTT pressed again - if (++gPttDebounceCounter >= 3 || SerialConfigInProgress()) // 30ms - { // stop transmitting - gPttOnePushCounter = 3; - } - } - else if ((GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT) || SerialConfigInProgress()) && gPttOnePushCounter == 3) - { // PTT released or serial comms config in progress - if (++gPttDebounceCounter >= 3 || SerialConfigInProgress()) // 30ms - { // stop transmitting - ProcessKey(KEY_PTT, false, false); - gPttIsPressed = false; - if (gKeyReading1 != KEY_INVALID) - gPttWasReleased = true; - gPttOnePushCounter = 0; - ST7565_ContrastAndInv(); - } - } - else - gPttDebounceCounter = 0; - - //gDebug = gPttOnePushCounter; - } - else - { - if (gPttIsPressed) - { - if (GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT) || SerialConfigInProgress()) - { // PTT released or serial comms config in progress - if (++gPttDebounceCounter >= 3 || SerialConfigInProgress()) // 30ms - { // stop transmitting - ProcessKey(KEY_PTT, false, false); - gPttIsPressed = false; - if (gKeyReading1 != KEY_INVALID) - gPttWasReleased = true; - ST7565_ContrastAndInv(); - } - } - else - gPttDebounceCounter = 0; - } - else if (!GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT) && !SerialConfigInProgress()) - { // PTT pressed - if (++gPttDebounceCounter >= 3) // 30ms - { // start transmitting - boot_counter_10ms = 0; - gPttDebounceCounter = 0; - gPttIsPressed = true; - ProcessKey(KEY_PTT, true, false); - } - } - else - gPttDebounceCounter = 0; - } + if (gSetting_set_ptt_session) + { + if (!GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT) && !SerialConfigInProgress() && gPttOnePushCounter == 0) + { // PTT pressed + if (++gPttDebounceCounter >= 3) // 30ms + { // start transmitting + boot_counter_10ms = 0; + gPttDebounceCounter = 0; + gPttIsPressed = true; + gPttOnePushCounter = 1; + ProcessKey(KEY_PTT, true, false); + } + } + else if ((GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT) || SerialConfigInProgress()) && gPttOnePushCounter == 1) + { + // PTT released or serial comms config in progress + if (++gPttDebounceCounter >= 3 || SerialConfigInProgress()) // 30ms + { // stop transmitting + gPttOnePushCounter = 2; + } + } + else if (!GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT) && !SerialConfigInProgress() && gPttOnePushCounter == 2) + { // PTT pressed again + if (++gPttDebounceCounter >= 3 || SerialConfigInProgress()) // 30ms + { // stop transmitting + gPttOnePushCounter = 3; + } + } + else if ((GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT) || SerialConfigInProgress()) && gPttOnePushCounter == 3) + { // PTT released or serial comms config in progress + if (++gPttDebounceCounter >= 3 || SerialConfigInProgress()) // 30ms + { // stop transmitting + ProcessKey(KEY_PTT, false, false); + gPttIsPressed = false; + if (gKeyReading1 != KEY_INVALID) + gPttWasReleased = true; + gPttOnePushCounter = 0; + ST7565_ContrastAndInv(); + } + } + else + gPttDebounceCounter = 0; + + //gDebug = gPttOnePushCounter; + } + else + { + if (gPttIsPressed) + { + if (GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT) || SerialConfigInProgress()) + { // PTT released or serial comms config in progress + if (++gPttDebounceCounter >= 3 || SerialConfigInProgress()) // 30ms + { // stop transmitting + ProcessKey(KEY_PTT, false, false); + gPttIsPressed = false; + if (gKeyReading1 != KEY_INVALID) + gPttWasReleased = true; + ST7565_ContrastAndInv(); + } + } + else + gPttDebounceCounter = 0; + } + else if (!GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT) && !SerialConfigInProgress()) + { // PTT pressed + if (++gPttDebounceCounter >= 3) // 30ms + { // start transmitting + boot_counter_10ms = 0; + gPttDebounceCounter = 0; + gPttIsPressed = true; + ProcessKey(KEY_PTT, true, false); + } + } + else + gPttDebounceCounter = 0; + } #else - if (gPttIsPressed) - { - if (GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT) || SerialConfigInProgress()) - { // PTT released or serial comms config in progress - if (++gPttDebounceCounter >= 3 || SerialConfigInProgress()) // 30ms - { // stop transmitting - ProcessKey(KEY_PTT, false, false); - gPttIsPressed = false; - if (gKeyReading1 != KEY_INVALID) - gPttWasReleased = true; - } - } - else - gPttDebounceCounter = 0; - } - else if (!GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT) && !SerialConfigInProgress()) - { // PTT pressed - if (++gPttDebounceCounter >= 3) // 30ms - { // start transmitting - boot_counter_10ms = 0; - gPttDebounceCounter = 0; - gPttIsPressed = true; - ProcessKey(KEY_PTT, true, false); - } - } - else - gPttDebounceCounter = 0; + if (gPttIsPressed) + { + if (GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT) || SerialConfigInProgress()) + { // PTT released or serial comms config in progress + if (++gPttDebounceCounter >= 3 || SerialConfigInProgress()) // 30ms + { // stop transmitting + ProcessKey(KEY_PTT, false, false); + gPttIsPressed = false; + if (gKeyReading1 != KEY_INVALID) + gPttWasReleased = true; + } + } + else + gPttDebounceCounter = 0; + } + else if (!GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT) && !SerialConfigInProgress()) + { // PTT pressed + if (++gPttDebounceCounter >= 3) // 30ms + { // start transmitting + boot_counter_10ms = 0; + gPttDebounceCounter = 0; + gPttIsPressed = true; + ProcessKey(KEY_PTT, true, false); + } + } + else + gPttDebounceCounter = 0; #endif // --------------------- OTHER KEYS ---------------------------- - // scan the hardware keys - KEY_Code_t Key = KEYBOARD_Poll(); - - if (Key != KEY_INVALID) // any key pressed - boot_counter_10ms = 0; // cancel boot screen/beeps if any key pressed - - if (gKeyReading0 != Key) // new key pressed - { - - if (gKeyReading0 != KEY_INVALID && Key != KEY_INVALID) - ProcessKey(gKeyReading1, false, gKeyBeingHeld); // key pressed without releasing previous key - - gKeyReading0 = Key; - gDebounceCounter = 0; - return; - } - - gDebounceCounter++; - - if (gDebounceCounter == key_debounce_10ms) // debounced new key pressed - { - if (Key == KEY_INVALID) //all non PTT keys released - { - if (gKeyReading1 != KEY_INVALID) // some button was pressed before - { - ProcessKey(gKeyReading1, false, gKeyBeingHeld); // process last button released event - gKeyReading1 = KEY_INVALID; - } - } - else // process new key pressed - { - gKeyReading1 = Key; - ProcessKey(Key, true, false); - } - - gKeyBeingHeld = false; - return; - } - - if (gDebounceCounter < key_repeat_delay_10ms || Key == KEY_INVALID) // the button is not held long enough for repeat yet, or not really pressed - return; - - if (gDebounceCounter == key_repeat_delay_10ms) //initial key repeat with longer delay - { - if (Key != KEY_PTT) - { - gKeyBeingHeld = true; - ProcessKey(Key, true, true); // key held event - } - } - else //subsequent fast key repeats - { - if (Key == KEY_UP || Key == KEY_DOWN) // fast key repeats for up/down buttons - { - gKeyBeingHeld = true; - if ((gDebounceCounter % key_repeat_10ms) == 0) - ProcessKey(Key, true, true); // key held event - } - - if (gDebounceCounter < 0xFFFF) - return; - - gDebounceCounter = key_repeat_delay_10ms+1; - } + // scan the hardware keys + KEY_Code_t Key = KEYBOARD_Poll(); + + if (Key != KEY_INVALID) // any key pressed + boot_counter_10ms = 0; // cancel boot screen/beeps if any key pressed + + if (gKeyReading0 != Key) // new key pressed + { + + if (gKeyReading0 != KEY_INVALID && Key != KEY_INVALID) + ProcessKey(gKeyReading1, false, gKeyBeingHeld); // key pressed without releasing previous key + + gKeyReading0 = Key; + gDebounceCounter = 0; + return; + } + + gDebounceCounter++; + + if (gDebounceCounter == key_debounce_10ms) // debounced new key pressed + { + if (Key == KEY_INVALID) //all non PTT keys released + { + if (gKeyReading1 != KEY_INVALID) // some button was pressed before + { + ProcessKey(gKeyReading1, false, gKeyBeingHeld); // process last button released event + gKeyReading1 = KEY_INVALID; + } + } + else // process new key pressed + { + gKeyReading1 = Key; + ProcessKey(Key, true, false); + } + + gKeyBeingHeld = false; + return; + } + + if (gDebounceCounter < key_repeat_delay_10ms || Key == KEY_INVALID) // the button is not held long enough for repeat yet, or not really pressed + return; + + if (gDebounceCounter == key_repeat_delay_10ms) //initial key repeat with longer delay + { + if (Key != KEY_PTT) + { + gKeyBeingHeld = true; + ProcessKey(Key, true, true); // key held event + } + } + else //subsequent fast key repeats + { + if (Key == KEY_UP || Key == KEY_DOWN) // fast key repeats for up/down buttons + { + gKeyBeingHeld = true; + if ((gDebounceCounter % key_repeat_10ms) == 0) + ProcessKey(Key, true, true); // key held event + } + + if (gDebounceCounter < 0xFFFF) + return; + + gDebounceCounter = key_repeat_delay_10ms+1; + } } void APP_TimeSlice10ms(void) { - gNextTimeslice = false; - gFlashLightBlinkCounter++; + gNextTimeslice = false; + gFlashLightBlinkCounter++; #ifdef ENABLE_AM_FIX - if (gRxVfo->Modulation == MODULATION_AM) { - AM_fix_10ms(gEeprom.RX_VFO); - } + if (gRxVfo->Modulation == MODULATION_AM) { + AM_fix_10ms(gEeprom.RX_VFO); + } #endif #ifdef ENABLE_UART - if (UART_IsCommandAvailable()) { - __disable_irq(); - UART_HandleCommand(); - __enable_irq(); - } + if (UART_IsCommandAvailable()) { + __disable_irq(); + UART_HandleCommand(); + __enable_irq(); + } #endif - if (gReducedService) - return; + if (gReducedService) + return; - if (gCurrentFunction != FUNCTION_POWER_SAVE || !gRxIdleMode) - CheckRadioInterrupts(); + if (gCurrentFunction != FUNCTION_POWER_SAVE || !gRxIdleMode) + CheckRadioInterrupts(); - if (gCurrentFunction == FUNCTION_TRANSMIT) - { // transmitting + if (gCurrentFunction == FUNCTION_TRANSMIT) + { // transmitting #ifdef ENABLE_AUDIO_BAR - if (gSetting_mic_bar && (gFlashLightBlinkCounter % (150 / 10)) == 0) // once every 150ms - UI_DisplayAudioBar(); + if (gSetting_mic_bar && (gFlashLightBlinkCounter % (150 / 10)) == 0) // once every 150ms + UI_DisplayAudioBar(); #endif - } + } - if (gUpdateDisplay) { - gUpdateDisplay = false; - GUI_DisplayScreen(); - } + if (gUpdateDisplay) { + gUpdateDisplay = false; + GUI_DisplayScreen(); + } - if (gUpdateStatus) - UI_DisplayStatus(); + if (gUpdateStatus) + UI_DisplayStatus(); - // Skipping authentic device checks + // Skipping authentic device checks #ifdef ENABLE_FMRADIO - if (gFmRadioMode && gFmRadioCountdown_500ms > 0) // 1of11 - return; + if (gFmRadioMode && gFmRadioCountdown_500ms > 0) // 1of11 + return; #endif #ifndef ENABLE_FEAT_F4HWN - #ifdef ENABLE_FLASHLIGHT - FlashlightTimeSlice(); - #endif + #ifdef ENABLE_FLASHLIGHT + FlashlightTimeSlice(); + #endif #endif #ifdef ENABLE_VOX - if (gVoxResumeCountdown > 0) - gVoxResumeCountdown--; + if (gVoxResumeCountdown > 0) + gVoxResumeCountdown--; - if (gVoxPauseCountdown > 0) - gVoxPauseCountdown--; + if (gVoxPauseCountdown > 0) + gVoxPauseCountdown--; #endif - if (gCurrentFunction == FUNCTION_TRANSMIT) { + if (gCurrentFunction == FUNCTION_TRANSMIT) { #ifdef ENABLE_ALARM - if (gAlarmState == ALARM_STATE_TXALARM || gAlarmState == ALARM_STATE_SITE_ALARM) { - uint16_t Tone; - - gAlarmRunningCounter++; - gAlarmToneCounter++; - - Tone = 500 + (gAlarmToneCounter * 25); - if (Tone > 1500) { - Tone = 500; - gAlarmToneCounter = 0; - } - - BK4819_SetScrambleFrequencyControlWord(Tone); - - if (gEeprom.ALARM_MODE == ALARM_MODE_TONE && gAlarmRunningCounter == 512) { - gAlarmRunningCounter = 0; - - if (gAlarmState == ALARM_STATE_TXALARM) { - gAlarmState = ALARM_STATE_SITE_ALARM; - - if(gEeprom.TAIL_TONE_ELIMINATION) - RADIO_SendCssTail(); - BK4819_SetupPowerAmplifier(0, 0); - BK4819_ToggleGpioOut(BK4819_GPIO1_PIN29_PA_ENABLE, false); - BK4819_Enable_AfDac_DiscMode_TxDsp(); - BK4819_ToggleGpioOut(BK4819_GPIO5_PIN1_RED, false); - - GUI_DisplayScreen(); - } - else { - gAlarmState = ALARM_STATE_TXALARM; - - GUI_DisplayScreen(); - - BK4819_ToggleGpioOut(BK4819_GPIO5_PIN1_RED, true); - RADIO_SetTxParameters(); - BK4819_TransmitTone(true, 500); - SYSTEM_DelayMs(2); - AUDIO_AudioPathOn(); - - gEnableSpeaker = true; - gAlarmToneCounter = 0; - } - } - } -#endif - // repeater tail tone elimination - if (gRTTECountdown_10ms > 0) { - if (--gRTTECountdown_10ms == 0) { - //if (gCurrentFunction != FUNCTION_FOREGROUND) - FUNCTION_Select(FUNCTION_FOREGROUND); - - gUpdateStatus = true; - gUpdateDisplay = true; - } - } - } + if (gAlarmState == ALARM_STATE_TXALARM || gAlarmState == ALARM_STATE_SITE_ALARM) { + uint16_t Tone; + + gAlarmRunningCounter++; + gAlarmToneCounter++; + + Tone = 500 + (gAlarmToneCounter * 25); + if (Tone > 1500) { + Tone = 500; + gAlarmToneCounter = 0; + } + + BK4819_SetScrambleFrequencyControlWord(Tone); + + if (gEeprom.ALARM_MODE == ALARM_MODE_TONE && gAlarmRunningCounter == 512) { + gAlarmRunningCounter = 0; + + if (gAlarmState == ALARM_STATE_TXALARM) { + gAlarmState = ALARM_STATE_SITE_ALARM; + + if(gEeprom.TAIL_TONE_ELIMINATION) + RADIO_SendCssTail(); + BK4819_SetupPowerAmplifier(0, 0); + BK4819_ToggleGpioOut(BK4819_GPIO1_PIN29_PA_ENABLE, false); + BK4819_Enable_AfDac_DiscMode_TxDsp(); + BK4819_ToggleGpioOut(BK4819_GPIO5_PIN1_RED, false); + + GUI_DisplayScreen(); + } + else { + gAlarmState = ALARM_STATE_TXALARM; + + GUI_DisplayScreen(); + + BK4819_ToggleGpioOut(BK4819_GPIO5_PIN1_RED, true); + RADIO_SetTxParameters(); + BK4819_TransmitTone(true, 500); + SYSTEM_DelayMs(2); + AUDIO_AudioPathOn(); + + gEnableSpeaker = true; + gAlarmToneCounter = 0; + } + } + } +#endif + // repeater tail tone elimination + if (gRTTECountdown_10ms > 0) { + if (--gRTTECountdown_10ms == 0) { + //if (gCurrentFunction != FUNCTION_FOREGROUND) + FUNCTION_Select(FUNCTION_FOREGROUND); + + gUpdateStatus = true; + gUpdateDisplay = true; + } + } + } #ifdef ENABLE_FMRADIO - if (gFmRadioMode && gFM_RestoreCountdown_10ms > 0) { - if (--gFM_RestoreCountdown_10ms == 0) { - FM_Start(); // switch back to FM radio mode - GUI_SelectNextDisplay(DISPLAY_FM); - } - } + if (gFmRadioMode && gFM_RestoreCountdown_10ms > 0) { + if (--gFM_RestoreCountdown_10ms == 0) { + FM_Start(); // switch back to FM radio mode + GUI_SelectNextDisplay(DISPLAY_FM); + } + } #endif - SCANNER_TimeSlice10ms(); + SCANNER_TimeSlice10ms(); #ifdef ENABLE_AIRCOPY - if (gScreenToDisplay == DISPLAY_AIRCOPY && gAircopyState == AIRCOPY_TRANSFER && gAirCopyIsSendMode == 1) { - if (!AIRCOPY_SendMessage()) { - GUI_DisplayScreen(); - } - } + if (gScreenToDisplay == DISPLAY_AIRCOPY && gAircopyState == AIRCOPY_TRANSFER && gAirCopyIsSendMode == 1) { + if (!AIRCOPY_SendMessage()) { + GUI_DisplayScreen(); + } + } #endif - CheckKeys(); + CheckKeys(); } void cancelUserInputModes(void) { - if (gDTMF_InputMode || gDTMF_InputBox_Index > 0) - { - DTMF_clear_input_box(); - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - gRequestDisplayScreen = DISPLAY_MAIN; - gUpdateDisplay = true; - } - - if (gWasFKeyPressed || gKeyInputCountdown > 0 || gInputBoxIndex > 0) - { - gWasFKeyPressed = false; - gInputBoxIndex = 0; - gKeyInputCountdown = 0; - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - gUpdateStatus = true; - gUpdateDisplay = true; - } + if (gDTMF_InputMode || gDTMF_InputBox_Index > 0) + { + DTMF_clear_input_box(); + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + gRequestDisplayScreen = DISPLAY_MAIN; + gUpdateDisplay = true; + } + + if (gWasFKeyPressed || gKeyInputCountdown > 0 || gInputBoxIndex > 0) + { + gWasFKeyPressed = false; + gInputBoxIndex = 0; + gKeyInputCountdown = 0; + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + gUpdateStatus = true; + gUpdateDisplay = true; + } } // this is called once every 500ms void APP_TimeSlice500ms(void) { - gNextTimeslice_500ms = false; - bool exit_menu = false; - - // Skipped authentic device check - - if (gKeypadLocked > 0) - if (--gKeypadLocked == 0) - gUpdateDisplay = true; - - if (gKeyInputCountdown > 0) - { - if (--gKeyInputCountdown == 0) - { - - if (IS_MR_CHANNEL(gTxVfo->CHANNEL_SAVE) && (gInputBoxIndex == 1 || gInputBoxIndex == 2)) - { - channelMoveSwitch(); - - if (gBeepToPlay == BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL) { - AUDIO_PlayBeep(gBeepToPlay); - } - - SETTINGS_SaveVfoIndices(); - } - - cancelUserInputModes(); - } - } - - if (gDTMF_RX_live_timeout > 0) - { - #ifdef ENABLE_RSSI_BAR - if (center_line == CENTER_LINE_DTMF_DEC || - center_line == CENTER_LINE_NONE) // wait till the center line is free for us to use before timing out - #endif - { - if (--gDTMF_RX_live_timeout == 0) - { - if (gDTMF_RX_live[0] != 0) - { - memset(gDTMF_RX_live, 0, sizeof(gDTMF_RX_live)); - gUpdateDisplay = true; - } - } - } - } - - if (gMenuCountdown > 0) - if (--gMenuCountdown == 0) - exit_menu = (gScreenToDisplay == DISPLAY_MENU); // exit menu mode + gNextTimeslice_500ms = false; + bool exit_menu = false; + + // Skipped authentic device check + + if (gKeypadLocked > 0) + if (--gKeypadLocked == 0) + gUpdateDisplay = true; + + if (gKeyInputCountdown > 0) + { + if (--gKeyInputCountdown == 0) + { + + if (IS_MR_CHANNEL(gTxVfo->CHANNEL_SAVE) && (gInputBoxIndex == 1 || gInputBoxIndex == 2)) + { + channelMoveSwitch(); + + if (gBeepToPlay == BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL) { + AUDIO_PlayBeep(gBeepToPlay); + } + + SETTINGS_SaveVfoIndices(); + } + + cancelUserInputModes(); + } + } + + if (gDTMF_RX_live_timeout > 0) + { + #ifdef ENABLE_RSSI_BAR + if (center_line == CENTER_LINE_DTMF_DEC || + center_line == CENTER_LINE_NONE) // wait till the center line is free for us to use before timing out + #endif + { + if (--gDTMF_RX_live_timeout == 0) + { + if (gDTMF_RX_live[0] != 0) + { + memset(gDTMF_RX_live, 0, sizeof(gDTMF_RX_live)); + gUpdateDisplay = true; + } + } + } + } + + if (gMenuCountdown > 0) + if (--gMenuCountdown == 0) + exit_menu = (gScreenToDisplay == DISPLAY_MENU); // exit menu mode #ifdef ENABLE_DTMF_CALLING - if (gDTMF_RX_timeout > 0) - if (--gDTMF_RX_timeout == 0) - DTMF_clear_RX(); + if (gDTMF_RX_timeout > 0) + if (--gDTMF_RX_timeout == 0) + DTMF_clear_RX(); #endif - // Skipped authentic device check + // Skipped authentic device check #ifdef ENABLE_FMRADIO - if (gFmRadioCountdown_500ms > 0) - { - gFmRadioCountdown_500ms--; - if (gFmRadioMode) // 1of11 - return; - } -#endif - - if (gBacklightCountdown_500ms > 0 && !gAskToSave && !gCssBackgroundScan - // don't turn off backlight if user is in backlight menu option - && !(gScreenToDisplay == DISPLAY_MENU && (UI_MENU_GetCurrentMenuId() == MENU_ABR || UI_MENU_GetCurrentMenuId() == MENU_ABR_MAX)) - && --gBacklightCountdown_500ms == 0 - && gEeprom.BACKLIGHT_TIME < 61 - ) { - BACKLIGHT_TurnOff(); - } - - if (gReducedService) - { - BOARD_ADC_GetBatteryInfo(&gBatteryCurrentVoltage, &gBatteryCurrent); - - if (gBatteryCurrent > 500 || gBatteryCalibration[3] < gBatteryCurrentVoltage) - { - #ifdef ENABLE_OVERLAY - overlay_FLASH_RebootToBootloader(); - #else - NVIC_SystemReset(); - #endif - } - - return; - } - - gBatteryCheckCounter++; - - // Skipped authentic device check - - if (gCurrentFunction != FUNCTION_TRANSMIT) - { - - if ((gBatteryCheckCounter & 1) == 0) - { - BOARD_ADC_GetBatteryInfo(&gBatteryVoltages[gBatteryVoltageIndex++], &gBatteryCurrent); - if (gBatteryVoltageIndex > 3) - gBatteryVoltageIndex = 0; - BATTERY_GetReadings(true); - } - } - - // regular display updates (once every 2 sec) - if need be - if ((gBatteryCheckCounter & 3) == 0) - { - if (gChargingWithTypeC || gSetting_battery_text > 0) - gUpdateStatus = true; - #ifdef ENABLE_SHOW_CHARGE_LEVEL - if (gChargingWithTypeC) - gUpdateDisplay = true; - #endif - } - - if (!gCssBackgroundScan && gScanStateDir == SCAN_OFF && !SCANNER_IsScanning() + if (gFmRadioCountdown_500ms > 0) + { + gFmRadioCountdown_500ms--; + if (gFmRadioMode) // 1of11 + return; + } +#endif + + if (gBacklightCountdown_500ms > 0 && !gAskToSave && !gCssBackgroundScan + // don't turn off backlight if user is in backlight menu option + && !(gScreenToDisplay == DISPLAY_MENU && (UI_MENU_GetCurrentMenuId() == MENU_ABR || UI_MENU_GetCurrentMenuId() == MENU_ABR_MAX)) + && --gBacklightCountdown_500ms == 0 + && gEeprom.BACKLIGHT_TIME < 61 + ) { + BACKLIGHT_TurnOff(); + } + + if (gReducedService) + { + BOARD_ADC_GetBatteryInfo(&gBatteryCurrentVoltage, &gBatteryCurrent); + + if (gBatteryCurrent > 500 || gBatteryCalibration[3] < gBatteryCurrentVoltage) + { + #ifdef ENABLE_OVERLAY + overlay_FLASH_RebootToBootloader(); + #else + NVIC_SystemReset(); + #endif + } + + return; + } + + gBatteryCheckCounter++; + + // Skipped authentic device check + + if (gCurrentFunction != FUNCTION_TRANSMIT) + { + + if ((gBatteryCheckCounter & 1) == 0) + { + BOARD_ADC_GetBatteryInfo(&gBatteryVoltages[gBatteryVoltageIndex++], &gBatteryCurrent); + if (gBatteryVoltageIndex > 3) + gBatteryVoltageIndex = 0; + BATTERY_GetReadings(true); + } + } + + // regular display updates (once every 2 sec) - if need be + if ((gBatteryCheckCounter & 3) == 0) + { + if (gChargingWithTypeC || gSetting_battery_text > 0) + gUpdateStatus = true; + #ifdef ENABLE_SHOW_CHARGE_LEVEL + if (gChargingWithTypeC) + gUpdateDisplay = true; + #endif + } + + if (!gCssBackgroundScan && gScanStateDir == SCAN_OFF && !SCANNER_IsScanning() #ifdef ENABLE_FMRADIO - && (gFM_ScanState == FM_SCAN_OFF || gAskToSave) + && (gFM_ScanState == FM_SCAN_OFF || gAskToSave) #endif #ifdef ENABLE_AIRCOPY - && gScreenToDisplay != DISPLAY_AIRCOPY -#endif - ) { - if (gEeprom.AUTO_KEYPAD_LOCK && gKeyLockCountdown > 0 && !gDTMF_InputMode - && gScreenToDisplay != DISPLAY_MENU && --gKeyLockCountdown == 0) - { - gEeprom.KEY_LOCK = true; // lock the keyboard - gUpdateStatus = true; // lock symbol needs showing - } - - if (exit_menu) { - gMenuCountdown = 0; - - if (gEeprom.BACKLIGHT_TIME == 0) { - BACKLIGHT_TurnOff(); - } - - if (gInputBoxIndex > 0 || gDTMF_InputMode) { - AUDIO_PlayBeep(BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL); - } + && gScreenToDisplay != DISPLAY_AIRCOPY +#endif + ) { + if (gEeprom.AUTO_KEYPAD_LOCK && gKeyLockCountdown > 0 && !gDTMF_InputMode + && gScreenToDisplay != DISPLAY_MENU && --gKeyLockCountdown == 0) + { + gEeprom.KEY_LOCK = true; // lock the keyboard + gUpdateStatus = true; // lock symbol needs showing + } + + if (exit_menu) { + gMenuCountdown = 0; + + if (gEeprom.BACKLIGHT_TIME == 0) { + BACKLIGHT_TurnOff(); + } + + if (gInputBoxIndex > 0 || gDTMF_InputMode) { + AUDIO_PlayBeep(BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL); + } /* - if (SCANNER_IsScanning()) { - BK4819_StopScan(); + if (SCANNER_IsScanning()) { + BK4819_StopScan(); - RADIO_ConfigureChannel(0, VFO_CONFIGURE_RELOAD); - RADIO_ConfigureChannel(1, VFO_CONFIGURE_RELOAD); + RADIO_ConfigureChannel(0, VFO_CONFIGURE_RELOAD); + RADIO_ConfigureChannel(1, VFO_CONFIGURE_RELOAD); - RADIO_SetupRegisters(true); - } + RADIO_SetupRegisters(true); + } */ - DTMF_clear_input_box(); + DTMF_clear_input_box(); - gWasFKeyPressed = false; - gInputBoxIndex = 0; + gWasFKeyPressed = false; + gInputBoxIndex = 0; - gAskToSave = false; - gAskToDelete = false; + gAskToSave = false; + gAskToDelete = false; - gUpdateStatus = true; - gUpdateDisplay = true; + gUpdateStatus = true; + gUpdateDisplay = true; - GUI_DisplayType_t disp = DISPLAY_INVALID; + GUI_DisplayType_t disp = DISPLAY_INVALID; #ifdef ENABLE_FMRADIO - if (gFmRadioMode && ! FUNCTION_IsRx()) { - disp = DISPLAY_FM; - } + if (gFmRadioMode && ! FUNCTION_IsRx()) { + disp = DISPLAY_FM; + } #endif - if (disp == DISPLAY_INVALID + if (disp == DISPLAY_INVALID #ifdef ENABLE_NO_CODE_SCAN_TIMEOUT - && !SCANNER_IsScanning() + && !SCANNER_IsScanning() #endif - ) { - disp = DISPLAY_MAIN; - } + ) { + disp = DISPLAY_MAIN; + } - if (disp != DISPLAY_INVALID) { - GUI_SelectNextDisplay(disp); - } - } - } + if (disp != DISPLAY_INVALID) { + GUI_SelectNextDisplay(disp); + } + } + } - if (!gPttIsPressed && gVFOStateResumeCountdown_500ms > 0 && --gVFOStateResumeCountdown_500ms == 0) { - RADIO_SetVfoState(VFO_STATE_NORMAL); + if (!gPttIsPressed && gVFOStateResumeCountdown_500ms > 0 && --gVFOStateResumeCountdown_500ms == 0) { + RADIO_SetVfoState(VFO_STATE_NORMAL); #ifdef ENABLE_FMRADIO - if (gFmRadioMode && !FUNCTION_IsRx()) { - // switch back to FM radio mode - FM_Start(); - GUI_SelectNextDisplay(DISPLAY_FM); - } + if (gFmRadioMode && !FUNCTION_IsRx()) { + // switch back to FM radio mode + FM_Start(); + GUI_SelectNextDisplay(DISPLAY_FM); + } #endif - } + } - BATTERY_TimeSlice500ms(); - SCANNER_TimeSlice500ms(); - UI_MAIN_TimeSlice500ms(); + BATTERY_TimeSlice500ms(); + SCANNER_TimeSlice500ms(); + UI_MAIN_TimeSlice500ms(); #ifdef ENABLE_DTMF_CALLING - if (gCurrentFunction != FUNCTION_TRANSMIT) { - if (gDTMF_DecodeRingCountdown_500ms > 0) { - // make "ring-ring" sound - gDTMF_DecodeRingCountdown_500ms--; - AUDIO_PlayBeep(BEEP_880HZ_200MS); - } - } else { - gDTMF_DecodeRingCountdown_500ms = 0; - } - - if (gDTMF_CallState != DTMF_CALL_STATE_NONE && gCurrentFunction != FUNCTION_TRANSMIT - && gCurrentFunction != FUNCTION_RECEIVE && gDTMF_auto_reset_time_500ms > 0 - && --gDTMF_auto_reset_time_500ms == 0) - { - gUpdateDisplay = true; - if (gDTMF_CallState == DTMF_CALL_STATE_RECEIVED && gEeprom.DTMF_auto_reset_time >= DTMF_HOLD_MAX) { - gDTMF_CallState = DTMF_CALL_STATE_RECEIVED_STAY; // keep message on-screen till a key is pressed - } else { - gDTMF_CallState = DTMF_CALL_STATE_NONE; - } - } - - if (gDTMF_IsTx && gDTMF_TxStopCountdown_500ms > 0 && --gDTMF_TxStopCountdown_500ms == 0) { - gDTMF_IsTx = false; - gUpdateDisplay = true; - } + if (gCurrentFunction != FUNCTION_TRANSMIT) { + if (gDTMF_DecodeRingCountdown_500ms > 0) { + // make "ring-ring" sound + gDTMF_DecodeRingCountdown_500ms--; + AUDIO_PlayBeep(BEEP_880HZ_200MS); + } + } else { + gDTMF_DecodeRingCountdown_500ms = 0; + } + + if (gDTMF_CallState != DTMF_CALL_STATE_NONE && gCurrentFunction != FUNCTION_TRANSMIT + && gCurrentFunction != FUNCTION_RECEIVE && gDTMF_auto_reset_time_500ms > 0 + && --gDTMF_auto_reset_time_500ms == 0) + { + gUpdateDisplay = true; + if (gDTMF_CallState == DTMF_CALL_STATE_RECEIVED && gEeprom.DTMF_auto_reset_time >= DTMF_HOLD_MAX) { + gDTMF_CallState = DTMF_CALL_STATE_RECEIVED_STAY; // keep message on-screen till a key is pressed + } else { + gDTMF_CallState = DTMF_CALL_STATE_NONE; + } + } + + if (gDTMF_IsTx && gDTMF_TxStopCountdown_500ms > 0 && --gDTMF_TxStopCountdown_500ms == 0) { + gDTMF_IsTx = false; + gUpdateDisplay = true; + } #endif } #if defined(ENABLE_ALARM) || defined(ENABLE_TX1750) static void ALARM_Off(void) { - AUDIO_AudioPathOff(); - gEnableSpeaker = false; + AUDIO_AudioPathOff(); + gEnableSpeaker = false; - if (gAlarmState == ALARM_STATE_TXALARM || gAlarmState == ALARM_STATE_TX1750) { - RADIO_SendEndOfTransmission(); - } + if (gAlarmState == ALARM_STATE_TXALARM || gAlarmState == ALARM_STATE_TX1750) { + RADIO_SendEndOfTransmission(); + } - gAlarmState = ALARM_STATE_OFF; + gAlarmState = ALARM_STATE_OFF; #ifdef ENABLE_VOX - gVoxResumeCountdown = 80; + gVoxResumeCountdown = 80; #endif - SYSTEM_DelayMs(5); + SYSTEM_DelayMs(5); - RADIO_SetupRegisters(true); + RADIO_SetupRegisters(true); - if (gScreenToDisplay != DISPLAY_MENU) // 1of11 .. don't close the menu - gRequestDisplayScreen = DISPLAY_MAIN; + if (gScreenToDisplay != DISPLAY_MENU) // 1of11 .. don't close the menu + gRequestDisplayScreen = DISPLAY_MAIN; } #endif static void ProcessKey(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld) { - if (Key == KEY_EXIT && !BACKLIGHT_IsOn() && gEeprom.BACKLIGHT_TIME > 0) - { // just turn the light on for now so the user can see what's what - BACKLIGHT_TurnOn(); - gBeepToPlay = BEEP_NONE; - return; - } + if (Key == KEY_EXIT && !BACKLIGHT_IsOn() && gEeprom.BACKLIGHT_TIME > 0) + { // just turn the light on for now so the user can see what's what + BACKLIGHT_TurnOn(); + gBeepToPlay = BEEP_NONE; + return; + } - if (gCurrentFunction == FUNCTION_POWER_SAVE) - FUNCTION_Select(FUNCTION_FOREGROUND); + if (gCurrentFunction == FUNCTION_POWER_SAVE) + FUNCTION_Select(FUNCTION_FOREGROUND); - gBatterySaveCountdown_10ms = battery_save_count_10ms; + gBatterySaveCountdown_10ms = battery_save_count_10ms; - if (gEeprom.AUTO_KEYPAD_LOCK) - gKeyLockCountdown = 30; // 15 seconds + if (gEeprom.AUTO_KEYPAD_LOCK) + gKeyLockCountdown = 30; // 15 seconds - if (!bKeyPressed) { // key released - if (flagSaveVfo) { - SETTINGS_SaveVfoIndices(); - flagSaveVfo = false; - } + if (!bKeyPressed) { // key released + if (flagSaveVfo) { + SETTINGS_SaveVfoIndices(); + flagSaveVfo = false; + } - if (flagSaveSettings) { - SETTINGS_SaveSettings(); - flagSaveSettings = false; - } + if (flagSaveSettings) { + SETTINGS_SaveSettings(); + flagSaveSettings = false; + } #ifdef ENABLE_FMRADIO - if (gFlagSaveFM) { - SETTINGS_SaveFM(); - gFlagSaveFM = false; - } -#endif - - if (flagSaveChannel) { - SETTINGS_SaveChannel(gTxVfo->CHANNEL_SAVE, gEeprom.TX_VFO, gTxVfo, flagSaveChannel); - flagSaveChannel = false; - - if (!SCANNER_IsScanning() && gVfoConfigureMode == VFO_CONFIGURE_NONE) - // gVfoConfigureMode is so as we don't wipe out previously setting this variable elsewhere - gVfoConfigureMode = VFO_CONFIGURE; - } - } - else { // key pressed or held - const int m = UI_MENU_GetCurrentMenuId(); - if ( //not when PTT and the backlight shouldn't turn on on TX - !(Key == KEY_PTT && !(gSetting_backlight_on_tx_rx & BACKLIGHT_ON_TR_TX)) - // not in the backlight menu - && !(gScreenToDisplay == DISPLAY_MENU && ( m == MENU_ABR || m == MENU_ABR_MAX || m == MENU_ABR_MIN)) - ) - { - BACKLIGHT_TurnOn(); - } - - if (Key == KEY_EXIT && bKeyHeld) { // exit key held pressed - // clear the live DTMF decoder - if (gDTMF_RX_live[0] != 0) { - memset(gDTMF_RX_live, 0, sizeof(gDTMF_RX_live)); - gDTMF_RX_live_timeout = 0; - gUpdateDisplay = true; - } - - // cancel user input - cancelUserInputModes(); - - if (gMonitor) - ACTION_Monitor(); //turn off the monitor + if (gFlagSaveFM) { + SETTINGS_SaveFM(); + gFlagSaveFM = false; + } +#endif + + if (flagSaveChannel) { + SETTINGS_SaveChannel(gTxVfo->CHANNEL_SAVE, gEeprom.TX_VFO, gTxVfo, flagSaveChannel); + flagSaveChannel = false; + + if (!SCANNER_IsScanning() && gVfoConfigureMode == VFO_CONFIGURE_NONE) + // gVfoConfigureMode is so as we don't wipe out previously setting this variable elsewhere + gVfoConfigureMode = VFO_CONFIGURE; + } + } + else { // key pressed or held + const int m = UI_MENU_GetCurrentMenuId(); + if ( //not when PTT and the backlight shouldn't turn on on TX + !(Key == KEY_PTT && !(gSetting_backlight_on_tx_rx & BACKLIGHT_ON_TR_TX)) + // not in the backlight menu + && !(gScreenToDisplay == DISPLAY_MENU && ( m == MENU_ABR || m == MENU_ABR_MAX || m == MENU_ABR_MIN)) + ) + { + BACKLIGHT_TurnOn(); + } + + if (Key == KEY_EXIT && bKeyHeld) { // exit key held pressed + // clear the live DTMF decoder + if (gDTMF_RX_live[0] != 0) { + memset(gDTMF_RX_live, 0, sizeof(gDTMF_RX_live)); + gDTMF_RX_live_timeout = 0; + gUpdateDisplay = true; + } + + // cancel user input + cancelUserInputModes(); + + if (gMonitor) + ACTION_Monitor(); //turn off the monitor #ifdef ENABLE_SCAN_RANGES - gScanRangeStart = 0; + gScanRangeStart = 0; #endif - } + } - if (gScreenToDisplay == DISPLAY_MENU) // 1of11 - gMenuCountdown = menu_timeout_500ms; + if (gScreenToDisplay == DISPLAY_MENU) // 1of11 + gMenuCountdown = menu_timeout_500ms; #ifdef ENABLE_DTMF_CALLING - if (gDTMF_DecodeRingCountdown_500ms > 0) { // cancel the ringing - gDTMF_DecodeRingCountdown_500ms = 0; + if (gDTMF_DecodeRingCountdown_500ms > 0) { // cancel the ringing + gDTMF_DecodeRingCountdown_500ms = 0; - AUDIO_PlayBeep(BEEP_1KHZ_60MS_OPTIONAL); + AUDIO_PlayBeep(BEEP_1KHZ_60MS_OPTIONAL); - if (Key != KEY_PTT) { - gPttWasReleased = true; - return; - } - } + if (Key != KEY_PTT) { + gPttWasReleased = true; + return; + } + } #endif - } + } - bool lowBatPopup = gLowBattery && !gLowBatteryConfirmed && gScreenToDisplay == DISPLAY_MAIN; + bool lowBatPopup = gLowBattery && !gLowBatteryConfirmed && gScreenToDisplay == DISPLAY_MAIN; #ifdef ENABLE_FEAT_F4HWN // Disable PTT if KEY_LOCK - bool lck_condition = false; + bool lck_condition = false; - if(gSetting_set_lck) - lck_condition = (gEeprom.KEY_LOCK || lowBatPopup) && gCurrentFunction != FUNCTION_TRANSMIT; - else - lck_condition = (gEeprom.KEY_LOCK || lowBatPopup) && gCurrentFunction != FUNCTION_TRANSMIT && Key != KEY_PTT; + if(gSetting_set_lck) + lck_condition = (gEeprom.KEY_LOCK || lowBatPopup) && gCurrentFunction != FUNCTION_TRANSMIT; + else + lck_condition = (gEeprom.KEY_LOCK || lowBatPopup) && gCurrentFunction != FUNCTION_TRANSMIT && Key != KEY_PTT; - if (lck_condition) + if (lck_condition) #else - if ((gEeprom.KEY_LOCK || lowBatPopup) && gCurrentFunction != FUNCTION_TRANSMIT && Key != KEY_PTT) -#endif - { // keyboard is locked or low battery popup - - // close low battery popup - if(Key == KEY_EXIT && bKeyPressed && lowBatPopup) { - gLowBatteryConfirmed = true; - gUpdateDisplay = true; - AUDIO_PlayBeep(BEEP_1KHZ_60MS_OPTIONAL); - return; - } - - if (Key == KEY_F) { // function/key-lock key - if (!bKeyPressed) - return; - - if (!bKeyHeld) { // keypad is locked, tell the user - AUDIO_PlayBeep(BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL); - gKeypadLocked = 4; // 2 seconds - gUpdateDisplay = true; - return; - } - } - // KEY_MENU has a special treatment here, because we want to pass hold event to ACTION_Handle - // but we don't want it to complain when initial press happens - // we want to react on realese instead - else if (Key != KEY_SIDE1 && Key != KEY_SIDE2 && // pass side buttons - !(Key == KEY_MENU && bKeyHeld)) // pass KEY_MENU held - { - if ((!bKeyPressed || bKeyHeld || (Key == KEY_MENU && bKeyPressed)) && // prevent released or held, prevent KEY_MENU pressed - !(Key == KEY_MENU && !bKeyPressed)) // pass KEY_MENU released - return; - - // keypad is locked, tell the user - AUDIO_PlayBeep(BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL); - gKeypadLocked = 4; // 2 seconds - gUpdateDisplay = true; - return; - } - } - - if (Key <= KEY_9 || Key == KEY_F) { - //if (gScanStateDir != SCAN_OFF || gCssBackgroundScan) { // FREQ/CTCSS/DCS scanning - if (gCssBackgroundScan) { // FREQ/CTCSS/DCS scanning - if (bKeyPressed && !bKeyHeld) - AUDIO_PlayBeep(BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL); - return; - } - } - - bool bFlag = false; - if (Key == KEY_PTT) { - if (gPttWasPressed) { - bFlag = bKeyHeld; - if (!bKeyPressed) { - bFlag = true; - gPttWasPressed = false; - } - } - } - else if (gPttWasReleased) { - if (bKeyHeld) - bFlag = true; - if (!bKeyPressed) { - bFlag = true; - gPttWasReleased = false; - } - } + if ((gEeprom.KEY_LOCK || lowBatPopup) && gCurrentFunction != FUNCTION_TRANSMIT && Key != KEY_PTT) +#endif + { // keyboard is locked or low battery popup + + // close low battery popup + if(Key == KEY_EXIT && bKeyPressed && lowBatPopup) { + gLowBatteryConfirmed = true; + gUpdateDisplay = true; + AUDIO_PlayBeep(BEEP_1KHZ_60MS_OPTIONAL); + return; + } + + if (Key == KEY_F) { // function/key-lock key + if (!bKeyPressed) + return; + + if (!bKeyHeld) { // keypad is locked, tell the user + AUDIO_PlayBeep(BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL); + gKeypadLocked = 4; // 2 seconds + gUpdateDisplay = true; + return; + } + } + // KEY_MENU has a special treatment here, because we want to pass hold event to ACTION_Handle + // but we don't want it to complain when initial press happens + // we want to react on realese instead + else if (Key != KEY_SIDE1 && Key != KEY_SIDE2 && // pass side buttons + !(Key == KEY_MENU && bKeyHeld)) // pass KEY_MENU held + { + if ((!bKeyPressed || bKeyHeld || (Key == KEY_MENU && bKeyPressed)) && // prevent released or held, prevent KEY_MENU pressed + !(Key == KEY_MENU && !bKeyPressed)) // pass KEY_MENU released + return; + + // keypad is locked, tell the user + AUDIO_PlayBeep(BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL); + gKeypadLocked = 4; // 2 seconds + gUpdateDisplay = true; + return; + } + } + + if (Key <= KEY_9 || Key == KEY_F) { + //if (gScanStateDir != SCAN_OFF || gCssBackgroundScan) { // FREQ/CTCSS/DCS scanning + if (gCssBackgroundScan) { // FREQ/CTCSS/DCS scanning + if (bKeyPressed && !bKeyHeld) + AUDIO_PlayBeep(BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL); + return; + } + } + + bool bFlag = false; + if (Key == KEY_PTT) { + if (gPttWasPressed) { + bFlag = bKeyHeld; + if (!bKeyPressed) { + bFlag = true; + gPttWasPressed = false; + } + } + } + else if (gPttWasReleased) { + if (bKeyHeld) + bFlag = true; + if (!bKeyPressed) { + bFlag = true; + gPttWasReleased = false; + } + } #ifdef ENABLE_FEAT_F4HWN // For F + SIDE1 or F + SIDE2 - if (gWasFKeyPressed && (Key == KEY_PTT || Key == KEY_EXIT)) { + if (gWasFKeyPressed && (Key == KEY_PTT || Key == KEY_EXIT)) { #else - if (gWasFKeyPressed && (Key == KEY_PTT || Key == KEY_EXIT || Key == KEY_SIDE1 || Key == KEY_SIDE2)) { + if (gWasFKeyPressed && (Key == KEY_PTT || Key == KEY_EXIT || Key == KEY_SIDE1 || Key == KEY_SIDE2)) { #endif - // cancel the F-key - gWasFKeyPressed = false; - gUpdateStatus = true; - } + // cancel the F-key + gWasFKeyPressed = false; + gUpdateStatus = true; + } - if (bFlag) { - goto Skip; - } + if (bFlag) { + goto Skip; + } - if (gCurrentFunction == FUNCTION_TRANSMIT) { + if (gCurrentFunction == FUNCTION_TRANSMIT) { #if defined(ENABLE_ALARM) || defined(ENABLE_TX1750) - if (gAlarmState == ALARM_STATE_OFF) + if (gAlarmState == ALARM_STATE_OFF) #endif - { - char Code; + { + char Code; - if (Key == KEY_PTT) { - GENERIC_Key_PTT(bKeyPressed); - goto Skip; - } + if (Key == KEY_PTT) { + GENERIC_Key_PTT(bKeyPressed); + goto Skip; + } - if (Key == KEY_SIDE2) { // transmit 1750Hz tone - Code = 0xFE; - } - else { - Code = DTMF_GetCharacter(Key - KEY_0); - if (Code == 0xFF) - goto Skip; - // transmit DTMF keys - } + if (Key == KEY_SIDE2) { // transmit 1750Hz tone + Code = 0xFE; + } + else { + Code = DTMF_GetCharacter(Key - KEY_0); + if (Code == 0xFF) + goto Skip; + // transmit DTMF keys + } - if (!bKeyPressed || bKeyHeld) { - if (!bKeyPressed) { - AUDIO_AudioPathOff(); + if (!bKeyPressed || bKeyHeld) { + if (!bKeyPressed) { + AUDIO_AudioPathOff(); - gEnableSpeaker = false; + gEnableSpeaker = false; - BK4819_ExitDTMF_TX(false); + BK4819_ExitDTMF_TX(false); #ifndef ENABLE_FEAT_F4HWN - if (gCurrentVfo->SCRAMBLING_TYPE == 0 || !gSetting_ScrambleEnable) - BK4819_DisableScramble(); - else - BK4819_EnableScramble(gCurrentVfo->SCRAMBLING_TYPE - 1); + if (gCurrentVfo->SCRAMBLING_TYPE == 0 || !gSetting_ScrambleEnable) + BK4819_DisableScramble(); + else + BK4819_EnableScramble(gCurrentVfo->SCRAMBLING_TYPE - 1); #else - BK4819_DisableScramble(); -#endif - } - } - else { - if (gEeprom.DTMF_SIDE_TONE) { // user will here the DTMF tones in speaker - AUDIO_AudioPathOn(); - gEnableSpeaker = true; - } - - BK4819_DisableScramble(); - - if (Code == 0xFE) - BK4819_TransmitTone(gEeprom.DTMF_SIDE_TONE, 1750); - else - BK4819_PlayDTMFEx(gEeprom.DTMF_SIDE_TONE, Code); - } - } + BK4819_DisableScramble(); +#endif + } + } + else { + if (gEeprom.DTMF_SIDE_TONE) { // user will here the DTMF tones in speaker + AUDIO_AudioPathOn(); + gEnableSpeaker = true; + } + + BK4819_DisableScramble(); + + if (Code == 0xFE) + BK4819_TransmitTone(gEeprom.DTMF_SIDE_TONE, 1750); + else + BK4819_PlayDTMFEx(gEeprom.DTMF_SIDE_TONE, Code); + } + } #if defined(ENABLE_ALARM) || defined(ENABLE_TX1750) - else if ((!bKeyHeld && bKeyPressed) || (gAlarmState == ALARM_STATE_TX1750 && bKeyHeld && !bKeyPressed)) { - ALARM_Off(); + else if ((!bKeyHeld && bKeyPressed) || (gAlarmState == ALARM_STATE_TX1750 && bKeyHeld && !bKeyPressed)) { + ALARM_Off(); - if (gEeprom.REPEATER_TAIL_TONE_ELIMINATION == 0) - FUNCTION_Select(FUNCTION_FOREGROUND); - else - gRTTECountdown_10ms = gEeprom.REPEATER_TAIL_TONE_ELIMINATION * 10; + if (gEeprom.REPEATER_TAIL_TONE_ELIMINATION == 0) + FUNCTION_Select(FUNCTION_FOREGROUND); + else + gRTTECountdown_10ms = gEeprom.REPEATER_TAIL_TONE_ELIMINATION * 10; - if (Key == KEY_PTT) - gPttWasPressed = true; - else if (!bKeyHeld) - gPttWasReleased = true; - } + if (Key == KEY_PTT) + gPttWasPressed = true; + else if (!bKeyHeld) + gPttWasReleased = true; + } #endif - } + } #ifdef ENABLE_FEAT_F4HWN // For F + SIDE1 or F + SIDE2 - else if (gWasFKeyPressed && (Key == KEY_SIDE1 || Key == KEY_SIDE2)) { - ProcessKeysFunctions[gScreenToDisplay](Key, bKeyPressed, bKeyHeld); - } - else if (Key != KEY_SIDE1 && Key != KEY_SIDE2 && gScreenToDisplay != DISPLAY_INVALID) { - ProcessKeysFunctions[gScreenToDisplay](Key, bKeyPressed, bKeyHeld); - } + else if (gWasFKeyPressed && (Key == KEY_SIDE1 || Key == KEY_SIDE2)) { + ProcessKeysFunctions[gScreenToDisplay](Key, bKeyPressed, bKeyHeld); + } + else if (Key != KEY_SIDE1 && Key != KEY_SIDE2 && gScreenToDisplay != DISPLAY_INVALID) { + ProcessKeysFunctions[gScreenToDisplay](Key, bKeyPressed, bKeyHeld); + } #else - else if (Key != KEY_SIDE1 && Key != KEY_SIDE2 && gScreenToDisplay != DISPLAY_INVALID) { - ProcessKeysFunctions[gScreenToDisplay](Key, bKeyPressed, bKeyHeld); - } + else if (Key != KEY_SIDE1 && Key != KEY_SIDE2 && gScreenToDisplay != DISPLAY_INVALID) { + ProcessKeysFunctions[gScreenToDisplay](Key, bKeyPressed, bKeyHeld); + } #endif - else if (!SCANNER_IsScanning() + else if (!SCANNER_IsScanning() #ifdef ENABLE_AIRCOPY - && gScreenToDisplay != DISPLAY_AIRCOPY + && gScreenToDisplay != DISPLAY_AIRCOPY #endif - ) { - ACTION_Handle(Key, bKeyPressed, bKeyHeld); - } - else if (!bKeyHeld && bKeyPressed) { - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - } + ) { + ACTION_Handle(Key, bKeyPressed, bKeyHeld); + } + else if (!bKeyHeld && bKeyPressed) { + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + } Skip: - if (gBeepToPlay != BEEP_NONE) { - AUDIO_PlayBeep(gBeepToPlay); - gBeepToPlay = BEEP_NONE; - } + if (gBeepToPlay != BEEP_NONE) { + AUDIO_PlayBeep(gBeepToPlay); + gBeepToPlay = BEEP_NONE; + } - if (gFlagAcceptSetting) { - gMenuCountdown = menu_timeout_500ms; + if (gFlagAcceptSetting) { + gMenuCountdown = menu_timeout_500ms; - MENU_AcceptSetting(); + MENU_AcceptSetting(); - gFlagRefreshSetting = true; - gFlagAcceptSetting = false; - } + gFlagRefreshSetting = true; + gFlagAcceptSetting = false; + } - if (gRequestSaveSettings) { - if (!bKeyHeld) - SETTINGS_SaveSettings(); - else - flagSaveSettings = 1; - gRequestSaveSettings = false; - gUpdateStatus = true; - } + if (gRequestSaveSettings) { + if (!bKeyHeld) + SETTINGS_SaveSettings(); + else + flagSaveSettings = 1; + gRequestSaveSettings = false; + gUpdateStatus = true; + } #ifdef ENABLE_FMRADIO - if (gRequestSaveFM) { - gRequestSaveFM = false; - if (!bKeyHeld) - SETTINGS_SaveFM(); - else - gFlagSaveFM = true; - } -#endif - - if (gRequestSaveVFO) { - gRequestSaveVFO = false; - if (!bKeyHeld) - SETTINGS_SaveVfoIndices(); - else - flagSaveVfo = true; - } - - if (gRequestSaveChannel > 0) { // TODO: remove the gRequestSaveChannel, why use global variable for that?? - if ((!bKeyHeld && !bKeyPressed) || UI_MENU_GetCurrentMenuId()) - { - SETTINGS_SaveChannel(gTxVfo->CHANNEL_SAVE, gEeprom.TX_VFO, gTxVfo, gRequestSaveChannel); - - if (!SCANNER_IsScanning() && gVfoConfigureMode == VFO_CONFIGURE_NONE) - // gVfoConfigureMode is so as we don't wipe out previously setting this variable elsewhere - gVfoConfigureMode = VFO_CONFIGURE; - } - else { // this is probably so settings are not saved when up/down button is held and save is postponed to btn release - flagSaveChannel = gRequestSaveChannel; - - if (gRequestDisplayScreen == DISPLAY_INVALID) - gRequestDisplayScreen = DISPLAY_MAIN; - } - - gRequestSaveChannel = 0; - } - - if (gVfoConfigureMode != VFO_CONFIGURE_NONE) { - if (gFlagResetVfos) { - RADIO_ConfigureChannel(0, gVfoConfigureMode); - RADIO_ConfigureChannel(1, gVfoConfigureMode); - } - else - RADIO_ConfigureChannel(gEeprom.TX_VFO, gVfoConfigureMode); - - if (gRequestDisplayScreen == DISPLAY_INVALID) - gRequestDisplayScreen = DISPLAY_MAIN; - - gFlagReconfigureVfos = true; - gVfoConfigureMode = VFO_CONFIGURE_NONE; - gFlagResetVfos = false; - } - - if (gFlagReconfigureVfos) { - RADIO_SelectVfos(); + if (gRequestSaveFM) { + gRequestSaveFM = false; + if (!bKeyHeld) + SETTINGS_SaveFM(); + else + gFlagSaveFM = true; + } +#endif + + if (gRequestSaveVFO) { + gRequestSaveVFO = false; + if (!bKeyHeld) + SETTINGS_SaveVfoIndices(); + else + flagSaveVfo = true; + } + + if (gRequestSaveChannel > 0) { // TODO: remove the gRequestSaveChannel, why use global variable for that?? + if ((!bKeyHeld && !bKeyPressed) || UI_MENU_GetCurrentMenuId()) + { + SETTINGS_SaveChannel(gTxVfo->CHANNEL_SAVE, gEeprom.TX_VFO, gTxVfo, gRequestSaveChannel); + + if (!SCANNER_IsScanning() && gVfoConfigureMode == VFO_CONFIGURE_NONE) + // gVfoConfigureMode is so as we don't wipe out previously setting this variable elsewhere + gVfoConfigureMode = VFO_CONFIGURE; + } + else { // this is probably so settings are not saved when up/down button is held and save is postponed to btn release + flagSaveChannel = gRequestSaveChannel; + + if (gRequestDisplayScreen == DISPLAY_INVALID) + gRequestDisplayScreen = DISPLAY_MAIN; + } + + gRequestSaveChannel = 0; + } + + if (gVfoConfigureMode != VFO_CONFIGURE_NONE) { + if (gFlagResetVfos) { + RADIO_ConfigureChannel(0, gVfoConfigureMode); + RADIO_ConfigureChannel(1, gVfoConfigureMode); + } + else + RADIO_ConfigureChannel(gEeprom.TX_VFO, gVfoConfigureMode); + + if (gRequestDisplayScreen == DISPLAY_INVALID) + gRequestDisplayScreen = DISPLAY_MAIN; + + gFlagReconfigureVfos = true; + gVfoConfigureMode = VFO_CONFIGURE_NONE; + gFlagResetVfos = false; + } + + if (gFlagReconfigureVfos) { + RADIO_SelectVfos(); #ifdef ENABLE_NOAA - RADIO_ConfigureNOAA(); + RADIO_ConfigureNOAA(); #endif - RADIO_SetupRegisters(true); + RADIO_SetupRegisters(true); #ifdef ENABLE_DTMF_CALLING - gDTMF_auto_reset_time_500ms = 0; - gDTMF_CallState = DTMF_CALL_STATE_NONE; - gDTMF_TxStopCountdown_500ms = 0; - gDTMF_IsTx = false; + gDTMF_auto_reset_time_500ms = 0; + gDTMF_CallState = DTMF_CALL_STATE_NONE; + gDTMF_TxStopCountdown_500ms = 0; + gDTMF_IsTx = false; #endif - gVFO_RSSI_bar_level[0] = 0; - gVFO_RSSI_bar_level[1] = 0; + gVFO_RSSI_bar_level[0] = 0; + gVFO_RSSI_bar_level[1] = 0; - gFlagReconfigureVfos = false; + gFlagReconfigureVfos = false; - if (gMonitor) - ACTION_Monitor(); // 1of11 - } + if (gMonitor) + ACTION_Monitor(); // 1of11 + } - if (gFlagRefreshSetting) { - gFlagRefreshSetting = false; - gMenuCountdown = menu_timeout_500ms; + if (gFlagRefreshSetting) { + gFlagRefreshSetting = false; + gMenuCountdown = menu_timeout_500ms; - MENU_ShowCurrentSetting(); - } + MENU_ShowCurrentSetting(); + } - if (gFlagPrepareTX) { - RADIO_PrepareTX(); - gFlagPrepareTX = false; - } + if (gFlagPrepareTX) { + RADIO_PrepareTX(); + gFlagPrepareTX = false; + } #ifdef ENABLE_VOICE - if (gAnotherVoiceID != VOICE_ID_INVALID) { - if (gAnotherVoiceID < 76) - AUDIO_SetVoiceID(0, gAnotherVoiceID); - AUDIO_PlaySingleVoice(false); - gAnotherVoiceID = VOICE_ID_INVALID; - } + if (gAnotherVoiceID != VOICE_ID_INVALID) { + if (gAnotherVoiceID < 76) + AUDIO_SetVoiceID(0, gAnotherVoiceID); + AUDIO_PlaySingleVoice(false); + gAnotherVoiceID = VOICE_ID_INVALID; + } #endif - GUI_SelectNextDisplay(gRequestDisplayScreen); - gRequestDisplayScreen = DISPLAY_INVALID; + GUI_SelectNextDisplay(gRequestDisplayScreen); + gRequestDisplayScreen = DISPLAY_INVALID; - gUpdateDisplay = true; + gUpdateDisplay = true; } diff --git a/app/chFrScanner.c b/app/chFrScanner.c index 5b5ae7eb1..bc00c1fc1 100644 --- a/app/chFrScanner.c +++ b/app/chFrScanner.c @@ -16,22 +16,22 @@ uint32_t gScanRangeStop; #endif typedef enum { - SCAN_NEXT_CHAN_SCANLIST1 = 0, - SCAN_NEXT_CHAN_SCANLIST2, - SCAN_NEXT_CHAN_DUAL_WATCH, - SCAN_NEXT_CHAN_MR, - SCAN_NEXT_NUM + SCAN_NEXT_CHAN_SCANLIST1 = 0, + SCAN_NEXT_CHAN_SCANLIST2, + SCAN_NEXT_CHAN_DUAL_WATCH, + SCAN_NEXT_CHAN_MR, + SCAN_NEXT_NUM } scan_next_chan_t; -scan_next_chan_t currentScanList; +scan_next_chan_t currentScanList; uint32_t initialFrqOrChan; -uint8_t initialCROSS_BAND_RX_TX; +uint8_t initialCROSS_BAND_RX_TX; #ifndef ENABLE_FEAT_F4HWN - uint32_t lastFoundFrqOrChan; + uint32_t lastFoundFrqOrChan; #else - uint32_t lastFoundFrqOrChan; - uint32_t lastFoundFrqOrChanOld; + uint32_t lastFoundFrqOrChan; + uint32_t lastFoundFrqOrChanOld; #endif static void NextFreqChannel(void); @@ -39,276 +39,276 @@ static void NextMemChannel(void); void CHFRSCANNER_Start(const bool storeBackupSettings, const int8_t scan_direction) { - if (storeBackupSettings) { - initialCROSS_BAND_RX_TX = gEeprom.CROSS_BAND_RX_TX; - gEeprom.CROSS_BAND_RX_TX = CROSS_BAND_OFF; - gScanKeepResult = false; - } - - RADIO_SelectVfos(); - - gNextMrChannel = gRxVfo->CHANNEL_SAVE; - currentScanList = SCAN_NEXT_CHAN_SCANLIST1; - gScanStateDir = scan_direction; - - if (IS_MR_CHANNEL(gNextMrChannel)) - { // channel mode - if (storeBackupSettings) { - initialFrqOrChan = gRxVfo->CHANNEL_SAVE; - lastFoundFrqOrChan = initialFrqOrChan; - } - NextMemChannel(); - } - else - { // frequency mode - if (storeBackupSettings) { - initialFrqOrChan = gRxVfo->freq_config_RX.Frequency; - lastFoundFrqOrChan = initialFrqOrChan; - } - NextFreqChannel(); - } + if (storeBackupSettings) { + initialCROSS_BAND_RX_TX = gEeprom.CROSS_BAND_RX_TX; + gEeprom.CROSS_BAND_RX_TX = CROSS_BAND_OFF; + gScanKeepResult = false; + } + + RADIO_SelectVfos(); + + gNextMrChannel = gRxVfo->CHANNEL_SAVE; + currentScanList = SCAN_NEXT_CHAN_SCANLIST1; + gScanStateDir = scan_direction; + + if (IS_MR_CHANNEL(gNextMrChannel)) + { // channel mode + if (storeBackupSettings) { + initialFrqOrChan = gRxVfo->CHANNEL_SAVE; + lastFoundFrqOrChan = initialFrqOrChan; + } + NextMemChannel(); + } + else + { // frequency mode + if (storeBackupSettings) { + initialFrqOrChan = gRxVfo->freq_config_RX.Frequency; + lastFoundFrqOrChan = initialFrqOrChan; + } + NextFreqChannel(); + } #ifdef ENABLE_FEAT_F4HWN - lastFoundFrqOrChanOld = lastFoundFrqOrChan; + lastFoundFrqOrChanOld = lastFoundFrqOrChan; #endif - gScanPauseDelayIn_10ms = scan_pause_delay_in_2_10ms; - gScheduleScanListen = false; - gRxReceptionMode = RX_MODE_NONE; - gScanPauseMode = false; + gScanPauseDelayIn_10ms = scan_pause_delay_in_2_10ms; + gScheduleScanListen = false; + gRxReceptionMode = RX_MODE_NONE; + gScanPauseMode = false; } void CHFRSCANNER_ContinueScanning(void) { - if (IS_FREQ_CHANNEL(gNextMrChannel)) - { - if (gCurrentFunction == FUNCTION_INCOMING) - APP_StartListening(gMonitor ? FUNCTION_MONITOR : FUNCTION_RECEIVE); - else - NextFreqChannel(); // switch to next frequency - } - else - { - if (gCurrentCodeType == CODE_TYPE_OFF && gCurrentFunction == FUNCTION_INCOMING) - APP_StartListening(gMonitor ? FUNCTION_MONITOR : FUNCTION_RECEIVE); - else - NextMemChannel(); // switch to next channel - } - - gScanPauseMode = false; - gRxReceptionMode = RX_MODE_NONE; - gScheduleScanListen = false; + if (IS_FREQ_CHANNEL(gNextMrChannel)) + { + if (gCurrentFunction == FUNCTION_INCOMING) + APP_StartListening(gMonitor ? FUNCTION_MONITOR : FUNCTION_RECEIVE); + else + NextFreqChannel(); // switch to next frequency + } + else + { + if (gCurrentCodeType == CODE_TYPE_OFF && gCurrentFunction == FUNCTION_INCOMING) + APP_StartListening(gMonitor ? FUNCTION_MONITOR : FUNCTION_RECEIVE); + else + NextMemChannel(); // switch to next channel + } + + gScanPauseMode = false; + gRxReceptionMode = RX_MODE_NONE; + gScheduleScanListen = false; } void CHFRSCANNER_Found(void) { - switch (gEeprom.SCAN_RESUME_MODE) - { - case SCAN_RESUME_TO: - if (!gScanPauseMode) - { - gScanPauseDelayIn_10ms = scan_pause_delay_in_1_10ms; - gScheduleScanListen = false; - gScanPauseMode = true; - } - break; - - case SCAN_RESUME_CO: - case SCAN_RESUME_SE: - gScanPauseDelayIn_10ms = 0; - gScheduleScanListen = false; - break; - } + switch (gEeprom.SCAN_RESUME_MODE) + { + case SCAN_RESUME_TO: + if (!gScanPauseMode) + { + gScanPauseDelayIn_10ms = scan_pause_delay_in_1_10ms; + gScheduleScanListen = false; + gScanPauseMode = true; + } + break; + + case SCAN_RESUME_CO: + case SCAN_RESUME_SE: + gScanPauseDelayIn_10ms = 0; + gScheduleScanListen = false; + break; + } #ifdef ENABLE_FEAT_F4HWN - lastFoundFrqOrChanOld = lastFoundFrqOrChan; + lastFoundFrqOrChanOld = lastFoundFrqOrChan; #endif - if (IS_MR_CHANNEL(gRxVfo->CHANNEL_SAVE)) { //memory scan - lastFoundFrqOrChan = gRxVfo->CHANNEL_SAVE; - } - else { // frequency scan - lastFoundFrqOrChan = gRxVfo->freq_config_RX.Frequency; - } + if (IS_MR_CHANNEL(gRxVfo->CHANNEL_SAVE)) { //memory scan + lastFoundFrqOrChan = gRxVfo->CHANNEL_SAVE; + } + else { // frequency scan + lastFoundFrqOrChan = gRxVfo->freq_config_RX.Frequency; + } - gScanKeepResult = true; + gScanKeepResult = true; } void CHFRSCANNER_Stop(void) { - if(initialCROSS_BAND_RX_TX != CROSS_BAND_OFF) { - gEeprom.CROSS_BAND_RX_TX = initialCROSS_BAND_RX_TX; - initialCROSS_BAND_RX_TX = CROSS_BAND_OFF; - } - - gScanStateDir = SCAN_OFF; - - const uint32_t chFr = gScanKeepResult ? lastFoundFrqOrChan : initialFrqOrChan; - const bool channelChanged = chFr != initialFrqOrChan; - if (IS_MR_CHANNEL(gNextMrChannel)) { - gEeprom.MrChannel[gEeprom.RX_VFO] = chFr; - gEeprom.ScreenChannel[gEeprom.RX_VFO] = chFr; - RADIO_ConfigureChannel(gEeprom.RX_VFO, VFO_CONFIGURE_RELOAD); - - if(channelChanged) { - SETTINGS_SaveVfoIndices(); - gUpdateStatus = true; - } - } - else { - gRxVfo->freq_config_RX.Frequency = chFr; - RADIO_ApplyOffset(gRxVfo); - RADIO_ConfigureSquelchAndOutputPower(gRxVfo); - if(channelChanged) { - SETTINGS_SaveChannel(gRxVfo->CHANNEL_SAVE, gEeprom.RX_VFO, gRxVfo, 1); - } - } - - RADIO_SetupRegisters(true); - gUpdateDisplay = true; + if(initialCROSS_BAND_RX_TX != CROSS_BAND_OFF) { + gEeprom.CROSS_BAND_RX_TX = initialCROSS_BAND_RX_TX; + initialCROSS_BAND_RX_TX = CROSS_BAND_OFF; + } + + gScanStateDir = SCAN_OFF; + + const uint32_t chFr = gScanKeepResult ? lastFoundFrqOrChan : initialFrqOrChan; + const bool channelChanged = chFr != initialFrqOrChan; + if (IS_MR_CHANNEL(gNextMrChannel)) { + gEeprom.MrChannel[gEeprom.RX_VFO] = chFr; + gEeprom.ScreenChannel[gEeprom.RX_VFO] = chFr; + RADIO_ConfigureChannel(gEeprom.RX_VFO, VFO_CONFIGURE_RELOAD); + + if(channelChanged) { + SETTINGS_SaveVfoIndices(); + gUpdateStatus = true; + } + } + else { + gRxVfo->freq_config_RX.Frequency = chFr; + RADIO_ApplyOffset(gRxVfo); + RADIO_ConfigureSquelchAndOutputPower(gRxVfo); + if(channelChanged) { + SETTINGS_SaveChannel(gRxVfo->CHANNEL_SAVE, gEeprom.RX_VFO, gRxVfo, 1); + } + } + + RADIO_SetupRegisters(true); + gUpdateDisplay = true; } static void NextFreqChannel(void) { #ifdef ENABLE_SCAN_RANGES - if(gScanRangeStart) { - gRxVfo->freq_config_RX.Frequency = APP_SetFreqByStepAndLimits(gRxVfo, gScanStateDir, gScanRangeStart, gScanRangeStop); - } - else + if(gScanRangeStart) { + gRxVfo->freq_config_RX.Frequency = APP_SetFreqByStepAndLimits(gRxVfo, gScanStateDir, gScanRangeStart, gScanRangeStop); + } + else #endif - gRxVfo->freq_config_RX.Frequency = APP_SetFrequencyByStep(gRxVfo, gScanStateDir); + gRxVfo->freq_config_RX.Frequency = APP_SetFrequencyByStep(gRxVfo, gScanStateDir); - RADIO_ApplyOffset(gRxVfo); - RADIO_ConfigureSquelchAndOutputPower(gRxVfo); - RADIO_SetupRegisters(true); + RADIO_ApplyOffset(gRxVfo); + RADIO_ConfigureSquelchAndOutputPower(gRxVfo); + RADIO_SetupRegisters(true); #ifdef ENABLE_FASTER_CHANNEL_SCAN - gScanPauseDelayIn_10ms = 9; // 90ms + gScanPauseDelayIn_10ms = 9; // 90ms #else - gScanPauseDelayIn_10ms = scan_pause_delay_in_6_10ms; + gScanPauseDelayIn_10ms = scan_pause_delay_in_6_10ms; #endif - gUpdateDisplay = true; + gUpdateDisplay = true; } static void NextMemChannel(void) { - static unsigned int prev_mr_chan = 0; - const bool enabled = (gEeprom.SCAN_LIST_DEFAULT > 0 && gEeprom.SCAN_LIST_DEFAULT < 4) ? gEeprom.SCAN_LIST_ENABLED[gEeprom.SCAN_LIST_DEFAULT - 1] : true; - const int chan1 = (gEeprom.SCAN_LIST_DEFAULT > 0 && gEeprom.SCAN_LIST_DEFAULT < 4) ? gEeprom.SCANLIST_PRIORITY_CH1[gEeprom.SCAN_LIST_DEFAULT - 1] : -1; - const int chan2 = (gEeprom.SCAN_LIST_DEFAULT > 0 && gEeprom.SCAN_LIST_DEFAULT < 4) ? gEeprom.SCANLIST_PRIORITY_CH2[gEeprom.SCAN_LIST_DEFAULT - 1] : -1; - const unsigned int prev_chan = gNextMrChannel; - unsigned int chan = 0; - - //char str[64] = ""; - - if (enabled) - { - switch (currentScanList) - { - case SCAN_NEXT_CHAN_SCANLIST1: - prev_mr_chan = gNextMrChannel; - - //sprintf(str, "-> Chan1 %d\n", chan1 + 1); - //LogUart(str); - - if (chan1 >= 0) - { - if (RADIO_CheckValidChannel(chan1, false, gEeprom.SCAN_LIST_DEFAULT)) - { - currentScanList = SCAN_NEXT_CHAN_SCANLIST1; - gNextMrChannel = chan1; - break; - } - } - - [[fallthrough]]; - case SCAN_NEXT_CHAN_SCANLIST2: - - //sprintf(str, "-> Chan2 %d\n", chan2 + 1); - //LogUart(str); - - if (chan2 >= 0) - { - if (RADIO_CheckValidChannel(chan2, false, gEeprom.SCAN_LIST_DEFAULT)) - { - currentScanList = SCAN_NEXT_CHAN_SCANLIST2; - gNextMrChannel = chan2; - break; - } - } - - [[fallthrough]]; - /* - case SCAN_NEXT_CHAN_SCANLIST3: - if (chan3 >= 0) - { - if (RADIO_CheckValidChannel(chan3, false, 0)) - { - currentScanList = SCAN_NEXT_CHAN_SCANLIST3; - gNextMrChannel = chan3; - break; - } - } - [[fallthrough]]; - */ - // this bit doesn't yet work if the other VFO is a frequency - case SCAN_NEXT_CHAN_DUAL_WATCH: - // dual watch is enabled - include the other VFO in the scan -// if (gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) -// { -// chan = (gEeprom.RX_VFO + 1) & 1u; -// chan = gEeprom.ScreenChannel[chan]; -// if (IS_MR_CHANNEL(chan)) -// { -// currentScanList = SCAN_NEXT_CHAN_DUAL_WATCH; -// gNextMrChannel = chan; -// break; -// } -// } - - default: - case SCAN_NEXT_CHAN_MR: - currentScanList = SCAN_NEXT_CHAN_MR; - gNextMrChannel = prev_mr_chan; - chan = 0xff; - break; - } - } - - if (!enabled || chan == 0xff) - { - chan = RADIO_FindNextChannel(gNextMrChannel + gScanStateDir, gScanStateDir, true, gEeprom.SCAN_LIST_DEFAULT); - if (chan == 0xFF) - { // no valid channel found - chan = MR_CHANNEL_FIRST; - } - - gNextMrChannel = chan; - - //sprintf(str, "----> Chan %d\n", chan + 1); - //LogUart(str); - } - - if (gNextMrChannel != prev_chan) - { - gEeprom.MrChannel[ gEeprom.RX_VFO] = gNextMrChannel; - gEeprom.ScreenChannel[gEeprom.RX_VFO] = gNextMrChannel; - - RADIO_ConfigureChannel(gEeprom.RX_VFO, VFO_CONFIGURE_RELOAD); - RADIO_SetupRegisters(true); - - gUpdateDisplay = true; - } + static unsigned int prev_mr_chan = 0; + const bool enabled = (gEeprom.SCAN_LIST_DEFAULT > 0 && gEeprom.SCAN_LIST_DEFAULT < 4) ? gEeprom.SCAN_LIST_ENABLED[gEeprom.SCAN_LIST_DEFAULT - 1] : true; + const int chan1 = (gEeprom.SCAN_LIST_DEFAULT > 0 && gEeprom.SCAN_LIST_DEFAULT < 4) ? gEeprom.SCANLIST_PRIORITY_CH1[gEeprom.SCAN_LIST_DEFAULT - 1] : -1; + const int chan2 = (gEeprom.SCAN_LIST_DEFAULT > 0 && gEeprom.SCAN_LIST_DEFAULT < 4) ? gEeprom.SCANLIST_PRIORITY_CH2[gEeprom.SCAN_LIST_DEFAULT - 1] : -1; + const unsigned int prev_chan = gNextMrChannel; + unsigned int chan = 0; + + //char str[64] = ""; + + if (enabled) + { + switch (currentScanList) + { + case SCAN_NEXT_CHAN_SCANLIST1: + prev_mr_chan = gNextMrChannel; + + //sprintf(str, "-> Chan1 %d\n", chan1 + 1); + //LogUart(str); + + if (chan1 >= 0) + { + if (RADIO_CheckValidChannel(chan1, false, gEeprom.SCAN_LIST_DEFAULT)) + { + currentScanList = SCAN_NEXT_CHAN_SCANLIST1; + gNextMrChannel = chan1; + break; + } + } + + [[fallthrough]]; + case SCAN_NEXT_CHAN_SCANLIST2: + + //sprintf(str, "-> Chan2 %d\n", chan2 + 1); + //LogUart(str); + + if (chan2 >= 0) + { + if (RADIO_CheckValidChannel(chan2, false, gEeprom.SCAN_LIST_DEFAULT)) + { + currentScanList = SCAN_NEXT_CHAN_SCANLIST2; + gNextMrChannel = chan2; + break; + } + } + + [[fallthrough]]; + /* + case SCAN_NEXT_CHAN_SCANLIST3: + if (chan3 >= 0) + { + if (RADIO_CheckValidChannel(chan3, false, 0)) + { + currentScanList = SCAN_NEXT_CHAN_SCANLIST3; + gNextMrChannel = chan3; + break; + } + } + [[fallthrough]]; + */ + // this bit doesn't yet work if the other VFO is a frequency + case SCAN_NEXT_CHAN_DUAL_WATCH: + // dual watch is enabled - include the other VFO in the scan +// if (gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) +// { +// chan = (gEeprom.RX_VFO + 1) & 1u; +// chan = gEeprom.ScreenChannel[chan]; +// if (IS_MR_CHANNEL(chan)) +// { +// currentScanList = SCAN_NEXT_CHAN_DUAL_WATCH; +// gNextMrChannel = chan; +// break; +// } +// } + + default: + case SCAN_NEXT_CHAN_MR: + currentScanList = SCAN_NEXT_CHAN_MR; + gNextMrChannel = prev_mr_chan; + chan = 0xff; + break; + } + } + + if (!enabled || chan == 0xff) + { + chan = RADIO_FindNextChannel(gNextMrChannel + gScanStateDir, gScanStateDir, true, gEeprom.SCAN_LIST_DEFAULT); + if (chan == 0xFF) + { // no valid channel found + chan = MR_CHANNEL_FIRST; + } + + gNextMrChannel = chan; + + //sprintf(str, "----> Chan %d\n", chan + 1); + //LogUart(str); + } + + if (gNextMrChannel != prev_chan) + { + gEeprom.MrChannel[ gEeprom.RX_VFO] = gNextMrChannel; + gEeprom.ScreenChannel[gEeprom.RX_VFO] = gNextMrChannel; + + RADIO_ConfigureChannel(gEeprom.RX_VFO, VFO_CONFIGURE_RELOAD); + RADIO_SetupRegisters(true); + + gUpdateDisplay = true; + } #ifdef ENABLE_FASTER_CHANNEL_SCAN - gScanPauseDelayIn_10ms = 9; // 90ms .. <= ~60ms it misses signals (squelch response and/or PLL lock time) ? + gScanPauseDelayIn_10ms = 9; // 90ms .. <= ~60ms it misses signals (squelch response and/or PLL lock time) ? #else - gScanPauseDelayIn_10ms = scan_pause_delay_in_3_10ms; + gScanPauseDelayIn_10ms = scan_pause_delay_in_3_10ms; #endif - if (enabled) - if (++currentScanList >= SCAN_NEXT_NUM) - currentScanList = SCAN_NEXT_CHAN_SCANLIST1; // back round we go + if (enabled) + if (++currentScanList >= SCAN_NEXT_NUM) + currentScanList = SCAN_NEXT_CHAN_SCANLIST1; // back round we go } diff --git a/app/chFrScanner.h b/app/chFrScanner.h index 484b726ae..1b425627f 100644 --- a/app/chFrScanner.h +++ b/app/chFrScanner.h @@ -21,8 +21,8 @@ void CHFRSCANNER_Start(const bool storeBackupSettings, const int8_t scan_directi void CHFRSCANNER_ContinueScanning(void); #ifdef ENABLE_FEAT_F4HWN - extern uint32_t lastFoundFrqOrChan; - extern uint32_t lastFoundFrqOrChanOld; + extern uint32_t lastFoundFrqOrChan; + extern uint32_t lastFoundFrqOrChanOld; #endif #endif \ No newline at end of file diff --git a/app/common.c b/app/common.c index 4265dfa35..8bc2168c5 100644 --- a/app/common.c +++ b/app/common.c @@ -10,7 +10,7 @@ void COMMON_KeypadLockToggle() if (gScreenToDisplay != DISPLAY_MENU && gCurrentFunction != FUNCTION_TRANSMIT) - { // toggle the keyboad lock + { // toggle the keyboad lock #ifdef ENABLE_VOICE gAnotherVoiceID = gEeprom.KEY_LOCK ? VOICE_ID_UNLOCK : VOICE_ID_LOCK; @@ -50,7 +50,7 @@ void COMMON_SwitchVFOMode() #endif { if (IS_MR_CHANNEL(gTxVfo->CHANNEL_SAVE)) - { // swap to frequency mode + { // swap to frequency mode gEeprom.ScreenChannel[gEeprom.TX_VFO] = gEeprom.FreqChannel[gEeprom.TX_VFO]; #ifdef ENABLE_VOICE gAnotherVoiceID = VOICE_ID_FREQUENCY_MODE; @@ -62,7 +62,7 @@ void COMMON_SwitchVFOMode() uint8_t Channel = RADIO_FindNextChannel(gEeprom.MrChannel[gEeprom.TX_VFO], 1, false, 0); if (Channel != 0xFF) - { // swap to channel mode + { // swap to channel mode gEeprom.ScreenChannel[gEeprom.TX_VFO] = Channel; #ifdef ENABLE_VOICE AUDIO_SetVoiceID(0, VOICE_ID_CHANNEL_MODE); diff --git a/app/dtmf.c b/app/dtmf.c index 7376b967c..91b5868eb 100644 --- a/app/dtmf.c +++ b/app/dtmf.c @@ -19,7 +19,7 @@ #include "app/chFrScanner.h" #ifdef ENABLE_FMRADIO - #include "app/fm.h" + #include "app/fm.h" #endif #include "app/scanner.h" #include "bsp/dp32g030/gpio.h" @@ -71,429 +71,429 @@ DTMF_ReplyState_t gDTMF_ReplyState; #ifdef ENABLE_DTMF_CALLING void DTMF_clear_RX(void) { - gDTMF_RX_timeout = 0; - gDTMF_RX_index = 0; - gDTMF_RX_pending = false; - memset(gDTMF_RX, 0, sizeof(gDTMF_RX)); + gDTMF_RX_timeout = 0; + gDTMF_RX_index = 0; + gDTMF_RX_pending = false; + memset(gDTMF_RX, 0, sizeof(gDTMF_RX)); } #endif void DTMF_SendEndOfTransmission(void) { - if (gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_APOLLO) { - BK4819_PlaySingleTone(2475, 250, 28, gEeprom.DTMF_SIDE_TONE); - } + if (gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_APOLLO) { + BK4819_PlaySingleTone(2475, 250, 28, gEeprom.DTMF_SIDE_TONE); + } - if ((gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_TX_DOWN || gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_BOTH) + if ((gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_TX_DOWN || gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_BOTH) #ifdef ENABLE_DTMF_CALLING - && gDTMF_CallState == DTMF_CALL_STATE_NONE + && gDTMF_CallState == DTMF_CALL_STATE_NONE #endif - ) { // end-of-tx - if (gEeprom.DTMF_SIDE_TONE) { - AUDIO_AudioPathOn(); - gEnableSpeaker = true; - SYSTEM_DelayMs(60); - } - - BK4819_EnterDTMF_TX(gEeprom.DTMF_SIDE_TONE); - - BK4819_PlayDTMFString( - gEeprom.DTMF_DOWN_CODE, - 0, - gEeprom.DTMF_FIRST_CODE_PERSIST_TIME, - gEeprom.DTMF_HASH_CODE_PERSIST_TIME, - gEeprom.DTMF_CODE_PERSIST_TIME, - gEeprom.DTMF_CODE_INTERVAL_TIME); - - AUDIO_AudioPathOff(); - gEnableSpeaker = false; - } - - BK4819_ExitDTMF_TX(true); + ) { // end-of-tx + if (gEeprom.DTMF_SIDE_TONE) { + AUDIO_AudioPathOn(); + gEnableSpeaker = true; + SYSTEM_DelayMs(60); + } + + BK4819_EnterDTMF_TX(gEeprom.DTMF_SIDE_TONE); + + BK4819_PlayDTMFString( + gEeprom.DTMF_DOWN_CODE, + 0, + gEeprom.DTMF_FIRST_CODE_PERSIST_TIME, + gEeprom.DTMF_HASH_CODE_PERSIST_TIME, + gEeprom.DTMF_CODE_PERSIST_TIME, + gEeprom.DTMF_CODE_INTERVAL_TIME); + + AUDIO_AudioPathOff(); + gEnableSpeaker = false; + } + + BK4819_ExitDTMF_TX(true); } bool DTMF_ValidateCodes(char *pCode, const unsigned int size) { - unsigned int i; + unsigned int i; - if (pCode[0] == 0xFF || pCode[0] == 0) - return false; + if (pCode[0] == 0xFF || pCode[0] == 0) + return false; - for (i = 0; i < size; i++) - { - if (pCode[i] == 0xFF || pCode[i] == 0) - { - pCode[i] = 0; - break; - } + for (i = 0; i < size; i++) + { + if (pCode[i] == 0xFF || pCode[i] == 0) + { + pCode[i] = 0; + break; + } - if ((pCode[i] < '0' || pCode[i] > '9') && (pCode[i] < 'A' || pCode[i] > 'D') && pCode[i] != '*' && pCode[i] != '#') - return false; - } + if ((pCode[i] < '0' || pCode[i] > '9') && (pCode[i] < 'A' || pCode[i] > 'D') && pCode[i] != '*' && pCode[i] != '#') + return false; + } - return true; + return true; } #ifdef ENABLE_DTMF_CALLING bool DTMF_GetContact(const int Index, char *pContact) { - if (Index < 0 || Index >= MAX_DTMF_CONTACTS || pContact == NULL) { - return false; - } + if (Index < 0 || Index >= MAX_DTMF_CONTACTS || pContact == NULL) { + return false; + } - EEPROM_ReadBuffer(0x1C00 + (Index * 16), pContact, 16); + EEPROM_ReadBuffer(0x1C00 + (Index * 16), pContact, 16); - // check whether the first character is printable or not - return (pContact[0] >= ' ' && pContact[0] < 127); + // check whether the first character is printable or not + return (pContact[0] >= ' ' && pContact[0] < 127); } bool DTMF_FindContact(const char *pContact, char *pResult) { - pResult[0] = 0; - - for (unsigned int i = 0; i < MAX_DTMF_CONTACTS; i++) { - char Contact[16]; - if (!DTMF_GetContact(i, Contact)) { - return false; - } - - if (memcmp(pContact, Contact + 8, 3) == 0) { - memcpy(pResult, Contact, 8); - pResult[8] = 0; - return true; - } - } - - return false; + pResult[0] = 0; + + for (unsigned int i = 0; i < MAX_DTMF_CONTACTS; i++) { + char Contact[16]; + if (!DTMF_GetContact(i, Contact)) { + return false; + } + + if (memcmp(pContact, Contact + 8, 3) == 0) { + memcpy(pResult, Contact, 8); + pResult[8] = 0; + return true; + } + } + + return false; } #endif char DTMF_GetCharacter(const unsigned int code) { - if (code <= KEY_9) - return '0' + code; - - switch (code) - { - case KEY_MENU: return 'A'; - case KEY_UP: return 'B'; - case KEY_DOWN: return 'C'; - case KEY_EXIT: return 'D'; - case KEY_STAR: return '*'; - case KEY_F: return '#'; - default: return 0xff; - } + if (code <= KEY_9) + return '0' + code; + + switch (code) + { + case KEY_MENU: return 'A'; + case KEY_UP: return 'B'; + case KEY_DOWN: return 'C'; + case KEY_EXIT: return 'D'; + case KEY_STAR: return '*'; + case KEY_F: return '#'; + default: return 0xff; + } } #ifdef ENABLE_DTMF_CALLING static bool CompareMessage(const char *pMsg, const char *pTemplate, const unsigned int size, const bool bCheckGroup) { - unsigned int i; - for (i = 0; i < size; i++) - { - if (pMsg[i] != pTemplate[i]) - { - if (!bCheckGroup || pMsg[i] != gEeprom.DTMF_GROUP_CALL_CODE) - return false; - gDTMF_IsGroupCall = true; - } - } - - return true; + unsigned int i; + for (i = 0; i < size; i++) + { + if (pMsg[i] != pTemplate[i]) + { + if (!bCheckGroup || pMsg[i] != gEeprom.DTMF_GROUP_CALL_CODE) + return false; + gDTMF_IsGroupCall = true; + } + } + + return true; } DTMF_CallMode_t DTMF_CheckGroupCall(const char *pMsg, const unsigned int size) { - for (unsigned int i = 0; i < size; i++) - if (pMsg[i] == gEeprom.DTMF_GROUP_CALL_CODE) { - return DTMF_CALL_MODE_GROUP; - } + for (unsigned int i = 0; i < size; i++) + if (pMsg[i] == gEeprom.DTMF_GROUP_CALL_CODE) { + return DTMF_CALL_MODE_GROUP; + } - return DTMF_CALL_MODE_NOT_GROUP; + return DTMF_CALL_MODE_NOT_GROUP; } #endif void DTMF_clear_input_box(void) { - memset(gDTMF_InputBox, 0, sizeof(gDTMF_InputBox)); - gDTMF_InputBox_Index = 0; - gDTMF_InputMode = false; + memset(gDTMF_InputBox, 0, sizeof(gDTMF_InputBox)); + gDTMF_InputBox_Index = 0; + gDTMF_InputMode = false; } void DTMF_Append(const char code) { - if (gDTMF_InputBox_Index == 0) - { - memset(gDTMF_InputBox, '-', sizeof(gDTMF_InputBox) - 1); - gDTMF_InputBox[sizeof(gDTMF_InputBox) - 1] = 0; - } - - if (gDTMF_InputBox_Index < (sizeof(gDTMF_InputBox) - 1)) - gDTMF_InputBox[gDTMF_InputBox_Index++] = code; + if (gDTMF_InputBox_Index == 0) + { + memset(gDTMF_InputBox, '-', sizeof(gDTMF_InputBox) - 1); + gDTMF_InputBox[sizeof(gDTMF_InputBox) - 1] = 0; + } + + if (gDTMF_InputBox_Index < (sizeof(gDTMF_InputBox) - 1)) + gDTMF_InputBox[gDTMF_InputBox_Index++] = code; } #ifdef ENABLE_DTMF_CALLING void DTMF_HandleRequest(void) -{ // proccess the RX'ed DTMF characters +{ // proccess the RX'ed DTMF characters - char String[21]; - unsigned int Offset; + char String[21]; + unsigned int Offset; - if (!gDTMF_RX_pending) - return; // nothing new received + if (!gDTMF_RX_pending) + return; // nothing new received - if (gScanStateDir != SCAN_OFF || gCssBackgroundScan) - { // we're busy scanning - DTMF_clear_RX(); - return; - } + if (gScanStateDir != SCAN_OFF || gCssBackgroundScan) + { // we're busy scanning + DTMF_clear_RX(); + return; + } - if (!gRxVfo->DTMF_DECODING_ENABLE && !gSetting_KILLED) - { // D-DCD is disabled or we're alive - DTMF_clear_RX(); - return; - } + if (!gRxVfo->DTMF_DECODING_ENABLE && !gSetting_KILLED) + { // D-DCD is disabled or we're alive + DTMF_clear_RX(); + return; + } - gDTMF_RX_pending = false; + gDTMF_RX_pending = false; - if (gDTMF_RX_index >= 9) - { // look for the KILL code + if (gDTMF_RX_index >= 9) + { // look for the KILL code - sprintf(String, "%s%c%s", gEeprom.ANI_DTMF_ID, gEeprom.DTMF_SEPARATE_CODE, gEeprom.KILL_CODE); + sprintf(String, "%s%c%s", gEeprom.ANI_DTMF_ID, gEeprom.DTMF_SEPARATE_CODE, gEeprom.KILL_CODE); - Offset = gDTMF_RX_index - strlen(String); + Offset = gDTMF_RX_index - strlen(String); - if (CompareMessage(gDTMF_RX + Offset, String, strlen(String), true)) - { // bugger + if (CompareMessage(gDTMF_RX + Offset, String, strlen(String), true)) + { // bugger - if (gEeprom.PERMIT_REMOTE_KILL) - { - gSetting_KILLED = true; // oooerr ! + if (gEeprom.PERMIT_REMOTE_KILL) + { + gSetting_KILLED = true; // oooerr ! - DTMF_clear_RX(); + DTMF_clear_RX(); - SETTINGS_SaveSettings(); + SETTINGS_SaveSettings(); - gDTMF_ReplyState = DTMF_REPLY_AB; + gDTMF_ReplyState = DTMF_REPLY_AB; - #ifdef ENABLE_FMRADIO - if (gFmRadioMode) - { - FM_TurnOff(); - GUI_SelectNextDisplay(DISPLAY_MAIN); - } - #endif - } - else - { - gDTMF_ReplyState = DTMF_REPLY_NONE; - } + #ifdef ENABLE_FMRADIO + if (gFmRadioMode) + { + FM_TurnOff(); + GUI_SelectNextDisplay(DISPLAY_MAIN); + } + #endif + } + else + { + gDTMF_ReplyState = DTMF_REPLY_NONE; + } - gDTMF_CallState = DTMF_CALL_STATE_NONE; + gDTMF_CallState = DTMF_CALL_STATE_NONE; - gUpdateDisplay = true; - gUpdateStatus = true; - return; - } - } + gUpdateDisplay = true; + gUpdateStatus = true; + return; + } + } - if (gDTMF_RX_index >= 9) - { // look for the REVIVE code + if (gDTMF_RX_index >= 9) + { // look for the REVIVE code - sprintf(String, "%s%c%s", gEeprom.ANI_DTMF_ID, gEeprom.DTMF_SEPARATE_CODE, gEeprom.REVIVE_CODE); + sprintf(String, "%s%c%s", gEeprom.ANI_DTMF_ID, gEeprom.DTMF_SEPARATE_CODE, gEeprom.REVIVE_CODE); - Offset = gDTMF_RX_index - strlen(String); + Offset = gDTMF_RX_index - strlen(String); - if (CompareMessage(gDTMF_RX + Offset, String, strlen(String), true)) - { // shit, we're back ! + if (CompareMessage(gDTMF_RX + Offset, String, strlen(String), true)) + { // shit, we're back ! - gSetting_KILLED = false; + gSetting_KILLED = false; - DTMF_clear_RX(); + DTMF_clear_RX(); - SETTINGS_SaveSettings(); + SETTINGS_SaveSettings(); - gDTMF_ReplyState = DTMF_REPLY_AB; - gDTMF_CallState = DTMF_CALL_STATE_NONE; + gDTMF_ReplyState = DTMF_REPLY_AB; + gDTMF_CallState = DTMF_CALL_STATE_NONE; - gUpdateDisplay = true; - gUpdateStatus = true; - return; - } - } + gUpdateDisplay = true; + gUpdateStatus = true; + return; + } + } - if (gDTMF_RX_index >= 2) - { // look for ACK reply - char *pPrintStr = "AB"; + if (gDTMF_RX_index >= 2) + { // look for ACK reply + char *pPrintStr = "AB"; - Offset = gDTMF_RX_index - strlen(pPrintStr); + Offset = gDTMF_RX_index - strlen(pPrintStr); - if (CompareMessage(gDTMF_RX + Offset, pPrintStr, strlen(pPrintStr), true)) { - // ends with "AB" + if (CompareMessage(gDTMF_RX + Offset, pPrintStr, strlen(pPrintStr), true)) { + // ends with "AB" - if (gDTMF_ReplyState != DTMF_REPLY_NONE) // 1of11 -// if (gDTMF_CallState != DTMF_CALL_STATE_NONE) // 1of11 -// if (gDTMF_CallState == DTMF_CALL_STATE_CALL_OUT) // 1of11 - { - gDTMF_State = DTMF_STATE_TX_SUCC; - DTMF_clear_RX(); - gUpdateDisplay = true; - return; - } - } - } + if (gDTMF_ReplyState != DTMF_REPLY_NONE) // 1of11 +// if (gDTMF_CallState != DTMF_CALL_STATE_NONE) // 1of11 +// if (gDTMF_CallState == DTMF_CALL_STATE_CALL_OUT) // 1of11 + { + gDTMF_State = DTMF_STATE_TX_SUCC; + DTMF_clear_RX(); + gUpdateDisplay = true; + return; + } + } + } - if (gDTMF_CallState == DTMF_CALL_STATE_CALL_OUT && - gDTMF_CallMode == DTMF_CALL_MODE_NOT_GROUP && - gDTMF_RX_index >= 9) - { // waiting for a reply + if (gDTMF_CallState == DTMF_CALL_STATE_CALL_OUT && + gDTMF_CallMode == DTMF_CALL_MODE_NOT_GROUP && + gDTMF_RX_index >= 9) + { // waiting for a reply - sprintf(String, "%s%c%s", gDTMF_String, gEeprom.DTMF_SEPARATE_CODE, "AAAAA"); + sprintf(String, "%s%c%s", gDTMF_String, gEeprom.DTMF_SEPARATE_CODE, "AAAAA"); - Offset = gDTMF_RX_index - strlen(String); + Offset = gDTMF_RX_index - strlen(String); - if (CompareMessage(gDTMF_RX + Offset, String, strlen(String), false)) - { // we got a response - gDTMF_State = DTMF_STATE_CALL_OUT_RSP; - DTMF_clear_RX(); - gUpdateDisplay = true; - } - } + if (CompareMessage(gDTMF_RX + Offset, String, strlen(String), false)) + { // we got a response + gDTMF_State = DTMF_STATE_CALL_OUT_RSP; + DTMF_clear_RX(); + gUpdateDisplay = true; + } + } - if (gSetting_KILLED || gDTMF_CallState != DTMF_CALL_STATE_NONE) - { // we've been killed or expecting a reply - return; - } + if (gSetting_KILLED || gDTMF_CallState != DTMF_CALL_STATE_NONE) + { // we've been killed or expecting a reply + return; + } - if (gDTMF_RX_index >= 7) - { // see if we're being called + if (gDTMF_RX_index >= 7) + { // see if we're being called - gDTMF_IsGroupCall = false; + gDTMF_IsGroupCall = false; - sprintf(String, "%s%c", gEeprom.ANI_DTMF_ID, gEeprom.DTMF_SEPARATE_CODE); + sprintf(String, "%s%c", gEeprom.ANI_DTMF_ID, gEeprom.DTMF_SEPARATE_CODE); - Offset = gDTMF_RX_index - strlen(String) - 3; - - if (CompareMessage(gDTMF_RX + Offset, String, strlen(String), true)) - { // it's for us ! - - gDTMF_CallState = DTMF_CALL_STATE_RECEIVED; - - memset(gDTMF_Callee, 0, sizeof(gDTMF_Callee)); - memset(gDTMF_Caller, 0, sizeof(gDTMF_Caller)); - memcpy(gDTMF_Callee, gDTMF_RX + Offset + 0, 3); - memcpy(gDTMF_Caller, gDTMF_RX + Offset + 4, 3); + Offset = gDTMF_RX_index - strlen(String) - 3; + + if (CompareMessage(gDTMF_RX + Offset, String, strlen(String), true)) + { // it's for us ! + + gDTMF_CallState = DTMF_CALL_STATE_RECEIVED; + + memset(gDTMF_Callee, 0, sizeof(gDTMF_Callee)); + memset(gDTMF_Caller, 0, sizeof(gDTMF_Caller)); + memcpy(gDTMF_Callee, gDTMF_RX + Offset + 0, 3); + memcpy(gDTMF_Caller, gDTMF_RX + Offset + 4, 3); - DTMF_clear_RX(); + DTMF_clear_RX(); - gUpdateDisplay = true; + gUpdateDisplay = true; - switch (gEeprom.DTMF_DECODE_RESPONSE) - { - case DTMF_DEC_RESPONSE_BOTH: - gDTMF_DecodeRingCountdown_500ms = DTMF_decode_ring_countdown_500ms; - [[fallthrough]]; - case DTMF_DEC_RESPONSE_REPLY: - gDTMF_ReplyState = DTMF_REPLY_AAAAA; - break; - case DTMF_DEC_RESPONSE_RING: - gDTMF_DecodeRingCountdown_500ms = DTMF_decode_ring_countdown_500ms; - break; - default: - case DTMF_DEC_RESPONSE_NONE: - gDTMF_DecodeRingCountdown_500ms = 0; - gDTMF_ReplyState = DTMF_REPLY_NONE; - break; - } - - if (gDTMF_IsGroupCall) - gDTMF_ReplyState = DTMF_REPLY_NONE; - } - } + switch (gEeprom.DTMF_DECODE_RESPONSE) + { + case DTMF_DEC_RESPONSE_BOTH: + gDTMF_DecodeRingCountdown_500ms = DTMF_decode_ring_countdown_500ms; + [[fallthrough]]; + case DTMF_DEC_RESPONSE_REPLY: + gDTMF_ReplyState = DTMF_REPLY_AAAAA; + break; + case DTMF_DEC_RESPONSE_RING: + gDTMF_DecodeRingCountdown_500ms = DTMF_decode_ring_countdown_500ms; + break; + default: + case DTMF_DEC_RESPONSE_NONE: + gDTMF_DecodeRingCountdown_500ms = 0; + gDTMF_ReplyState = DTMF_REPLY_NONE; + break; + } + + if (gDTMF_IsGroupCall) + gDTMF_ReplyState = DTMF_REPLY_NONE; + } + } } #endif void DTMF_Reply(void) { - uint16_t Delay; + uint16_t Delay; #ifdef ENABLE_DTMF_CALLING - char String[23]; + char String[23]; #endif - const char *pString = NULL; + const char *pString = NULL; - switch (gDTMF_ReplyState) - { - case DTMF_REPLY_ANI: + switch (gDTMF_ReplyState) + { + case DTMF_REPLY_ANI: #ifdef ENABLE_DTMF_CALLING - if (gDTMF_CallMode != DTMF_CALL_MODE_DTMF) - { // append our ID code onto the end of the DTMF code to send - sprintf(String, "%s%c%s", gDTMF_String, gEeprom.DTMF_SEPARATE_CODE, gEeprom.ANI_DTMF_ID); - pString = String; - } - else + if (gDTMF_CallMode != DTMF_CALL_MODE_DTMF) + { // append our ID code onto the end of the DTMF code to send + sprintf(String, "%s%c%s", gDTMF_String, gEeprom.DTMF_SEPARATE_CODE, gEeprom.ANI_DTMF_ID); + pString = String; + } + else #endif - { - pString = gDTMF_String; - } + { + pString = gDTMF_String; + } - break; + break; #ifdef ENABLE_DTMF_CALLING - case DTMF_REPLY_AB: - pString = "AB"; - break; - - case DTMF_REPLY_AAAAA: - sprintf(String, "%s%c%s", gEeprom.ANI_DTMF_ID, gEeprom.DTMF_SEPARATE_CODE, "AAAAA"); - pString = String; - break; + case DTMF_REPLY_AB: + pString = "AB"; + break; + + case DTMF_REPLY_AAAAA: + sprintf(String, "%s%c%s", gEeprom.ANI_DTMF_ID, gEeprom.DTMF_SEPARATE_CODE, "AAAAA"); + pString = String; + break; #endif - default: - case DTMF_REPLY_NONE: - if ( + default: + case DTMF_REPLY_NONE: + if ( #ifdef ENABLE_DTMF_CALLING - gDTMF_CallState != DTMF_CALL_STATE_NONE || + gDTMF_CallState != DTMF_CALL_STATE_NONE || #endif - gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_APOLLO || - gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_OFF || - gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_TX_DOWN) - { - gDTMF_ReplyState = DTMF_REPLY_NONE; - return; - } + gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_APOLLO || + gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_OFF || + gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_TX_DOWN) + { + gDTMF_ReplyState = DTMF_REPLY_NONE; + return; + } - // send TX-UP DTMF - pString = gEeprom.DTMF_UP_CODE; - break; - } + // send TX-UP DTMF + pString = gEeprom.DTMF_UP_CODE; + break; + } - gDTMF_ReplyState = DTMF_REPLY_NONE; + gDTMF_ReplyState = DTMF_REPLY_NONE; - if (pString == NULL) - return; + if (pString == NULL) + return; - Delay = (gEeprom.DTMF_PRELOAD_TIME < 200) ? 200 : gEeprom.DTMF_PRELOAD_TIME; + Delay = (gEeprom.DTMF_PRELOAD_TIME < 200) ? 200 : gEeprom.DTMF_PRELOAD_TIME; - if (gEeprom.DTMF_SIDE_TONE) - { // the user will also hear the transmitted tones - AUDIO_AudioPathOn(); - gEnableSpeaker = true; - } + if (gEeprom.DTMF_SIDE_TONE) + { // the user will also hear the transmitted tones + AUDIO_AudioPathOn(); + gEnableSpeaker = true; + } - SYSTEM_DelayMs(Delay); + SYSTEM_DelayMs(Delay); - BK4819_EnterDTMF_TX(gEeprom.DTMF_SIDE_TONE); + BK4819_EnterDTMF_TX(gEeprom.DTMF_SIDE_TONE); - BK4819_PlayDTMFString( - pString, - 1, - gEeprom.DTMF_FIRST_CODE_PERSIST_TIME, - gEeprom.DTMF_HASH_CODE_PERSIST_TIME, - gEeprom.DTMF_CODE_PERSIST_TIME, - gEeprom.DTMF_CODE_INTERVAL_TIME); + BK4819_PlayDTMFString( + pString, + 1, + gEeprom.DTMF_FIRST_CODE_PERSIST_TIME, + gEeprom.DTMF_HASH_CODE_PERSIST_TIME, + gEeprom.DTMF_CODE_PERSIST_TIME, + gEeprom.DTMF_CODE_INTERVAL_TIME); - AUDIO_AudioPathOff(); + AUDIO_AudioPathOff(); - gEnableSpeaker = false; + gEnableSpeaker = false; - BK4819_ExitDTMF_TX(false); + BK4819_ExitDTMF_TX(false); } diff --git a/app/dtmf.h b/app/dtmf.h index 8e112b355..0e513838a 100644 --- a/app/dtmf.h +++ b/app/dtmf.h @@ -23,47 +23,47 @@ #define MAX_DTMF_CONTACTS 16 enum DTMF_State_t { - DTMF_STATE_0 = 0, - DTMF_STATE_TX_SUCC, - DTMF_STATE_CALL_OUT_RSP + DTMF_STATE_0 = 0, + DTMF_STATE_TX_SUCC, + DTMF_STATE_CALL_OUT_RSP }; typedef enum DTMF_State_t DTMF_State_t; enum DTMF_CallState_t { - DTMF_CALL_STATE_NONE = 0, - DTMF_CALL_STATE_CALL_OUT, - DTMF_CALL_STATE_RECEIVED, - DTMF_CALL_STATE_RECEIVED_STAY + DTMF_CALL_STATE_NONE = 0, + DTMF_CALL_STATE_CALL_OUT, + DTMF_CALL_STATE_RECEIVED, + DTMF_CALL_STATE_RECEIVED_STAY }; enum DTMF_DecodeResponse_t { - DTMF_DEC_RESPONSE_NONE = 0, - DTMF_DEC_RESPONSE_RING, - DTMF_DEC_RESPONSE_REPLY, - DTMF_DEC_RESPONSE_BOTH + DTMF_DEC_RESPONSE_NONE = 0, + DTMF_DEC_RESPONSE_RING, + DTMF_DEC_RESPONSE_REPLY, + DTMF_DEC_RESPONSE_BOTH }; typedef enum DTMF_CallState_t DTMF_CallState_t; enum DTMF_ReplyState_t { - DTMF_REPLY_NONE = 0, - DTMF_REPLY_ANI, - DTMF_REPLY_AB, - DTMF_REPLY_AAAAA + DTMF_REPLY_NONE = 0, + DTMF_REPLY_ANI, + DTMF_REPLY_AB, + DTMF_REPLY_AAAAA }; typedef enum DTMF_ReplyState_t DTMF_ReplyState_t; enum DTMF_CallMode_t { - DTMF_CALL_MODE_NOT_GROUP = 0, - DTMF_CALL_MODE_GROUP, - DTMF_CALL_MODE_DTMF + DTMF_CALL_MODE_NOT_GROUP = 0, + DTMF_CALL_MODE_GROUP, + DTMF_CALL_MODE_DTMF }; enum { // seconds - DTMF_HOLD_MIN = 5, - DTMF_HOLD_MAX = 60 + DTMF_HOLD_MIN = 5, + DTMF_HOLD_MAX = 60 }; typedef enum DTMF_CallMode_t DTMF_CallMode_t; diff --git a/app/flashlight.c b/app/flashlight.c index 9cb94b9cf..28a48b958 100644 --- a/app/flashlight.c +++ b/app/flashlight.c @@ -6,78 +6,78 @@ #include "flashlight.h" #ifndef ENABLE_FEAT_F4HWN - enum FlashlightMode_t gFlashLightState; + enum FlashlightMode_t gFlashLightState; - void FlashlightTimeSlice() - { - if (gFlashLightState == FLASHLIGHT_BLINK && (gFlashLightBlinkCounter & 15u) == 0) { - GPIO_FlipBit(&GPIOC->DATA, GPIOC_PIN_FLASHLIGHT); - return; - } + void FlashlightTimeSlice() + { + if (gFlashLightState == FLASHLIGHT_BLINK && (gFlashLightBlinkCounter & 15u) == 0) { + GPIO_FlipBit(&GPIOC->DATA, GPIOC_PIN_FLASHLIGHT); + return; + } - if (gFlashLightState == FLASHLIGHT_SOS) { - const uint16_t u = 15; - static uint8_t c; - static uint16_t next; + if (gFlashLightState == FLASHLIGHT_SOS) { + const uint16_t u = 15; + static uint8_t c; + static uint16_t next; - if (gFlashLightBlinkCounter - next > 7 * u) { - c = 0; - next = gFlashLightBlinkCounter + 1; - return; - } + if (gFlashLightBlinkCounter - next > 7 * u) { + c = 0; + next = gFlashLightBlinkCounter + 1; + return; + } - if (gFlashLightBlinkCounter == next) { - if (c==0) { - GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_FLASHLIGHT); - } else { - GPIO_FlipBit(&GPIOC->DATA, GPIOC_PIN_FLASHLIGHT); - } + if (gFlashLightBlinkCounter == next) { + if (c==0) { + GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_FLASHLIGHT); + } else { + GPIO_FlipBit(&GPIOC->DATA, GPIOC_PIN_FLASHLIGHT); + } - if (c >= 18) { - next = gFlashLightBlinkCounter + 7 * u; - c = 0; - } else if(c==7 || c==9 || c==11) { - next = gFlashLightBlinkCounter + 3 * u; - } else { - next = gFlashLightBlinkCounter + u; - } - c++; - } - } - } + if (c >= 18) { + next = gFlashLightBlinkCounter + 7 * u; + c = 0; + } else if(c==7 || c==9 || c==11) { + next = gFlashLightBlinkCounter + 3 * u; + } else { + next = gFlashLightBlinkCounter + u; + } + c++; + } + } + } - void ACTION_FlashLight(void) - { - switch (gFlashLightState) { - case FLASHLIGHT_OFF: - gFlashLightState++; - GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_FLASHLIGHT); - break; - case FLASHLIGHT_ON: - case FLASHLIGHT_BLINK: - gFlashLightState++; - break; - case FLASHLIGHT_SOS: - default: - gFlashLightState = 0; - GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_FLASHLIGHT); - } - } + void ACTION_FlashLight(void) + { + switch (gFlashLightState) { + case FLASHLIGHT_OFF: + gFlashLightState++; + GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_FLASHLIGHT); + break; + case FLASHLIGHT_ON: + case FLASHLIGHT_BLINK: + gFlashLightState++; + break; + case FLASHLIGHT_SOS: + default: + gFlashLightState = 0; + GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_FLASHLIGHT); + } + } #else - void ACTION_FlashLight(void) - { - static bool gFlashLightState = false; + void ACTION_FlashLight(void) + { + static bool gFlashLightState = false; - if(gFlashLightState) - { - GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_FLASHLIGHT); - } - else - { - GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_FLASHLIGHT); - } + if(gFlashLightState) + { + GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_FLASHLIGHT); + } + else + { + GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_FLASHLIGHT); + } - gFlashLightState = (gFlashLightState) ? false : true; - } + gFlashLightState = (gFlashLightState) ? false : true; + } #endif #endif diff --git a/app/fm.c b/app/fm.c index d53a73149..248ad2cdf 100644 --- a/app/fm.c +++ b/app/fm.c @@ -33,7 +33,7 @@ #include "ui/ui.h" #ifndef ARRAY_SIZE - #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) + #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) #endif uint16_t gFM_Channels[20]; @@ -62,544 +62,544 @@ static void Key_FUNC(KEY_Code_t Key, uint8_t state); bool FM_CheckValidChannel(uint8_t Channel) { - return Channel < ARRAY_SIZE(gFM_Channels) && - gFM_Channels[Channel] >= BK1080_GetFreqLoLimit(gEeprom.FM_Band) && - gFM_Channels[Channel] < BK1080_GetFreqHiLimit(gEeprom.FM_Band); + return Channel < ARRAY_SIZE(gFM_Channels) && + gFM_Channels[Channel] >= BK1080_GetFreqLoLimit(gEeprom.FM_Band) && + gFM_Channels[Channel] < BK1080_GetFreqHiLimit(gEeprom.FM_Band); } uint8_t FM_FindNextChannel(uint8_t Channel, uint8_t Direction) { - for (unsigned i = 0; i < ARRAY_SIZE(gFM_Channels); i++) { - if (Channel == 0xFF) - Channel = ARRAY_SIZE(gFM_Channels) - 1; - else if (Channel >= ARRAY_SIZE(gFM_Channels)) - Channel = 0; - if (FM_CheckValidChannel(Channel)) - return Channel; - Channel += Direction; - } - - return 0xFF; + for (unsigned i = 0; i < ARRAY_SIZE(gFM_Channels); i++) { + if (Channel == 0xFF) + Channel = ARRAY_SIZE(gFM_Channels) - 1; + else if (Channel >= ARRAY_SIZE(gFM_Channels)) + Channel = 0; + if (FM_CheckValidChannel(Channel)) + return Channel; + Channel += Direction; + } + + return 0xFF; } int FM_ConfigureChannelState(void) { - gEeprom.FM_FrequencyPlaying = gEeprom.FM_SelectedFrequency; - - if (gEeprom.FM_IsMrMode) { - const uint8_t Channel = FM_FindNextChannel(gEeprom.FM_SelectedChannel, FM_CHANNEL_UP); - if (Channel == 0xFF) { - gEeprom.FM_IsMrMode = false; - return -1; - } - gEeprom.FM_SelectedChannel = Channel; - gEeprom.FM_FrequencyPlaying = gFM_Channels[Channel]; - } - - return 0; + gEeprom.FM_FrequencyPlaying = gEeprom.FM_SelectedFrequency; + + if (gEeprom.FM_IsMrMode) { + const uint8_t Channel = FM_FindNextChannel(gEeprom.FM_SelectedChannel, FM_CHANNEL_UP); + if (Channel == 0xFF) { + gEeprom.FM_IsMrMode = false; + return -1; + } + gEeprom.FM_SelectedChannel = Channel; + gEeprom.FM_FrequencyPlaying = gFM_Channels[Channel]; + } + + return 0; } void FM_TurnOff(void) { - gFmRadioMode = false; - gFM_ScanState = FM_SCAN_OFF; - gFM_RestoreCountdown_10ms = 0; + gFmRadioMode = false; + gFM_ScanState = FM_SCAN_OFF; + gFM_RestoreCountdown_10ms = 0; - AUDIO_AudioPathOff(); - gEnableSpeaker = false; + AUDIO_AudioPathOff(); + gEnableSpeaker = false; - BK1080_Init0(); + BK1080_Init0(); - gUpdateStatus = true; + gUpdateStatus = true; } void FM_EraseChannels(void) { - uint8_t Template[8]; - memset(Template, 0xFF, sizeof(Template)); + uint8_t Template[8]; + memset(Template, 0xFF, sizeof(Template)); - for (unsigned i = 0; i < 5; i++) - EEPROM_WriteBuffer(0x0E40 + (i * 8), Template); + for (unsigned i = 0; i < 5; i++) + EEPROM_WriteBuffer(0x0E40 + (i * 8), Template); - memset(gFM_Channels, 0xFF, sizeof(gFM_Channels)); + memset(gFM_Channels, 0xFF, sizeof(gFM_Channels)); } void FM_Tune(uint16_t Frequency, int8_t Step, bool bFlag) { - AUDIO_AudioPathOff(); + AUDIO_AudioPathOff(); - gEnableSpeaker = false; + gEnableSpeaker = false; - gFmPlayCountdown_10ms = (gFM_ScanState == FM_SCAN_OFF) ? fm_play_countdown_noscan_10ms : fm_play_countdown_scan_10ms; + gFmPlayCountdown_10ms = (gFM_ScanState == FM_SCAN_OFF) ? fm_play_countdown_noscan_10ms : fm_play_countdown_scan_10ms; - gScheduleFM = false; - gFM_FoundFrequency = false; - gAskToSave = false; - gAskToDelete = false; - gEeprom.FM_FrequencyPlaying = Frequency; + gScheduleFM = false; + gFM_FoundFrequency = false; + gAskToSave = false; + gAskToDelete = false; + gEeprom.FM_FrequencyPlaying = Frequency; - if (!bFlag) { - Frequency += Step; - if (Frequency < BK1080_GetFreqLoLimit(gEeprom.FM_Band)) - Frequency = BK1080_GetFreqHiLimit(gEeprom.FM_Band); - else if (Frequency > BK1080_GetFreqHiLimit(gEeprom.FM_Band)) - Frequency = BK1080_GetFreqLoLimit(gEeprom.FM_Band); + if (!bFlag) { + Frequency += Step; + if (Frequency < BK1080_GetFreqLoLimit(gEeprom.FM_Band)) + Frequency = BK1080_GetFreqHiLimit(gEeprom.FM_Band); + else if (Frequency > BK1080_GetFreqHiLimit(gEeprom.FM_Band)) + Frequency = BK1080_GetFreqLoLimit(gEeprom.FM_Band); - gEeprom.FM_FrequencyPlaying = Frequency; - } + gEeprom.FM_FrequencyPlaying = Frequency; + } - gFM_ScanState = Step; + gFM_ScanState = Step; - BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/); + BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/); } void FM_PlayAndUpdate(void) { - gFM_ScanState = FM_SCAN_OFF; + gFM_ScanState = FM_SCAN_OFF; - if (gFM_AutoScan) { - gEeprom.FM_IsMrMode = true; - gEeprom.FM_SelectedChannel = 0; - } + if (gFM_AutoScan) { + gEeprom.FM_IsMrMode = true; + gEeprom.FM_SelectedChannel = 0; + } - FM_ConfigureChannelState(); - BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/); - SETTINGS_SaveFM(); + FM_ConfigureChannelState(); + BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/); + SETTINGS_SaveFM(); - gFmPlayCountdown_10ms = 0; - gScheduleFM = false; - gAskToSave = false; + gFmPlayCountdown_10ms = 0; + gScheduleFM = false; + gAskToSave = false; - AUDIO_AudioPathOn(); + AUDIO_AudioPathOn(); - gEnableSpeaker = true; + gEnableSpeaker = true; } int FM_CheckFrequencyLock(uint16_t Frequency, uint16_t LowerLimit) { - int ret = -1; + int ret = -1; - const uint16_t Test2 = BK1080_ReadRegister(BK1080_REG_07); + const uint16_t Test2 = BK1080_ReadRegister(BK1080_REG_07); - // This is supposed to be a signed value, but above function is unsigned - const uint16_t Deviation = BK1080_REG_07_GET_FREQD(Test2); + // This is supposed to be a signed value, but above function is unsigned + const uint16_t Deviation = BK1080_REG_07_GET_FREQD(Test2); - if (BK1080_REG_07_GET_SNR(Test2) <= 2) { - goto Bail; - } + if (BK1080_REG_07_GET_SNR(Test2) <= 2) { + goto Bail; + } - const uint16_t Status = BK1080_ReadRegister(BK1080_REG_10); + const uint16_t Status = BK1080_ReadRegister(BK1080_REG_10); - if ((Status & BK1080_REG_10_MASK_AFCRL) != BK1080_REG_10_AFCRL_NOT_RAILED || BK1080_REG_10_GET_RSSI(Status) < 10) { - goto Bail; - } + if ((Status & BK1080_REG_10_MASK_AFCRL) != BK1080_REG_10_AFCRL_NOT_RAILED || BK1080_REG_10_GET_RSSI(Status) < 10) { + goto Bail; + } - //if (Deviation > -281 && Deviation < 280) - if (Deviation >= 280 && Deviation <= 3815) { - goto Bail; - } + //if (Deviation > -281 && Deviation < 280) + if (Deviation >= 280 && Deviation <= 3815) { + goto Bail; + } - // not BLE(less than or equal) - if (Frequency > LowerLimit && (Frequency - BK1080_BaseFrequency) == 1) { - if (BK1080_FrequencyDeviation & 0x800 || (BK1080_FrequencyDeviation < 20)) - goto Bail; - } + // not BLE(less than or equal) + if (Frequency > LowerLimit && (Frequency - BK1080_BaseFrequency) == 1) { + if (BK1080_FrequencyDeviation & 0x800 || (BK1080_FrequencyDeviation < 20)) + goto Bail; + } - // not BLT(less than) + // not BLT(less than) - if (Frequency >= LowerLimit && (BK1080_BaseFrequency - Frequency) == 1) { - if ((BK1080_FrequencyDeviation & 0x800) == 0 || (BK1080_FrequencyDeviation > 4075)) - goto Bail; - } + if (Frequency >= LowerLimit && (BK1080_BaseFrequency - Frequency) == 1) { + if ((BK1080_FrequencyDeviation & 0x800) == 0 || (BK1080_FrequencyDeviation > 4075)) + goto Bail; + } - ret = 0; + ret = 0; Bail: - BK1080_FrequencyDeviation = Deviation; - BK1080_BaseFrequency = Frequency; + BK1080_FrequencyDeviation = Deviation; + BK1080_BaseFrequency = Frequency; - return ret; + return ret; } static void Key_DIGITS(KEY_Code_t Key, uint8_t state) { - enum { STATE_FREQ_MODE, STATE_MR_MODE, STATE_SAVE }; - - if (state == BUTTON_EVENT_SHORT && !gWasFKeyPressed) { - uint8_t State; - - if (gAskToDelete) { - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - return; - } - - if (gAskToSave) { - State = STATE_SAVE; - } - else { - if (gFM_ScanState != FM_SCAN_OFF) { - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - return; - } - - State = gEeprom.FM_IsMrMode ? STATE_MR_MODE : STATE_FREQ_MODE; - } - - INPUTBOX_Append(Key); - - gRequestDisplayScreen = DISPLAY_FM; - - if (State == STATE_FREQ_MODE) { - if (gInputBoxIndex == 1) { - if (gInputBox[0] > 1) { - gInputBox[1] = gInputBox[0]; - gInputBox[0] = 0; - gInputBoxIndex = 2; - } - } - else if (gInputBoxIndex > 3) { - uint32_t Frequency; - - gInputBoxIndex = 0; - Frequency = StrToUL(INPUTBOX_GetAscii()); - - if (Frequency < BK1080_GetFreqLoLimit(gEeprom.FM_Band) || BK1080_GetFreqHiLimit(gEeprom.FM_Band) < Frequency) { - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - gRequestDisplayScreen = DISPLAY_FM; - return; - } - - gEeprom.FM_SelectedFrequency = (uint16_t)Frequency; + enum { STATE_FREQ_MODE, STATE_MR_MODE, STATE_SAVE }; + + if (state == BUTTON_EVENT_SHORT && !gWasFKeyPressed) { + uint8_t State; + + if (gAskToDelete) { + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + return; + } + + if (gAskToSave) { + State = STATE_SAVE; + } + else { + if (gFM_ScanState != FM_SCAN_OFF) { + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + return; + } + + State = gEeprom.FM_IsMrMode ? STATE_MR_MODE : STATE_FREQ_MODE; + } + + INPUTBOX_Append(Key); + + gRequestDisplayScreen = DISPLAY_FM; + + if (State == STATE_FREQ_MODE) { + if (gInputBoxIndex == 1) { + if (gInputBox[0] > 1) { + gInputBox[1] = gInputBox[0]; + gInputBox[0] = 0; + gInputBoxIndex = 2; + } + } + else if (gInputBoxIndex > 3) { + uint32_t Frequency; + + gInputBoxIndex = 0; + Frequency = StrToUL(INPUTBOX_GetAscii()); + + if (Frequency < BK1080_GetFreqLoLimit(gEeprom.FM_Band) || BK1080_GetFreqHiLimit(gEeprom.FM_Band) < Frequency) { + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + gRequestDisplayScreen = DISPLAY_FM; + return; + } + + gEeprom.FM_SelectedFrequency = (uint16_t)Frequency; #ifdef ENABLE_VOICE - gAnotherVoiceID = (VOICE_ID_t)Key; + gAnotherVoiceID = (VOICE_ID_t)Key; #endif - gEeprom.FM_FrequencyPlaying = gEeprom.FM_SelectedFrequency; - BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/); - gRequestSaveFM = true; - return; - } - } - else if (gInputBoxIndex == 2) { - uint8_t Channel; - - gInputBoxIndex = 0; - Channel = ((gInputBox[0] * 10) + gInputBox[1]) - 1; - - if (State == STATE_MR_MODE) { - if (FM_CheckValidChannel(Channel)) { + gEeprom.FM_FrequencyPlaying = gEeprom.FM_SelectedFrequency; + BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/); + gRequestSaveFM = true; + return; + } + } + else if (gInputBoxIndex == 2) { + uint8_t Channel; + + gInputBoxIndex = 0; + Channel = ((gInputBox[0] * 10) + gInputBox[1]) - 1; + + if (State == STATE_MR_MODE) { + if (FM_CheckValidChannel(Channel)) { #ifdef ENABLE_VOICE - gAnotherVoiceID = (VOICE_ID_t)Key; + gAnotherVoiceID = (VOICE_ID_t)Key; #endif - gEeprom.FM_SelectedChannel = Channel; - gEeprom.FM_FrequencyPlaying = gFM_Channels[Channel]; - BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/); - gRequestSaveFM = true; - return; - } - } - else if (Channel < 20) { + gEeprom.FM_SelectedChannel = Channel; + gEeprom.FM_FrequencyPlaying = gFM_Channels[Channel]; + BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/); + gRequestSaveFM = true; + return; + } + } + else if (Channel < 20) { #ifdef ENABLE_VOICE - gAnotherVoiceID = (VOICE_ID_t)Key; + gAnotherVoiceID = (VOICE_ID_t)Key; #endif - gRequestDisplayScreen = DISPLAY_FM; - gInputBoxIndex = 0; - gFM_ChannelPosition = Channel; - return; - } + gRequestDisplayScreen = DISPLAY_FM; + gInputBoxIndex = 0; + gFM_ChannelPosition = Channel; + return; + } - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - return; - } + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + return; + } #ifdef ENABLE_VOICE - gAnotherVoiceID = (VOICE_ID_t)Key; + gAnotherVoiceID = (VOICE_ID_t)Key; #endif - } - else - Key_FUNC(Key, state); + } + else + Key_FUNC(Key, state); } static void Key_FUNC(KEY_Code_t Key, uint8_t state) { - if (state == BUTTON_EVENT_SHORT || state == BUTTON_EVENT_HELD) { - bool autoScan = gWasFKeyPressed || (state == BUTTON_EVENT_HELD); - - gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; - gWasFKeyPressed = false; - gUpdateStatus = true; - gRequestDisplayScreen = DISPLAY_FM; - - switch (Key) { - case KEY_0: - ACTION_FM(); - break; - - case KEY_1: - gEeprom.FM_Band++; - gRequestSaveFM = true; - break; - - // case KEY_2: - // gEeprom.FM_Space = (gEeprom.FM_Space + 1) % 3; - // gRequestSaveFM = true; - // break; - - case KEY_3: - gEeprom.FM_IsMrMode = !gEeprom.FM_IsMrMode; - - if (!FM_ConfigureChannelState()) { - BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/); - gRequestSaveFM = true; - } - else - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - break; - - case KEY_STAR: - ACTION_Scan(autoScan); - break; - - default: - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - break; - } - } + if (state == BUTTON_EVENT_SHORT || state == BUTTON_EVENT_HELD) { + bool autoScan = gWasFKeyPressed || (state == BUTTON_EVENT_HELD); + + gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; + gWasFKeyPressed = false; + gUpdateStatus = true; + gRequestDisplayScreen = DISPLAY_FM; + + switch (Key) { + case KEY_0: + ACTION_FM(); + break; + + case KEY_1: + gEeprom.FM_Band++; + gRequestSaveFM = true; + break; + + // case KEY_2: + // gEeprom.FM_Space = (gEeprom.FM_Space + 1) % 3; + // gRequestSaveFM = true; + // break; + + case KEY_3: + gEeprom.FM_IsMrMode = !gEeprom.FM_IsMrMode; + + if (!FM_ConfigureChannelState()) { + BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/); + gRequestSaveFM = true; + } + else + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + break; + + case KEY_STAR: + ACTION_Scan(autoScan); + break; + + default: + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + break; + } + } } static void Key_EXIT(uint8_t state) { - if (state != BUTTON_EVENT_SHORT) - return; - - gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; - - if (gFM_ScanState == FM_SCAN_OFF) { - if (gInputBoxIndex == 0) { - if (!gAskToSave && !gAskToDelete) { - ACTION_FM(); - return; - } - - gAskToSave = false; - gAskToDelete = false; - } - else { - gInputBox[--gInputBoxIndex] = 10; - - if (gInputBoxIndex) { - if (gInputBoxIndex != 1) { - gRequestDisplayScreen = DISPLAY_FM; - return; - } - - if (gInputBox[0] != 0) { - gRequestDisplayScreen = DISPLAY_FM; - return; - } - } - gInputBoxIndex = 0; - } + if (state != BUTTON_EVENT_SHORT) + return; + + gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; + + if (gFM_ScanState == FM_SCAN_OFF) { + if (gInputBoxIndex == 0) { + if (!gAskToSave && !gAskToDelete) { + ACTION_FM(); + return; + } + + gAskToSave = false; + gAskToDelete = false; + } + else { + gInputBox[--gInputBoxIndex] = 10; + + if (gInputBoxIndex) { + if (gInputBoxIndex != 1) { + gRequestDisplayScreen = DISPLAY_FM; + return; + } + + if (gInputBox[0] != 0) { + gRequestDisplayScreen = DISPLAY_FM; + return; + } + } + gInputBoxIndex = 0; + } #ifdef ENABLE_VOICE - gAnotherVoiceID = VOICE_ID_CANCEL; + gAnotherVoiceID = VOICE_ID_CANCEL; #endif - } - else { - FM_PlayAndUpdate(); + } + else { + FM_PlayAndUpdate(); #ifdef ENABLE_VOICE - gAnotherVoiceID = VOICE_ID_SCANNING_STOP; + gAnotherVoiceID = VOICE_ID_SCANNING_STOP; #endif - } + } - gRequestDisplayScreen = DISPLAY_FM; + gRequestDisplayScreen = DISPLAY_FM; } static void Key_MENU(uint8_t state) { - if (state != BUTTON_EVENT_SHORT) - return; - - - gRequestDisplayScreen = DISPLAY_FM; - gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; - - if (gFM_ScanState == FM_SCAN_OFF) { - if (!gEeprom.FM_IsMrMode) { - if (gAskToSave) { - gFM_Channels[gFM_ChannelPosition] = gEeprom.FM_FrequencyPlaying; - gRequestSaveFM = true; - } - gAskToSave = !gAskToSave; - } - else { - if (gAskToDelete) { - gFM_Channels[gEeprom.FM_SelectedChannel] = 0xFFFF; - - FM_ConfigureChannelState(); - BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/); - - gRequestSaveFM = true; - } - gAskToDelete = !gAskToDelete; - } - } - else { - if (gFM_AutoScan || !gFM_FoundFrequency) { - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - gInputBoxIndex = 0; - return; - } - - if (gAskToSave) { - gFM_Channels[gFM_ChannelPosition] = gEeprom.FM_FrequencyPlaying; - gRequestSaveFM = true; - } - gAskToSave = !gAskToSave; - } + if (state != BUTTON_EVENT_SHORT) + return; + + + gRequestDisplayScreen = DISPLAY_FM; + gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; + + if (gFM_ScanState == FM_SCAN_OFF) { + if (!gEeprom.FM_IsMrMode) { + if (gAskToSave) { + gFM_Channels[gFM_ChannelPosition] = gEeprom.FM_FrequencyPlaying; + gRequestSaveFM = true; + } + gAskToSave = !gAskToSave; + } + else { + if (gAskToDelete) { + gFM_Channels[gEeprom.FM_SelectedChannel] = 0xFFFF; + + FM_ConfigureChannelState(); + BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/); + + gRequestSaveFM = true; + } + gAskToDelete = !gAskToDelete; + } + } + else { + if (gFM_AutoScan || !gFM_FoundFrequency) { + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + gInputBoxIndex = 0; + return; + } + + if (gAskToSave) { + gFM_Channels[gFM_ChannelPosition] = gEeprom.FM_FrequencyPlaying; + gRequestSaveFM = true; + } + gAskToSave = !gAskToSave; + } } static void Key_UP_DOWN(uint8_t state, int8_t Step) { - if (state == BUTTON_EVENT_PRESSED) { - if (gInputBoxIndex) { - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - return; - } - - gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; - } else if (gInputBoxIndex || state!=BUTTON_EVENT_HELD) { - return; - } - - if (gAskToSave) { - gRequestDisplayScreen = DISPLAY_FM; - gFM_ChannelPosition = NUMBER_AddWithWraparound(gFM_ChannelPosition, Step, 0, 19); - return; - } - - if (gFM_ScanState != FM_SCAN_OFF) { - if (gFM_AutoScan) { - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - return; - } - - FM_Tune(gEeprom.FM_FrequencyPlaying, Step, false); - gRequestDisplayScreen = DISPLAY_FM; - return; - } - - if (gEeprom.FM_IsMrMode) { - const uint8_t Channel = FM_FindNextChannel(gEeprom.FM_SelectedChannel + Step, Step); - if (Channel == 0xFF || gEeprom.FM_SelectedChannel == Channel) - goto Bail; - - gEeprom.FM_SelectedChannel = Channel; - gEeprom.FM_FrequencyPlaying = gFM_Channels[Channel]; - } - else { - uint16_t Frequency = gEeprom.FM_SelectedFrequency + Step; - - if (Frequency < BK1080_GetFreqLoLimit(gEeprom.FM_Band)) - Frequency = BK1080_GetFreqHiLimit(gEeprom.FM_Band); - else if (Frequency > BK1080_GetFreqHiLimit(gEeprom.FM_Band)) - Frequency = BK1080_GetFreqLoLimit(gEeprom.FM_Band); - - gEeprom.FM_FrequencyPlaying = Frequency; - gEeprom.FM_SelectedFrequency = gEeprom.FM_FrequencyPlaying; - } - - gRequestSaveFM = true; + if (state == BUTTON_EVENT_PRESSED) { + if (gInputBoxIndex) { + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + return; + } + + gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; + } else if (gInputBoxIndex || state!=BUTTON_EVENT_HELD) { + return; + } + + if (gAskToSave) { + gRequestDisplayScreen = DISPLAY_FM; + gFM_ChannelPosition = NUMBER_AddWithWraparound(gFM_ChannelPosition, Step, 0, 19); + return; + } + + if (gFM_ScanState != FM_SCAN_OFF) { + if (gFM_AutoScan) { + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + return; + } + + FM_Tune(gEeprom.FM_FrequencyPlaying, Step, false); + gRequestDisplayScreen = DISPLAY_FM; + return; + } + + if (gEeprom.FM_IsMrMode) { + const uint8_t Channel = FM_FindNextChannel(gEeprom.FM_SelectedChannel + Step, Step); + if (Channel == 0xFF || gEeprom.FM_SelectedChannel == Channel) + goto Bail; + + gEeprom.FM_SelectedChannel = Channel; + gEeprom.FM_FrequencyPlaying = gFM_Channels[Channel]; + } + else { + uint16_t Frequency = gEeprom.FM_SelectedFrequency + Step; + + if (Frequency < BK1080_GetFreqLoLimit(gEeprom.FM_Band)) + Frequency = BK1080_GetFreqHiLimit(gEeprom.FM_Band); + else if (Frequency > BK1080_GetFreqHiLimit(gEeprom.FM_Band)) + Frequency = BK1080_GetFreqLoLimit(gEeprom.FM_Band); + + gEeprom.FM_FrequencyPlaying = Frequency; + gEeprom.FM_SelectedFrequency = gEeprom.FM_FrequencyPlaying; + } + + gRequestSaveFM = true; Bail: - BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/); + BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/); - gRequestDisplayScreen = DISPLAY_FM; + gRequestDisplayScreen = DISPLAY_FM; } void FM_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld) { - uint8_t state = bKeyPressed + 2 * bKeyHeld; - - switch (Key) { - case KEY_0...KEY_9: - Key_DIGITS(Key, state); - break; - case KEY_STAR: - Key_FUNC(Key, state); - break; - case KEY_MENU: - Key_MENU(state); - break; - case KEY_UP: - Key_UP_DOWN(state, 1); - break; - case KEY_DOWN: - Key_UP_DOWN(state, -1); - break;; - case KEY_EXIT: - Key_EXIT(state); - break; - case KEY_F: - GENERIC_Key_F(bKeyPressed, bKeyHeld); - break; - case KEY_PTT: - GENERIC_Key_PTT(bKeyPressed); - break; - default: - if (!bKeyHeld && bKeyPressed) - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - break; - } + uint8_t state = bKeyPressed + 2 * bKeyHeld; + + switch (Key) { + case KEY_0...KEY_9: + Key_DIGITS(Key, state); + break; + case KEY_STAR: + Key_FUNC(Key, state); + break; + case KEY_MENU: + Key_MENU(state); + break; + case KEY_UP: + Key_UP_DOWN(state, 1); + break; + case KEY_DOWN: + Key_UP_DOWN(state, -1); + break;; + case KEY_EXIT: + Key_EXIT(state); + break; + case KEY_F: + GENERIC_Key_F(bKeyPressed, bKeyHeld); + break; + case KEY_PTT: + GENERIC_Key_PTT(bKeyPressed); + break; + default: + if (!bKeyHeld && bKeyPressed) + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + break; + } } void FM_Play(void) { - if (!FM_CheckFrequencyLock(gEeprom.FM_FrequencyPlaying, BK1080_GetFreqLoLimit(gEeprom.FM_Band))) { - if (!gFM_AutoScan) { - gFmPlayCountdown_10ms = 0; - gFM_FoundFrequency = true; + if (!FM_CheckFrequencyLock(gEeprom.FM_FrequencyPlaying, BK1080_GetFreqLoLimit(gEeprom.FM_Band))) { + if (!gFM_AutoScan) { + gFmPlayCountdown_10ms = 0; + gFM_FoundFrequency = true; - if (!gEeprom.FM_IsMrMode) - gEeprom.FM_SelectedFrequency = gEeprom.FM_FrequencyPlaying; + if (!gEeprom.FM_IsMrMode) + gEeprom.FM_SelectedFrequency = gEeprom.FM_FrequencyPlaying; - AUDIO_AudioPathOn(); - gEnableSpeaker = true; + AUDIO_AudioPathOn(); + gEnableSpeaker = true; - GUI_SelectNextDisplay(DISPLAY_FM); - return; - } + GUI_SelectNextDisplay(DISPLAY_FM); + return; + } - if (gFM_ChannelPosition < 20) - gFM_Channels[gFM_ChannelPosition++] = gEeprom.FM_FrequencyPlaying; + if (gFM_ChannelPosition < 20) + gFM_Channels[gFM_ChannelPosition++] = gEeprom.FM_FrequencyPlaying; - if (gFM_ChannelPosition >= 20) { - FM_PlayAndUpdate(); - GUI_SelectNextDisplay(DISPLAY_FM); - return; - } - } + if (gFM_ChannelPosition >= 20) { + FM_PlayAndUpdate(); + GUI_SelectNextDisplay(DISPLAY_FM); + return; + } + } - if (gFM_AutoScan && gEeprom.FM_FrequencyPlaying >= BK1080_GetFreqHiLimit(1)) - FM_PlayAndUpdate(); - else - FM_Tune(gEeprom.FM_FrequencyPlaying, gFM_ScanState, false); + if (gFM_AutoScan && gEeprom.FM_FrequencyPlaying >= BK1080_GetFreqHiLimit(1)) + FM_PlayAndUpdate(); + else + FM_Tune(gEeprom.FM_FrequencyPlaying, gFM_ScanState, false); - GUI_SelectNextDisplay(DISPLAY_FM); + GUI_SelectNextDisplay(DISPLAY_FM); } void FM_Start(void) { - gDualWatchActive = false; - gFmRadioMode = true; - gFM_ScanState = FM_SCAN_OFF; - gFM_RestoreCountdown_10ms = 0; + gDualWatchActive = false; + gFmRadioMode = true; + gFM_ScanState = FM_SCAN_OFF; + gFM_RestoreCountdown_10ms = 0; - BK1080_Init(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/); + BK1080_Init(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/); - AUDIO_AudioPathOn(); + AUDIO_AudioPathOn(); - gEnableSpeaker = true; - gUpdateStatus = true; + gEnableSpeaker = true; + gUpdateStatus = true; } #endif diff --git a/app/fm.h b/app/fm.h index 51bac66a6..346cd90b1 100644 --- a/app/fm.h +++ b/app/fm.h @@ -21,11 +21,11 @@ #include "driver/keyboard.h" -#define FM_CHANNEL_UP 0x01 -#define FM_CHANNEL_DOWN 0xFF +#define FM_CHANNEL_UP 0x01 +#define FM_CHANNEL_DOWN 0xFF enum { - FM_SCAN_OFF = 0U, + FM_SCAN_OFF = 0U, }; extern uint16_t gFM_Channels[20]; diff --git a/app/generic.c b/app/generic.c index 00f9205ec..542e660ea 100644 --- a/app/generic.c +++ b/app/generic.c @@ -21,7 +21,7 @@ #include "app/common.h" #ifdef ENABLE_FMRADIO - #include "app/fm.h" + #include "app/fm.h" #endif #include "app/generic.h" @@ -39,187 +39,187 @@ void GENERIC_Key_F(bool bKeyPressed, bool bKeyHeld) { - if (gInputBoxIndex > 0) { - if (!bKeyHeld && bKeyPressed) // short pressed - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - return; - } - - if (bKeyHeld || !bKeyPressed) { // held or released - if (bKeyHeld || bKeyPressed) { // held or pressed (cannot be held and not pressed I guess, so it checks only if HELD?) - if (!bKeyHeld) // won't ever pass - return; - - if (!bKeyPressed) // won't ever pass - return; - - COMMON_KeypadLockToggle(); - } - else { // released + if (gInputBoxIndex > 0) { + if (!bKeyHeld && bKeyPressed) // short pressed + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + return; + } + + if (bKeyHeld || !bKeyPressed) { // held or released + if (bKeyHeld || bKeyPressed) { // held or pressed (cannot be held and not pressed I guess, so it checks only if HELD?) + if (!bKeyHeld) // won't ever pass + return; + + if (!bKeyPressed) // won't ever pass + return; + + COMMON_KeypadLockToggle(); + } + else { // released #ifdef ENABLE_FMRADIO - if ((gFmRadioMode || gScreenToDisplay != DISPLAY_MAIN) && gScreenToDisplay != DISPLAY_FM) - return; + if ((gFmRadioMode || gScreenToDisplay != DISPLAY_MAIN) && gScreenToDisplay != DISPLAY_FM) + return; #else - if (gScreenToDisplay != DISPLAY_MAIN) - return; + if (gScreenToDisplay != DISPLAY_MAIN) + return; #endif - gWasFKeyPressed = !gWasFKeyPressed; // toggle F function + gWasFKeyPressed = !gWasFKeyPressed; // toggle F function - if (gWasFKeyPressed) - gKeyInputCountdown = key_input_timeout_500ms; + if (gWasFKeyPressed) + gKeyInputCountdown = key_input_timeout_500ms; #ifdef ENABLE_VOICE - if (!gWasFKeyPressed) - gAnotherVoiceID = VOICE_ID_CANCEL; + if (!gWasFKeyPressed) + gAnotherVoiceID = VOICE_ID_CANCEL; #endif - gUpdateStatus = true; - } - } - else { // short pressed + gUpdateStatus = true; + } + } + else { // short pressed #ifdef ENABLE_FMRADIO - if (gScreenToDisplay != DISPLAY_FM) + if (gScreenToDisplay != DISPLAY_FM) #endif - { - gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; - return; - } + { + gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; + return; + } #ifdef ENABLE_FMRADIO - if (gFM_ScanState == FM_SCAN_OFF) { // not scanning - gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; - return; - } + if (gFM_ScanState == FM_SCAN_OFF) { // not scanning + gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; + return; + } #endif - gBeepToPlay = BEEP_440HZ_500MS; - gPttWasReleased = true; - } + gBeepToPlay = BEEP_440HZ_500MS; + gPttWasReleased = true; + } } void GENERIC_Key_PTT(bool bKeyPressed) { - gInputBoxIndex = 0; - - if (!bKeyPressed || SerialConfigInProgress()) - { // PTT released - if (gCurrentFunction == FUNCTION_TRANSMIT) { - // we are transmitting .. stop - if (gFlagEndTransmission) { - FUNCTION_Select(FUNCTION_FOREGROUND); - } - else { - APP_EndTransmission(); - - if (gEeprom.REPEATER_TAIL_TONE_ELIMINATION == 0) - FUNCTION_Select(FUNCTION_FOREGROUND); - else - gRTTECountdown_10ms = gEeprom.REPEATER_TAIL_TONE_ELIMINATION * 10; - } - - gFlagEndTransmission = false; + gInputBoxIndex = 0; + + if (!bKeyPressed || SerialConfigInProgress()) + { // PTT released + if (gCurrentFunction == FUNCTION_TRANSMIT) { + // we are transmitting .. stop + if (gFlagEndTransmission) { + FUNCTION_Select(FUNCTION_FOREGROUND); + } + else { + APP_EndTransmission(); + + if (gEeprom.REPEATER_TAIL_TONE_ELIMINATION == 0) + FUNCTION_Select(FUNCTION_FOREGROUND); + else + gRTTECountdown_10ms = gEeprom.REPEATER_TAIL_TONE_ELIMINATION * 10; + } + + gFlagEndTransmission = false; #ifdef ENABLE_VOX - gVOX_NoiseDetected = false; + gVOX_NoiseDetected = false; #endif - RADIO_SetVfoState(VFO_STATE_NORMAL); + RADIO_SetVfoState(VFO_STATE_NORMAL); - if (gScreenToDisplay != DISPLAY_MENU) // 1of11 .. don't close the menu - gRequestDisplayScreen = DISPLAY_MAIN; - } + if (gScreenToDisplay != DISPLAY_MENU) // 1of11 .. don't close the menu + gRequestDisplayScreen = DISPLAY_MAIN; + } - return; - } + return; + } - // PTT pressed + // PTT pressed - if (SCANNER_IsScanning()) { - SCANNER_Stop(); // CTCSS/CDCSS scanning .. stop - goto cancel_tx; - } + if (SCANNER_IsScanning()) { + SCANNER_Stop(); // CTCSS/CDCSS scanning .. stop + goto cancel_tx; + } - if (gScanStateDir != SCAN_OFF) { - CHFRSCANNER_Stop(); // frequency/channel scanning . .stop - goto cancel_tx; - } + if (gScanStateDir != SCAN_OFF) { + CHFRSCANNER_Stop(); // frequency/channel scanning . .stop + goto cancel_tx; + } #ifdef ENABLE_FMRADIO - if (gFM_ScanState != FM_SCAN_OFF) { // FM radio is scanning .. stop - FM_PlayAndUpdate(); + if (gFM_ScanState != FM_SCAN_OFF) { // FM radio is scanning .. stop + FM_PlayAndUpdate(); #ifdef ENABLE_VOICE - gAnotherVoiceID = VOICE_ID_SCANNING_STOP; + gAnotherVoiceID = VOICE_ID_SCANNING_STOP; #endif - gRequestDisplayScreen = DISPLAY_FM; - goto cancel_tx; - } + gRequestDisplayScreen = DISPLAY_FM; + goto cancel_tx; + } #endif #ifdef ENABLE_FMRADIO - if (gScreenToDisplay == DISPLAY_FM) - goto start_tx; // listening to the FM radio .. start TX'ing + if (gScreenToDisplay == DISPLAY_FM) + goto start_tx; // listening to the FM radio .. start TX'ing #endif - if (gCurrentFunction == FUNCTION_TRANSMIT && gRTTECountdown_10ms == 0) {// already transmitting - gInputBoxIndex = 0; - return; - } + if (gCurrentFunction == FUNCTION_TRANSMIT && gRTTECountdown_10ms == 0) {// already transmitting + gInputBoxIndex = 0; + return; + } - if (gScreenToDisplay != DISPLAY_MENU) // 1of11 .. don't close the menu - gRequestDisplayScreen = DISPLAY_MAIN; + if (gScreenToDisplay != DISPLAY_MENU) // 1of11 .. don't close the menu + gRequestDisplayScreen = DISPLAY_MAIN; - if (!gDTMF_InputMode && gDTMF_InputBox_Index == 0) - goto start_tx; // wasn't entering a DTMF code .. start TX'ing (maybe) + if (!gDTMF_InputMode && gDTMF_InputBox_Index == 0) + goto start_tx; // wasn't entering a DTMF code .. start TX'ing (maybe) - // was entering a DTMF string + // was entering a DTMF string - if (gDTMF_InputBox_Index > 0 || gDTMF_PreviousIndex > 0) { // going to transmit a DTMF string - if (gDTMF_InputBox_Index == 0 && gDTMF_PreviousIndex > 0) - gDTMF_InputBox_Index = gDTMF_PreviousIndex; // use the previous DTMF string + if (gDTMF_InputBox_Index > 0 || gDTMF_PreviousIndex > 0) { // going to transmit a DTMF string + if (gDTMF_InputBox_Index == 0 && gDTMF_PreviousIndex > 0) + gDTMF_InputBox_Index = gDTMF_PreviousIndex; // use the previous DTMF string - if (gDTMF_InputBox_Index < sizeof(gDTMF_InputBox)) - gDTMF_InputBox[gDTMF_InputBox_Index] = 0; // NULL term the string + if (gDTMF_InputBox_Index < sizeof(gDTMF_InputBox)) + gDTMF_InputBox[gDTMF_InputBox_Index] = 0; // NULL term the string #ifdef ENABLE_DTMF_CALLING - // append our DTMF ID to the inputted DTMF code - - // IF the user inputted code is exactly 3 digits long and D-DCD is enabled - if (gDTMF_InputBox_Index == 3 && gTxVfo->DTMF_DECODING_ENABLE > 0) - gDTMF_CallMode = DTMF_CheckGroupCall(gDTMF_InputBox, 3); - else - gDTMF_CallMode = DTMF_CALL_MODE_DTMF; - - gDTMF_State = DTMF_STATE_0; + // append our DTMF ID to the inputted DTMF code - + // IF the user inputted code is exactly 3 digits long and D-DCD is enabled + if (gDTMF_InputBox_Index == 3 && gTxVfo->DTMF_DECODING_ENABLE > 0) + gDTMF_CallMode = DTMF_CheckGroupCall(gDTMF_InputBox, 3); + else + gDTMF_CallMode = DTMF_CALL_MODE_DTMF; + + gDTMF_State = DTMF_STATE_0; #endif - // remember the DTMF string - gDTMF_PreviousIndex = gDTMF_InputBox_Index; - strcpy(gDTMF_String, gDTMF_InputBox); - gDTMF_ReplyState = DTMF_REPLY_ANI; - } + // remember the DTMF string + gDTMF_PreviousIndex = gDTMF_InputBox_Index; + strcpy(gDTMF_String, gDTMF_InputBox); + gDTMF_ReplyState = DTMF_REPLY_ANI; + } - DTMF_clear_input_box(); + DTMF_clear_input_box(); start_tx: - // request start TX - gFlagPrepareTX = true; - goto done; + // request start TX + gFlagPrepareTX = true; + goto done; cancel_tx: - if (gPttIsPressed) { - gPttWasPressed = true; - } + if (gPttIsPressed) { + gPttWasPressed = true; + } done: - gPttDebounceCounter = 0; - if (gScreenToDisplay != DISPLAY_MENU + gPttDebounceCounter = 0; + if (gScreenToDisplay != DISPLAY_MENU #ifdef ENABLE_FMRADIO - && gRequestDisplayScreen != DISPLAY_FM + && gRequestDisplayScreen != DISPLAY_FM #endif - ) { - // 1of11 .. don't close the menu - gRequestDisplayScreen = DISPLAY_MAIN; - } + ) { + // 1of11 .. don't close the menu + gRequestDisplayScreen = DISPLAY_MAIN; + } - gUpdateStatus = true; - gUpdateDisplay = true; + gUpdateStatus = true; + gUpdateDisplay = true; } diff --git a/app/menu.c b/app/menu.c index bc07c3882..52987c95a 100644 --- a/app/menu.c +++ b/app/menu.c @@ -17,7 +17,7 @@ #include #if !defined(ENABLE_OVERLAY) - #include "ARMCM0.h" + #include "ARMCM0.h" #endif #include "app/dtmf.h" #include "app/generic.h" @@ -36,1908 +36,1908 @@ #include "misc.h" #include "settings.h" #if defined(ENABLE_OVERLAY) - #include "sram-overlay.h" + #include "sram-overlay.h" #endif #include "ui/inputbox.h" #include "ui/menu.h" #include "ui/ui.h" #ifndef ARRAY_SIZE - #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) + #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) #endif uint8_t gUnlockAllTxConfCnt; #ifdef ENABLE_F_CAL_MENU - void writeXtalFreqCal(const int32_t value, const bool update_eeprom) - { - BK4819_WriteRegister(BK4819_REG_3B, 22656 + value); - - if (update_eeprom) - { - struct - { - int16_t BK4819_XtalFreqLow; - uint16_t EEPROM_1F8A; - uint16_t EEPROM_1F8C; - uint8_t VOLUME_GAIN; - uint8_t DAC_GAIN; - } __attribute__((packed)) misc; - - gEeprom.BK4819_XTAL_FREQ_LOW = value; - - // radio 1 .. 04 00 46 00 50 00 2C 0E - // radio 2 .. 05 00 46 00 50 00 2C 0E - // - EEPROM_ReadBuffer(0x1F88, &misc, 8); - misc.BK4819_XtalFreqLow = value; - EEPROM_WriteBuffer(0x1F88, &misc); - } - } + void writeXtalFreqCal(const int32_t value, const bool update_eeprom) + { + BK4819_WriteRegister(BK4819_REG_3B, 22656 + value); + + if (update_eeprom) + { + struct + { + int16_t BK4819_XtalFreqLow; + uint16_t EEPROM_1F8A; + uint16_t EEPROM_1F8C; + uint8_t VOLUME_GAIN; + uint8_t DAC_GAIN; + } __attribute__((packed)) misc; + + gEeprom.BK4819_XTAL_FREQ_LOW = value; + + // radio 1 .. 04 00 46 00 50 00 2C 0E + // radio 2 .. 05 00 46 00 50 00 2C 0E + // + EEPROM_ReadBuffer(0x1F88, &misc, 8); + misc.BK4819_XtalFreqLow = value; + EEPROM_WriteBuffer(0x1F88, &misc); + } + } #endif void MENU_StartCssScan(void) { - SCANNER_Start(true); - gUpdateStatus = true; - gCssBackgroundScan = true; + SCANNER_Start(true); + gUpdateStatus = true; + gCssBackgroundScan = true; - gRequestDisplayScreen = DISPLAY_MENU; + gRequestDisplayScreen = DISPLAY_MENU; } void MENU_CssScanFound(void) { - if(gScanCssResultType == CODE_TYPE_DIGITAL || gScanCssResultType == CODE_TYPE_REVERSE_DIGITAL) { - gMenuCursor = UI_MENU_GetMenuIdx(MENU_R_DCS); - } - else if(gScanCssResultType == CODE_TYPE_CONTINUOUS_TONE) { - gMenuCursor = UI_MENU_GetMenuIdx(MENU_R_CTCS); - } + if(gScanCssResultType == CODE_TYPE_DIGITAL || gScanCssResultType == CODE_TYPE_REVERSE_DIGITAL) { + gMenuCursor = UI_MENU_GetMenuIdx(MENU_R_DCS); + } + else if(gScanCssResultType == CODE_TYPE_CONTINUOUS_TONE) { + gMenuCursor = UI_MENU_GetMenuIdx(MENU_R_CTCS); + } - MENU_ShowCurrentSetting(); + MENU_ShowCurrentSetting(); - gUpdateStatus = true; - gUpdateDisplay = true; + gUpdateStatus = true; + gUpdateDisplay = true; } void MENU_StopCssScan(void) { - gCssBackgroundScan = false; + gCssBackgroundScan = false; #ifdef ENABLE_VOICE - gAnotherVoiceID = VOICE_ID_SCANNING_STOP; + gAnotherVoiceID = VOICE_ID_SCANNING_STOP; #endif - gUpdateDisplay = true; - gUpdateStatus = true; + gUpdateDisplay = true; + gUpdateStatus = true; } int MENU_GetLimits(uint8_t menu_id, int32_t *pMin, int32_t *pMax) { - *pMin = 0; - - switch (menu_id) - { - case MENU_SQL: - //*pMin = 0; - *pMax = 9; - break; - - case MENU_STEP: - //*pMin = 0; - *pMax = STEP_N_ELEM - 1; - break; - - case MENU_ABR: - //*pMin = 0; - *pMax = 61; - break; - - case MENU_ABR_MIN: - //*pMin = 0; - *pMax = 9; - break; - - case MENU_ABR_MAX: - *pMin = 1; - *pMax = 10; - break; - - case MENU_F_LOCK: - //*pMin = 0; - *pMax = ARRAY_SIZE(gSubMenu_F_LOCK) - 1; - break; - - case MENU_MDF: - //*pMin = 0; - *pMax = ARRAY_SIZE(gSubMenu_MDF) - 1; - break; - - case MENU_TXP: - //*pMin = 0; - *pMax = ARRAY_SIZE(gSubMenu_TXP) - 1; - break; - - case MENU_SFT_D: - //*pMin = 0; - *pMax = ARRAY_SIZE(gSubMenu_SFT_D) - 1; - break; - - case MENU_TDR: - //*pMin = 0; - *pMax = ARRAY_SIZE(gSubMenu_RXMode) - 1; - break; - - #ifdef ENABLE_VOICE - case MENU_VOICE: - //*pMin = 0; - *pMax = ARRAY_SIZE(gSubMenu_VOICE) - 1; - break; - #endif - - case MENU_SC_REV: - //*pMin = 0; - *pMax = ARRAY_SIZE(gSubMenu_SC_REV) - 1; - break; - - case MENU_ROGER: - //*pMin = 0; - *pMax = ARRAY_SIZE(gSubMenu_ROGER) - 1; - break; - - case MENU_PONMSG: - //*pMin = 0; - *pMax = ARRAY_SIZE(gSubMenu_PONMSG) - 1; - break; - - case MENU_R_DCS: - case MENU_T_DCS: - //*pMin = 0; - *pMax = 208; - //*pMax = (ARRAY_SIZE(DCS_Options) * 2); - break; - - case MENU_R_CTCS: - case MENU_T_CTCS: - //*pMin = 0; - *pMax = ARRAY_SIZE(CTCSS_Options); - break; - - case MENU_W_N: - //*pMin = 0; - *pMax = ARRAY_SIZE(gSubMenu_W_N) - 1; - break; - - #ifdef ENABLE_ALARM - case MENU_AL_MOD: - //*pMin = 0; - *pMax = ARRAY_SIZE(gSubMenu_AL_MOD) - 1; - break; - #endif - - case MENU_RESET: - //*pMin = 0; - *pMax = ARRAY_SIZE(gSubMenu_RESET) - 1; - break; - - case MENU_COMPAND: - case MENU_ABR_ON_TX_RX: - //*pMin = 0; - *pMax = ARRAY_SIZE(gSubMenu_RX_TX) - 1; - break; - - #ifndef ENABLE_FEAT_F4HWN - #ifdef ENABLE_AM_FIX - case MENU_AM_FIX: - #endif - #endif - #ifdef ENABLE_AUDIO_BAR - case MENU_MIC_BAR: - #endif - case MENU_BCL: - case MENU_BEEP: - case MENU_AUTOLK: - case MENU_S_ADD1: - case MENU_S_ADD2: - case MENU_S_ADD3: - case MENU_STE: - case MENU_D_ST: + *pMin = 0; + + switch (menu_id) + { + case MENU_SQL: + //*pMin = 0; + *pMax = 9; + break; + + case MENU_STEP: + //*pMin = 0; + *pMax = STEP_N_ELEM - 1; + break; + + case MENU_ABR: + //*pMin = 0; + *pMax = 61; + break; + + case MENU_ABR_MIN: + //*pMin = 0; + *pMax = 9; + break; + + case MENU_ABR_MAX: + *pMin = 1; + *pMax = 10; + break; + + case MENU_F_LOCK: + //*pMin = 0; + *pMax = ARRAY_SIZE(gSubMenu_F_LOCK) - 1; + break; + + case MENU_MDF: + //*pMin = 0; + *pMax = ARRAY_SIZE(gSubMenu_MDF) - 1; + break; + + case MENU_TXP: + //*pMin = 0; + *pMax = ARRAY_SIZE(gSubMenu_TXP) - 1; + break; + + case MENU_SFT_D: + //*pMin = 0; + *pMax = ARRAY_SIZE(gSubMenu_SFT_D) - 1; + break; + + case MENU_TDR: + //*pMin = 0; + *pMax = ARRAY_SIZE(gSubMenu_RXMode) - 1; + break; + + #ifdef ENABLE_VOICE + case MENU_VOICE: + //*pMin = 0; + *pMax = ARRAY_SIZE(gSubMenu_VOICE) - 1; + break; + #endif + + case MENU_SC_REV: + //*pMin = 0; + *pMax = ARRAY_SIZE(gSubMenu_SC_REV) - 1; + break; + + case MENU_ROGER: + //*pMin = 0; + *pMax = ARRAY_SIZE(gSubMenu_ROGER) - 1; + break; + + case MENU_PONMSG: + //*pMin = 0; + *pMax = ARRAY_SIZE(gSubMenu_PONMSG) - 1; + break; + + case MENU_R_DCS: + case MENU_T_DCS: + //*pMin = 0; + *pMax = 208; + //*pMax = (ARRAY_SIZE(DCS_Options) * 2); + break; + + case MENU_R_CTCS: + case MENU_T_CTCS: + //*pMin = 0; + *pMax = ARRAY_SIZE(CTCSS_Options); + break; + + case MENU_W_N: + //*pMin = 0; + *pMax = ARRAY_SIZE(gSubMenu_W_N) - 1; + break; + + #ifdef ENABLE_ALARM + case MENU_AL_MOD: + //*pMin = 0; + *pMax = ARRAY_SIZE(gSubMenu_AL_MOD) - 1; + break; + #endif + + case MENU_RESET: + //*pMin = 0; + *pMax = ARRAY_SIZE(gSubMenu_RESET) - 1; + break; + + case MENU_COMPAND: + case MENU_ABR_ON_TX_RX: + //*pMin = 0; + *pMax = ARRAY_SIZE(gSubMenu_RX_TX) - 1; + break; + + #ifndef ENABLE_FEAT_F4HWN + #ifdef ENABLE_AM_FIX + case MENU_AM_FIX: + #endif + #endif + #ifdef ENABLE_AUDIO_BAR + case MENU_MIC_BAR: + #endif + case MENU_BCL: + case MENU_BEEP: + case MENU_AUTOLK: + case MENU_S_ADD1: + case MENU_S_ADD2: + case MENU_S_ADD3: + case MENU_STE: + case MENU_D_ST: #ifdef ENABLE_DTMF_CALLING - case MENU_D_DCD: + case MENU_D_DCD: #endif - case MENU_D_LIVE_DEC: - #ifdef ENABLE_NOAA - case MENU_NOAA_S: - #endif - case MENU_350TX: - case MENU_200TX: - case MENU_500TX: - case MENU_350EN: + case MENU_D_LIVE_DEC: + #ifdef ENABLE_NOAA + case MENU_NOAA_S: + #endif + case MENU_350TX: + case MENU_200TX: + case MENU_500TX: + case MENU_350EN: #ifndef ENABLE_FEAT_F4HWN - case MENU_SCREN: + case MENU_SCREN: #endif #ifdef ENABLE_FEAT_F4HWN - case MENU_SET_TMR: + case MENU_SET_TMR: #endif - //*pMin = 0; - *pMax = ARRAY_SIZE(gSubMenu_OFF_ON) - 1; - break; - case MENU_AM: - //*pMin = 0; - *pMax = ARRAY_SIZE(gModulationStr) - 1; - break; + //*pMin = 0; + *pMax = ARRAY_SIZE(gSubMenu_OFF_ON) - 1; + break; + case MENU_AM: + //*pMin = 0; + *pMax = ARRAY_SIZE(gModulationStr) - 1; + break; #ifndef ENABLE_FEAT_F4HWN - case MENU_SCR: - //*pMin = 0; - *pMax = ARRAY_SIZE(gSubMenu_SCRAMBLER) - 1; - break; + case MENU_SCR: + //*pMin = 0; + *pMax = ARRAY_SIZE(gSubMenu_SCRAMBLER) - 1; + break; #endif - case MENU_TOT: - //*pMin = 0; - *pMin = 5; - *pMax = 179; - break; - - #ifdef ENABLE_VOX - case MENU_VOX: - #endif - case MENU_RP_STE: - //*pMin = 0; - *pMax = 10; - break; - - case MENU_MEM_CH: - case MENU_1_CALL: - case MENU_DEL_CH: - case MENU_MEM_NAME: - //*pMin = 0; - *pMax = MR_CHANNEL_LAST; - break; - - case MENU_SLIST1: - case MENU_SLIST2: - case MENU_SLIST3: - *pMin = -1; - *pMax = MR_CHANNEL_LAST; - break; - - case MENU_SAVE: - //*pMin = 0; - *pMax = ARRAY_SIZE(gSubMenu_SAVE) - 1; - break; - - case MENU_MIC: - //*pMin = 0; - *pMax = 4; - break; - - case MENU_S_LIST: - //*pMin = 0; - *pMax = 5; - break; + case MENU_TOT: + //*pMin = 0; + *pMin = 5; + *pMax = 179; + break; + + #ifdef ENABLE_VOX + case MENU_VOX: + #endif + case MENU_RP_STE: + //*pMin = 0; + *pMax = 10; + break; + + case MENU_MEM_CH: + case MENU_1_CALL: + case MENU_DEL_CH: + case MENU_MEM_NAME: + //*pMin = 0; + *pMax = MR_CHANNEL_LAST; + break; + + case MENU_SLIST1: + case MENU_SLIST2: + case MENU_SLIST3: + *pMin = -1; + *pMax = MR_CHANNEL_LAST; + break; + + case MENU_SAVE: + //*pMin = 0; + *pMax = ARRAY_SIZE(gSubMenu_SAVE) - 1; + break; + + case MENU_MIC: + //*pMin = 0; + *pMax = 4; + break; + + case MENU_S_LIST: + //*pMin = 0; + *pMax = 5; + break; #ifdef ENABLE_DTMF_CALLING - case MENU_D_RSP: - //*pMin = 0; - *pMax = ARRAY_SIZE(gSubMenu_D_RSP) - 1; - break; + case MENU_D_RSP: + //*pMin = 0; + *pMax = ARRAY_SIZE(gSubMenu_D_RSP) - 1; + break; #endif - case MENU_PTT_ID: - //*pMin = 0; - *pMax = ARRAY_SIZE(gSubMenu_PTT_ID) - 1; - break; + case MENU_PTT_ID: + //*pMin = 0; + *pMax = ARRAY_SIZE(gSubMenu_PTT_ID) - 1; + break; - case MENU_BAT_TXT: - //*pMin = 0; - *pMax = ARRAY_SIZE(gSubMenu_BAT_TXT) - 1; - break; + case MENU_BAT_TXT: + //*pMin = 0; + *pMax = ARRAY_SIZE(gSubMenu_BAT_TXT) - 1; + break; #ifdef ENABLE_DTMF_CALLING - case MENU_D_HOLD: - *pMin = 5; - *pMax = 60; - break; + case MENU_D_HOLD: + *pMin = 5; + *pMax = 60; + break; #endif - case MENU_D_PRE: - *pMin = 3; - *pMax = 99; - break; + case MENU_D_PRE: + *pMin = 3; + *pMax = 99; + break; #ifdef ENABLE_DTMF_CALLING - case MENU_D_LIST: - *pMin = 1; - *pMax = 16; - break; + case MENU_D_LIST: + *pMin = 1; + *pMax = 16; + break; #endif - #ifdef ENABLE_F_CAL_MENU - case MENU_F_CALI: - *pMin = -50; - *pMax = +50; - break; - #endif - - case MENU_BATCAL: - *pMin = 1600; - *pMax = 2200; - break; - - case MENU_BATTYP: - //*pMin = 0; - *pMax = 2; - break; - - case MENU_F1SHRT: - case MENU_F1LONG: - case MENU_F2SHRT: - case MENU_F2LONG: - case MENU_MLONG: - //*pMin = 0; - *pMax = gSubMenu_SIDEFUNCTIONS_size-1; - break; + #ifdef ENABLE_F_CAL_MENU + case MENU_F_CALI: + *pMin = -50; + *pMax = +50; + break; + #endif + + case MENU_BATCAL: + *pMin = 1600; + *pMax = 2200; + break; + + case MENU_BATTYP: + //*pMin = 0; + *pMax = 2; + break; + + case MENU_F1SHRT: + case MENU_F1LONG: + case MENU_F2SHRT: + case MENU_F2LONG: + case MENU_MLONG: + //*pMin = 0; + *pMax = gSubMenu_SIDEFUNCTIONS_size-1; + break; #ifdef ENABLE_FEAT_F4HWN - case MENU_SET_PWR: - *pMax = ARRAY_SIZE(gSubMenu_SET_PWR) - 1; - break; - case MENU_SET_PTT: - //*pMin = 0; - *pMax = ARRAY_SIZE(gSubMenu_SET_PTT) - 1; - break; - case MENU_SET_TOT: - case MENU_SET_EOT: - //*pMin = 0; - *pMax = ARRAY_SIZE(gSubMenu_SET_TOT) - 1; - break; - case MENU_SET_CTR: - *pMin = 1; - *pMax = 15; - break; - case MENU_TX_LOCK: + case MENU_SET_PWR: + *pMax = ARRAY_SIZE(gSubMenu_SET_PWR) - 1; + break; + case MENU_SET_PTT: + //*pMin = 0; + *pMax = ARRAY_SIZE(gSubMenu_SET_PTT) - 1; + break; + case MENU_SET_TOT: + case MENU_SET_EOT: + //*pMin = 0; + *pMax = ARRAY_SIZE(gSubMenu_SET_TOT) - 1; + break; + case MENU_SET_CTR: + *pMin = 1; + *pMax = 15; + break; + case MENU_TX_LOCK: case MENU_SET_INV: - //*pMin = 0; - *pMax = ARRAY_SIZE(gSubMenu_OFF_ON) - 1; - break; - case MENU_SET_LCK: - //*pMin = 0; - *pMax = ARRAY_SIZE(gSubMenu_SET_LCK) - 1; - break; - case MENU_SET_MET: - case MENU_SET_GUI: - //*pMin = 0; - *pMax = ARRAY_SIZE(gSubMenu_SET_MET) - 1; - break; + //*pMin = 0; + *pMax = ARRAY_SIZE(gSubMenu_OFF_ON) - 1; + break; + case MENU_SET_LCK: + //*pMin = 0; + *pMax = ARRAY_SIZE(gSubMenu_SET_LCK) - 1; + break; + case MENU_SET_MET: + case MENU_SET_GUI: + //*pMin = 0; + *pMax = ARRAY_SIZE(gSubMenu_SET_MET) - 1; + break; #endif - default: - return -1; - } + default: + return -1; + } - return 0; + return 0; } void MENU_AcceptSetting(void) { - int32_t Min; - int32_t Max; - FREQ_Config_t *pConfig = &gTxVfo->freq_config_RX; - - if (!MENU_GetLimits(UI_MENU_GetCurrentMenuId(), &Min, &Max)) - { - if (gSubMenuSelection < Min) gSubMenuSelection = Min; - else - if (gSubMenuSelection > Max) gSubMenuSelection = Max; - } - - switch (UI_MENU_GetCurrentMenuId()) - { - default: - return; - - case MENU_SQL: - gEeprom.SQUELCH_LEVEL = gSubMenuSelection; - gVfoConfigureMode = VFO_CONFIGURE; - break; - - case MENU_STEP: - gTxVfo->STEP_SETTING = FREQUENCY_GetStepIdxFromSortedIdx(gSubMenuSelection); - if (IS_FREQ_CHANNEL(gTxVfo->CHANNEL_SAVE)) - { - gRequestSaveChannel = 1; - } - return; - - case MENU_TXP: - gTxVfo->OUTPUT_POWER = gSubMenuSelection; - gRequestSaveChannel = 1; - return; - - case MENU_T_DCS: - pConfig = &gTxVfo->freq_config_TX; - - // Fallthrough - - case MENU_R_DCS: { - if (gSubMenuSelection == 0) { - if (pConfig->CodeType == CODE_TYPE_CONTINUOUS_TONE) { - return; - } - pConfig->Code = 0; - pConfig->CodeType = CODE_TYPE_OFF; - } - else if (gSubMenuSelection < 105) { - pConfig->CodeType = CODE_TYPE_DIGITAL; - pConfig->Code = gSubMenuSelection - 1; - } - else { - pConfig->CodeType = CODE_TYPE_REVERSE_DIGITAL; - pConfig->Code = gSubMenuSelection - 105; - } - - gRequestSaveChannel = 1; - return; - } - case MENU_T_CTCS: - pConfig = &gTxVfo->freq_config_TX; - [[fallthrough]]; - case MENU_R_CTCS: { - if (gSubMenuSelection == 0) { - if (pConfig->CodeType != CODE_TYPE_CONTINUOUS_TONE) { - return; - } - pConfig->Code = 0; - pConfig->CodeType = CODE_TYPE_OFF; - } - else { - pConfig->Code = gSubMenuSelection - 1; - pConfig->CodeType = CODE_TYPE_CONTINUOUS_TONE; - } - - gRequestSaveChannel = 1; - return; - } - case MENU_SFT_D: - gTxVfo->TX_OFFSET_FREQUENCY_DIRECTION = gSubMenuSelection; - gRequestSaveChannel = 1; - return; - - case MENU_OFFSET: - gTxVfo->TX_OFFSET_FREQUENCY = gSubMenuSelection; - gRequestSaveChannel = 1; - return; - - case MENU_W_N: - gTxVfo->CHANNEL_BANDWIDTH = gSubMenuSelection; - gRequestSaveChannel = 1; - return; + int32_t Min; + int32_t Max; + FREQ_Config_t *pConfig = &gTxVfo->freq_config_RX; + + if (!MENU_GetLimits(UI_MENU_GetCurrentMenuId(), &Min, &Max)) + { + if (gSubMenuSelection < Min) gSubMenuSelection = Min; + else + if (gSubMenuSelection > Max) gSubMenuSelection = Max; + } + + switch (UI_MENU_GetCurrentMenuId()) + { + default: + return; + + case MENU_SQL: + gEeprom.SQUELCH_LEVEL = gSubMenuSelection; + gVfoConfigureMode = VFO_CONFIGURE; + break; + + case MENU_STEP: + gTxVfo->STEP_SETTING = FREQUENCY_GetStepIdxFromSortedIdx(gSubMenuSelection); + if (IS_FREQ_CHANNEL(gTxVfo->CHANNEL_SAVE)) + { + gRequestSaveChannel = 1; + } + return; + + case MENU_TXP: + gTxVfo->OUTPUT_POWER = gSubMenuSelection; + gRequestSaveChannel = 1; + return; + + case MENU_T_DCS: + pConfig = &gTxVfo->freq_config_TX; + + // Fallthrough + + case MENU_R_DCS: { + if (gSubMenuSelection == 0) { + if (pConfig->CodeType == CODE_TYPE_CONTINUOUS_TONE) { + return; + } + pConfig->Code = 0; + pConfig->CodeType = CODE_TYPE_OFF; + } + else if (gSubMenuSelection < 105) { + pConfig->CodeType = CODE_TYPE_DIGITAL; + pConfig->Code = gSubMenuSelection - 1; + } + else { + pConfig->CodeType = CODE_TYPE_REVERSE_DIGITAL; + pConfig->Code = gSubMenuSelection - 105; + } + + gRequestSaveChannel = 1; + return; + } + case MENU_T_CTCS: + pConfig = &gTxVfo->freq_config_TX; + [[fallthrough]]; + case MENU_R_CTCS: { + if (gSubMenuSelection == 0) { + if (pConfig->CodeType != CODE_TYPE_CONTINUOUS_TONE) { + return; + } + pConfig->Code = 0; + pConfig->CodeType = CODE_TYPE_OFF; + } + else { + pConfig->Code = gSubMenuSelection - 1; + pConfig->CodeType = CODE_TYPE_CONTINUOUS_TONE; + } + + gRequestSaveChannel = 1; + return; + } + case MENU_SFT_D: + gTxVfo->TX_OFFSET_FREQUENCY_DIRECTION = gSubMenuSelection; + gRequestSaveChannel = 1; + return; + + case MENU_OFFSET: + gTxVfo->TX_OFFSET_FREQUENCY = gSubMenuSelection; + gRequestSaveChannel = 1; + return; + + case MENU_W_N: + gTxVfo->CHANNEL_BANDWIDTH = gSubMenuSelection; + gRequestSaveChannel = 1; + return; #ifndef ENABLE_FEAT_F4HWN - case MENU_SCR: - gTxVfo->SCRAMBLING_TYPE = gSubMenuSelection; - #if 0 - if (gSubMenuSelection > 0 && gSetting_ScrambleEnable) - BK4819_EnableScramble(gSubMenuSelection - 1); - else - BK4819_DisableScramble(); - #endif - gRequestSaveChannel = 1; - return; + case MENU_SCR: + gTxVfo->SCRAMBLING_TYPE = gSubMenuSelection; + #if 0 + if (gSubMenuSelection > 0 && gSetting_ScrambleEnable) + BK4819_EnableScramble(gSubMenuSelection - 1); + else + BK4819_DisableScramble(); + #endif + gRequestSaveChannel = 1; + return; #endif - case MENU_BCL: - gTxVfo->BUSY_CHANNEL_LOCK = gSubMenuSelection; - gRequestSaveChannel = 1; - return; - - case MENU_MEM_CH: - gTxVfo->CHANNEL_SAVE = gSubMenuSelection; - #if 0 - gEeprom.MrChannel[0] = gSubMenuSelection; - #else - gEeprom.MrChannel[gEeprom.TX_VFO] = gSubMenuSelection; - #endif - gRequestSaveChannel = 2; - gVfoConfigureMode = VFO_CONFIGURE_RELOAD; - gFlagResetVfos = true; - return; - - case MENU_MEM_NAME: - for (int i = 9; i >= 0; i--) { - if (edit[i] != ' ' && edit[i] != '_' && edit[i] != 0x00 && edit[i] != 0xff) - break; - edit[i] = ' '; - } - - SETTINGS_SaveChannelName(gSubMenuSelection, edit); - return; - - case MENU_SAVE: - gEeprom.BATTERY_SAVE = gSubMenuSelection; - break; - - #ifdef ENABLE_VOX - case MENU_VOX: - gEeprom.VOX_SWITCH = gSubMenuSelection != 0; - if (gEeprom.VOX_SWITCH) - gEeprom.VOX_LEVEL = gSubMenuSelection - 1; - SETTINGS_LoadCalibration(); - gFlagReconfigureVfos = true; - gUpdateStatus = true; - break; - #endif - - case MENU_ABR: - gEeprom.BACKLIGHT_TIME = gSubMenuSelection; - #ifdef ENABLE_FEAT_F4HWN - gBackLight = false; - #endif - break; - - case MENU_ABR_MIN: - gEeprom.BACKLIGHT_MIN = gSubMenuSelection; - gEeprom.BACKLIGHT_MAX = MAX(gSubMenuSelection + 1 , gEeprom.BACKLIGHT_MAX); - break; - - case MENU_ABR_MAX: - gEeprom.BACKLIGHT_MAX = gSubMenuSelection; - gEeprom.BACKLIGHT_MIN = MIN(gSubMenuSelection - 1, gEeprom.BACKLIGHT_MIN); - break; - - case MENU_ABR_ON_TX_RX: - gSetting_backlight_on_tx_rx = gSubMenuSelection; - break; - - case MENU_TDR: - gEeprom.DUAL_WATCH = (gEeprom.TX_VFO + 1) * (gSubMenuSelection & 1); - gEeprom.CROSS_BAND_RX_TX = (gEeprom.TX_VFO + 1) * ((gSubMenuSelection & 2) > 0); - - #ifdef ENABLE_FEAT_F4HWN - gDW = gEeprom.DUAL_WATCH; - gCB = gEeprom.CROSS_BAND_RX_TX; - gSaveRxMode = true; - #endif - - gFlagReconfigureVfos = true; - gUpdateStatus = true; - break; - - case MENU_BEEP: - gEeprom.BEEP_CONTROL = gSubMenuSelection; - break; - - case MENU_TOT: - gEeprom.TX_TIMEOUT_TIMER = gSubMenuSelection; - break; - - #ifdef ENABLE_VOICE - case MENU_VOICE: - gEeprom.VOICE_PROMPT = gSubMenuSelection; - gUpdateStatus = true; - break; - #endif - - case MENU_SC_REV: - gEeprom.SCAN_RESUME_MODE = gSubMenuSelection; - break; - - case MENU_MDF: - gEeprom.CHANNEL_DISPLAY_MODE = gSubMenuSelection; - break; - - case MENU_AUTOLK: - gEeprom.AUTO_KEYPAD_LOCK = gSubMenuSelection; - gKeyLockCountdown = 30; - break; - - case MENU_S_ADD1: - gTxVfo->SCANLIST1_PARTICIPATION = gSubMenuSelection; - SETTINGS_UpdateChannel(gTxVfo->CHANNEL_SAVE, gTxVfo, true, false, true); - gVfoConfigureMode = VFO_CONFIGURE; - gFlagResetVfos = true; - return; - - case MENU_S_ADD2: - gTxVfo->SCANLIST2_PARTICIPATION = gSubMenuSelection; - SETTINGS_UpdateChannel(gTxVfo->CHANNEL_SAVE, gTxVfo, true, false, true); - gVfoConfigureMode = VFO_CONFIGURE; - gFlagResetVfos = true; - return; - - case MENU_S_ADD3: - gTxVfo->SCANLIST3_PARTICIPATION = gSubMenuSelection; - SETTINGS_UpdateChannel(gTxVfo->CHANNEL_SAVE, gTxVfo, true, false, true); - gVfoConfigureMode = VFO_CONFIGURE; - gFlagResetVfos = true; - return; - - case MENU_STE: - gEeprom.TAIL_TONE_ELIMINATION = gSubMenuSelection; - break; - - case MENU_RP_STE: - gEeprom.REPEATER_TAIL_TONE_ELIMINATION = gSubMenuSelection; - break; - - case MENU_MIC: - gEeprom.MIC_SENSITIVITY = gSubMenuSelection; - SETTINGS_LoadCalibration(); - gFlagReconfigureVfos = true; - break; - - #ifdef ENABLE_AUDIO_BAR - case MENU_MIC_BAR: - gSetting_mic_bar = gSubMenuSelection; - break; - #endif - - case MENU_COMPAND: - gTxVfo->Compander = gSubMenuSelection; - SETTINGS_UpdateChannel(gTxVfo->CHANNEL_SAVE, gTxVfo, true, false, true); - gVfoConfigureMode = VFO_CONFIGURE; - gFlagResetVfos = true; -// gRequestSaveChannel = 1; - return; - - case MENU_1_CALL: - gEeprom.CHAN_1_CALL = gSubMenuSelection; - break; - - case MENU_S_LIST: - gEeprom.SCAN_LIST_DEFAULT = gSubMenuSelection; - break; - - #ifdef ENABLE_ALARM - case MENU_AL_MOD: - gEeprom.ALARM_MODE = gSubMenuSelection; - break; - #endif - - case MENU_D_ST: - gEeprom.DTMF_SIDE_TONE = gSubMenuSelection; - break; + case MENU_BCL: + gTxVfo->BUSY_CHANNEL_LOCK = gSubMenuSelection; + gRequestSaveChannel = 1; + return; + + case MENU_MEM_CH: + gTxVfo->CHANNEL_SAVE = gSubMenuSelection; + #if 0 + gEeprom.MrChannel[0] = gSubMenuSelection; + #else + gEeprom.MrChannel[gEeprom.TX_VFO] = gSubMenuSelection; + #endif + gRequestSaveChannel = 2; + gVfoConfigureMode = VFO_CONFIGURE_RELOAD; + gFlagResetVfos = true; + return; + + case MENU_MEM_NAME: + for (int i = 9; i >= 0; i--) { + if (edit[i] != ' ' && edit[i] != '_' && edit[i] != 0x00 && edit[i] != 0xff) + break; + edit[i] = ' '; + } + + SETTINGS_SaveChannelName(gSubMenuSelection, edit); + return; + + case MENU_SAVE: + gEeprom.BATTERY_SAVE = gSubMenuSelection; + break; + + #ifdef ENABLE_VOX + case MENU_VOX: + gEeprom.VOX_SWITCH = gSubMenuSelection != 0; + if (gEeprom.VOX_SWITCH) + gEeprom.VOX_LEVEL = gSubMenuSelection - 1; + SETTINGS_LoadCalibration(); + gFlagReconfigureVfos = true; + gUpdateStatus = true; + break; + #endif + + case MENU_ABR: + gEeprom.BACKLIGHT_TIME = gSubMenuSelection; + #ifdef ENABLE_FEAT_F4HWN + gBackLight = false; + #endif + break; + + case MENU_ABR_MIN: + gEeprom.BACKLIGHT_MIN = gSubMenuSelection; + gEeprom.BACKLIGHT_MAX = MAX(gSubMenuSelection + 1 , gEeprom.BACKLIGHT_MAX); + break; + + case MENU_ABR_MAX: + gEeprom.BACKLIGHT_MAX = gSubMenuSelection; + gEeprom.BACKLIGHT_MIN = MIN(gSubMenuSelection - 1, gEeprom.BACKLIGHT_MIN); + break; + + case MENU_ABR_ON_TX_RX: + gSetting_backlight_on_tx_rx = gSubMenuSelection; + break; + + case MENU_TDR: + gEeprom.DUAL_WATCH = (gEeprom.TX_VFO + 1) * (gSubMenuSelection & 1); + gEeprom.CROSS_BAND_RX_TX = (gEeprom.TX_VFO + 1) * ((gSubMenuSelection & 2) > 0); + + #ifdef ENABLE_FEAT_F4HWN + gDW = gEeprom.DUAL_WATCH; + gCB = gEeprom.CROSS_BAND_RX_TX; + gSaveRxMode = true; + #endif + + gFlagReconfigureVfos = true; + gUpdateStatus = true; + break; + + case MENU_BEEP: + gEeprom.BEEP_CONTROL = gSubMenuSelection; + break; + + case MENU_TOT: + gEeprom.TX_TIMEOUT_TIMER = gSubMenuSelection; + break; + + #ifdef ENABLE_VOICE + case MENU_VOICE: + gEeprom.VOICE_PROMPT = gSubMenuSelection; + gUpdateStatus = true; + break; + #endif + + case MENU_SC_REV: + gEeprom.SCAN_RESUME_MODE = gSubMenuSelection; + break; + + case MENU_MDF: + gEeprom.CHANNEL_DISPLAY_MODE = gSubMenuSelection; + break; + + case MENU_AUTOLK: + gEeprom.AUTO_KEYPAD_LOCK = gSubMenuSelection; + gKeyLockCountdown = 30; + break; + + case MENU_S_ADD1: + gTxVfo->SCANLIST1_PARTICIPATION = gSubMenuSelection; + SETTINGS_UpdateChannel(gTxVfo->CHANNEL_SAVE, gTxVfo, true, false, true); + gVfoConfigureMode = VFO_CONFIGURE; + gFlagResetVfos = true; + return; + + case MENU_S_ADD2: + gTxVfo->SCANLIST2_PARTICIPATION = gSubMenuSelection; + SETTINGS_UpdateChannel(gTxVfo->CHANNEL_SAVE, gTxVfo, true, false, true); + gVfoConfigureMode = VFO_CONFIGURE; + gFlagResetVfos = true; + return; + + case MENU_S_ADD3: + gTxVfo->SCANLIST3_PARTICIPATION = gSubMenuSelection; + SETTINGS_UpdateChannel(gTxVfo->CHANNEL_SAVE, gTxVfo, true, false, true); + gVfoConfigureMode = VFO_CONFIGURE; + gFlagResetVfos = true; + return; + + case MENU_STE: + gEeprom.TAIL_TONE_ELIMINATION = gSubMenuSelection; + break; + + case MENU_RP_STE: + gEeprom.REPEATER_TAIL_TONE_ELIMINATION = gSubMenuSelection; + break; + + case MENU_MIC: + gEeprom.MIC_SENSITIVITY = gSubMenuSelection; + SETTINGS_LoadCalibration(); + gFlagReconfigureVfos = true; + break; + + #ifdef ENABLE_AUDIO_BAR + case MENU_MIC_BAR: + gSetting_mic_bar = gSubMenuSelection; + break; + #endif + + case MENU_COMPAND: + gTxVfo->Compander = gSubMenuSelection; + SETTINGS_UpdateChannel(gTxVfo->CHANNEL_SAVE, gTxVfo, true, false, true); + gVfoConfigureMode = VFO_CONFIGURE; + gFlagResetVfos = true; +// gRequestSaveChannel = 1; + return; + + case MENU_1_CALL: + gEeprom.CHAN_1_CALL = gSubMenuSelection; + break; + + case MENU_S_LIST: + gEeprom.SCAN_LIST_DEFAULT = gSubMenuSelection; + break; + + #ifdef ENABLE_ALARM + case MENU_AL_MOD: + gEeprom.ALARM_MODE = gSubMenuSelection; + break; + #endif + + case MENU_D_ST: + gEeprom.DTMF_SIDE_TONE = gSubMenuSelection; + break; #ifdef ENABLE_DTMF_CALLING - case MENU_D_RSP: - gEeprom.DTMF_DECODE_RESPONSE = gSubMenuSelection; - break; + case MENU_D_RSP: + gEeprom.DTMF_DECODE_RESPONSE = gSubMenuSelection; + break; - case MENU_D_HOLD: - gEeprom.DTMF_auto_reset_time = gSubMenuSelection; - break; + case MENU_D_HOLD: + gEeprom.DTMF_auto_reset_time = gSubMenuSelection; + break; #endif - case MENU_D_PRE: - gEeprom.DTMF_PRELOAD_TIME = gSubMenuSelection * 10; - break; + case MENU_D_PRE: + gEeprom.DTMF_PRELOAD_TIME = gSubMenuSelection * 10; + break; - case MENU_PTT_ID: - gTxVfo->DTMF_PTT_ID_TX_MODE = gSubMenuSelection; - gRequestSaveChannel = 1; - return; + case MENU_PTT_ID: + gTxVfo->DTMF_PTT_ID_TX_MODE = gSubMenuSelection; + gRequestSaveChannel = 1; + return; - case MENU_BAT_TXT: - gSetting_battery_text = gSubMenuSelection; - break; + case MENU_BAT_TXT: + gSetting_battery_text = gSubMenuSelection; + break; #ifdef ENABLE_DTMF_CALLING - case MENU_D_DCD: - gTxVfo->DTMF_DECODING_ENABLE = gSubMenuSelection; - DTMF_clear_RX(); - gRequestSaveChannel = 1; - return; + case MENU_D_DCD: + gTxVfo->DTMF_DECODING_ENABLE = gSubMenuSelection; + DTMF_clear_RX(); + gRequestSaveChannel = 1; + return; #endif - case MENU_D_LIVE_DEC: - gSetting_live_DTMF_decoder = gSubMenuSelection; - gDTMF_RX_live_timeout = 0; - memset(gDTMF_RX_live, 0, sizeof(gDTMF_RX_live)); - if (!gSetting_live_DTMF_decoder) - BK4819_DisableDTMF(); - gFlagReconfigureVfos = true; - gUpdateStatus = true; - break; + case MENU_D_LIVE_DEC: + gSetting_live_DTMF_decoder = gSubMenuSelection; + gDTMF_RX_live_timeout = 0; + memset(gDTMF_RX_live, 0, sizeof(gDTMF_RX_live)); + if (!gSetting_live_DTMF_decoder) + BK4819_DisableDTMF(); + gFlagReconfigureVfos = true; + gUpdateStatus = true; + break; #ifdef ENABLE_DTMF_CALLING - case MENU_D_LIST: - gDTMF_chosen_contact = gSubMenuSelection - 1; - if (gIsDtmfContactValid) - { - GUI_SelectNextDisplay(DISPLAY_MAIN); - gDTMF_InputMode = true; - gDTMF_InputBox_Index = 3; - memcpy(gDTMF_InputBox, gDTMF_ID, 4); - gRequestDisplayScreen = DISPLAY_INVALID; - } - return; + case MENU_D_LIST: + gDTMF_chosen_contact = gSubMenuSelection - 1; + if (gIsDtmfContactValid) + { + GUI_SelectNextDisplay(DISPLAY_MAIN); + gDTMF_InputMode = true; + gDTMF_InputBox_Index = 3; + memcpy(gDTMF_InputBox, gDTMF_ID, 4); + gRequestDisplayScreen = DISPLAY_INVALID; + } + return; #endif - case MENU_PONMSG: - gEeprom.POWER_ON_DISPLAY_MODE = gSubMenuSelection; - break; - - case MENU_ROGER: - gEeprom.ROGER = gSubMenuSelection; - break; - - case MENU_AM: - gTxVfo->Modulation = gSubMenuSelection; - gRequestSaveChannel = 1; - return; - - #ifndef ENABLE_FEAT_F4HWN - #ifdef ENABLE_AM_FIX - case MENU_AM_FIX: - gSetting_AM_fix = gSubMenuSelection; - gVfoConfigureMode = VFO_CONFIGURE_RELOAD; - gFlagResetVfos = true; - break; - #endif - #endif - - #ifdef ENABLE_NOAA - case MENU_NOAA_S: - gEeprom.NOAA_AUTO_SCAN = gSubMenuSelection; - gFlagReconfigureVfos = true; - break; - #endif - - case MENU_DEL_CH: - SETTINGS_UpdateChannel(gSubMenuSelection, NULL, false, false, true); - gVfoConfigureMode = VFO_CONFIGURE_RELOAD; - gFlagResetVfos = true; - return; - - case MENU_RESET: - SETTINGS_FactoryReset(gSubMenuSelection); - return; - - case MENU_350TX: - gSetting_350TX = gSubMenuSelection; - break; - - case MENU_F_LOCK: { - if(gSubMenuSelection == F_LOCK_NONE) { // select 10 times to enable - gUnlockAllTxConfCnt++; + case MENU_PONMSG: + gEeprom.POWER_ON_DISPLAY_MODE = gSubMenuSelection; + break; + + case MENU_ROGER: + gEeprom.ROGER = gSubMenuSelection; + break; + + case MENU_AM: + gTxVfo->Modulation = gSubMenuSelection; + gRequestSaveChannel = 1; + return; + + #ifndef ENABLE_FEAT_F4HWN + #ifdef ENABLE_AM_FIX + case MENU_AM_FIX: + gSetting_AM_fix = gSubMenuSelection; + gVfoConfigureMode = VFO_CONFIGURE_RELOAD; + gFlagResetVfos = true; + break; + #endif + #endif + + #ifdef ENABLE_NOAA + case MENU_NOAA_S: + gEeprom.NOAA_AUTO_SCAN = gSubMenuSelection; + gFlagReconfigureVfos = true; + break; + #endif + + case MENU_DEL_CH: + SETTINGS_UpdateChannel(gSubMenuSelection, NULL, false, false, true); + gVfoConfigureMode = VFO_CONFIGURE_RELOAD; + gFlagResetVfos = true; + return; + + case MENU_RESET: + SETTINGS_FactoryReset(gSubMenuSelection); + return; + + case MENU_350TX: + gSetting_350TX = gSubMenuSelection; + break; + + case MENU_F_LOCK: { + if(gSubMenuSelection == F_LOCK_NONE) { // select 10 times to enable + gUnlockAllTxConfCnt++; #ifdef ENABLE_FEAT_F4HWN - if(gUnlockAllTxConfCnt < 3) + if(gUnlockAllTxConfCnt < 3) #else - if(gUnlockAllTxConfCnt < 10) + if(gUnlockAllTxConfCnt < 10) #endif - return; - } - else - gUnlockAllTxConfCnt = 0; - - gSetting_F_LOCK = gSubMenuSelection; - break; - } - case MENU_200TX: - gSetting_200TX = gSubMenuSelection; - break; - - case MENU_500TX: - gSetting_500TX = gSubMenuSelection; - break; - - case MENU_350EN: - gSetting_350EN = gSubMenuSelection; - gVfoConfigureMode = VFO_CONFIGURE_RELOAD; - gFlagResetVfos = true; - break; + return; + } + else + gUnlockAllTxConfCnt = 0; + + gSetting_F_LOCK = gSubMenuSelection; + break; + } + case MENU_200TX: + gSetting_200TX = gSubMenuSelection; + break; + + case MENU_500TX: + gSetting_500TX = gSubMenuSelection; + break; + + case MENU_350EN: + gSetting_350EN = gSubMenuSelection; + gVfoConfigureMode = VFO_CONFIGURE_RELOAD; + gFlagResetVfos = true; + break; #ifndef ENABLE_FEAT_F4HWN - case MENU_SCREN: - gSetting_ScrambleEnable = gSubMenuSelection; - gFlagReconfigureVfos = true; - break; + case MENU_SCREN: + gSetting_ScrambleEnable = gSubMenuSelection; + gFlagReconfigureVfos = true; + break; #endif - #ifdef ENABLE_F_CAL_MENU - case MENU_F_CALI: - writeXtalFreqCal(gSubMenuSelection, true); - return; - #endif - - case MENU_BATCAL: - { // voltages are averages between discharge curves of 1600 and 2200 mAh - // gBatteryCalibration[0] = (520ul * gSubMenuSelection) / 760; // 5.20V empty, blinking above this value, reduced functionality below - // gBatteryCalibration[1] = (689ul * gSubMenuSelection) / 760; // 6.89V, ~5%, 1 bars above this value - // gBatteryCalibration[2] = (724ul * gSubMenuSelection) / 760; // 7.24V, ~17%, 2 bars above this value - gBatteryCalibration[3] = gSubMenuSelection; // 7.6V, ~29%, 3 bars above this value - // gBatteryCalibration[4] = (771ul * gSubMenuSelection) / 760; // 7.71V, ~65%, 4 bars above this value - // gBatteryCalibration[5] = 2300; - SETTINGS_SaveBatteryCalibration(gBatteryCalibration); - return; - } - - case MENU_BATTYP: - gEeprom.BATTERY_TYPE = gSubMenuSelection; - break; - - case MENU_F1SHRT: - case MENU_F1LONG: - case MENU_F2SHRT: - case MENU_F2LONG: - case MENU_MLONG: - { - uint8_t * fun[]= { - &gEeprom.KEY_1_SHORT_PRESS_ACTION, - &gEeprom.KEY_1_LONG_PRESS_ACTION, - &gEeprom.KEY_2_SHORT_PRESS_ACTION, - &gEeprom.KEY_2_LONG_PRESS_ACTION, - &gEeprom.KEY_M_LONG_PRESS_ACTION}; - *fun[UI_MENU_GetCurrentMenuId()-MENU_F1SHRT] = gSubMenu_SIDEFUNCTIONS[gSubMenuSelection].id; - } - break; + #ifdef ENABLE_F_CAL_MENU + case MENU_F_CALI: + writeXtalFreqCal(gSubMenuSelection, true); + return; + #endif + + case MENU_BATCAL: + { // voltages are averages between discharge curves of 1600 and 2200 mAh + // gBatteryCalibration[0] = (520ul * gSubMenuSelection) / 760; // 5.20V empty, blinking above this value, reduced functionality below + // gBatteryCalibration[1] = (689ul * gSubMenuSelection) / 760; // 6.89V, ~5%, 1 bars above this value + // gBatteryCalibration[2] = (724ul * gSubMenuSelection) / 760; // 7.24V, ~17%, 2 bars above this value + gBatteryCalibration[3] = gSubMenuSelection; // 7.6V, ~29%, 3 bars above this value + // gBatteryCalibration[4] = (771ul * gSubMenuSelection) / 760; // 7.71V, ~65%, 4 bars above this value + // gBatteryCalibration[5] = 2300; + SETTINGS_SaveBatteryCalibration(gBatteryCalibration); + return; + } + + case MENU_BATTYP: + gEeprom.BATTERY_TYPE = gSubMenuSelection; + break; + + case MENU_F1SHRT: + case MENU_F1LONG: + case MENU_F2SHRT: + case MENU_F2LONG: + case MENU_MLONG: + { + uint8_t * fun[]= { + &gEeprom.KEY_1_SHORT_PRESS_ACTION, + &gEeprom.KEY_1_LONG_PRESS_ACTION, + &gEeprom.KEY_2_SHORT_PRESS_ACTION, + &gEeprom.KEY_2_LONG_PRESS_ACTION, + &gEeprom.KEY_M_LONG_PRESS_ACTION}; + *fun[UI_MENU_GetCurrentMenuId()-MENU_F1SHRT] = gSubMenu_SIDEFUNCTIONS[gSubMenuSelection].id; + } + break; #ifdef ENABLE_FEAT_F4HWN - case MENU_SET_PWR: - gSetting_set_pwr = gSubMenuSelection; - gRequestSaveChannel = 1; - break; - case MENU_SET_PTT: - gSetting_set_ptt = gSubMenuSelection; - gSetting_set_ptt_session = gSetting_set_ptt; // Special for action - break; - case MENU_SET_TOT: - gSetting_set_tot = gSubMenuSelection; - break; - case MENU_SET_EOT: - gSetting_set_eot = gSubMenuSelection; - break; - case MENU_SET_CTR: - gSetting_set_ctr = gSubMenuSelection; - break; - case MENU_SET_INV: - gSetting_set_inv = gSubMenuSelection; - break; - case MENU_SET_LCK: - gSetting_set_lck = gSubMenuSelection; - break; - case MENU_SET_MET: - gSetting_set_met = gSubMenuSelection; - break; - case MENU_SET_GUI: - gSetting_set_gui = gSubMenuSelection; - break; - case MENU_SET_TMR: - gSetting_set_tmr = gSubMenuSelection; - break; - case MENU_TX_LOCK: - gTxVfo->TX_LOCK = gSubMenuSelection; - gRequestSaveChannel = 1; - return; + case MENU_SET_PWR: + gSetting_set_pwr = gSubMenuSelection; + gRequestSaveChannel = 1; + break; + case MENU_SET_PTT: + gSetting_set_ptt = gSubMenuSelection; + gSetting_set_ptt_session = gSetting_set_ptt; // Special for action + break; + case MENU_SET_TOT: + gSetting_set_tot = gSubMenuSelection; + break; + case MENU_SET_EOT: + gSetting_set_eot = gSubMenuSelection; + break; + case MENU_SET_CTR: + gSetting_set_ctr = gSubMenuSelection; + break; + case MENU_SET_INV: + gSetting_set_inv = gSubMenuSelection; + break; + case MENU_SET_LCK: + gSetting_set_lck = gSubMenuSelection; + break; + case MENU_SET_MET: + gSetting_set_met = gSubMenuSelection; + break; + case MENU_SET_GUI: + gSetting_set_gui = gSubMenuSelection; + break; + case MENU_SET_TMR: + gSetting_set_tmr = gSubMenuSelection; + break; + case MENU_TX_LOCK: + gTxVfo->TX_LOCK = gSubMenuSelection; + gRequestSaveChannel = 1; + return; #endif - } + } - gRequestSaveSettings = true; + gRequestSaveSettings = true; } static void MENU_ClampSelection(int8_t Direction) { - int32_t Min; - int32_t Max; - - if (!MENU_GetLimits(UI_MENU_GetCurrentMenuId(), &Min, &Max)) - { - int32_t Selection = gSubMenuSelection; - if (Selection < Min) Selection = Min; - else - if (Selection > Max) Selection = Max; - gSubMenuSelection = NUMBER_AddWithWraparound(Selection, Direction, Min, Max); - } + int32_t Min; + int32_t Max; + + if (!MENU_GetLimits(UI_MENU_GetCurrentMenuId(), &Min, &Max)) + { + int32_t Selection = gSubMenuSelection; + if (Selection < Min) Selection = Min; + else + if (Selection > Max) Selection = Max; + gSubMenuSelection = NUMBER_AddWithWraparound(Selection, Direction, Min, Max); + } } void MENU_ShowCurrentSetting(void) { - switch (UI_MENU_GetCurrentMenuId()) - { - case MENU_SQL: - gSubMenuSelection = gEeprom.SQUELCH_LEVEL; - break; - - case MENU_STEP: - gSubMenuSelection = FREQUENCY_GetSortedIdxFromStepIdx(gTxVfo->STEP_SETTING); - break; - - case MENU_TXP: - gSubMenuSelection = gTxVfo->OUTPUT_POWER; - break; - - case MENU_RESET: - gSubMenuSelection = 0; - break; - - case MENU_R_DCS: - case MENU_R_CTCS: - { - DCS_CodeType_t type = gTxVfo->freq_config_RX.CodeType; - uint8_t code = gTxVfo->freq_config_RX.Code; - int menuid = UI_MENU_GetCurrentMenuId(); - - if(gScanUseCssResult) { - gScanUseCssResult = false; - type = gScanCssResultType; - code = gScanCssResultCode; - } - if((menuid==MENU_R_CTCS) ^ (type==CODE_TYPE_CONTINUOUS_TONE)) { //not the same type - gSubMenuSelection = 0; - break; - } - - switch (type) { - case CODE_TYPE_CONTINUOUS_TONE: - case CODE_TYPE_DIGITAL: - gSubMenuSelection = code + 1; - break; - case CODE_TYPE_REVERSE_DIGITAL: - gSubMenuSelection = code + 105; - break; - default: - gSubMenuSelection = 0; - break; - } - break; - } - - case MENU_T_DCS: - switch (gTxVfo->freq_config_TX.CodeType) - { - case CODE_TYPE_DIGITAL: - gSubMenuSelection = gTxVfo->freq_config_TX.Code + 1; - break; - case CODE_TYPE_REVERSE_DIGITAL: - gSubMenuSelection = gTxVfo->freq_config_TX.Code + 105; - break; - default: - gSubMenuSelection = 0; - break; - } - break; - - case MENU_T_CTCS: - gSubMenuSelection = (gTxVfo->freq_config_TX.CodeType == CODE_TYPE_CONTINUOUS_TONE) ? gTxVfo->freq_config_TX.Code + 1 : 0; - break; - - case MENU_SFT_D: - gSubMenuSelection = gTxVfo->TX_OFFSET_FREQUENCY_DIRECTION; - break; - - case MENU_OFFSET: - gSubMenuSelection = gTxVfo->TX_OFFSET_FREQUENCY; - break; - - case MENU_W_N: - gSubMenuSelection = gTxVfo->CHANNEL_BANDWIDTH; - break; + switch (UI_MENU_GetCurrentMenuId()) + { + case MENU_SQL: + gSubMenuSelection = gEeprom.SQUELCH_LEVEL; + break; + + case MENU_STEP: + gSubMenuSelection = FREQUENCY_GetSortedIdxFromStepIdx(gTxVfo->STEP_SETTING); + break; + + case MENU_TXP: + gSubMenuSelection = gTxVfo->OUTPUT_POWER; + break; + + case MENU_RESET: + gSubMenuSelection = 0; + break; + + case MENU_R_DCS: + case MENU_R_CTCS: + { + DCS_CodeType_t type = gTxVfo->freq_config_RX.CodeType; + uint8_t code = gTxVfo->freq_config_RX.Code; + int menuid = UI_MENU_GetCurrentMenuId(); + + if(gScanUseCssResult) { + gScanUseCssResult = false; + type = gScanCssResultType; + code = gScanCssResultCode; + } + if((menuid==MENU_R_CTCS) ^ (type==CODE_TYPE_CONTINUOUS_TONE)) { //not the same type + gSubMenuSelection = 0; + break; + } + + switch (type) { + case CODE_TYPE_CONTINUOUS_TONE: + case CODE_TYPE_DIGITAL: + gSubMenuSelection = code + 1; + break; + case CODE_TYPE_REVERSE_DIGITAL: + gSubMenuSelection = code + 105; + break; + default: + gSubMenuSelection = 0; + break; + } + break; + } + + case MENU_T_DCS: + switch (gTxVfo->freq_config_TX.CodeType) + { + case CODE_TYPE_DIGITAL: + gSubMenuSelection = gTxVfo->freq_config_TX.Code + 1; + break; + case CODE_TYPE_REVERSE_DIGITAL: + gSubMenuSelection = gTxVfo->freq_config_TX.Code + 105; + break; + default: + gSubMenuSelection = 0; + break; + } + break; + + case MENU_T_CTCS: + gSubMenuSelection = (gTxVfo->freq_config_TX.CodeType == CODE_TYPE_CONTINUOUS_TONE) ? gTxVfo->freq_config_TX.Code + 1 : 0; + break; + + case MENU_SFT_D: + gSubMenuSelection = gTxVfo->TX_OFFSET_FREQUENCY_DIRECTION; + break; + + case MENU_OFFSET: + gSubMenuSelection = gTxVfo->TX_OFFSET_FREQUENCY; + break; + + case MENU_W_N: + gSubMenuSelection = gTxVfo->CHANNEL_BANDWIDTH; + break; #ifndef ENABLE_FEAT_F4HWN - case MENU_SCR: - gSubMenuSelection = gTxVfo->SCRAMBLING_TYPE; - break; + case MENU_SCR: + gSubMenuSelection = gTxVfo->SCRAMBLING_TYPE; + break; #endif - case MENU_BCL: - gSubMenuSelection = gTxVfo->BUSY_CHANNEL_LOCK; - break; + case MENU_BCL: + gSubMenuSelection = gTxVfo->BUSY_CHANNEL_LOCK; + break; - case MENU_MEM_CH: - #if 0 - gSubMenuSelection = gEeprom.MrChannel[0]; - #else - gSubMenuSelection = gEeprom.MrChannel[gEeprom.TX_VFO]; - #endif - break; + case MENU_MEM_CH: + #if 0 + gSubMenuSelection = gEeprom.MrChannel[0]; + #else + gSubMenuSelection = gEeprom.MrChannel[gEeprom.TX_VFO]; + #endif + break; - case MENU_MEM_NAME: - gSubMenuSelection = gEeprom.MrChannel[gEeprom.TX_VFO]; - break; + case MENU_MEM_NAME: + gSubMenuSelection = gEeprom.MrChannel[gEeprom.TX_VFO]; + break; - case MENU_SAVE: - gSubMenuSelection = gEeprom.BATTERY_SAVE; - break; + case MENU_SAVE: + gSubMenuSelection = gEeprom.BATTERY_SAVE; + break; #ifdef ENABLE_VOX - case MENU_VOX: - gSubMenuSelection = gEeprom.VOX_SWITCH ? gEeprom.VOX_LEVEL + 1 : 0; - break; + case MENU_VOX: + gSubMenuSelection = gEeprom.VOX_SWITCH ? gEeprom.VOX_LEVEL + 1 : 0; + break; #endif - case MENU_ABR: - #ifdef ENABLE_FEAT_F4HWN - if(gBackLight) - { - gSubMenuSelection = gBacklightTimeOriginal; - } - else - { - gSubMenuSelection = gEeprom.BACKLIGHT_TIME; - } - #else - gSubMenuSelection = gEeprom.BACKLIGHT_TIME; - #endif - break; - - case MENU_ABR_MIN: - gSubMenuSelection = gEeprom.BACKLIGHT_MIN; - break; - - case MENU_ABR_MAX: - gSubMenuSelection = gEeprom.BACKLIGHT_MAX; - break; - - case MENU_ABR_ON_TX_RX: - gSubMenuSelection = gSetting_backlight_on_tx_rx; - break; - - case MENU_TDR: - gSubMenuSelection = (gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) + (gEeprom.CROSS_BAND_RX_TX != CROSS_BAND_OFF) * 2; - break; - - case MENU_BEEP: - gSubMenuSelection = gEeprom.BEEP_CONTROL; - break; - - case MENU_TOT: - gSubMenuSelection = gEeprom.TX_TIMEOUT_TIMER; - break; + case MENU_ABR: + #ifdef ENABLE_FEAT_F4HWN + if(gBackLight) + { + gSubMenuSelection = gBacklightTimeOriginal; + } + else + { + gSubMenuSelection = gEeprom.BACKLIGHT_TIME; + } + #else + gSubMenuSelection = gEeprom.BACKLIGHT_TIME; + #endif + break; + + case MENU_ABR_MIN: + gSubMenuSelection = gEeprom.BACKLIGHT_MIN; + break; + + case MENU_ABR_MAX: + gSubMenuSelection = gEeprom.BACKLIGHT_MAX; + break; + + case MENU_ABR_ON_TX_RX: + gSubMenuSelection = gSetting_backlight_on_tx_rx; + break; + + case MENU_TDR: + gSubMenuSelection = (gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) + (gEeprom.CROSS_BAND_RX_TX != CROSS_BAND_OFF) * 2; + break; + + case MENU_BEEP: + gSubMenuSelection = gEeprom.BEEP_CONTROL; + break; + + case MENU_TOT: + gSubMenuSelection = gEeprom.TX_TIMEOUT_TIMER; + break; #ifdef ENABLE_VOICE - case MENU_VOICE: - gSubMenuSelection = gEeprom.VOICE_PROMPT; - break; + case MENU_VOICE: + gSubMenuSelection = gEeprom.VOICE_PROMPT; + break; #endif - case MENU_SC_REV: - gSubMenuSelection = gEeprom.SCAN_RESUME_MODE; - break; + case MENU_SC_REV: + gSubMenuSelection = gEeprom.SCAN_RESUME_MODE; + break; - case MENU_MDF: - gSubMenuSelection = gEeprom.CHANNEL_DISPLAY_MODE; - break; + case MENU_MDF: + gSubMenuSelection = gEeprom.CHANNEL_DISPLAY_MODE; + break; - case MENU_AUTOLK: - gSubMenuSelection = gEeprom.AUTO_KEYPAD_LOCK; - break; + case MENU_AUTOLK: + gSubMenuSelection = gEeprom.AUTO_KEYPAD_LOCK; + break; - case MENU_S_ADD1: - gSubMenuSelection = gTxVfo->SCANLIST1_PARTICIPATION; - break; + case MENU_S_ADD1: + gSubMenuSelection = gTxVfo->SCANLIST1_PARTICIPATION; + break; - case MENU_S_ADD2: - gSubMenuSelection = gTxVfo->SCANLIST2_PARTICIPATION; - break; + case MENU_S_ADD2: + gSubMenuSelection = gTxVfo->SCANLIST2_PARTICIPATION; + break; - case MENU_S_ADD3: - gSubMenuSelection = gTxVfo->SCANLIST3_PARTICIPATION; - break; + case MENU_S_ADD3: + gSubMenuSelection = gTxVfo->SCANLIST3_PARTICIPATION; + break; - case MENU_STE: - gSubMenuSelection = gEeprom.TAIL_TONE_ELIMINATION; - break; + case MENU_STE: + gSubMenuSelection = gEeprom.TAIL_TONE_ELIMINATION; + break; - case MENU_RP_STE: - gSubMenuSelection = gEeprom.REPEATER_TAIL_TONE_ELIMINATION; - break; + case MENU_RP_STE: + gSubMenuSelection = gEeprom.REPEATER_TAIL_TONE_ELIMINATION; + break; - case MENU_MIC: - gSubMenuSelection = gEeprom.MIC_SENSITIVITY; - break; + case MENU_MIC: + gSubMenuSelection = gEeprom.MIC_SENSITIVITY; + break; #ifdef ENABLE_AUDIO_BAR - case MENU_MIC_BAR: - gSubMenuSelection = gSetting_mic_bar; - break; + case MENU_MIC_BAR: + gSubMenuSelection = gSetting_mic_bar; + break; #endif - case MENU_COMPAND: - gSubMenuSelection = gTxVfo->Compander; - return; + case MENU_COMPAND: + gSubMenuSelection = gTxVfo->Compander; + return; - case MENU_1_CALL: - gSubMenuSelection = gEeprom.CHAN_1_CALL; - break; + case MENU_1_CALL: + gSubMenuSelection = gEeprom.CHAN_1_CALL; + break; - case MENU_S_LIST: - gSubMenuSelection = gEeprom.SCAN_LIST_DEFAULT; - break; + case MENU_S_LIST: + gSubMenuSelection = gEeprom.SCAN_LIST_DEFAULT; + break; - case MENU_SLIST1: - gSubMenuSelection = RADIO_FindNextChannel(0, 1, true, 1); - break; + case MENU_SLIST1: + gSubMenuSelection = RADIO_FindNextChannel(0, 1, true, 1); + break; - case MENU_SLIST2: - gSubMenuSelection = RADIO_FindNextChannel(0, 1, true, 2); - break; + case MENU_SLIST2: + gSubMenuSelection = RADIO_FindNextChannel(0, 1, true, 2); + break; - case MENU_SLIST3: - gSubMenuSelection = RADIO_FindNextChannel(0, 1, true, 3); - break; + case MENU_SLIST3: + gSubMenuSelection = RADIO_FindNextChannel(0, 1, true, 3); + break; - #ifdef ENABLE_ALARM - case MENU_AL_MOD: - gSubMenuSelection = gEeprom.ALARM_MODE; - break; - #endif + #ifdef ENABLE_ALARM + case MENU_AL_MOD: + gSubMenuSelection = gEeprom.ALARM_MODE; + break; + #endif - case MENU_D_ST: - gSubMenuSelection = gEeprom.DTMF_SIDE_TONE; - break; + case MENU_D_ST: + gSubMenuSelection = gEeprom.DTMF_SIDE_TONE; + break; #ifdef ENABLE_DTMF_CALLING - case MENU_D_RSP: - gSubMenuSelection = gEeprom.DTMF_DECODE_RESPONSE; - break; + case MENU_D_RSP: + gSubMenuSelection = gEeprom.DTMF_DECODE_RESPONSE; + break; - case MENU_D_HOLD: - gSubMenuSelection = gEeprom.DTMF_auto_reset_time; - break; + case MENU_D_HOLD: + gSubMenuSelection = gEeprom.DTMF_auto_reset_time; + break; #endif - case MENU_D_PRE: - gSubMenuSelection = gEeprom.DTMF_PRELOAD_TIME / 10; - break; + case MENU_D_PRE: + gSubMenuSelection = gEeprom.DTMF_PRELOAD_TIME / 10; + break; - case MENU_PTT_ID: - gSubMenuSelection = gTxVfo->DTMF_PTT_ID_TX_MODE; - break; + case MENU_PTT_ID: + gSubMenuSelection = gTxVfo->DTMF_PTT_ID_TX_MODE; + break; - case MENU_BAT_TXT: - gSubMenuSelection = gSetting_battery_text; - return; + case MENU_BAT_TXT: + gSubMenuSelection = gSetting_battery_text; + return; #ifdef ENABLE_DTMF_CALLING - case MENU_D_DCD: - gSubMenuSelection = gTxVfo->DTMF_DECODING_ENABLE; - break; + case MENU_D_DCD: + gSubMenuSelection = gTxVfo->DTMF_DECODING_ENABLE; + break; - case MENU_D_LIST: - gSubMenuSelection = gDTMF_chosen_contact + 1; - break; + case MENU_D_LIST: + gSubMenuSelection = gDTMF_chosen_contact + 1; + break; #endif - case MENU_D_LIVE_DEC: - gSubMenuSelection = gSetting_live_DTMF_decoder; - break; + case MENU_D_LIVE_DEC: + gSubMenuSelection = gSetting_live_DTMF_decoder; + break; - case MENU_PONMSG: - gSubMenuSelection = gEeprom.POWER_ON_DISPLAY_MODE; - break; + case MENU_PONMSG: + gSubMenuSelection = gEeprom.POWER_ON_DISPLAY_MODE; + break; - case MENU_ROGER: - gSubMenuSelection = gEeprom.ROGER; - break; + case MENU_ROGER: + gSubMenuSelection = gEeprom.ROGER; + break; - case MENU_AM: - gSubMenuSelection = gTxVfo->Modulation; - break; + case MENU_AM: + gSubMenuSelection = gTxVfo->Modulation; + break; #ifndef ENABLE_FEAT_F4HWN - #ifdef ENABLE_AM_FIX - case MENU_AM_FIX: - gSubMenuSelection = gSetting_AM_fix; - break; - #endif + #ifdef ENABLE_AM_FIX + case MENU_AM_FIX: + gSubMenuSelection = gSetting_AM_fix; + break; + #endif #endif - - #ifdef ENABLE_NOAA - case MENU_NOAA_S: - gSubMenuSelection = gEeprom.NOAA_AUTO_SCAN; - break; - #endif - - case MENU_DEL_CH: - #if 0 - gSubMenuSelection = RADIO_FindNextChannel(gEeprom.MrChannel[0], 1, false, 1); - #else - gSubMenuSelection = RADIO_FindNextChannel(gEeprom.MrChannel[gEeprom.TX_VFO], 1, false, 1); - #endif - break; - - case MENU_350TX: - gSubMenuSelection = gSetting_350TX; - break; - - case MENU_F_LOCK: - gSubMenuSelection = gSetting_F_LOCK; - break; - - case MENU_200TX: - gSubMenuSelection = gSetting_200TX; - break; - - case MENU_500TX: - gSubMenuSelection = gSetting_500TX; - break; - - case MENU_350EN: - gSubMenuSelection = gSetting_350EN; - break; + + #ifdef ENABLE_NOAA + case MENU_NOAA_S: + gSubMenuSelection = gEeprom.NOAA_AUTO_SCAN; + break; + #endif + + case MENU_DEL_CH: + #if 0 + gSubMenuSelection = RADIO_FindNextChannel(gEeprom.MrChannel[0], 1, false, 1); + #else + gSubMenuSelection = RADIO_FindNextChannel(gEeprom.MrChannel[gEeprom.TX_VFO], 1, false, 1); + #endif + break; + + case MENU_350TX: + gSubMenuSelection = gSetting_350TX; + break; + + case MENU_F_LOCK: + gSubMenuSelection = gSetting_F_LOCK; + break; + + case MENU_200TX: + gSubMenuSelection = gSetting_200TX; + break; + + case MENU_500TX: + gSubMenuSelection = gSetting_500TX; + break; + + case MENU_350EN: + gSubMenuSelection = gSetting_350EN; + break; #ifndef ENABLE_FEAT_F4HWN - case MENU_SCREN: - gSubMenuSelection = gSetting_ScrambleEnable; - break; + case MENU_SCREN: + gSubMenuSelection = gSetting_ScrambleEnable; + break; #endif - #ifdef ENABLE_F_CAL_MENU - case MENU_F_CALI: - gSubMenuSelection = gEeprom.BK4819_XTAL_FREQ_LOW; - break; - #endif - - case MENU_BATCAL: - gSubMenuSelection = gBatteryCalibration[3]; - break; - - case MENU_BATTYP: - gSubMenuSelection = gEeprom.BATTERY_TYPE; - break; - - case MENU_F1SHRT: - case MENU_F1LONG: - case MENU_F2SHRT: - case MENU_F2LONG: - case MENU_MLONG: - { - uint8_t * fun[]= { - &gEeprom.KEY_1_SHORT_PRESS_ACTION, - &gEeprom.KEY_1_LONG_PRESS_ACTION, - &gEeprom.KEY_2_SHORT_PRESS_ACTION, - &gEeprom.KEY_2_LONG_PRESS_ACTION, - &gEeprom.KEY_M_LONG_PRESS_ACTION}; - uint8_t id = *fun[UI_MENU_GetCurrentMenuId()-MENU_F1SHRT]; - - for(int i = 0; i < gSubMenu_SIDEFUNCTIONS_size; i++) { - if(gSubMenu_SIDEFUNCTIONS[i].id==id) { - gSubMenuSelection = i; - break; - } - - } - break; - } + #ifdef ENABLE_F_CAL_MENU + case MENU_F_CALI: + gSubMenuSelection = gEeprom.BK4819_XTAL_FREQ_LOW; + break; + #endif + + case MENU_BATCAL: + gSubMenuSelection = gBatteryCalibration[3]; + break; + + case MENU_BATTYP: + gSubMenuSelection = gEeprom.BATTERY_TYPE; + break; + + case MENU_F1SHRT: + case MENU_F1LONG: + case MENU_F2SHRT: + case MENU_F2LONG: + case MENU_MLONG: + { + uint8_t * fun[]= { + &gEeprom.KEY_1_SHORT_PRESS_ACTION, + &gEeprom.KEY_1_LONG_PRESS_ACTION, + &gEeprom.KEY_2_SHORT_PRESS_ACTION, + &gEeprom.KEY_2_LONG_PRESS_ACTION, + &gEeprom.KEY_M_LONG_PRESS_ACTION}; + uint8_t id = *fun[UI_MENU_GetCurrentMenuId()-MENU_F1SHRT]; + + for(int i = 0; i < gSubMenu_SIDEFUNCTIONS_size; i++) { + if(gSubMenu_SIDEFUNCTIONS[i].id==id) { + gSubMenuSelection = i; + break; + } + + } + break; + } #ifdef ENABLE_FEAT_F4HWN - case MENU_SET_PWR: - gSubMenuSelection = gSetting_set_pwr; - break; - case MENU_SET_PTT: - gSubMenuSelection = gSetting_set_ptt_session; - break; - case MENU_SET_TOT: - gSubMenuSelection = gSetting_set_tot; - break; + case MENU_SET_PWR: + gSubMenuSelection = gSetting_set_pwr; + break; + case MENU_SET_PTT: + gSubMenuSelection = gSetting_set_ptt_session; + break; + case MENU_SET_TOT: + gSubMenuSelection = gSetting_set_tot; + break; case MENU_SET_EOT: - gSubMenuSelection = gSetting_set_eot; - break; - case MENU_SET_CTR: - gSubMenuSelection = gSetting_set_ctr; - break; + gSubMenuSelection = gSetting_set_eot; + break; + case MENU_SET_CTR: + gSubMenuSelection = gSetting_set_ctr; + break; case MENU_SET_INV: - gSubMenuSelection = gSetting_set_inv; - break; + gSubMenuSelection = gSetting_set_inv; + break; case MENU_SET_LCK: - gSubMenuSelection = gSetting_set_lck; - break; - case MENU_SET_MET: - gSubMenuSelection = gSetting_set_met; - break; - case MENU_SET_GUI: - gSubMenuSelection = gSetting_set_gui; - break; - case MENU_SET_TMR: - gSubMenuSelection = gSetting_set_tmr; - break; - case MENU_TX_LOCK: - gSubMenuSelection = gTxVfo->TX_LOCK; - break; + gSubMenuSelection = gSetting_set_lck; + break; + case MENU_SET_MET: + gSubMenuSelection = gSetting_set_met; + break; + case MENU_SET_GUI: + gSubMenuSelection = gSetting_set_gui; + break; + case MENU_SET_TMR: + gSubMenuSelection = gSetting_set_tmr; + break; + case MENU_TX_LOCK: + gSubMenuSelection = gTxVfo->TX_LOCK; + break; #endif - default: - return; - } + default: + return; + } } static void MENU_Key_0_to_9(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld) { - uint8_t Offset; - int32_t Min; - int32_t Max; - uint16_t Value = 0; - - if (bKeyHeld || !bKeyPressed) - return; - - gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; - - if (UI_MENU_GetCurrentMenuId() == MENU_MEM_NAME && edit_index >= 0) - { // currently editing the channel name - - if (edit_index < 10) - { - if (Key <= KEY_9) - { - edit[edit_index] = '0' + Key - KEY_0; - - if (++edit_index >= 10) - { // exit edit - gFlagAcceptSetting = false; - gAskForConfirmation = 1; - } - - gRequestDisplayScreen = DISPLAY_MENU; - } - } - - return; - } - - INPUTBOX_Append(Key); - - gRequestDisplayScreen = DISPLAY_MENU; - - if (!gIsInSubMenu) - { - switch (gInputBoxIndex) - { - case 2: - gInputBoxIndex = 0; - - Value = (gInputBox[0] * 10) + gInputBox[1]; - - if (Value > 0 && Value <= gMenuListCount) - { - gMenuCursor = Value - 1; - gFlagRefreshSetting = true; - return; - } - - if (Value <= gMenuListCount) - break; - - gInputBox[0] = gInputBox[1]; - gInputBoxIndex = 1; - [[fallthrough]]; - case 1: - Value = gInputBox[0]; - if (Value > 0 && Value <= gMenuListCount) - { - gMenuCursor = Value - 1; - gFlagRefreshSetting = true; - return; - } - break; - } - - gInputBoxIndex = 0; - - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - return; - } - - if (UI_MENU_GetCurrentMenuId() == MENU_OFFSET) - { - uint32_t Frequency; - - if (gInputBoxIndex < 6) - { // invalid frequency - #ifdef ENABLE_VOICE - gAnotherVoiceID = (VOICE_ID_t)Key; - #endif - return; - } - - #ifdef ENABLE_VOICE - gAnotherVoiceID = (VOICE_ID_t)Key; - #endif - - Frequency = StrToUL(INPUTBOX_GetAscii())*100; - gSubMenuSelection = FREQUENCY_RoundToStep(Frequency, gTxVfo->StepFrequency); - - gInputBoxIndex = 0; - return; - } - - if (UI_MENU_GetCurrentMenuId() == MENU_MEM_CH || - UI_MENU_GetCurrentMenuId() == MENU_DEL_CH || - UI_MENU_GetCurrentMenuId() == MENU_1_CALL || - UI_MENU_GetCurrentMenuId() == MENU_MEM_NAME) - { // enter 3-digit channel number - - if (gInputBoxIndex < 3) - { - #ifdef ENABLE_VOICE - gAnotherVoiceID = (VOICE_ID_t)Key; - #endif - gRequestDisplayScreen = DISPLAY_MENU; - return; - } - - gInputBoxIndex = 0; - - Value = ((gInputBox[0] * 100) + (gInputBox[1] * 10) + gInputBox[2]) - 1; - - if (IS_MR_CHANNEL(Value)) - { - #ifdef ENABLE_VOICE - gAnotherVoiceID = (VOICE_ID_t)Key; - #endif - gSubMenuSelection = Value; - return; - } - - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - return; - } - - if (MENU_GetLimits(UI_MENU_GetCurrentMenuId(), &Min, &Max)) - { - gInputBoxIndex = 0; - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - return; - } - - Offset = (Max >= 100) ? 3 : (Max >= 10) ? 2 : 1; - - switch (gInputBoxIndex) - { - case 1: - Value = gInputBox[0]; - break; - case 2: - Value = (gInputBox[0] * 10) + gInputBox[1]; - break; - case 3: - Value = (gInputBox[0] * 100) + (gInputBox[1] * 10) + gInputBox[2]; - break; - } - - if (Offset == gInputBoxIndex) - gInputBoxIndex = 0; - - if (Value <= Max) - { - gSubMenuSelection = Value; - return; - } - - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + uint8_t Offset; + int32_t Min; + int32_t Max; + uint16_t Value = 0; + + if (bKeyHeld || !bKeyPressed) + return; + + gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; + + if (UI_MENU_GetCurrentMenuId() == MENU_MEM_NAME && edit_index >= 0) + { // currently editing the channel name + + if (edit_index < 10) + { + if (Key <= KEY_9) + { + edit[edit_index] = '0' + Key - KEY_0; + + if (++edit_index >= 10) + { // exit edit + gFlagAcceptSetting = false; + gAskForConfirmation = 1; + } + + gRequestDisplayScreen = DISPLAY_MENU; + } + } + + return; + } + + INPUTBOX_Append(Key); + + gRequestDisplayScreen = DISPLAY_MENU; + + if (!gIsInSubMenu) + { + switch (gInputBoxIndex) + { + case 2: + gInputBoxIndex = 0; + + Value = (gInputBox[0] * 10) + gInputBox[1]; + + if (Value > 0 && Value <= gMenuListCount) + { + gMenuCursor = Value - 1; + gFlagRefreshSetting = true; + return; + } + + if (Value <= gMenuListCount) + break; + + gInputBox[0] = gInputBox[1]; + gInputBoxIndex = 1; + [[fallthrough]]; + case 1: + Value = gInputBox[0]; + if (Value > 0 && Value <= gMenuListCount) + { + gMenuCursor = Value - 1; + gFlagRefreshSetting = true; + return; + } + break; + } + + gInputBoxIndex = 0; + + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + return; + } + + if (UI_MENU_GetCurrentMenuId() == MENU_OFFSET) + { + uint32_t Frequency; + + if (gInputBoxIndex < 6) + { // invalid frequency + #ifdef ENABLE_VOICE + gAnotherVoiceID = (VOICE_ID_t)Key; + #endif + return; + } + + #ifdef ENABLE_VOICE + gAnotherVoiceID = (VOICE_ID_t)Key; + #endif + + Frequency = StrToUL(INPUTBOX_GetAscii())*100; + gSubMenuSelection = FREQUENCY_RoundToStep(Frequency, gTxVfo->StepFrequency); + + gInputBoxIndex = 0; + return; + } + + if (UI_MENU_GetCurrentMenuId() == MENU_MEM_CH || + UI_MENU_GetCurrentMenuId() == MENU_DEL_CH || + UI_MENU_GetCurrentMenuId() == MENU_1_CALL || + UI_MENU_GetCurrentMenuId() == MENU_MEM_NAME) + { // enter 3-digit channel number + + if (gInputBoxIndex < 3) + { + #ifdef ENABLE_VOICE + gAnotherVoiceID = (VOICE_ID_t)Key; + #endif + gRequestDisplayScreen = DISPLAY_MENU; + return; + } + + gInputBoxIndex = 0; + + Value = ((gInputBox[0] * 100) + (gInputBox[1] * 10) + gInputBox[2]) - 1; + + if (IS_MR_CHANNEL(Value)) + { + #ifdef ENABLE_VOICE + gAnotherVoiceID = (VOICE_ID_t)Key; + #endif + gSubMenuSelection = Value; + return; + } + + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + return; + } + + if (MENU_GetLimits(UI_MENU_GetCurrentMenuId(), &Min, &Max)) + { + gInputBoxIndex = 0; + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + return; + } + + Offset = (Max >= 100) ? 3 : (Max >= 10) ? 2 : 1; + + switch (gInputBoxIndex) + { + case 1: + Value = gInputBox[0]; + break; + case 2: + Value = (gInputBox[0] * 10) + gInputBox[1]; + break; + case 3: + Value = (gInputBox[0] * 100) + (gInputBox[1] * 10) + gInputBox[2]; + break; + } + + if (Offset == gInputBoxIndex) + gInputBoxIndex = 0; + + if (Value <= Max) + { + gSubMenuSelection = Value; + return; + } + + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; } static void MENU_Key_EXIT(bool bKeyPressed, bool bKeyHeld) { - if (bKeyHeld || !bKeyPressed) - return; - - gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; - - if (!gCssBackgroundScan) - { - /* Backlight related menus set full brightness. Set it back to the configured value, - just in case we are exiting from one of them. */ - BACKLIGHT_TurnOn(); - - if (gIsInSubMenu) - { - if (gInputBoxIndex == 0 || UI_MENU_GetCurrentMenuId() != MENU_OFFSET) - { - gAskForConfirmation = 0; - gIsInSubMenu = false; - gInputBoxIndex = 0; - gFlagRefreshSetting = true; - - #ifdef ENABLE_VOICE - gAnotherVoiceID = VOICE_ID_CANCEL; - #endif - } - else - gInputBox[--gInputBoxIndex] = 10; - - // *********************** - - gRequestDisplayScreen = DISPLAY_MENU; - return; - } - - #ifdef ENABLE_VOICE - gAnotherVoiceID = VOICE_ID_CANCEL; - #endif - - gRequestDisplayScreen = DISPLAY_MAIN; - - if (gEeprom.BACKLIGHT_TIME == 0) // backlight set to always off - { - BACKLIGHT_TurnOff(); // turn the backlight OFF - } - } - else - { - MENU_StopCssScan(); - - #ifdef ENABLE_VOICE - gAnotherVoiceID = VOICE_ID_SCANNING_STOP; - #endif - - gRequestDisplayScreen = DISPLAY_MENU; - } - - gPttWasReleased = true; + if (bKeyHeld || !bKeyPressed) + return; + + gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; + + if (!gCssBackgroundScan) + { + /* Backlight related menus set full brightness. Set it back to the configured value, + just in case we are exiting from one of them. */ + BACKLIGHT_TurnOn(); + + if (gIsInSubMenu) + { + if (gInputBoxIndex == 0 || UI_MENU_GetCurrentMenuId() != MENU_OFFSET) + { + gAskForConfirmation = 0; + gIsInSubMenu = false; + gInputBoxIndex = 0; + gFlagRefreshSetting = true; + + #ifdef ENABLE_VOICE + gAnotherVoiceID = VOICE_ID_CANCEL; + #endif + } + else + gInputBox[--gInputBoxIndex] = 10; + + // *********************** + + gRequestDisplayScreen = DISPLAY_MENU; + return; + } + + #ifdef ENABLE_VOICE + gAnotherVoiceID = VOICE_ID_CANCEL; + #endif + + gRequestDisplayScreen = DISPLAY_MAIN; + + if (gEeprom.BACKLIGHT_TIME == 0) // backlight set to always off + { + BACKLIGHT_TurnOff(); // turn the backlight OFF + } + } + else + { + MENU_StopCssScan(); + + #ifdef ENABLE_VOICE + gAnotherVoiceID = VOICE_ID_SCANNING_STOP; + #endif + + gRequestDisplayScreen = DISPLAY_MENU; + } + + gPttWasReleased = true; } static void MENU_Key_MENU(const bool bKeyPressed, const bool bKeyHeld) { - if (bKeyHeld || !bKeyPressed) - return; - - gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; - gRequestDisplayScreen = DISPLAY_MENU; - - if (!gIsInSubMenu) - { - #ifdef ENABLE_VOICE - if (UI_MENU_GetCurrentMenuId() != MENU_SCR) - gAnotherVoiceID = MenuList[gMenuCursor].voice_id; - #endif + if (bKeyHeld || !bKeyPressed) + return; + + gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; + gRequestDisplayScreen = DISPLAY_MENU; + + if (!gIsInSubMenu) + { + #ifdef ENABLE_VOICE + if (UI_MENU_GetCurrentMenuId() != MENU_SCR) + gAnotherVoiceID = MenuList[gMenuCursor].voice_id; + #endif if (UI_MENU_GetCurrentMenuId() == MENU_UPCODE - || UI_MENU_GetCurrentMenuId() == MENU_DWCODE + || UI_MENU_GetCurrentMenuId() == MENU_DWCODE #ifdef ENABLE_DTMF_CALLING - || UI_MENU_GetCurrentMenuId() == MENU_ANI_ID + || UI_MENU_GetCurrentMenuId() == MENU_ANI_ID #endif - ) + ) return; - #if 1 - if (UI_MENU_GetCurrentMenuId() == MENU_DEL_CH || UI_MENU_GetCurrentMenuId() == MENU_MEM_NAME) - if (!RADIO_CheckValidChannel(gSubMenuSelection, false, 0)) - return; // invalid channel - #endif - - gAskForConfirmation = 0; - gIsInSubMenu = true; - -// if (UI_MENU_GetCurrentMenuId() != MENU_D_LIST) - { - gInputBoxIndex = 0; - edit_index = -1; - } - - return; - } - - if (UI_MENU_GetCurrentMenuId() == MENU_MEM_NAME) - { - if (edit_index < 0) - { // enter channel name edit mode - if (!RADIO_CheckValidChannel(gSubMenuSelection, false, 0)) - return; - - SETTINGS_FetchChannelName(edit, gSubMenuSelection); - - // pad the channel name out with '_' - edit_index = strlen(edit); - while (edit_index < 10) - edit[edit_index++] = '_'; - edit[edit_index] = 0; - edit_index = 0; // 'edit_index' is going to be used as the cursor position - - // make a copy so we can test for change when exiting the menu item - memcpy(edit_original, edit, sizeof(edit_original)); - - return; - } - else - if (edit_index >= 0 && edit_index < 10) - { // editing the channel name characters - - if (++edit_index < 10) - return; // next char - - // exit - gFlagAcceptSetting = false; - gAskForConfirmation = 0; - if (memcmp(edit_original, edit, sizeof(edit_original)) == 0) { - // no change - drop it - gIsInSubMenu = false; - } - } - } - - // exiting the sub menu - - if (gIsInSubMenu) - { - if (UI_MENU_GetCurrentMenuId() == MENU_RESET || - UI_MENU_GetCurrentMenuId() == MENU_MEM_CH || - UI_MENU_GetCurrentMenuId() == MENU_DEL_CH || - UI_MENU_GetCurrentMenuId() == MENU_MEM_NAME) - { - switch (gAskForConfirmation) - { - case 0: - gAskForConfirmation = 1; - break; - - case 1: - gAskForConfirmation = 2; - - UI_DisplayMenu(); - - if (UI_MENU_GetCurrentMenuId() == MENU_RESET) - { - #ifdef ENABLE_VOICE - AUDIO_SetVoiceID(0, VOICE_ID_CONFIRM); - AUDIO_PlaySingleVoice(true); - #endif - - MENU_AcceptSetting(); - - #if defined(ENABLE_OVERLAY) - overlay_FLASH_RebootToBootloader(); - #else - NVIC_SystemReset(); - #endif - } - - gFlagAcceptSetting = true; - gIsInSubMenu = false; - gAskForConfirmation = 0; - } - } - else - { - gFlagAcceptSetting = true; - gIsInSubMenu = false; - } - } - - SCANNER_Stop(); - - #ifdef ENABLE_VOICE - if (UI_MENU_GetCurrentMenuId() == MENU_SCR) - gAnotherVoiceID = (gSubMenuSelection == 0) ? VOICE_ID_SCRAMBLER_OFF : VOICE_ID_SCRAMBLER_ON; - else - gAnotherVoiceID = VOICE_ID_CONFIRM; - #endif - - gInputBoxIndex = 0; + #if 1 + if (UI_MENU_GetCurrentMenuId() == MENU_DEL_CH || UI_MENU_GetCurrentMenuId() == MENU_MEM_NAME) + if (!RADIO_CheckValidChannel(gSubMenuSelection, false, 0)) + return; // invalid channel + #endif + + gAskForConfirmation = 0; + gIsInSubMenu = true; + +// if (UI_MENU_GetCurrentMenuId() != MENU_D_LIST) + { + gInputBoxIndex = 0; + edit_index = -1; + } + + return; + } + + if (UI_MENU_GetCurrentMenuId() == MENU_MEM_NAME) + { + if (edit_index < 0) + { // enter channel name edit mode + if (!RADIO_CheckValidChannel(gSubMenuSelection, false, 0)) + return; + + SETTINGS_FetchChannelName(edit, gSubMenuSelection); + + // pad the channel name out with '_' + edit_index = strlen(edit); + while (edit_index < 10) + edit[edit_index++] = '_'; + edit[edit_index] = 0; + edit_index = 0; // 'edit_index' is going to be used as the cursor position + + // make a copy so we can test for change when exiting the menu item + memcpy(edit_original, edit, sizeof(edit_original)); + + return; + } + else + if (edit_index >= 0 && edit_index < 10) + { // editing the channel name characters + + if (++edit_index < 10) + return; // next char + + // exit + gFlagAcceptSetting = false; + gAskForConfirmation = 0; + if (memcmp(edit_original, edit, sizeof(edit_original)) == 0) { + // no change - drop it + gIsInSubMenu = false; + } + } + } + + // exiting the sub menu + + if (gIsInSubMenu) + { + if (UI_MENU_GetCurrentMenuId() == MENU_RESET || + UI_MENU_GetCurrentMenuId() == MENU_MEM_CH || + UI_MENU_GetCurrentMenuId() == MENU_DEL_CH || + UI_MENU_GetCurrentMenuId() == MENU_MEM_NAME) + { + switch (gAskForConfirmation) + { + case 0: + gAskForConfirmation = 1; + break; + + case 1: + gAskForConfirmation = 2; + + UI_DisplayMenu(); + + if (UI_MENU_GetCurrentMenuId() == MENU_RESET) + { + #ifdef ENABLE_VOICE + AUDIO_SetVoiceID(0, VOICE_ID_CONFIRM); + AUDIO_PlaySingleVoice(true); + #endif + + MENU_AcceptSetting(); + + #if defined(ENABLE_OVERLAY) + overlay_FLASH_RebootToBootloader(); + #else + NVIC_SystemReset(); + #endif + } + + gFlagAcceptSetting = true; + gIsInSubMenu = false; + gAskForConfirmation = 0; + } + } + else + { + gFlagAcceptSetting = true; + gIsInSubMenu = false; + } + } + + SCANNER_Stop(); + + #ifdef ENABLE_VOICE + if (UI_MENU_GetCurrentMenuId() == MENU_SCR) + gAnotherVoiceID = (gSubMenuSelection == 0) ? VOICE_ID_SCRAMBLER_OFF : VOICE_ID_SCRAMBLER_ON; + else + gAnotherVoiceID = VOICE_ID_CONFIRM; + #endif + + gInputBoxIndex = 0; } static void MENU_Key_STAR(const bool bKeyPressed, const bool bKeyHeld) { - if (bKeyHeld || !bKeyPressed) - return; - - gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; - - if (UI_MENU_GetCurrentMenuId() == MENU_MEM_NAME && edit_index >= 0) - { // currently editing the channel name - - if (edit_index < 10) - { - edit[edit_index] = '-'; - - if (++edit_index >= 10) - { // exit edit - gFlagAcceptSetting = false; - gAskForConfirmation = 1; - } - - gRequestDisplayScreen = DISPLAY_MENU; - } - - return; - } - - RADIO_SelectVfos(); - - #ifdef ENABLE_NOAA - if (!IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE) && gRxVfo->Modulation == MODULATION_FM) - #else - if (gRxVfo->Modulation == MODULATION_FM) - #endif - { - if ((UI_MENU_GetCurrentMenuId() == MENU_R_CTCS || UI_MENU_GetCurrentMenuId() == MENU_R_DCS) && gIsInSubMenu) - { // scan CTCSS or DCS to find the tone/code of the incoming signal - if (!SCANNER_IsScanning()) - MENU_StartCssScan(); - else - MENU_StopCssScan(); - } - - gPttWasReleased = true; - return; - } - - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + if (bKeyHeld || !bKeyPressed) + return; + + gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; + + if (UI_MENU_GetCurrentMenuId() == MENU_MEM_NAME && edit_index >= 0) + { // currently editing the channel name + + if (edit_index < 10) + { + edit[edit_index] = '-'; + + if (++edit_index >= 10) + { // exit edit + gFlagAcceptSetting = false; + gAskForConfirmation = 1; + } + + gRequestDisplayScreen = DISPLAY_MENU; + } + + return; + } + + RADIO_SelectVfos(); + + #ifdef ENABLE_NOAA + if (!IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE) && gRxVfo->Modulation == MODULATION_FM) + #else + if (gRxVfo->Modulation == MODULATION_FM) + #endif + { + if ((UI_MENU_GetCurrentMenuId() == MENU_R_CTCS || UI_MENU_GetCurrentMenuId() == MENU_R_DCS) && gIsInSubMenu) + { // scan CTCSS or DCS to find the tone/code of the incoming signal + if (!SCANNER_IsScanning()) + MENU_StartCssScan(); + else + MENU_StopCssScan(); + } + + gPttWasReleased = true; + return; + } + + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; } static void MENU_Key_UP_DOWN(bool bKeyPressed, bool bKeyHeld, int8_t Direction) { - uint8_t VFO; - uint8_t Channel; - bool bCheckScanList; - - if (UI_MENU_GetCurrentMenuId() == MENU_MEM_NAME && gIsInSubMenu && edit_index >= 0) - { // change the character - if (bKeyPressed && edit_index < 10 && Direction != 0) - { - const char unwanted[] = "$%&!\"':;?^`|{}"; - char c = edit[edit_index] + Direction; - unsigned int i = 0; - while (i < sizeof(unwanted) && c >= 32 && c <= 126) - { - if (c == unwanted[i++]) - { // choose next character - c += Direction; - i = 0; - } - } - edit[edit_index] = (c < 32) ? 126 : (c > 126) ? 32 : c; - - gRequestDisplayScreen = DISPLAY_MENU; - } - return; - } - - if (!bKeyHeld) - { - if (!bKeyPressed) - return; - - gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; - - gInputBoxIndex = 0; - } - else - if (!bKeyPressed) - return; - - if (SCANNER_IsScanning()) { - return; - } - - if (!gIsInSubMenu) - { - gMenuCursor = NUMBER_AddWithWraparound(gMenuCursor, -Direction, 0, gMenuListCount - 1); - - gFlagRefreshSetting = true; - - gRequestDisplayScreen = DISPLAY_MENU; - - if (UI_MENU_GetCurrentMenuId() != MENU_ABR - && UI_MENU_GetCurrentMenuId() != MENU_ABR_MIN - && UI_MENU_GetCurrentMenuId() != MENU_ABR_MAX - && gEeprom.BACKLIGHT_TIME == 0) // backlight always off and not in the backlight menu - { - BACKLIGHT_TurnOff(); - } - - return; - } - - if (UI_MENU_GetCurrentMenuId() == MENU_OFFSET) - { - int32_t Offset = (Direction * gTxVfo->StepFrequency) + gSubMenuSelection; - if (Offset < 99999990) - { - if (Offset < 0) - Offset = 99999990; - } - else - Offset = 0; - - gSubMenuSelection = FREQUENCY_RoundToStep(Offset, gTxVfo->StepFrequency); - gRequestDisplayScreen = DISPLAY_MENU; - return; - } - - VFO = 0; - - switch (UI_MENU_GetCurrentMenuId()) - { - case MENU_DEL_CH: - case MENU_1_CALL: - case MENU_MEM_NAME: - bCheckScanList = false; - break; - - case MENU_SLIST3: - bCheckScanList = true; - VFO = 3; - break; - case MENU_SLIST2: - bCheckScanList = true; - VFO = 2; - break; - case MENU_SLIST1: - VFO = 1; - bCheckScanList = true; - break; - - default: - MENU_ClampSelection(Direction); - gRequestDisplayScreen = DISPLAY_MENU; - return; - } - - Channel = RADIO_FindNextChannel(gSubMenuSelection + Direction, Direction, bCheckScanList, VFO); - if (Channel != 0xFF) - gSubMenuSelection = Channel; - - gRequestDisplayScreen = DISPLAY_MENU; + uint8_t VFO; + uint8_t Channel; + bool bCheckScanList; + + if (UI_MENU_GetCurrentMenuId() == MENU_MEM_NAME && gIsInSubMenu && edit_index >= 0) + { // change the character + if (bKeyPressed && edit_index < 10 && Direction != 0) + { + const char unwanted[] = "$%&!\"':;?^`|{}"; + char c = edit[edit_index] + Direction; + unsigned int i = 0; + while (i < sizeof(unwanted) && c >= 32 && c <= 126) + { + if (c == unwanted[i++]) + { // choose next character + c += Direction; + i = 0; + } + } + edit[edit_index] = (c < 32) ? 126 : (c > 126) ? 32 : c; + + gRequestDisplayScreen = DISPLAY_MENU; + } + return; + } + + if (!bKeyHeld) + { + if (!bKeyPressed) + return; + + gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; + + gInputBoxIndex = 0; + } + else + if (!bKeyPressed) + return; + + if (SCANNER_IsScanning()) { + return; + } + + if (!gIsInSubMenu) + { + gMenuCursor = NUMBER_AddWithWraparound(gMenuCursor, -Direction, 0, gMenuListCount - 1); + + gFlagRefreshSetting = true; + + gRequestDisplayScreen = DISPLAY_MENU; + + if (UI_MENU_GetCurrentMenuId() != MENU_ABR + && UI_MENU_GetCurrentMenuId() != MENU_ABR_MIN + && UI_MENU_GetCurrentMenuId() != MENU_ABR_MAX + && gEeprom.BACKLIGHT_TIME == 0) // backlight always off and not in the backlight menu + { + BACKLIGHT_TurnOff(); + } + + return; + } + + if (UI_MENU_GetCurrentMenuId() == MENU_OFFSET) + { + int32_t Offset = (Direction * gTxVfo->StepFrequency) + gSubMenuSelection; + if (Offset < 99999990) + { + if (Offset < 0) + Offset = 99999990; + } + else + Offset = 0; + + gSubMenuSelection = FREQUENCY_RoundToStep(Offset, gTxVfo->StepFrequency); + gRequestDisplayScreen = DISPLAY_MENU; + return; + } + + VFO = 0; + + switch (UI_MENU_GetCurrentMenuId()) + { + case MENU_DEL_CH: + case MENU_1_CALL: + case MENU_MEM_NAME: + bCheckScanList = false; + break; + + case MENU_SLIST3: + bCheckScanList = true; + VFO = 3; + break; + case MENU_SLIST2: + bCheckScanList = true; + VFO = 2; + break; + case MENU_SLIST1: + VFO = 1; + bCheckScanList = true; + break; + + default: + MENU_ClampSelection(Direction); + gRequestDisplayScreen = DISPLAY_MENU; + return; + } + + Channel = RADIO_FindNextChannel(gSubMenuSelection + Direction, Direction, bCheckScanList, VFO); + if (Channel != 0xFF) + gSubMenuSelection = Channel; + + gRequestDisplayScreen = DISPLAY_MENU; } void MENU_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld) { - switch (Key) - { - case KEY_0: - case KEY_1: - case KEY_2: - case KEY_3: - case KEY_4: - case KEY_5: - case KEY_6: - case KEY_7: - case KEY_8: - case KEY_9: - MENU_Key_0_to_9(Key, bKeyPressed, bKeyHeld); - break; - case KEY_MENU: - MENU_Key_MENU(bKeyPressed, bKeyHeld); - break; - case KEY_UP: - MENU_Key_UP_DOWN(bKeyPressed, bKeyHeld, 1); - break; - case KEY_DOWN: - MENU_Key_UP_DOWN(bKeyPressed, bKeyHeld, -1); - break; - case KEY_EXIT: - MENU_Key_EXIT(bKeyPressed, bKeyHeld); - break; - case KEY_STAR: - MENU_Key_STAR(bKeyPressed, bKeyHeld); - break; - case KEY_F: - if (UI_MENU_GetCurrentMenuId() == MENU_MEM_NAME && edit_index >= 0) - { // currently editing the channel name - if (!bKeyHeld && bKeyPressed) - { - gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; - if (edit_index < 10) - { - edit[edit_index] = ' '; - if (++edit_index >= 10) - { // exit edit - gFlagAcceptSetting = false; - gAskForConfirmation = 1; - } - gRequestDisplayScreen = DISPLAY_MENU; - } - } - break; - } - - GENERIC_Key_F(bKeyPressed, bKeyHeld); - break; - case KEY_PTT: - GENERIC_Key_PTT(bKeyPressed); - break; - default: - if (!bKeyHeld && bKeyPressed) - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - break; - } - - if (gScreenToDisplay == DISPLAY_MENU) - { - if (UI_MENU_GetCurrentMenuId() == MENU_VOL || - #ifdef ENABLE_F_CAL_MENU - UI_MENU_GetCurrentMenuId() == MENU_F_CALI || - #endif - UI_MENU_GetCurrentMenuId() == MENU_BATCAL) - { - gMenuCountdown = menu_timeout_long_500ms; - } - else - { - gMenuCountdown = menu_timeout_500ms; - } - } + switch (Key) + { + case KEY_0: + case KEY_1: + case KEY_2: + case KEY_3: + case KEY_4: + case KEY_5: + case KEY_6: + case KEY_7: + case KEY_8: + case KEY_9: + MENU_Key_0_to_9(Key, bKeyPressed, bKeyHeld); + break; + case KEY_MENU: + MENU_Key_MENU(bKeyPressed, bKeyHeld); + break; + case KEY_UP: + MENU_Key_UP_DOWN(bKeyPressed, bKeyHeld, 1); + break; + case KEY_DOWN: + MENU_Key_UP_DOWN(bKeyPressed, bKeyHeld, -1); + break; + case KEY_EXIT: + MENU_Key_EXIT(bKeyPressed, bKeyHeld); + break; + case KEY_STAR: + MENU_Key_STAR(bKeyPressed, bKeyHeld); + break; + case KEY_F: + if (UI_MENU_GetCurrentMenuId() == MENU_MEM_NAME && edit_index >= 0) + { // currently editing the channel name + if (!bKeyHeld && bKeyPressed) + { + gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; + if (edit_index < 10) + { + edit[edit_index] = ' '; + if (++edit_index >= 10) + { // exit edit + gFlagAcceptSetting = false; + gAskForConfirmation = 1; + } + gRequestDisplayScreen = DISPLAY_MENU; + } + } + break; + } + + GENERIC_Key_F(bKeyPressed, bKeyHeld); + break; + case KEY_PTT: + GENERIC_Key_PTT(bKeyPressed); + break; + default: + if (!bKeyHeld && bKeyPressed) + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + break; + } + + if (gScreenToDisplay == DISPLAY_MENU) + { + if (UI_MENU_GetCurrentMenuId() == MENU_VOL || + #ifdef ENABLE_F_CAL_MENU + UI_MENU_GetCurrentMenuId() == MENU_F_CALI || + #endif + UI_MENU_GetCurrentMenuId() == MENU_BATCAL) + { + gMenuCountdown = menu_timeout_long_500ms; + } + else + { + gMenuCountdown = menu_timeout_500ms; + } + } } diff --git a/app/menu.h b/app/menu.h index 0b8a15c55..fbca3bfb7 100644 --- a/app/menu.h +++ b/app/menu.h @@ -20,7 +20,7 @@ #include "driver/keyboard.h" #ifdef ENABLE_F_CAL_MENU - void writeXtalFreqCal(const int32_t value, const bool update_eeprom); + void writeXtalFreqCal(const int32_t value, const bool update_eeprom); #endif extern uint8_t gUnlockAllTxConfCnt; diff --git a/app/scanner.c b/app/scanner.c index 6ef610840..2d7c523a4 100644 --- a/app/scanner.c +++ b/app/scanner.c @@ -43,476 +43,476 @@ uint8_t scanHitCount; static void SCANNER_Key_DIGITS(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld) { - if (!bKeyHeld && bKeyPressed) - { - if (gScannerSaveState == SCAN_SAVE_CHAN_SEL) { - gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; + if (!bKeyHeld && bKeyPressed) + { + if (gScannerSaveState == SCAN_SAVE_CHAN_SEL) { + gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; - INPUTBOX_Append(Key); + INPUTBOX_Append(Key); - gRequestDisplayScreen = DISPLAY_SCANNER; + gRequestDisplayScreen = DISPLAY_SCANNER; - if (gInputBoxIndex < 3) { + if (gInputBoxIndex < 3) { #ifdef ENABLE_VOICE - gAnotherVoiceID = (VOICE_ID_t)Key; + gAnotherVoiceID = (VOICE_ID_t)Key; #endif - return; - } + return; + } - gInputBoxIndex = 0; + gInputBoxIndex = 0; - uint16_t chan = ((gInputBox[0] * 100) + (gInputBox[1] * 10) + gInputBox[2]) - 1; - if (IS_MR_CHANNEL(chan)) { + uint16_t chan = ((gInputBox[0] * 100) + (gInputBox[1] * 10) + gInputBox[2]) - 1; + if (IS_MR_CHANNEL(chan)) { #ifdef ENABLE_VOICE - gAnotherVoiceID = (VOICE_ID_t)Key; + gAnotherVoiceID = (VOICE_ID_t)Key; #endif - gShowChPrefix = RADIO_CheckValidChannel(chan, false, 0); - gScanChannel = (uint8_t)chan; - return; - } - } - - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - } + gShowChPrefix = RADIO_CheckValidChannel(chan, false, 0); + gScanChannel = (uint8_t)chan; + return; + } + } + + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + } } static void SCANNER_Key_EXIT(bool bKeyPressed, bool bKeyHeld) { - if (!bKeyHeld && bKeyPressed) { // short pressed - gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; - - switch (gScannerSaveState) { - case SCAN_SAVE_NO_PROMPT: - SCANNER_Stop(); - gRequestDisplayScreen = DISPLAY_MAIN; - break; - - case SCAN_SAVE_CHAN_SEL: - if (gInputBoxIndex > 0) { - gInputBox[--gInputBoxIndex] = 10; - gRequestDisplayScreen = DISPLAY_SCANNER; - break; - } - - // Fallthrough - - case SCAN_SAVE_CHANNEL: - gScannerSaveState = SCAN_SAVE_NO_PROMPT; + if (!bKeyHeld && bKeyPressed) { // short pressed + gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; + + switch (gScannerSaveState) { + case SCAN_SAVE_NO_PROMPT: + SCANNER_Stop(); + gRequestDisplayScreen = DISPLAY_MAIN; + break; + + case SCAN_SAVE_CHAN_SEL: + if (gInputBoxIndex > 0) { + gInputBox[--gInputBoxIndex] = 10; + gRequestDisplayScreen = DISPLAY_SCANNER; + break; + } + + // Fallthrough + + case SCAN_SAVE_CHANNEL: + gScannerSaveState = SCAN_SAVE_NO_PROMPT; #ifdef ENABLE_VOICE - gAnotherVoiceID = VOICE_ID_CANCEL; + gAnotherVoiceID = VOICE_ID_CANCEL; #endif - gRequestDisplayScreen = DISPLAY_SCANNER; - break; - } - } + gRequestDisplayScreen = DISPLAY_SCANNER; + break; + } + } } static void SCANNER_Key_MENU(bool bKeyPressed, bool bKeyHeld) { - if (bKeyHeld || !bKeyPressed) // ignore long press or release button events - return; - - if (gScanCssState == SCAN_CSS_STATE_OFF && !gScanSingleFrequency) { - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - return; - } - - if (gScanCssState == SCAN_CSS_STATE_SCANNING && gScanSingleFrequency) { - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - return; - } - - if (gScanCssState == SCAN_CSS_STATE_FAILED) { - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - return; - } - - gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; - - switch (gScannerSaveState) { - case SCAN_SAVE_NO_PROMPT: - if (!gScanSingleFrequency) - { - uint32_t freq250 = FREQUENCY_RoundToStep(gScanFrequency, 250); - uint32_t freq625 = FREQUENCY_RoundToStep(gScanFrequency, 625); - - uint32_t diff250 = gScanFrequency > freq250 ? gScanFrequency - freq250 : freq250 - gScanFrequency; - uint32_t diff625 = gScanFrequency > freq625 ? gScanFrequency - freq625 : freq625 - gScanFrequency; - - if(diff250 > diff625) { - stepSetting = STEP_6_25kHz; - gScanFrequency = freq625; - } - else { - stepSetting = STEP_2_5kHz; - gScanFrequency = freq250; - } - } - - if (IS_MR_CHANNEL(gTxVfo->CHANNEL_SAVE)) { - gScannerSaveState = SCAN_SAVE_CHAN_SEL; - gScanChannel = gTxVfo->CHANNEL_SAVE; - gShowChPrefix = RADIO_CheckValidChannel(gTxVfo->CHANNEL_SAVE, false, 0); - } - else { - gScannerSaveState = SCAN_SAVE_CHANNEL; - } - - gScanCssState = SCAN_CSS_STATE_FOUND; + if (bKeyHeld || !bKeyPressed) // ignore long press or release button events + return; + + if (gScanCssState == SCAN_CSS_STATE_OFF && !gScanSingleFrequency) { + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + return; + } + + if (gScanCssState == SCAN_CSS_STATE_SCANNING && gScanSingleFrequency) { + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + return; + } + + if (gScanCssState == SCAN_CSS_STATE_FAILED) { + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + return; + } + + gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; + + switch (gScannerSaveState) { + case SCAN_SAVE_NO_PROMPT: + if (!gScanSingleFrequency) + { + uint32_t freq250 = FREQUENCY_RoundToStep(gScanFrequency, 250); + uint32_t freq625 = FREQUENCY_RoundToStep(gScanFrequency, 625); + + uint32_t diff250 = gScanFrequency > freq250 ? gScanFrequency - freq250 : freq250 - gScanFrequency; + uint32_t diff625 = gScanFrequency > freq625 ? gScanFrequency - freq625 : freq625 - gScanFrequency; + + if(diff250 > diff625) { + stepSetting = STEP_6_25kHz; + gScanFrequency = freq625; + } + else { + stepSetting = STEP_2_5kHz; + gScanFrequency = freq250; + } + } + + if (IS_MR_CHANNEL(gTxVfo->CHANNEL_SAVE)) { + gScannerSaveState = SCAN_SAVE_CHAN_SEL; + gScanChannel = gTxVfo->CHANNEL_SAVE; + gShowChPrefix = RADIO_CheckValidChannel(gTxVfo->CHANNEL_SAVE, false, 0); + } + else { + gScannerSaveState = SCAN_SAVE_CHANNEL; + } + + gScanCssState = SCAN_CSS_STATE_FOUND; #ifdef ENABLE_VOICE - gAnotherVoiceID = VOICE_ID_MEMORY_CHANNEL; + gAnotherVoiceID = VOICE_ID_MEMORY_CHANNEL; #endif - gRequestDisplayScreen = DISPLAY_SCANNER; - - gUpdateStatus = true; - break; - - case SCAN_SAVE_CHAN_SEL: - if (gInputBoxIndex == 0) { - gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; - gRequestDisplayScreen = DISPLAY_SCANNER; - gScannerSaveState = SCAN_SAVE_CHANNEL; - } - break; - - case SCAN_SAVE_CHANNEL: - if (!gScanSingleFrequency) { - RADIO_InitInfo(gTxVfo, gTxVfo->CHANNEL_SAVE, gScanFrequency); - - if (gScanUseCssResult) { - gTxVfo->freq_config_RX.CodeType = gScanCssResultType; - gTxVfo->freq_config_RX.Code = gScanCssResultCode; - } - - gTxVfo->freq_config_TX = gTxVfo->freq_config_RX; - gTxVfo->STEP_SETTING = stepSetting; - } - else { - RADIO_ConfigureChannel(0, VFO_CONFIGURE_RELOAD); - RADIO_ConfigureChannel(1, VFO_CONFIGURE_RELOAD); - - gTxVfo->freq_config_RX.CodeType = gScanCssResultType; - gTxVfo->freq_config_RX.Code = gScanCssResultCode; - gTxVfo->freq_config_TX.CodeType = gScanCssResultType; - gTxVfo->freq_config_TX.Code = gScanCssResultCode; - } - - uint8_t chan; - if (IS_MR_CHANNEL(gTxVfo->CHANNEL_SAVE)) { - chan = gScanChannel; - gEeprom.MrChannel[gEeprom.TX_VFO] = chan; - } - else { - chan = gTxVfo->Band + FREQ_CHANNEL_FIRST; - gEeprom.FreqChannel[gEeprom.TX_VFO] = chan; - } - - gTxVfo->CHANNEL_SAVE = chan; - gEeprom.ScreenChannel[gEeprom.TX_VFO] = chan; -#ifdef ENABLE_VOICE - gAnotherVoiceID = VOICE_ID_CONFIRM; + gRequestDisplayScreen = DISPLAY_SCANNER; + + gUpdateStatus = true; + break; + + case SCAN_SAVE_CHAN_SEL: + if (gInputBoxIndex == 0) { + gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; + gRequestDisplayScreen = DISPLAY_SCANNER; + gScannerSaveState = SCAN_SAVE_CHANNEL; + } + break; + + case SCAN_SAVE_CHANNEL: + if (!gScanSingleFrequency) { + RADIO_InitInfo(gTxVfo, gTxVfo->CHANNEL_SAVE, gScanFrequency); + + if (gScanUseCssResult) { + gTxVfo->freq_config_RX.CodeType = gScanCssResultType; + gTxVfo->freq_config_RX.Code = gScanCssResultCode; + } + + gTxVfo->freq_config_TX = gTxVfo->freq_config_RX; + gTxVfo->STEP_SETTING = stepSetting; + } + else { + RADIO_ConfigureChannel(0, VFO_CONFIGURE_RELOAD); + RADIO_ConfigureChannel(1, VFO_CONFIGURE_RELOAD); + + gTxVfo->freq_config_RX.CodeType = gScanCssResultType; + gTxVfo->freq_config_RX.Code = gScanCssResultCode; + gTxVfo->freq_config_TX.CodeType = gScanCssResultType; + gTxVfo->freq_config_TX.Code = gScanCssResultCode; + } + + uint8_t chan; + if (IS_MR_CHANNEL(gTxVfo->CHANNEL_SAVE)) { + chan = gScanChannel; + gEeprom.MrChannel[gEeprom.TX_VFO] = chan; + } + else { + chan = gTxVfo->Band + FREQ_CHANNEL_FIRST; + gEeprom.FreqChannel[gEeprom.TX_VFO] = chan; + } + + gTxVfo->CHANNEL_SAVE = chan; + gEeprom.ScreenChannel[gEeprom.TX_VFO] = chan; +#ifdef ENABLE_VOICE + gAnotherVoiceID = VOICE_ID_CONFIRM; #endif - gRequestDisplayScreen = DISPLAY_SCANNER; - gRequestSaveChannel = 2; - gScannerSaveState = SCAN_SAVE_NO_PROMPT; - break; - - default: - gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; - break; - } + gRequestDisplayScreen = DISPLAY_SCANNER; + gRequestSaveChannel = 2; + gScannerSaveState = SCAN_SAVE_NO_PROMPT; + break; + + default: + gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; + break; + } } static void SCANNER_Key_STAR(bool bKeyPressed, bool bKeyHeld) { - if (!bKeyHeld && bKeyPressed) { - gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; - SCANNER_Start(gScanSingleFrequency); - } - return; + if (!bKeyHeld && bKeyPressed) { + gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; + SCANNER_Start(gScanSingleFrequency); + } + return; } static void SCANNER_Key_UP_DOWN(bool bKeyPressed, bool pKeyHeld, int8_t Direction) { - if (pKeyHeld) { - if (!bKeyPressed) - return; - } - else { - if (!bKeyPressed) - return; - - gInputBoxIndex = 0; - gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; - } - - if (gScannerSaveState == SCAN_SAVE_CHAN_SEL) { - gScanChannel = NUMBER_AddWithWraparound(gScanChannel, Direction, 0, MR_CHANNEL_LAST); - gShowChPrefix = RADIO_CheckValidChannel(gScanChannel, false, 0); - gRequestDisplayScreen = DISPLAY_SCANNER; - } - else - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + if (pKeyHeld) { + if (!bKeyPressed) + return; + } + else { + if (!bKeyPressed) + return; + + gInputBoxIndex = 0; + gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; + } + + if (gScannerSaveState == SCAN_SAVE_CHAN_SEL) { + gScanChannel = NUMBER_AddWithWraparound(gScanChannel, Direction, 0, MR_CHANNEL_LAST); + gShowChPrefix = RADIO_CheckValidChannel(gScanChannel, false, 0); + gRequestDisplayScreen = DISPLAY_SCANNER; + } + else + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; } void SCANNER_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld) { - switch (Key) { - case KEY_0...KEY_9: - SCANNER_Key_DIGITS(Key, bKeyPressed, bKeyHeld); - break; - case KEY_MENU: - SCANNER_Key_MENU(bKeyPressed, bKeyHeld); - break; - case KEY_UP: - SCANNER_Key_UP_DOWN(bKeyPressed, bKeyHeld, 1); - break; - case KEY_DOWN: - SCANNER_Key_UP_DOWN(bKeyPressed, bKeyHeld, -1); - break; - case KEY_EXIT: - SCANNER_Key_EXIT(bKeyPressed, bKeyHeld); - break; - case KEY_STAR: - SCANNER_Key_STAR(bKeyPressed, bKeyHeld); - break; - case KEY_PTT: - GENERIC_Key_PTT(bKeyPressed); - break; - default: - if (!bKeyHeld && bKeyPressed) - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - break; - } + switch (Key) { + case KEY_0...KEY_9: + SCANNER_Key_DIGITS(Key, bKeyPressed, bKeyHeld); + break; + case KEY_MENU: + SCANNER_Key_MENU(bKeyPressed, bKeyHeld); + break; + case KEY_UP: + SCANNER_Key_UP_DOWN(bKeyPressed, bKeyHeld, 1); + break; + case KEY_DOWN: + SCANNER_Key_UP_DOWN(bKeyPressed, bKeyHeld, -1); + break; + case KEY_EXIT: + SCANNER_Key_EXIT(bKeyPressed, bKeyHeld); + break; + case KEY_STAR: + SCANNER_Key_STAR(bKeyPressed, bKeyHeld); + break; + case KEY_PTT: + GENERIC_Key_PTT(bKeyPressed); + break; + default: + if (!bKeyHeld && bKeyPressed) + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + break; + } } void SCANNER_Start(bool singleFreq) { - gScanSingleFrequency = singleFreq; - gMonitor = false; + gScanSingleFrequency = singleFreq; + gMonitor = false; #ifdef ENABLE_VOICE - gAnotherVoiceID = VOICE_ID_SCANNING_BEGIN; + gAnotherVoiceID = VOICE_ID_SCANNING_BEGIN; #endif - BK4819_StopScan(); - RADIO_SelectVfos(); + BK4819_StopScan(); + RADIO_SelectVfos(); #ifdef ENABLE_NOAA - if (IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE)) - gRxVfo->CHANNEL_SAVE = FREQ_CHANNEL_FIRST + BAND6_400MHz; + if (IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE)) + gRxVfo->CHANNEL_SAVE = FREQ_CHANNEL_FIRST + BAND6_400MHz; #endif - uint8_t backupStep = gRxVfo->STEP_SETTING; - uint16_t backupFrequency = gRxVfo->StepFrequency; + uint8_t backupStep = gRxVfo->STEP_SETTING; + uint16_t backupFrequency = gRxVfo->StepFrequency; - RADIO_InitInfo(gRxVfo, gRxVfo->CHANNEL_SAVE, gRxVfo->pRX->Frequency); + RADIO_InitInfo(gRxVfo, gRxVfo->CHANNEL_SAVE, gRxVfo->pRX->Frequency); - gRxVfo->STEP_SETTING = backupStep; - gRxVfo->StepFrequency = backupFrequency; + gRxVfo->STEP_SETTING = backupStep; + gRxVfo->StepFrequency = backupFrequency; - RADIO_SetupRegisters(true); + RADIO_SetupRegisters(true); #ifdef ENABLE_NOAA - gIsNoaaMode = false; + gIsNoaaMode = false; #endif - if (gScanSingleFrequency) { - gScanCssState = SCAN_CSS_STATE_SCANNING; - gScanFrequency = gRxVfo->pRX->Frequency; - stepSetting = gRxVfo->STEP_SETTING; + if (gScanSingleFrequency) { + gScanCssState = SCAN_CSS_STATE_SCANNING; + gScanFrequency = gRxVfo->pRX->Frequency; + stepSetting = gRxVfo->STEP_SETTING; - BK4819_PickRXFilterPathBasedOnFrequency(gScanFrequency); - BK4819_SetScanFrequency(gScanFrequency); + BK4819_PickRXFilterPathBasedOnFrequency(gScanFrequency); + BK4819_SetScanFrequency(gScanFrequency); - gUpdateStatus = true; - } - else { - gScanCssState = SCAN_CSS_STATE_OFF; - gScanFrequency = 0xFFFFFFFF; + gUpdateStatus = true; + } + else { + gScanCssState = SCAN_CSS_STATE_OFF; + gScanFrequency = 0xFFFFFFFF; - BK4819_PickRXFilterPathBasedOnFrequency(gScanFrequency); - BK4819_EnableFrequencyScan(); + BK4819_PickRXFilterPathBasedOnFrequency(gScanFrequency); + BK4819_EnableFrequencyScan(); - gUpdateStatus = true; - } + gUpdateStatus = true; + } #ifdef ENABLE_DTMF_CALLING - DTMF_clear_RX(); + DTMF_clear_RX(); #endif - gScanDelay_10ms = scan_delay_10ms; - gScanCssResultCode = 0xFF; - gScanCssResultType = 0xFF; - scanHitCount = 0; - gScanUseCssResult = false; - g_CxCSS_TAIL_Found = false; - g_CDCSS_Lost = false; - gCDCSSCodeType = 0; - g_CTCSS_Lost = false; + gScanDelay_10ms = scan_delay_10ms; + gScanCssResultCode = 0xFF; + gScanCssResultType = 0xFF; + scanHitCount = 0; + gScanUseCssResult = false; + g_CxCSS_TAIL_Found = false; + g_CDCSS_Lost = false; + gCDCSSCodeType = 0; + g_CTCSS_Lost = false; #ifdef ENABLE_VOX - g_VOX_Lost = false; + g_VOX_Lost = false; #endif - g_SquelchLost = false; - gScannerSaveState = SCAN_SAVE_NO_PROMPT; - gScanProgressIndicator = 0; + g_SquelchLost = false; + gScannerSaveState = SCAN_SAVE_NO_PROMPT; + gScanProgressIndicator = 0; } void SCANNER_Stop(void) { - if(SCANNER_IsScanning()) { - gEeprom.CROSS_BAND_RX_TX = gBackup_CROSS_BAND_RX_TX; - gVfoConfigureMode = VFO_CONFIGURE_RELOAD; - gFlagResetVfos = true; - gUpdateStatus = true; - gCssBackgroundScan = false; - gScanUseCssResult = false; + if(SCANNER_IsScanning()) { + gEeprom.CROSS_BAND_RX_TX = gBackup_CROSS_BAND_RX_TX; + gVfoConfigureMode = VFO_CONFIGURE_RELOAD; + gFlagResetVfos = true; + gUpdateStatus = true; + gCssBackgroundScan = false; + gScanUseCssResult = false; #ifdef ENABLE_VOICE - gAnotherVoiceID = VOICE_ID_CANCEL; + gAnotherVoiceID = VOICE_ID_CANCEL; #endif - BK4819_StopScan(); - } + BK4819_StopScan(); + } } void SCANNER_TimeSlice10ms(void) { - if (!SCANNER_IsScanning()) - return; - - if (gScanDelay_10ms > 0) { - gScanDelay_10ms--; - return; - } - - if (gScannerSaveState != SCAN_SAVE_NO_PROMPT) { - return; - } - - switch (gScanCssState) { - case SCAN_CSS_STATE_OFF: { - // must be RF frequency scanning if we're here ? - uint32_t result; - if (!BK4819_GetFrequencyScanResult(&result)) - break; - - int32_t delta = result - gScanFrequency; - gScanFrequency = result; - - if (delta < 0) - delta = -delta; - if (delta < 100) - scanHitCount++; - else - scanHitCount = 0; - - BK4819_DisableFrequencyScan(); - - if (scanHitCount < 3) { - BK4819_EnableFrequencyScan(); - } - else { - BK4819_SetScanFrequency(gScanFrequency); - gScanCssResultCode = 0xFF; - gScanCssResultType = 0xFF; - scanHitCount = 0; - gScanUseCssResult = false; - gScanProgressIndicator = 0; - gScanCssState = SCAN_CSS_STATE_SCANNING; - - if(!gCssBackgroundScan) - GUI_SelectNextDisplay(DISPLAY_SCANNER); - - gUpdateStatus = true; - } - - gScanDelay_10ms = scan_delay_10ms; - //gScanDelay_10ms = 1; // 10ms - break; - } - case SCAN_CSS_STATE_SCANNING: { - uint32_t cdcssFreq; - uint16_t ctcssFreq; - BK4819_CssScanResult_t scanResult = BK4819_GetCxCSSScanResult(&cdcssFreq, &ctcssFreq); - if (scanResult == BK4819_CSS_RESULT_NOT_FOUND) - break; - - BK4819_Disable(); - - if (scanResult == BK4819_CSS_RESULT_CDCSS) { - const uint8_t Code = DCS_GetCdcssCode(cdcssFreq); - if (Code != 0xFF) - { - gScanCssResultCode = Code; - gScanCssResultType = CODE_TYPE_DIGITAL; - gScanCssState = SCAN_CSS_STATE_FOUND; - gScanUseCssResult = true; - gUpdateStatus = true; - } - } - else if (scanResult == BK4819_CSS_RESULT_CTCSS) { - const uint8_t Code = DCS_GetCtcssCode(ctcssFreq); - if (Code != 0xFF) { - if (Code == gScanCssResultCode && gScanCssResultType == CODE_TYPE_CONTINUOUS_TONE) { - if (++scanHitCount >= 2) { - gScanCssState = SCAN_CSS_STATE_FOUND; - gScanUseCssResult = true; - gUpdateStatus = true; - } - } - else - scanHitCount = 0; - - gScanCssResultType = CODE_TYPE_CONTINUOUS_TONE; - gScanCssResultCode = Code; - } - } - - if (gScanCssState < SCAN_CSS_STATE_FOUND) { // scanning or off - BK4819_SetScanFrequency(gScanFrequency); - gScanDelay_10ms = scan_delay_10ms; - break; - } - - if(gCssBackgroundScan) { - gCssBackgroundScan = false; - if(gScanUseCssResult) - MENU_CssScanFound(); - } - else - GUI_SelectNextDisplay(DISPLAY_SCANNER); - - - break; - } - default: - gCssBackgroundScan = false; - break; - } + if (!SCANNER_IsScanning()) + return; + + if (gScanDelay_10ms > 0) { + gScanDelay_10ms--; + return; + } + + if (gScannerSaveState != SCAN_SAVE_NO_PROMPT) { + return; + } + + switch (gScanCssState) { + case SCAN_CSS_STATE_OFF: { + // must be RF frequency scanning if we're here ? + uint32_t result; + if (!BK4819_GetFrequencyScanResult(&result)) + break; + + int32_t delta = result - gScanFrequency; + gScanFrequency = result; + + if (delta < 0) + delta = -delta; + if (delta < 100) + scanHitCount++; + else + scanHitCount = 0; + + BK4819_DisableFrequencyScan(); + + if (scanHitCount < 3) { + BK4819_EnableFrequencyScan(); + } + else { + BK4819_SetScanFrequency(gScanFrequency); + gScanCssResultCode = 0xFF; + gScanCssResultType = 0xFF; + scanHitCount = 0; + gScanUseCssResult = false; + gScanProgressIndicator = 0; + gScanCssState = SCAN_CSS_STATE_SCANNING; + + if(!gCssBackgroundScan) + GUI_SelectNextDisplay(DISPLAY_SCANNER); + + gUpdateStatus = true; + } + + gScanDelay_10ms = scan_delay_10ms; + //gScanDelay_10ms = 1; // 10ms + break; + } + case SCAN_CSS_STATE_SCANNING: { + uint32_t cdcssFreq; + uint16_t ctcssFreq; + BK4819_CssScanResult_t scanResult = BK4819_GetCxCSSScanResult(&cdcssFreq, &ctcssFreq); + if (scanResult == BK4819_CSS_RESULT_NOT_FOUND) + break; + + BK4819_Disable(); + + if (scanResult == BK4819_CSS_RESULT_CDCSS) { + const uint8_t Code = DCS_GetCdcssCode(cdcssFreq); + if (Code != 0xFF) + { + gScanCssResultCode = Code; + gScanCssResultType = CODE_TYPE_DIGITAL; + gScanCssState = SCAN_CSS_STATE_FOUND; + gScanUseCssResult = true; + gUpdateStatus = true; + } + } + else if (scanResult == BK4819_CSS_RESULT_CTCSS) { + const uint8_t Code = DCS_GetCtcssCode(ctcssFreq); + if (Code != 0xFF) { + if (Code == gScanCssResultCode && gScanCssResultType == CODE_TYPE_CONTINUOUS_TONE) { + if (++scanHitCount >= 2) { + gScanCssState = SCAN_CSS_STATE_FOUND; + gScanUseCssResult = true; + gUpdateStatus = true; + } + } + else + scanHitCount = 0; + + gScanCssResultType = CODE_TYPE_CONTINUOUS_TONE; + gScanCssResultCode = Code; + } + } + + if (gScanCssState < SCAN_CSS_STATE_FOUND) { // scanning or off + BK4819_SetScanFrequency(gScanFrequency); + gScanDelay_10ms = scan_delay_10ms; + break; + } + + if(gCssBackgroundScan) { + gCssBackgroundScan = false; + if(gScanUseCssResult) + MENU_CssScanFound(); + } + else + GUI_SelectNextDisplay(DISPLAY_SCANNER); + + + break; + } + default: + gCssBackgroundScan = false; + break; + } } void SCANNER_TimeSlice500ms(void) { - if (SCANNER_IsScanning() && gScannerSaveState == SCAN_SAVE_NO_PROMPT && gScanCssState < SCAN_CSS_STATE_FOUND) { - gScanProgressIndicator++; + if (SCANNER_IsScanning() && gScannerSaveState == SCAN_SAVE_NO_PROMPT && gScanCssState < SCAN_CSS_STATE_FOUND) { + gScanProgressIndicator++; #ifndef ENABLE_NO_CODE_SCAN_TIMEOUT - if (gScanProgressIndicator > 32) { - if (gScanCssState == SCAN_CSS_STATE_SCANNING && !gScanSingleFrequency) - gScanCssState = SCAN_CSS_STATE_FOUND; - else - gScanCssState = SCAN_CSS_STATE_FAILED; - - gUpdateStatus = true; - } + if (gScanProgressIndicator > 32) { + if (gScanCssState == SCAN_CSS_STATE_SCANNING && !gScanSingleFrequency) + gScanCssState = SCAN_CSS_STATE_FOUND; + else + gScanCssState = SCAN_CSS_STATE_FAILED; + + gUpdateStatus = true; + } #endif - gUpdateDisplay = true; - } - else if(gCssBackgroundScan) { - gUpdateDisplay = true; - } + gUpdateDisplay = true; + } + else if(gCssBackgroundScan) { + gUpdateDisplay = true; + } } bool SCANNER_IsScanning(void) { - return gCssBackgroundScan || (gScreenToDisplay == DISPLAY_SCANNER); + return gCssBackgroundScan || (gScreenToDisplay == DISPLAY_SCANNER); } \ No newline at end of file diff --git a/app/scanner.h b/app/scanner.h index a62deb688..6217ef59f 100644 --- a/app/scanner.h +++ b/app/scanner.h @@ -22,17 +22,17 @@ typedef enum { - SCAN_CSS_STATE_OFF, - SCAN_CSS_STATE_SCANNING, - SCAN_CSS_STATE_FOUND, - SCAN_CSS_STATE_FAILED + SCAN_CSS_STATE_OFF, + SCAN_CSS_STATE_SCANNING, + SCAN_CSS_STATE_FOUND, + SCAN_CSS_STATE_FAILED } SCAN_CssState_t; typedef enum { - SCAN_SAVE_NO_PROMPT, // saving process not initiated - SCAN_SAVE_CHAN_SEL, // "SAVE: ", channel select prompt, actives only in channel mode - SCAN_SAVE_CHANNEL, // "SAVE?" prompt, waits for confirmation to save settings to channel, or current VFO + SCAN_SAVE_NO_PROMPT, // saving process not initiated + SCAN_SAVE_CHAN_SEL, // "SAVE: ", channel select prompt, actives only in channel mode + SCAN_SAVE_CHANNEL, // "SAVE?" prompt, waits for confirmation to save settings to channel, or current VFO } SCAN_SaveState_t; diff --git a/app/uart.c b/app/uart.c index a1b1fc577..b878d1d02 100644 --- a/app/uart.c +++ b/app/uart.c @@ -17,10 +17,10 @@ #include #if !defined(ENABLE_OVERLAY) - #include "ARMCM0.h" + #include "ARMCM0.h" #endif #ifdef ENABLE_FMRADIO - #include "app/fm.h" + #include "app/fm.h" #endif #include "app/uart.h" #include "board.h" @@ -39,7 +39,7 @@ #include "version.h" #if defined(ENABLE_OVERLAY) - #include "sram-overlay.h" + #include "sram-overlay.h" #endif #define UNUSED(x) (void)(x) @@ -47,113 +47,113 @@ #define DMA_INDEX(x, y) (((x) + (y)) % sizeof(UART_DMA_Buffer)) typedef struct { - uint16_t ID; - uint16_t Size; + uint16_t ID; + uint16_t Size; } Header_t; typedef struct { - uint8_t Padding[2]; - uint16_t ID; + uint8_t Padding[2]; + uint16_t ID; } Footer_t; typedef struct { - Header_t Header; - uint32_t Timestamp; + Header_t Header; + uint32_t Timestamp; } CMD_0514_t; typedef struct { - Header_t Header; - struct { - char Version[16]; - bool bHasCustomAesKey; - bool bIsInLockScreen; - uint8_t Padding[2]; - uint32_t Challenge[4]; - } Data; + Header_t Header; + struct { + char Version[16]; + bool bHasCustomAesKey; + bool bIsInLockScreen; + uint8_t Padding[2]; + uint32_t Challenge[4]; + } Data; } REPLY_0514_t; typedef struct { - Header_t Header; - uint16_t Offset; - uint8_t Size; - uint8_t Padding; - uint32_t Timestamp; + Header_t Header; + uint16_t Offset; + uint8_t Size; + uint8_t Padding; + uint32_t Timestamp; } CMD_051B_t; typedef struct { - Header_t Header; - struct { - uint16_t Offset; - uint8_t Size; - uint8_t Padding; - uint8_t Data[128]; - } Data; + Header_t Header; + struct { + uint16_t Offset; + uint8_t Size; + uint8_t Padding; + uint8_t Data[128]; + } Data; } REPLY_051B_t; typedef struct { - Header_t Header; - uint16_t Offset; - uint8_t Size; - bool bAllowPassword; - uint32_t Timestamp; - uint8_t Data[0]; + Header_t Header; + uint16_t Offset; + uint8_t Size; + bool bAllowPassword; + uint32_t Timestamp; + uint8_t Data[0]; } CMD_051D_t; typedef struct { - Header_t Header; - struct { - uint16_t Offset; - } Data; + Header_t Header; + struct { + uint16_t Offset; + } Data; } REPLY_051D_t; typedef struct { - Header_t Header; - struct { - uint16_t RSSI; - uint8_t ExNoiseIndicator; - uint8_t GlitchIndicator; - } Data; + Header_t Header; + struct { + uint16_t RSSI; + uint8_t ExNoiseIndicator; + uint8_t GlitchIndicator; + } Data; } REPLY_0527_t; typedef struct { - Header_t Header; - struct { - uint16_t Voltage; - uint16_t Current; - } Data; + Header_t Header; + struct { + uint16_t Voltage; + uint16_t Current; + } Data; } REPLY_0529_t; typedef struct { - Header_t Header; - uint32_t Response[4]; + Header_t Header; + uint32_t Response[4]; } CMD_052D_t; typedef struct { - Header_t Header; - struct { - bool bIsLocked; - uint8_t Padding[3]; - } Data; + Header_t Header; + struct { + bool bIsLocked; + uint8_t Padding[3]; + } Data; } REPLY_052D_t; typedef struct { - Header_t Header; - uint32_t Timestamp; + Header_t Header; + uint32_t Timestamp; } CMD_052F_t; static const uint8_t Obfuscation[16] = { - 0x16, 0x6C, 0x14, 0xE6, 0x2E, 0x91, 0x0D, 0x40, 0x21, 0x35, 0xD5, 0x40, 0x13, 0x03, 0xE9, 0x80 + 0x16, 0x6C, 0x14, 0xE6, 0x2E, 0x91, 0x0D, 0x40, 0x21, 0x35, 0xD5, 0x40, 0x13, 0x03, 0xE9, 0x80 }; static union { - uint8_t Buffer[256]; - struct - { - Header_t Header; - uint8_t Data[252]; - }; + uint8_t Buffer[256]; + struct + { + Header_t Header; + uint8_t Data[252]; + }; } UART_Command; static uint32_t Timestamp; @@ -162,243 +162,243 @@ static bool bIsEncrypted = true; static void SendReply(void *pReply, uint16_t Size) { - Header_t Header; - Footer_t Footer; - - if (bIsEncrypted) - { - uint8_t *pBytes = (uint8_t *)pReply; - unsigned int i; - for (i = 0; i < Size; i++) - pBytes[i] ^= Obfuscation[i % 16]; - } - - Header.ID = 0xCDAB; - Header.Size = Size; - UART_Send(&Header, sizeof(Header)); - UART_Send(pReply, Size); - - if (bIsEncrypted) - { - Footer.Padding[0] = Obfuscation[(Size + 0) % 16] ^ 0xFF; - Footer.Padding[1] = Obfuscation[(Size + 1) % 16] ^ 0xFF; - } - else - { - Footer.Padding[0] = 0xFF; - Footer.Padding[1] = 0xFF; - } - Footer.ID = 0xBADC; - - UART_Send(&Footer, sizeof(Footer)); + Header_t Header; + Footer_t Footer; + + if (bIsEncrypted) + { + uint8_t *pBytes = (uint8_t *)pReply; + unsigned int i; + for (i = 0; i < Size; i++) + pBytes[i] ^= Obfuscation[i % 16]; + } + + Header.ID = 0xCDAB; + Header.Size = Size; + UART_Send(&Header, sizeof(Header)); + UART_Send(pReply, Size); + + if (bIsEncrypted) + { + Footer.Padding[0] = Obfuscation[(Size + 0) % 16] ^ 0xFF; + Footer.Padding[1] = Obfuscation[(Size + 1) % 16] ^ 0xFF; + } + else + { + Footer.Padding[0] = 0xFF; + Footer.Padding[1] = 0xFF; + } + Footer.ID = 0xBADC; + + UART_Send(&Footer, sizeof(Footer)); } static void SendVersion(void) { - REPLY_0514_t Reply; - - Reply.Header.ID = 0x0515; - Reply.Header.Size = sizeof(Reply.Data); - strcpy(Reply.Data.Version, Version); - Reply.Data.bHasCustomAesKey = bHasCustomAesKey; - Reply.Data.bIsInLockScreen = bIsInLockScreen; - Reply.Data.Challenge[0] = gChallenge[0]; - Reply.Data.Challenge[1] = gChallenge[1]; - Reply.Data.Challenge[2] = gChallenge[2]; - Reply.Data.Challenge[3] = gChallenge[3]; - - SendReply(&Reply, sizeof(Reply)); + REPLY_0514_t Reply; + + Reply.Header.ID = 0x0515; + Reply.Header.Size = sizeof(Reply.Data); + strcpy(Reply.Data.Version, Version); + Reply.Data.bHasCustomAesKey = bHasCustomAesKey; + Reply.Data.bIsInLockScreen = bIsInLockScreen; + Reply.Data.Challenge[0] = gChallenge[0]; + Reply.Data.Challenge[1] = gChallenge[1]; + Reply.Data.Challenge[2] = gChallenge[2]; + Reply.Data.Challenge[3] = gChallenge[3]; + + SendReply(&Reply, sizeof(Reply)); } static bool IsBadChallenge(const uint32_t *pKey, const uint32_t *pIn, const uint32_t *pResponse) { - #ifdef ENABLE_FEAT_F4HWN - UNUSED(pKey); - UNUSED(pIn); - UNUSED(pResponse); + #ifdef ENABLE_FEAT_F4HWN + UNUSED(pKey); + UNUSED(pIn); + UNUSED(pResponse); #else - unsigned int i; - uint32_t IV[4]; + unsigned int i; + uint32_t IV[4]; - IV[0] = 0; - IV[1] = 0; - IV[2] = 0; - IV[3] = 0; + IV[0] = 0; + IV[1] = 0; + IV[2] = 0; + IV[3] = 0; - AES_Encrypt(pKey, IV, pIn, IV, true); + AES_Encrypt(pKey, IV, pIn, IV, true); - for (i = 0; i < 4; i++) - if (IV[i] != pResponse[i]) - return true; - #endif - return false; + for (i = 0; i < 4; i++) + if (IV[i] != pResponse[i]) + return true; + #endif + return false; } // session init, sends back version info and state // timestamp is a session id really static void CMD_0514(const uint8_t *pBuffer) { - const CMD_0514_t *pCmd = (const CMD_0514_t *)pBuffer; + const CMD_0514_t *pCmd = (const CMD_0514_t *)pBuffer; - Timestamp = pCmd->Timestamp; + Timestamp = pCmd->Timestamp; - #ifdef ENABLE_FMRADIO - gFmRadioCountdown_500ms = fm_radio_countdown_500ms; - #endif + #ifdef ENABLE_FMRADIO + gFmRadioCountdown_500ms = fm_radio_countdown_500ms; + #endif - gSerialConfigCountDown_500ms = 12; // 6 sec - - // turn the LCD backlight off - BACKLIGHT_TurnOff(); + gSerialConfigCountDown_500ms = 12; // 6 sec + + // turn the LCD backlight off + BACKLIGHT_TurnOff(); - SendVersion(); + SendVersion(); } // read eeprom static void CMD_051B(const uint8_t *pBuffer) { - const CMD_051B_t *pCmd = (const CMD_051B_t *)pBuffer; - REPLY_051B_t Reply; - bool bLocked = false; + const CMD_051B_t *pCmd = (const CMD_051B_t *)pBuffer; + REPLY_051B_t Reply; + bool bLocked = false; - if (pCmd->Timestamp != Timestamp) - return; + if (pCmd->Timestamp != Timestamp) + return; - gSerialConfigCountDown_500ms = 12; // 6 sec + gSerialConfigCountDown_500ms = 12; // 6 sec - #ifdef ENABLE_FMRADIO - gFmRadioCountdown_500ms = fm_radio_countdown_500ms; - #endif + #ifdef ENABLE_FMRADIO + gFmRadioCountdown_500ms = fm_radio_countdown_500ms; + #endif - memset(&Reply, 0, sizeof(Reply)); - Reply.Header.ID = 0x051C; - Reply.Header.Size = pCmd->Size + 4; - Reply.Data.Offset = pCmd->Offset; - Reply.Data.Size = pCmd->Size; + memset(&Reply, 0, sizeof(Reply)); + Reply.Header.ID = 0x051C; + Reply.Header.Size = pCmd->Size + 4; + Reply.Data.Offset = pCmd->Offset; + Reply.Data.Size = pCmd->Size; - if (bHasCustomAesKey) - bLocked = gIsLocked; + if (bHasCustomAesKey) + bLocked = gIsLocked; - if (!bLocked) - EEPROM_ReadBuffer(pCmd->Offset, Reply.Data.Data, pCmd->Size); + if (!bLocked) + EEPROM_ReadBuffer(pCmd->Offset, Reply.Data.Data, pCmd->Size); - SendReply(&Reply, pCmd->Size + 8); + SendReply(&Reply, pCmd->Size + 8); } // write eeprom static void CMD_051D(const uint8_t *pBuffer) { - const CMD_051D_t *pCmd = (const CMD_051D_t *)pBuffer; - REPLY_051D_t Reply; - bool bReloadEeprom; - bool bIsLocked; + const CMD_051D_t *pCmd = (const CMD_051D_t *)pBuffer; + REPLY_051D_t Reply; + bool bReloadEeprom; + bool bIsLocked; - if (pCmd->Timestamp != Timestamp) - return; + if (pCmd->Timestamp != Timestamp) + return; - gSerialConfigCountDown_500ms = 12; // 6 sec - - bReloadEeprom = false; + gSerialConfigCountDown_500ms = 12; // 6 sec + + bReloadEeprom = false; - #ifdef ENABLE_FMRADIO - gFmRadioCountdown_500ms = fm_radio_countdown_500ms; - #endif + #ifdef ENABLE_FMRADIO + gFmRadioCountdown_500ms = fm_radio_countdown_500ms; + #endif - Reply.Header.ID = 0x051E; - Reply.Header.Size = sizeof(Reply.Data); - Reply.Data.Offset = pCmd->Offset; + Reply.Header.ID = 0x051E; + Reply.Header.Size = sizeof(Reply.Data); + Reply.Data.Offset = pCmd->Offset; - bIsLocked = bHasCustomAesKey ? gIsLocked : bHasCustomAesKey; + bIsLocked = bHasCustomAesKey ? gIsLocked : bHasCustomAesKey; - if (!bIsLocked) - { - unsigned int i; - for (i = 0; i < (pCmd->Size / 8); i++) - { - const uint16_t Offset = pCmd->Offset + (i * 8U); + if (!bIsLocked) + { + unsigned int i; + for (i = 0; i < (pCmd->Size / 8); i++) + { + const uint16_t Offset = pCmd->Offset + (i * 8U); - if (Offset >= 0x0F30 && Offset < 0x0F40) - if (!gIsLocked) - bReloadEeprom = true; + if (Offset >= 0x0F30 && Offset < 0x0F40) + if (!gIsLocked) + bReloadEeprom = true; - if ((Offset < 0x0E98 || Offset >= 0x0EA0) || !bIsInLockScreen || pCmd->bAllowPassword) - EEPROM_WriteBuffer(Offset, &pCmd->Data[i * 8U]); - } + if ((Offset < 0x0E98 || Offset >= 0x0EA0) || !bIsInLockScreen || pCmd->bAllowPassword) + EEPROM_WriteBuffer(Offset, &pCmd->Data[i * 8U]); + } - if (bReloadEeprom) - SETTINGS_InitEEPROM(); - } + if (bReloadEeprom) + SETTINGS_InitEEPROM(); + } - SendReply(&Reply, sizeof(Reply)); + SendReply(&Reply, sizeof(Reply)); } // read RSSI static void CMD_0527(void) { - REPLY_0527_t Reply; + REPLY_0527_t Reply; - Reply.Header.ID = 0x0528; - Reply.Header.Size = sizeof(Reply.Data); - Reply.Data.RSSI = BK4819_ReadRegister(BK4819_REG_67) & 0x01FF; - Reply.Data.ExNoiseIndicator = BK4819_ReadRegister(BK4819_REG_65) & 0x007F; - Reply.Data.GlitchIndicator = BK4819_ReadRegister(BK4819_REG_63); + Reply.Header.ID = 0x0528; + Reply.Header.Size = sizeof(Reply.Data); + Reply.Data.RSSI = BK4819_ReadRegister(BK4819_REG_67) & 0x01FF; + Reply.Data.ExNoiseIndicator = BK4819_ReadRegister(BK4819_REG_65) & 0x007F; + Reply.Data.GlitchIndicator = BK4819_ReadRegister(BK4819_REG_63); - SendReply(&Reply, sizeof(Reply)); + SendReply(&Reply, sizeof(Reply)); } // read ADC static void CMD_0529(void) { - REPLY_0529_t Reply; + REPLY_0529_t Reply; - Reply.Header.ID = 0x52A; - Reply.Header.Size = sizeof(Reply.Data); + Reply.Header.ID = 0x52A; + Reply.Header.Size = sizeof(Reply.Data); - // Original doesn't actually send current! - BOARD_ADC_GetBatteryInfo(&Reply.Data.Voltage, &Reply.Data.Current); + // Original doesn't actually send current! + BOARD_ADC_GetBatteryInfo(&Reply.Data.Voltage, &Reply.Data.Current); - SendReply(&Reply, sizeof(Reply)); + SendReply(&Reply, sizeof(Reply)); } static void CMD_052D(const uint8_t *pBuffer) { - const CMD_052D_t *pCmd = (const CMD_052D_t *)pBuffer; - REPLY_052D_t Reply; - bool bIsLocked; - - #ifdef ENABLE_FMRADIO - gFmRadioCountdown_500ms = fm_radio_countdown_500ms; - #endif - Reply.Header.ID = 0x052E; - Reply.Header.Size = sizeof(Reply.Data); - - bIsLocked = bHasCustomAesKey; - - if (!bIsLocked) - bIsLocked = IsBadChallenge(gCustomAesKey, gChallenge, pCmd->Response); - - if (!bIsLocked) - { - bIsLocked = IsBadChallenge(gDefaultAesKey, gChallenge, pCmd->Response); - if (bIsLocked) - gTryCount++; - } - - if (gTryCount < 3) - { - if (!bIsLocked) - gTryCount = 0; - } - else - { - gTryCount = 3; - bIsLocked = true; - } - - gIsLocked = bIsLocked; - Reply.Data.bIsLocked = bIsLocked; - - SendReply(&Reply, sizeof(Reply)); + const CMD_052D_t *pCmd = (const CMD_052D_t *)pBuffer; + REPLY_052D_t Reply; + bool bIsLocked; + + #ifdef ENABLE_FMRADIO + gFmRadioCountdown_500ms = fm_radio_countdown_500ms; + #endif + Reply.Header.ID = 0x052E; + Reply.Header.Size = sizeof(Reply.Data); + + bIsLocked = bHasCustomAesKey; + + if (!bIsLocked) + bIsLocked = IsBadChallenge(gCustomAesKey, gChallenge, pCmd->Response); + + if (!bIsLocked) + { + bIsLocked = IsBadChallenge(gDefaultAesKey, gChallenge, pCmd->Response); + if (bIsLocked) + gTryCount++; + } + + if (gTryCount < 3) + { + if (!bIsLocked) + gTryCount = 0; + } + else + { + gTryCount = 3; + bIsLocked = true; + } + + gIsLocked = bIsLocked; + Reply.Data.bIsLocked = bIsLocked; + + SendReply(&Reply, sizeof(Reply)); } // session init, sends back version info and state @@ -408,223 +408,223 @@ static void CMD_052D(const uint8_t *pBuffer) // exits power save, sets main VFO to upper, static void CMD_052F(const uint8_t *pBuffer) { - const CMD_052F_t *pCmd = (const CMD_052F_t *)pBuffer; - - gEeprom.DUAL_WATCH = DUAL_WATCH_OFF; - gEeprom.CROSS_BAND_RX_TX = CROSS_BAND_OFF; - gEeprom.RX_VFO = 0; - gEeprom.DTMF_SIDE_TONE = false; - gEeprom.VfoInfo[0].FrequencyReverse = false; - gEeprom.VfoInfo[0].pRX = &gEeprom.VfoInfo[0].freq_config_RX; - gEeprom.VfoInfo[0].pTX = &gEeprom.VfoInfo[0].freq_config_TX; - gEeprom.VfoInfo[0].TX_OFFSET_FREQUENCY_DIRECTION = TX_OFFSET_FREQUENCY_DIRECTION_OFF; - gEeprom.VfoInfo[0].DTMF_PTT_ID_TX_MODE = PTT_ID_OFF; + const CMD_052F_t *pCmd = (const CMD_052F_t *)pBuffer; + + gEeprom.DUAL_WATCH = DUAL_WATCH_OFF; + gEeprom.CROSS_BAND_RX_TX = CROSS_BAND_OFF; + gEeprom.RX_VFO = 0; + gEeprom.DTMF_SIDE_TONE = false; + gEeprom.VfoInfo[0].FrequencyReverse = false; + gEeprom.VfoInfo[0].pRX = &gEeprom.VfoInfo[0].freq_config_RX; + gEeprom.VfoInfo[0].pTX = &gEeprom.VfoInfo[0].freq_config_TX; + gEeprom.VfoInfo[0].TX_OFFSET_FREQUENCY_DIRECTION = TX_OFFSET_FREQUENCY_DIRECTION_OFF; + gEeprom.VfoInfo[0].DTMF_PTT_ID_TX_MODE = PTT_ID_OFF; #ifdef ENABLE_DTMF_CALLING - gEeprom.VfoInfo[0].DTMF_DECODING_ENABLE = false; + gEeprom.VfoInfo[0].DTMF_DECODING_ENABLE = false; #endif - #ifdef ENABLE_NOAA - gIsNoaaMode = false; - #endif + #ifdef ENABLE_NOAA + gIsNoaaMode = false; + #endif - if (gCurrentFunction == FUNCTION_POWER_SAVE) - FUNCTION_Select(FUNCTION_FOREGROUND); + if (gCurrentFunction == FUNCTION_POWER_SAVE) + FUNCTION_Select(FUNCTION_FOREGROUND); - gSerialConfigCountDown_500ms = 12; // 6 sec + gSerialConfigCountDown_500ms = 12; // 6 sec - Timestamp = pCmd->Timestamp; + Timestamp = pCmd->Timestamp; - // turn the LCD backlight off - BACKLIGHT_TurnOff(); + // turn the LCD backlight off + BACKLIGHT_TurnOff(); - SendVersion(); + SendVersion(); } #ifdef ENABLE_UART_RW_BK_REGS static void CMD_0601_ReadBK4819Reg(const uint8_t *pBuffer) { - typedef struct __attribute__((__packed__)) { - Header_t header; - uint8_t reg; - } CMD_0601_t; - - CMD_0601_t *cmd = (CMD_0601_t*) pBuffer; - - struct __attribute__((__packed__)) { - Header_t header; - struct __attribute__((__packed__)) { - uint8_t reg; - uint16_t value; - } data; - } reply; - - reply.header.ID = 0x0601; - reply.header.Size = sizeof(reply.data); - reply.data.reg = cmd->reg; - reply.data.value = BK4819_ReadRegister(cmd->reg); - SendReply(&reply, sizeof(reply)); + typedef struct __attribute__((__packed__)) { + Header_t header; + uint8_t reg; + } CMD_0601_t; + + CMD_0601_t *cmd = (CMD_0601_t*) pBuffer; + + struct __attribute__((__packed__)) { + Header_t header; + struct __attribute__((__packed__)) { + uint8_t reg; + uint16_t value; + } data; + } reply; + + reply.header.ID = 0x0601; + reply.header.Size = sizeof(reply.data); + reply.data.reg = cmd->reg; + reply.data.value = BK4819_ReadRegister(cmd->reg); + SendReply(&reply, sizeof(reply)); } static void CMD_0602_WriteBK4819Reg(const uint8_t *pBuffer) { - typedef struct __attribute__((__packed__)) { - Header_t header; - uint8_t reg; - uint16_t value; - } CMD_0602_t; - - CMD_0602_t *cmd = (CMD_0602_t*) pBuffer; - BK4819_WriteRegister(cmd->reg, cmd->value); + typedef struct __attribute__((__packed__)) { + Header_t header; + uint8_t reg; + uint16_t value; + } CMD_0602_t; + + CMD_0602_t *cmd = (CMD_0602_t*) pBuffer; + BK4819_WriteRegister(cmd->reg, cmd->value); } #endif bool UART_IsCommandAvailable(void) { - uint16_t Index; - uint16_t TailIndex; - uint16_t Size; - uint16_t CRC; - uint16_t CommandLength; - uint16_t DmaLength = DMA_CH0->ST & 0xFFFU; - - while (1) - { - if (gUART_WriteIndex == DmaLength) - return false; - - while (gUART_WriteIndex != DmaLength && UART_DMA_Buffer[gUART_WriteIndex] != 0xABU) - gUART_WriteIndex = DMA_INDEX(gUART_WriteIndex, 1); - - if (gUART_WriteIndex == DmaLength) - return false; - - if (gUART_WriteIndex < DmaLength) - CommandLength = DmaLength - gUART_WriteIndex; - else - CommandLength = (DmaLength + sizeof(UART_DMA_Buffer)) - gUART_WriteIndex; - - if (CommandLength < 8) - return 0; - - if (UART_DMA_Buffer[DMA_INDEX(gUART_WriteIndex, 1)] == 0xCD) - break; - - gUART_WriteIndex = DMA_INDEX(gUART_WriteIndex, 1); - } - - Index = DMA_INDEX(gUART_WriteIndex, 2); - Size = (UART_DMA_Buffer[DMA_INDEX(Index, 1)] << 8) | UART_DMA_Buffer[Index]; - - if ((Size + 8u) > sizeof(UART_DMA_Buffer)) - { - gUART_WriteIndex = DmaLength; - return false; - } - - if (CommandLength < (Size + 8)) - return false; - - Index = DMA_INDEX(Index, 2); - TailIndex = DMA_INDEX(Index, Size + 2); - - if (UART_DMA_Buffer[TailIndex] != 0xDC || UART_DMA_Buffer[DMA_INDEX(TailIndex, 1)] != 0xBA) - { - gUART_WriteIndex = DmaLength; - return false; - } - - if (TailIndex < Index) - { - const uint16_t ChunkSize = sizeof(UART_DMA_Buffer) - Index; - memcpy(UART_Command.Buffer, UART_DMA_Buffer + Index, ChunkSize); - memcpy(UART_Command.Buffer + ChunkSize, UART_DMA_Buffer, TailIndex); - } - else - memcpy(UART_Command.Buffer, UART_DMA_Buffer + Index, TailIndex - Index); - - TailIndex = DMA_INDEX(TailIndex, 2); - if (TailIndex < gUART_WriteIndex) - { - memset(UART_DMA_Buffer + gUART_WriteIndex, 0, sizeof(UART_DMA_Buffer) - gUART_WriteIndex); - memset(UART_DMA_Buffer, 0, TailIndex); - } - else - memset(UART_DMA_Buffer + gUART_WriteIndex, 0, TailIndex - gUART_WriteIndex); - - gUART_WriteIndex = TailIndex; - - if (UART_Command.Header.ID == 0x0514) - bIsEncrypted = false; - - if (UART_Command.Header.ID == 0x6902) - bIsEncrypted = true; - - if (bIsEncrypted) - { - unsigned int i; - for (i = 0; i < (Size + 2u); i++) - UART_Command.Buffer[i] ^= Obfuscation[i % 16]; - } - - CRC = UART_Command.Buffer[Size] | (UART_Command.Buffer[Size + 1] << 8); - - return (CRC_Calculate(UART_Command.Buffer, Size) != CRC) ? false : true; + uint16_t Index; + uint16_t TailIndex; + uint16_t Size; + uint16_t CRC; + uint16_t CommandLength; + uint16_t DmaLength = DMA_CH0->ST & 0xFFFU; + + while (1) + { + if (gUART_WriteIndex == DmaLength) + return false; + + while (gUART_WriteIndex != DmaLength && UART_DMA_Buffer[gUART_WriteIndex] != 0xABU) + gUART_WriteIndex = DMA_INDEX(gUART_WriteIndex, 1); + + if (gUART_WriteIndex == DmaLength) + return false; + + if (gUART_WriteIndex < DmaLength) + CommandLength = DmaLength - gUART_WriteIndex; + else + CommandLength = (DmaLength + sizeof(UART_DMA_Buffer)) - gUART_WriteIndex; + + if (CommandLength < 8) + return 0; + + if (UART_DMA_Buffer[DMA_INDEX(gUART_WriteIndex, 1)] == 0xCD) + break; + + gUART_WriteIndex = DMA_INDEX(gUART_WriteIndex, 1); + } + + Index = DMA_INDEX(gUART_WriteIndex, 2); + Size = (UART_DMA_Buffer[DMA_INDEX(Index, 1)] << 8) | UART_DMA_Buffer[Index]; + + if ((Size + 8u) > sizeof(UART_DMA_Buffer)) + { + gUART_WriteIndex = DmaLength; + return false; + } + + if (CommandLength < (Size + 8)) + return false; + + Index = DMA_INDEX(Index, 2); + TailIndex = DMA_INDEX(Index, Size + 2); + + if (UART_DMA_Buffer[TailIndex] != 0xDC || UART_DMA_Buffer[DMA_INDEX(TailIndex, 1)] != 0xBA) + { + gUART_WriteIndex = DmaLength; + return false; + } + + if (TailIndex < Index) + { + const uint16_t ChunkSize = sizeof(UART_DMA_Buffer) - Index; + memcpy(UART_Command.Buffer, UART_DMA_Buffer + Index, ChunkSize); + memcpy(UART_Command.Buffer + ChunkSize, UART_DMA_Buffer, TailIndex); + } + else + memcpy(UART_Command.Buffer, UART_DMA_Buffer + Index, TailIndex - Index); + + TailIndex = DMA_INDEX(TailIndex, 2); + if (TailIndex < gUART_WriteIndex) + { + memset(UART_DMA_Buffer + gUART_WriteIndex, 0, sizeof(UART_DMA_Buffer) - gUART_WriteIndex); + memset(UART_DMA_Buffer, 0, TailIndex); + } + else + memset(UART_DMA_Buffer + gUART_WriteIndex, 0, TailIndex - gUART_WriteIndex); + + gUART_WriteIndex = TailIndex; + + if (UART_Command.Header.ID == 0x0514) + bIsEncrypted = false; + + if (UART_Command.Header.ID == 0x6902) + bIsEncrypted = true; + + if (bIsEncrypted) + { + unsigned int i; + for (i = 0; i < (Size + 2u); i++) + UART_Command.Buffer[i] ^= Obfuscation[i % 16]; + } + + CRC = UART_Command.Buffer[Size] | (UART_Command.Buffer[Size + 1] << 8); + + return (CRC_Calculate(UART_Command.Buffer, Size) != CRC) ? false : true; } void UART_HandleCommand(void) { - switch (UART_Command.Header.ID) - { - case 0x0514: - CMD_0514(UART_Command.Buffer); - break; - - case 0x051B: - CMD_051B(UART_Command.Buffer); - break; - - case 0x051D: - CMD_051D(UART_Command.Buffer); - break; - - case 0x051F: // Not implementing non-authentic command - break; - - case 0x0521: // Not implementing non-authentic command - break; - - case 0x0527: - CMD_0527(); - break; - - case 0x0529: - CMD_0529(); - break; - - case 0x052D: - CMD_052D(UART_Command.Buffer); - break; - - case 0x052F: - CMD_052F(UART_Command.Buffer); - break; - - case 0x05DD: // reset - #if defined(ENABLE_OVERLAY) - overlay_FLASH_RebootToBootloader(); - #else - NVIC_SystemReset(); - #endif - break; - + switch (UART_Command.Header.ID) + { + case 0x0514: + CMD_0514(UART_Command.Buffer); + break; + + case 0x051B: + CMD_051B(UART_Command.Buffer); + break; + + case 0x051D: + CMD_051D(UART_Command.Buffer); + break; + + case 0x051F: // Not implementing non-authentic command + break; + + case 0x0521: // Not implementing non-authentic command + break; + + case 0x0527: + CMD_0527(); + break; + + case 0x0529: + CMD_0529(); + break; + + case 0x052D: + CMD_052D(UART_Command.Buffer); + break; + + case 0x052F: + CMD_052F(UART_Command.Buffer); + break; + + case 0x05DD: // reset + #if defined(ENABLE_OVERLAY) + overlay_FLASH_RebootToBootloader(); + #else + NVIC_SystemReset(); + #endif + break; + #ifdef ENABLE_UART_RW_BK_REGS - case 0x0601: - CMD_0601_ReadBK4819Reg(UART_Command.Buffer); - break; - - case 0x0602: - CMD_0602_WriteBK4819Reg(UART_Command.Buffer); - break; + case 0x0601: + CMD_0601_ReadBK4819Reg(UART_Command.Buffer); + break; + + case 0x0602: + CMD_0602_WriteBK4819Reg(UART_Command.Buffer); + break; #endif - } + } } diff --git a/audio.c b/audio.c index f15be2294..8392c0838 100644 --- a/audio.c +++ b/audio.c @@ -15,12 +15,12 @@ */ #ifdef ENABLE_FMRADIO - #include "app/fm.h" + #include "app/fm.h" #endif #include "audio.h" #include "bsp/dp32g030/gpio.h" #ifdef ENABLE_FMRADIO - #include "driver/bk1080.h" + #include "driver/bk1080.h" #endif #include "driver/bk4819.h" #include "driver/gpio.h" @@ -37,162 +37,162 @@ BEEP_Type_t gBeepToPlay = BEEP_NONE; void AUDIO_PlayBeep(BEEP_Type_t Beep) { - if (Beep != BEEP_880HZ_60MS_DOUBLE_BEEP && - Beep != BEEP_500HZ_60MS_DOUBLE_BEEP && - Beep != BEEP_440HZ_500MS && + if (Beep != BEEP_880HZ_60MS_DOUBLE_BEEP && + Beep != BEEP_500HZ_60MS_DOUBLE_BEEP && + Beep != BEEP_440HZ_500MS && #ifdef ENABLE_DTMF_CALLING - Beep != BEEP_880HZ_200MS && - Beep != BEEP_880HZ_500MS && + Beep != BEEP_880HZ_200MS && + Beep != BEEP_880HZ_500MS && #endif #ifdef ENABLE_FEAT_F4HWN - Beep != BEEP_400HZ_30MS && - Beep != BEEP_500HZ_30MS && - Beep != BEEP_600HZ_30MS && + Beep != BEEP_400HZ_30MS && + Beep != BEEP_500HZ_30MS && + Beep != BEEP_600HZ_30MS && #endif - !gEeprom.BEEP_CONTROL) - return; + !gEeprom.BEEP_CONTROL) + return; #ifdef ENABLE_AIRCOPY - if (gScreenToDisplay == DISPLAY_AIRCOPY) - return; + if (gScreenToDisplay == DISPLAY_AIRCOPY) + return; #endif - if (gCurrentFunction == FUNCTION_RECEIVE) - return; + if (gCurrentFunction == FUNCTION_RECEIVE) + return; - if (gCurrentFunction == FUNCTION_MONITOR) - return; + if (gCurrentFunction == FUNCTION_MONITOR) + return; #ifdef ENABLE_FMRADIO - if (gFmRadioMode) - BK1080_Mute(true); + if (gFmRadioMode) + BK1080_Mute(true); #endif - AUDIO_AudioPathOff(); - - if (gCurrentFunction == FUNCTION_POWER_SAVE && gRxIdleMode) - BK4819_RX_TurnOn(); - - SYSTEM_DelayMs(20); - - uint16_t ToneConfig = BK4819_ReadRegister(BK4819_REG_71); - - uint16_t ToneFrequency; - switch (Beep) - { - default: - case BEEP_NONE: - ToneFrequency = 220; - break; - case BEEP_1KHZ_60MS_OPTIONAL: - ToneFrequency = 1000; - break; - case BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL: - case BEEP_500HZ_60MS_DOUBLE_BEEP: - ToneFrequency = 500; - break; - case BEEP_440HZ_500MS: - ToneFrequency = 440; - break; - case BEEP_880HZ_60MS_DOUBLE_BEEP: + AUDIO_AudioPathOff(); + + if (gCurrentFunction == FUNCTION_POWER_SAVE && gRxIdleMode) + BK4819_RX_TurnOn(); + + SYSTEM_DelayMs(20); + + uint16_t ToneConfig = BK4819_ReadRegister(BK4819_REG_71); + + uint16_t ToneFrequency; + switch (Beep) + { + default: + case BEEP_NONE: + ToneFrequency = 220; + break; + case BEEP_1KHZ_60MS_OPTIONAL: + ToneFrequency = 1000; + break; + case BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL: + case BEEP_500HZ_60MS_DOUBLE_BEEP: + ToneFrequency = 500; + break; + case BEEP_440HZ_500MS: + ToneFrequency = 440; + break; + case BEEP_880HZ_60MS_DOUBLE_BEEP: #ifndef ENABLE_FEAT_F4HWN - case BEEP_880HZ_200MS: - case BEEP_880HZ_500MS: + case BEEP_880HZ_200MS: + case BEEP_880HZ_500MS: #endif - ToneFrequency = 880; - break; + ToneFrequency = 880; + break; #ifdef ENABLE_FEAT_F4HWN - case BEEP_400HZ_30MS: - ToneFrequency = 400; - break; - case BEEP_500HZ_30MS: - ToneFrequency = 500; - break; - case BEEP_600HZ_30MS: - ToneFrequency = 600; - break; + case BEEP_400HZ_30MS: + ToneFrequency = 400; + break; + case BEEP_500HZ_30MS: + ToneFrequency = 500; + break; + case BEEP_600HZ_30MS: + ToneFrequency = 600; + break; #endif - } - - if(Beep == BEEP_400HZ_30MS || Beep == BEEP_500HZ_30MS || Beep == BEEP_600HZ_30MS) - { - BK4819_WriteRegister(BK4819_REG_70, BK4819_REG_70_ENABLE_TONE1 | ((1 & 0x7f) << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN)); - } - - BK4819_PlayTone(ToneFrequency, true); - - SYSTEM_DelayMs(2); - - AUDIO_AudioPathOn(); - - SYSTEM_DelayMs(60); - - uint16_t Duration; - switch (Beep) - { - case BEEP_880HZ_60MS_DOUBLE_BEEP: - BK4819_ExitTxMute(); - SYSTEM_DelayMs(60); - BK4819_EnterTxMute(); - SYSTEM_DelayMs(20); - [[fallthrough]]; - case BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL: - case BEEP_500HZ_60MS_DOUBLE_BEEP: - BK4819_ExitTxMute(); - SYSTEM_DelayMs(60); - BK4819_EnterTxMute(); - SYSTEM_DelayMs(20); - [[fallthrough]]; - case BEEP_1KHZ_60MS_OPTIONAL: - BK4819_ExitTxMute(); - Duration = 60; - break; + } + + if(Beep == BEEP_400HZ_30MS || Beep == BEEP_500HZ_30MS || Beep == BEEP_600HZ_30MS) + { + BK4819_WriteRegister(BK4819_REG_70, BK4819_REG_70_ENABLE_TONE1 | ((1 & 0x7f) << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN)); + } + + BK4819_PlayTone(ToneFrequency, true); + + SYSTEM_DelayMs(2); + + AUDIO_AudioPathOn(); + + SYSTEM_DelayMs(60); + + uint16_t Duration; + switch (Beep) + { + case BEEP_880HZ_60MS_DOUBLE_BEEP: + BK4819_ExitTxMute(); + SYSTEM_DelayMs(60); + BK4819_EnterTxMute(); + SYSTEM_DelayMs(20); + [[fallthrough]]; + case BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL: + case BEEP_500HZ_60MS_DOUBLE_BEEP: + BK4819_ExitTxMute(); + SYSTEM_DelayMs(60); + BK4819_EnterTxMute(); + SYSTEM_DelayMs(20); + [[fallthrough]]; + case BEEP_1KHZ_60MS_OPTIONAL: + BK4819_ExitTxMute(); + Duration = 60; + break; #ifdef ENABLE_FEAT_F4HWN - case BEEP_400HZ_30MS: - case BEEP_500HZ_30MS: - case BEEP_600HZ_30MS: - BK4819_ExitTxMute(); - Duration = 30; - break; + case BEEP_400HZ_30MS: + case BEEP_500HZ_30MS: + case BEEP_600HZ_30MS: + BK4819_ExitTxMute(); + Duration = 30; + break; #endif - case BEEP_440HZ_500MS: + case BEEP_440HZ_500MS: #ifndef ENABLE_FEAT_F4HWN - case BEEP_880HZ_200MS: - BK4819_ExitTxMute(); - Duration = 200; - break; - case BEEP_880HZ_500MS: + case BEEP_880HZ_200MS: + BK4819_ExitTxMute(); + Duration = 200; + break; + case BEEP_880HZ_500MS: #endif - default: - BK4819_ExitTxMute(); - Duration = 500; - break; - } + default: + BK4819_ExitTxMute(); + Duration = 500; + break; + } - SYSTEM_DelayMs(Duration); - BK4819_EnterTxMute(); - SYSTEM_DelayMs(20); + SYSTEM_DelayMs(Duration); + BK4819_EnterTxMute(); + SYSTEM_DelayMs(20); - AUDIO_AudioPathOff(); + AUDIO_AudioPathOff(); - SYSTEM_DelayMs(5); - BK4819_TurnsOffTones_TurnsOnRX(); - SYSTEM_DelayMs(5); - BK4819_WriteRegister(BK4819_REG_71, ToneConfig); + SYSTEM_DelayMs(5); + BK4819_TurnsOffTones_TurnsOnRX(); + SYSTEM_DelayMs(5); + BK4819_WriteRegister(BK4819_REG_71, ToneConfig); - if (gEnableSpeaker) - AUDIO_AudioPathOn(); + if (gEnableSpeaker) + AUDIO_AudioPathOn(); #ifdef ENABLE_FMRADIO - if (gFmRadioMode) - BK1080_Mute(false); + if (gFmRadioMode) + BK1080_Mute(false); #endif - if (gCurrentFunction == FUNCTION_POWER_SAVE && gRxIdleMode) - BK4819_Sleep(); + if (gCurrentFunction == FUNCTION_POWER_SAVE && gRxIdleMode) + BK4819_Sleep(); #ifdef ENABLE_VOX - gVoxResumeCountdown = 80; + gVoxResumeCountdown = 80; #endif } @@ -201,28 +201,28 @@ void AUDIO_PlayBeep(BEEP_Type_t Beep) static const uint8_t VoiceClipLengthChinese[58] = { - 0x32, 0x32, 0x32, 0x37, 0x37, 0x32, 0x32, 0x32, - 0x32, 0x37, 0x37, 0x32, 0x64, 0x64, 0x64, 0x64, - 0x64, 0x69, 0x64, 0x69, 0x5A, 0x5F, 0x5F, 0x64, - 0x64, 0x69, 0x64, 0x64, 0x69, 0x69, 0x69, 0x64, - 0x64, 0x6E, 0x69, 0x5F, 0x64, 0x64, 0x64, 0x69, - 0x69, 0x69, 0x64, 0x69, 0x64, 0x64, 0x55, 0x5F, - 0x5A, 0x4B, 0x4B, 0x46, 0x46, 0x69, 0x64, 0x6E, - 0x5A, 0x64, + 0x32, 0x32, 0x32, 0x37, 0x37, 0x32, 0x32, 0x32, + 0x32, 0x37, 0x37, 0x32, 0x64, 0x64, 0x64, 0x64, + 0x64, 0x69, 0x64, 0x69, 0x5A, 0x5F, 0x5F, 0x64, + 0x64, 0x69, 0x64, 0x64, 0x69, 0x69, 0x69, 0x64, + 0x64, 0x6E, 0x69, 0x5F, 0x64, 0x64, 0x64, 0x69, + 0x69, 0x69, 0x64, 0x69, 0x64, 0x64, 0x55, 0x5F, + 0x5A, 0x4B, 0x4B, 0x46, 0x46, 0x69, 0x64, 0x6E, + 0x5A, 0x64, }; static const uint8_t VoiceClipLengthEnglish[76] = { - 0x50, 0x32, 0x2D, 0x2D, 0x2D, 0x37, 0x37, 0x37, - 0x32, 0x32, 0x3C, 0x37, 0x46, 0x46, 0x4B, 0x82, - 0x82, 0x6E, 0x82, 0x46, 0x96, 0x64, 0x46, 0x6E, - 0x78, 0x6E, 0x87, 0x64, 0x96, 0x96, 0x46, 0x9B, - 0x91, 0x82, 0x82, 0x73, 0x78, 0x64, 0x82, 0x6E, - 0x78, 0x82, 0x87, 0x6E, 0x55, 0x78, 0x64, 0x69, - 0x9B, 0x5A, 0x50, 0x3C, 0x32, 0x55, 0x64, 0x64, - 0x50, 0x46, 0x46, 0x46, 0x4B, 0x4B, 0x50, 0x50, - 0x55, 0x4B, 0x4B, 0x32, 0x32, 0x32, 0x32, 0x37, - 0x41, 0x32, 0x3C, 0x37, + 0x50, 0x32, 0x2D, 0x2D, 0x2D, 0x37, 0x37, 0x37, + 0x32, 0x32, 0x3C, 0x37, 0x46, 0x46, 0x4B, 0x82, + 0x82, 0x6E, 0x82, 0x46, 0x96, 0x64, 0x46, 0x6E, + 0x78, 0x6E, 0x87, 0x64, 0x96, 0x96, 0x46, 0x9B, + 0x91, 0x82, 0x82, 0x73, 0x78, 0x64, 0x82, 0x6E, + 0x78, 0x82, 0x87, 0x6E, 0x55, 0x78, 0x64, 0x69, + 0x9B, 0x5A, 0x50, 0x3C, 0x32, 0x55, 0x64, 0x64, + 0x50, 0x46, 0x46, 0x46, 0x4B, 0x4B, 0x50, 0x50, + 0x55, 0x4B, 0x4B, 0x32, 0x32, 0x32, 0x32, 0x37, + 0x41, 0x32, 0x3C, 0x37, }; VOICE_ID_t gVoiceID[8]; @@ -235,236 +235,236 @@ VOICE_ID_t gAnotherVoiceID = VOICE_ID_INVALID; static void AUDIO_PlayVoice(uint8_t VoiceID) { - unsigned int i; - - GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_VOICE_0); - SYSTEM_DelayMs(20); - GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_VOICE_0); - - for (i = 0; i < 8; i++) - { - if ((VoiceID & 0x80U) == 0) - GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_VOICE_1); - else - GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_VOICE_1); - - SYSTICK_DelayUs(1000); - GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_VOICE_0); - SYSTICK_DelayUs(1200); - GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_VOICE_0); - VoiceID <<= 1; - SYSTICK_DelayUs(200); - } + unsigned int i; + + GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_VOICE_0); + SYSTEM_DelayMs(20); + GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_VOICE_0); + + for (i = 0; i < 8; i++) + { + if ((VoiceID & 0x80U) == 0) + GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_VOICE_1); + else + GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_VOICE_1); + + SYSTICK_DelayUs(1000); + GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_VOICE_0); + SYSTICK_DelayUs(1200); + GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_VOICE_0); + VoiceID <<= 1; + SYSTICK_DelayUs(200); + } } void AUDIO_PlaySingleVoice(bool bFlag) { - uint8_t VoiceID; - uint8_t Delay; + uint8_t VoiceID; + uint8_t Delay; - VoiceID = gVoiceID[0]; + VoiceID = gVoiceID[0]; - if (gEeprom.VOICE_PROMPT != VOICE_PROMPT_OFF && gVoiceWriteIndex > 0) - { - if (gEeprom.VOICE_PROMPT == VOICE_PROMPT_CHINESE) - { // Chinese - if (VoiceID >= ARRAY_SIZE(VoiceClipLengthChinese)) - goto Bailout; + if (gEeprom.VOICE_PROMPT != VOICE_PROMPT_OFF && gVoiceWriteIndex > 0) + { + if (gEeprom.VOICE_PROMPT == VOICE_PROMPT_CHINESE) + { // Chinese + if (VoiceID >= ARRAY_SIZE(VoiceClipLengthChinese)) + goto Bailout; - Delay = VoiceClipLengthChinese[VoiceID]; - VoiceID += VOICE_ID_CHI_BASE; - } - else - { // English - if (VoiceID >= ARRAY_SIZE(VoiceClipLengthEnglish)) - goto Bailout; + Delay = VoiceClipLengthChinese[VoiceID]; + VoiceID += VOICE_ID_CHI_BASE; + } + else + { // English + if (VoiceID >= ARRAY_SIZE(VoiceClipLengthEnglish)) + goto Bailout; - Delay = VoiceClipLengthEnglish[VoiceID]; - VoiceID += VOICE_ID_ENG_BASE; - } + Delay = VoiceClipLengthEnglish[VoiceID]; + VoiceID += VOICE_ID_ENG_BASE; + } - if (FUNCTION_IsRx()) // 1of11 - BK4819_SetAF(BK4819_AF_MUTE); + if (FUNCTION_IsRx()) // 1of11 + BK4819_SetAF(BK4819_AF_MUTE); - #ifdef ENABLE_FMRADIO - if (gFmRadioMode) - BK1080_Mute(true); - #endif + #ifdef ENABLE_FMRADIO + if (gFmRadioMode) + BK1080_Mute(true); + #endif - AUDIO_AudioPathOn(); + AUDIO_AudioPathOn(); - #ifdef ENABLE_VOX - gVoxResumeCountdown = 2000; - #endif + #ifdef ENABLE_VOX + gVoxResumeCountdown = 2000; + #endif - SYSTEM_DelayMs(5); - AUDIO_PlayVoice(VoiceID); + SYSTEM_DelayMs(5); + AUDIO_PlayVoice(VoiceID); - if (gVoiceWriteIndex == 1) - Delay += 3; + if (gVoiceWriteIndex == 1) + Delay += 3; - if (bFlag) - { - SYSTEM_DelayMs(Delay * 10); + if (bFlag) + { + SYSTEM_DelayMs(Delay * 10); - if (FUNCTION_IsRx()) // 1of11 - RADIO_SetModulation(gRxVfo->Modulation); + if (FUNCTION_IsRx()) // 1of11 + RADIO_SetModulation(gRxVfo->Modulation); - #ifdef ENABLE_FMRADIO - if (gFmRadioMode) - BK1080_Mute(false); - #endif + #ifdef ENABLE_FMRADIO + if (gFmRadioMode) + BK1080_Mute(false); + #endif - if (!gEnableSpeaker) - AUDIO_AudioPathOff(); + if (!gEnableSpeaker) + AUDIO_AudioPathOff(); - gVoiceWriteIndex = 0; - gVoiceReadIndex = 0; + gVoiceWriteIndex = 0; + gVoiceReadIndex = 0; - #ifdef ENABLE_VOX - gVoxResumeCountdown = 80; - #endif + #ifdef ENABLE_VOX + gVoxResumeCountdown = 80; + #endif - return; - } + return; + } - gVoiceReadIndex = 1; - gCountdownToPlayNextVoice_10ms = Delay; - gFlagPlayQueuedVoice = false; + gVoiceReadIndex = 1; + gCountdownToPlayNextVoice_10ms = Delay; + gFlagPlayQueuedVoice = false; - return; - } + return; + } Bailout: - gVoiceReadIndex = 0; - gVoiceWriteIndex = 0; + gVoiceReadIndex = 0; + gVoiceWriteIndex = 0; } void AUDIO_SetVoiceID(uint8_t Index, VOICE_ID_t VoiceID) { - if (Index >= ARRAY_SIZE(gVoiceID)) - return; + if (Index >= ARRAY_SIZE(gVoiceID)) + return; - if (Index == 0) - { - gVoiceWriteIndex = 0; - gVoiceReadIndex = 0; - } + if (Index == 0) + { + gVoiceWriteIndex = 0; + gVoiceReadIndex = 0; + } - gVoiceID[Index] = VoiceID; + gVoiceID[Index] = VoiceID; - gVoiceWriteIndex++; + gVoiceWriteIndex++; } uint8_t AUDIO_SetDigitVoice(uint8_t Index, uint16_t Value) { - uint16_t Remainder; - uint8_t Result; - uint8_t Count; - - if (Index == 0) - { - gVoiceWriteIndex = 0; - gVoiceReadIndex = 0; - } - - Count = 0; - Result = Value / 1000U; - Remainder = Value % 1000U; - if (Remainder < 100U) - { - if (Remainder < 10U) - goto Skip; - } - else - { - Result = Remainder / 100U; - gVoiceID[gVoiceWriteIndex++] = (VOICE_ID_t)Result; - Count++; - Remainder -= Result * 100U; - } - Result = Remainder / 10U; - gVoiceID[gVoiceWriteIndex++] = (VOICE_ID_t)Result; - Count++; - Remainder -= Result * 10U; + uint16_t Remainder; + uint8_t Result; + uint8_t Count; + + if (Index == 0) + { + gVoiceWriteIndex = 0; + gVoiceReadIndex = 0; + } + + Count = 0; + Result = Value / 1000U; + Remainder = Value % 1000U; + if (Remainder < 100U) + { + if (Remainder < 10U) + goto Skip; + } + else + { + Result = Remainder / 100U; + gVoiceID[gVoiceWriteIndex++] = (VOICE_ID_t)Result; + Count++; + Remainder -= Result * 100U; + } + Result = Remainder / 10U; + gVoiceID[gVoiceWriteIndex++] = (VOICE_ID_t)Result; + Count++; + Remainder -= Result * 10U; Skip: - gVoiceID[gVoiceWriteIndex++] = (VOICE_ID_t)Remainder; + gVoiceID[gVoiceWriteIndex++] = (VOICE_ID_t)Remainder; - return Count + 1U; + return Count + 1U; } void AUDIO_PlayQueuedVoice(void) { - uint8_t VoiceID; - uint8_t Delay; - bool Skip; - - Skip = false; - - if (gVoiceReadIndex != gVoiceWriteIndex && gEeprom.VOICE_PROMPT != VOICE_PROMPT_OFF) - { - VoiceID = gVoiceID[gVoiceReadIndex]; - if (gEeprom.VOICE_PROMPT == VOICE_PROMPT_CHINESE) - { - if (VoiceID < ARRAY_SIZE(VoiceClipLengthChinese)) - { - Delay = VoiceClipLengthChinese[VoiceID]; - VoiceID += VOICE_ID_CHI_BASE; - } - else - Skip = true; - } - else - { - if (VoiceID < ARRAY_SIZE(VoiceClipLengthEnglish)) - { - Delay = VoiceClipLengthEnglish[VoiceID]; - VoiceID += VOICE_ID_ENG_BASE; - } - else - Skip = true; - } - - gVoiceReadIndex++; - - if (!Skip) - { - if (gVoiceReadIndex == gVoiceWriteIndex) - Delay += 3; - - AUDIO_PlayVoice(VoiceID); - - gCountdownToPlayNextVoice_10ms = Delay; - gFlagPlayQueuedVoice = false; - - #ifdef ENABLE_VOX - gVoxResumeCountdown = 2000; - #endif - - return; - } - } - - if (FUNCTION_IsRx()) - { - RADIO_SetModulation(gRxVfo->Modulation); // 1of11 - } - - #ifdef ENABLE_FMRADIO - if (gFmRadioMode) - BK1080_Mute(false); - #endif - - if (!gEnableSpeaker) - AUDIO_AudioPathOff(); - - #ifdef ENABLE_VOX - gVoxResumeCountdown = 80; - #endif - - gVoiceWriteIndex = 0; - gVoiceReadIndex = 0; + uint8_t VoiceID; + uint8_t Delay; + bool Skip; + + Skip = false; + + if (gVoiceReadIndex != gVoiceWriteIndex && gEeprom.VOICE_PROMPT != VOICE_PROMPT_OFF) + { + VoiceID = gVoiceID[gVoiceReadIndex]; + if (gEeprom.VOICE_PROMPT == VOICE_PROMPT_CHINESE) + { + if (VoiceID < ARRAY_SIZE(VoiceClipLengthChinese)) + { + Delay = VoiceClipLengthChinese[VoiceID]; + VoiceID += VOICE_ID_CHI_BASE; + } + else + Skip = true; + } + else + { + if (VoiceID < ARRAY_SIZE(VoiceClipLengthEnglish)) + { + Delay = VoiceClipLengthEnglish[VoiceID]; + VoiceID += VOICE_ID_ENG_BASE; + } + else + Skip = true; + } + + gVoiceReadIndex++; + + if (!Skip) + { + if (gVoiceReadIndex == gVoiceWriteIndex) + Delay += 3; + + AUDIO_PlayVoice(VoiceID); + + gCountdownToPlayNextVoice_10ms = Delay; + gFlagPlayQueuedVoice = false; + + #ifdef ENABLE_VOX + gVoxResumeCountdown = 2000; + #endif + + return; + } + } + + if (FUNCTION_IsRx()) + { + RADIO_SetModulation(gRxVfo->Modulation); // 1of11 + } + + #ifdef ENABLE_FMRADIO + if (gFmRadioMode) + BK1080_Mute(false); + #endif + + if (!gEnableSpeaker) + AUDIO_AudioPathOff(); + + #ifdef ENABLE_VOX + gVoxResumeCountdown = 80; + #endif + + gVoiceWriteIndex = 0; + gVoiceReadIndex = 0; } #endif diff --git a/audio.h b/audio.h index e27b43700..26ed0b608 100644 --- a/audio.h +++ b/audio.h @@ -25,21 +25,21 @@ enum BEEP_Type_t { - BEEP_NONE = 0, - BEEP_1KHZ_60MS_OPTIONAL, - BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL, - BEEP_440HZ_500MS, + BEEP_NONE = 0, + BEEP_1KHZ_60MS_OPTIONAL, + BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL, + BEEP_440HZ_500MS, #ifdef ENABLE_DTMF_CALLING - BEEP_880HZ_200MS, - BEEP_880HZ_500MS, + BEEP_880HZ_200MS, + BEEP_880HZ_500MS, #endif - BEEP_500HZ_60MS_DOUBLE_BEEP, + BEEP_500HZ_60MS_DOUBLE_BEEP, #ifdef ENABLE_FEAT_F4HWN - BEEP_400HZ_30MS, - BEEP_500HZ_30MS, - BEEP_600HZ_30MS, + BEEP_400HZ_30MS, + BEEP_500HZ_30MS, + BEEP_600HZ_30MS, #endif - BEEP_880HZ_60MS_DOUBLE_BEEP + BEEP_880HZ_60MS_DOUBLE_BEEP }; typedef enum BEEP_Type_t BEEP_Type_t; @@ -47,117 +47,117 @@ typedef enum BEEP_Type_t BEEP_Type_t; extern BEEP_Type_t gBeepToPlay; void AUDIO_PlayBeep(BEEP_Type_t Beep); - + static inline void AUDIO_AudioPathOn(void) { - GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH); + GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH); } static inline void AUDIO_AudioPathOff(void) { - GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH); + GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH); } #ifdef ENABLE_VOICE - typedef enum VOICE_ID_t VOICE_ID_t; + typedef enum VOICE_ID_t VOICE_ID_t; - enum - { - VOICE_ID_CHI_BASE = 0x10U, - VOICE_ID_ENG_BASE = 0x60U, - }; + enum + { + VOICE_ID_CHI_BASE = 0x10U, + VOICE_ID_ENG_BASE = 0x60U, + }; - enum VOICE_ID_t - { - VOICE_ID_0 = 0x00U, - VOICE_ID_1 = 0x01U, - VOICE_ID_2 = 0x02U, - VOICE_ID_3 = 0x03U, - VOICE_ID_4 = 0x04U, - VOICE_ID_5 = 0x05U, - VOICE_ID_6 = 0x06U, - VOICE_ID_7 = 0x07U, - VOICE_ID_8 = 0x08U, - VOICE_ID_9 = 0x09U, - VOICE_ID_10 = 0x0AU, - VOICE_ID_100 = 0x0BU, - VOICE_ID_WELCOME = 0x0CU, - VOICE_ID_LOCK = 0x0DU, - VOICE_ID_UNLOCK = 0x0EU, - VOICE_ID_SCANNING_BEGIN = 0x0FU, - VOICE_ID_SCANNING_STOP = 0x10U, - VOICE_ID_SCRAMBLER_ON = 0x11U, - VOICE_ID_SCRAMBLER_OFF = 0x12U, - VOICE_ID_FUNCTION = 0x13U, - VOICE_ID_CTCSS = 0x14U, - VOICE_ID_DCS = 0x15U, - VOICE_ID_POWER = 0x16U, - VOICE_ID_SAVE_MODE = 0x17U, - VOICE_ID_MEMORY_CHANNEL = 0x18U, - VOICE_ID_DELETE_CHANNEL = 0x19U, - VOICE_ID_FREQUENCY_STEP = 0x1AU, - VOICE_ID_SQUELCH = 0x1BU, - VOICE_ID_TRANSMIT_OVER_TIME = 0x1CU, - VOICE_ID_BACKLIGHT_SELECTION = 0x1DU, - VOICE_ID_VOX = 0x1EU, - VOICE_ID_TX_OFFSET_FREQUENCY_DIRECTION = 0x1FU, - VOICE_ID_TX_OFFSET_FREQUENCY = 0x20U, - VOICE_ID_TRANSMITING_MEMORY = 0x21U, - VOICE_ID_RECEIVING_MEMORY = 0x22U, - VOICE_ID_EMERGENCY_CALL = 0x23U, - VOICE_ID_LOW_VOLTAGE = 0x24U, - VOICE_ID_CHANNEL_MODE = 0x25U, - VOICE_ID_FREQUENCY_MODE = 0x26U, - VOICE_ID_VOICE_PROMPT = 0x27U, - VOICE_ID_BAND_SELECTION = 0x28U, - VOICE_ID_DUAL_STANDBY = 0x29U, - VOICE_ID_CHANNEL_BANDWIDTH = 0x2AU, - VOICE_ID_OPTIONAL_SIGNAL = 0x2BU, - VOICE_ID_MUTE_MODE = 0x2CU, - VOICE_ID_BUSY_LOCKOUT = 0x2DU, - VOICE_ID_BEEP_PROMPT = 0x2EU, - VOICE_ID_ANI_CODE = 0x2FU, - VOICE_ID_INITIALISATION = 0x30U, - VOICE_ID_CONFIRM = 0x31U, - VOICE_ID_CANCEL = 0x32U, - VOICE_ID_ON = 0x33U, - VOICE_ID_OFF = 0x34U, - VOICE_ID_2_TONE = 0x35U, - VOICE_ID_5_TONE = 0x36U, - VOICE_ID_DIGITAL_SIGNAL = 0x37U, - VOICE_ID_REPEATER = 0x38U, - VOICE_ID_MENU = 0x39U, - VOICE_ID_11 = 0x3AU, - VOICE_ID_12 = 0x3BU, - VOICE_ID_13 = 0x3CU, - VOICE_ID_14 = 0x3DU, - VOICE_ID_15 = 0x3EU, - VOICE_ID_16 = 0x3FU, - VOICE_ID_17 = 0x40U, - VOICE_ID_18 = 0x41U, - VOICE_ID_19 = 0x42U, - VOICE_ID_20 = 0x43U, - VOICE_ID_30 = 0x44U, - VOICE_ID_40 = 0x45U, - VOICE_ID_50 = 0x46U, - VOICE_ID_60 = 0x47U, - VOICE_ID_70 = 0x48U, - VOICE_ID_80 = 0x49U, - VOICE_ID_90 = 0x4AU, - VOICE_ID_END = 0x4BU, + enum VOICE_ID_t + { + VOICE_ID_0 = 0x00U, + VOICE_ID_1 = 0x01U, + VOICE_ID_2 = 0x02U, + VOICE_ID_3 = 0x03U, + VOICE_ID_4 = 0x04U, + VOICE_ID_5 = 0x05U, + VOICE_ID_6 = 0x06U, + VOICE_ID_7 = 0x07U, + VOICE_ID_8 = 0x08U, + VOICE_ID_9 = 0x09U, + VOICE_ID_10 = 0x0AU, + VOICE_ID_100 = 0x0BU, + VOICE_ID_WELCOME = 0x0CU, + VOICE_ID_LOCK = 0x0DU, + VOICE_ID_UNLOCK = 0x0EU, + VOICE_ID_SCANNING_BEGIN = 0x0FU, + VOICE_ID_SCANNING_STOP = 0x10U, + VOICE_ID_SCRAMBLER_ON = 0x11U, + VOICE_ID_SCRAMBLER_OFF = 0x12U, + VOICE_ID_FUNCTION = 0x13U, + VOICE_ID_CTCSS = 0x14U, + VOICE_ID_DCS = 0x15U, + VOICE_ID_POWER = 0x16U, + VOICE_ID_SAVE_MODE = 0x17U, + VOICE_ID_MEMORY_CHANNEL = 0x18U, + VOICE_ID_DELETE_CHANNEL = 0x19U, + VOICE_ID_FREQUENCY_STEP = 0x1AU, + VOICE_ID_SQUELCH = 0x1BU, + VOICE_ID_TRANSMIT_OVER_TIME = 0x1CU, + VOICE_ID_BACKLIGHT_SELECTION = 0x1DU, + VOICE_ID_VOX = 0x1EU, + VOICE_ID_TX_OFFSET_FREQUENCY_DIRECTION = 0x1FU, + VOICE_ID_TX_OFFSET_FREQUENCY = 0x20U, + VOICE_ID_TRANSMITING_MEMORY = 0x21U, + VOICE_ID_RECEIVING_MEMORY = 0x22U, + VOICE_ID_EMERGENCY_CALL = 0x23U, + VOICE_ID_LOW_VOLTAGE = 0x24U, + VOICE_ID_CHANNEL_MODE = 0x25U, + VOICE_ID_FREQUENCY_MODE = 0x26U, + VOICE_ID_VOICE_PROMPT = 0x27U, + VOICE_ID_BAND_SELECTION = 0x28U, + VOICE_ID_DUAL_STANDBY = 0x29U, + VOICE_ID_CHANNEL_BANDWIDTH = 0x2AU, + VOICE_ID_OPTIONAL_SIGNAL = 0x2BU, + VOICE_ID_MUTE_MODE = 0x2CU, + VOICE_ID_BUSY_LOCKOUT = 0x2DU, + VOICE_ID_BEEP_PROMPT = 0x2EU, + VOICE_ID_ANI_CODE = 0x2FU, + VOICE_ID_INITIALISATION = 0x30U, + VOICE_ID_CONFIRM = 0x31U, + VOICE_ID_CANCEL = 0x32U, + VOICE_ID_ON = 0x33U, + VOICE_ID_OFF = 0x34U, + VOICE_ID_2_TONE = 0x35U, + VOICE_ID_5_TONE = 0x36U, + VOICE_ID_DIGITAL_SIGNAL = 0x37U, + VOICE_ID_REPEATER = 0x38U, + VOICE_ID_MENU = 0x39U, + VOICE_ID_11 = 0x3AU, + VOICE_ID_12 = 0x3BU, + VOICE_ID_13 = 0x3CU, + VOICE_ID_14 = 0x3DU, + VOICE_ID_15 = 0x3EU, + VOICE_ID_16 = 0x3FU, + VOICE_ID_17 = 0x40U, + VOICE_ID_18 = 0x41U, + VOICE_ID_19 = 0x42U, + VOICE_ID_20 = 0x43U, + VOICE_ID_30 = 0x44U, + VOICE_ID_40 = 0x45U, + VOICE_ID_50 = 0x46U, + VOICE_ID_60 = 0x47U, + VOICE_ID_70 = 0x48U, + VOICE_ID_80 = 0x49U, + VOICE_ID_90 = 0x4AU, + VOICE_ID_END = 0x4BU, - VOICE_ID_INVALID = 0xFFU, - }; + VOICE_ID_INVALID = 0xFFU, + }; - extern VOICE_ID_t gVoiceID[8]; - extern uint8_t gVoiceReadIndex; - extern uint8_t gVoiceWriteIndex; - extern volatile uint16_t gCountdownToPlayNextVoice_10ms; - extern volatile bool gFlagPlayQueuedVoice; - extern VOICE_ID_t gAnotherVoiceID; - - void AUDIO_PlaySingleVoice(bool bFlag); - void AUDIO_SetVoiceID(uint8_t Index, VOICE_ID_t VoiceID); - uint8_t AUDIO_SetDigitVoice(uint8_t Index, uint16_t Value); - void AUDIO_PlayQueuedVoice(void); + extern VOICE_ID_t gVoiceID[8]; + extern uint8_t gVoiceReadIndex; + extern uint8_t gVoiceWriteIndex; + extern volatile uint16_t gCountdownToPlayNextVoice_10ms; + extern volatile bool gFlagPlayQueuedVoice; + extern VOICE_ID_t gAnotherVoiceID; + + void AUDIO_PlaySingleVoice(bool bFlag); + void AUDIO_SetVoiceID(uint8_t Index, VOICE_ID_t VoiceID); + uint8_t AUDIO_SetDigitVoice(uint8_t Index, uint16_t Value); + void AUDIO_PlayQueuedVoice(void); #endif #endif diff --git a/bitmaps.c b/bitmaps.c index fa746a469..27569e10f 100644 --- a/bitmaps.c +++ b/bitmaps.c @@ -4,311 +4,310 @@ // all these images are on their right sides // turn your monitor 90-deg anti-clockwise to see the images - const uint8_t gFontPowerSave[2][6] = { - {0x00, 0x7f, 0x9, 0x9, 0x9, 0x6}, - {0x00, 0x26, 0x49, 0x49, 0x49, 0x32}, + {0x00, 0x7f, 0x9, 0x9, 0x9, 0x6}, + {0x00, 0x26, 0x49, 0x49, 0x49, 0x32}, }; const uint8_t gFontPttOnePush[2][6] = { - {0x00, 0x3e, 0x41, 0x41, 0x41, 0x3e}, - {0x00, 0x7f, 0x9, 0x9, 0x9, 0x6}, + {0x00, 0x3e, 0x41, 0x41, 0x41, 0x3e}, + {0x00, 0x7f, 0x9, 0x9, 0x9, 0x6}, }; const uint8_t gFontPttClassic[2][6] = { - {0x00, 0x3e, 0x41, 0x41, 0x41, 0x22}, - {0x00, 0x7f, 0x40, 0x40, 0x40, 0x40}, + {0x00, 0x3e, 0x41, 0x41, 0x41, 0x22}, + {0x00, 0x7f, 0x40, 0x40, 0x40, 0x40}, }; const uint8_t gFontF[1][8] = { - {0x7f, 0x00, 0x76, 0x76, 0x76, 0x76, 0x7e, 0x7f}, // 'F' + {0x7f, 0x00, 0x76, 0x76, 0x76, 0x76, 0x7e, 0x7f}, // 'F' }; const uint8_t gFontS[1][6] = { - {0x26, 0x49, 0x49, 0x49, 0x49, 0x32}, // 'S' + {0x26, 0x49, 0x49, 0x49, 0x49, 0x32}, // 'S' }; const uint8_t gFontKeyLock[1][9] = { - {0x7c, 0x46, 0x45, 0x45, 0x45, 0x45, 0x45, 0x46, 0x7c} + {0x7c, 0x46, 0x45, 0x45, 0x45, 0x45, 0x45, 0x46, 0x7c} }; const uint8_t gFontLight[9] = { - 0b00001100, - 0b00010010, - 0b00100001, - 0b01101101, - 0b01111001, - 0b01101101, - 0b00100001, - 0b00010010, - 0b00001100, + 0b00001100, + 0b00010010, + 0b00100001, + 0b01101101, + 0b01111001, + 0b01101101, + 0b00100001, + 0b00010010, + 0b00001100, }; const uint8_t gFontXB[2][6] = -{ // "XB" - {0x00, 0x63, 0x14, 0x8, 0x14, 0x63}, - {0x00, 0x7f, 0x49, 0x49, 0x49, 0x36}, +{ // "XB" + {0x00, 0x63, 0x14, 0x8, 0x14, 0x63}, + {0x00, 0x7f, 0x49, 0x49, 0x49, 0x36}, }; const uint8_t gFontMO[2][6] = -{ // "MO" - {0x00, 0x7f, 0x2, 0x1c, 0x2, 0x7f}, - {0x00, 0x3e, 0x41, 0x41, 0x41, 0x3e}, +{ // "MO" + {0x00, 0x7f, 0x2, 0x1c, 0x2, 0x7f}, + {0x00, 0x3e, 0x41, 0x41, 0x41, 0x3e}, }; const uint8_t gFontDWR[3][6] = -{ // "DWR" +{ // "DWR" - {0x00, 0x7f, 0x41, 0x41, 0x41, 0x3e}, - {0x00, 0x3f, 0x40, 0x38, 0x40, 0x3f}, - {0x00, 0x7f, 0x9, 0x19, 0x29, 0x46}, + {0x00, 0x7f, 0x41, 0x41, 0x41, 0x3e}, + {0x00, 0x3f, 0x40, 0x38, 0x40, 0x3f}, + {0x00, 0x7f, 0x9, 0x19, 0x29, 0x46}, }; const uint8_t gFontHold[2][5] = -{ // "><" .. DW on hold - {0x00, 0x41, 0x22, 0x14, 0x8}, - {0x00, 0x8, 0x14, 0x22, 0x41}, +{ // "><" .. DW on hold + {0x00, 0x41, 0x22, 0x14, 0x8}, + {0x00, 0x8, 0x14, 0x22, 0x41}, }; const uint8_t BITMAP_BatteryLevel[2] = { - 0b01011101, - 0b01011101 + 0b01011101, + 0b01011101 }; // Quansheng way (+ pole to the left) const uint8_t BITMAP_BatteryLevel1[17] = { - 0b00000000, - 0b00111110, - 0b00100010, - 0b01000001, - 0b01000001, - 0b01000001, - 0b01000001, - 0b01000001, - 0b01000001, - 0b01000001, - 0b01000001, - 0b01000001, - 0b01000001, - 0b01000001, - 0b01000001, - 0b01000001, - 0b01111111 + 0b00000000, + 0b00111110, + 0b00100010, + 0b01000001, + 0b01000001, + 0b01000001, + 0b01000001, + 0b01000001, + 0b01000001, + 0b01000001, + 0b01000001, + 0b01000001, + 0b01000001, + 0b01000001, + 0b01000001, + 0b01000001, + 0b01111111 }; const uint8_t BITMAP_USB_C[9] = { - 0b00000000, - 0b00011100, - 0b00100111, - 0b01000100, - 0b01000100, - 0b01000100, - 0b01000100, - 0b00100111, - 0b00011100 + 0b00000000, + 0b00011100, + 0b00100111, + 0b01000100, + 0b01000100, + 0b01000100, + 0b01000100, + 0b00100111, + 0b00011100 }; #ifdef ENABLE_VOX - const uint8_t gFontVox[2][6] = - { - {0x00, 0x1f, 0x20, 0x40, 0x20, 0x1f}, - {0x00, 0x63, 0x14, 0x8, 0x14, 0x63}, - }; + const uint8_t gFontVox[2][6] = + { + {0x00, 0x1f, 0x20, 0x40, 0x20, 0x1f}, + {0x00, 0x63, 0x14, 0x8, 0x14, 0x63}, + }; #endif const uint8_t BITMAP_Antenna[5] = { - 0b00000011, - 0b00000101, - 0b01111111, - 0b00000101, - 0b00000011 + 0b00000011, + 0b00000101, + 0b01111111, + 0b00000101, + 0b00000011 }; const uint8_t BITMAP_VFO_Lock[7] = { - 0b01111100, - 0b01000110, - 0b01000101, - 0b01000101, - 0b01000101, - 0b01000110, - 0b01111100, + 0b01111100, + 0b01000110, + 0b01000101, + 0b01000101, + 0b01000101, + 0b01000110, + 0b01111100, }; const uint8_t BITMAP_VFO_Default[7] = { - 0b01111111, - 0b01111111, - 0b00111110, - 0b00111110, - 0b00011100, - 0b00011100, - 0b00001000 + 0b01111111, + 0b01111111, + 0b00111110, + 0b00111110, + 0b00011100, + 0b00011100, + 0b00001000 }; const uint8_t BITMAP_VFO_NotDefault[7] = { - 0b01000001, - 0b01000001, - 0b00100010, - 0b00100010, - 0b00010100, - 0b00010100, - 0b00001000 + 0b01000001, + 0b01000001, + 0b00100010, + 0b00100010, + 0b00010100, + 0b00010100, + 0b00001000 }; const uint8_t BITMAP_ScanList0[7] = -{ // '0' symbol - 0b01111111, - 0b01111111, - 0b01000011, - 0b01011101, - 0b01100001, - 0b01111111, - 0b01111111 +{ // '0' symbol + 0b01111111, + 0b01111111, + 0b01000011, + 0b01011101, + 0b01100001, + 0b01111111, + 0b01111111 }; const uint8_t BITMAP_ScanList1[7] = -{ // '1' symbol - 0b01111111, - 0b01111111, - 0b01111011, - 0b01000001, - 0b01111111, - 0b01111111, - 0b01111111 +{ // '1' symbol + 0b01111111, + 0b01111111, + 0b01111011, + 0b01000001, + 0b01111111, + 0b01111111, + 0b01111111 }; const uint8_t BITMAP_ScanList2[7] = -{ // '2' symbol - 0b01111111, - 0b01111111, - 0b01001101, - 0b01010101, - 0b01011011, - 0b01111111, - 0b01111111 +{ // '2' symbol + 0b01111111, + 0b01111111, + 0b01001101, + 0b01010101, + 0b01011011, + 0b01111111, + 0b01111111 }; const uint8_t BITMAP_ScanList3[7] = -{ // '3' symbol - 0b01111111, - 0b01111111, - 0b01011101, - 0b01010101, - 0b01101011, - 0b01111111, - 0b01111111 +{ // '3' symbol + 0b01111111, + 0b01111111, + 0b01011101, + 0b01010101, + 0b01101011, + 0b01111111, + 0b01111111 }; const uint8_t BITMAP_ScanListE[7] = -{ // 'E' symbol - 0b01111111, - 0b01111111, - 0b01000001, - 0b01010101, - 0b01010101, - 0b01111111, - 0b01111111 +{ // 'E' symbol + 0b01111111, + 0b01111111, + 0b01000001, + 0b01010101, + 0b01010101, + 0b01111111, + 0b01111111 }; const uint8_t BITMAP_ScanList123[19] = { - // 'All' symbol - 0b01111111, - 0b01111111, - 0b01111011, - 0b01000001, - 0b01111111, - 0b01111111, - 0b01111111, - 0b01111111, - 0b01001101, - 0b01010101, - 0b01011011, - 0b01111111, - 0b01111111, - 0b01111111, - 0b01011101, - 0b01010101, - 0b01101011, - 0b01111111, - 0b01111111 + // 'All' symbol + 0b01111111, + 0b01111111, + 0b01111011, + 0b01000001, + 0b01111111, + 0b01111111, + 0b01111111, + 0b01111111, + 0b01001101, + 0b01010101, + 0b01011011, + 0b01111111, + 0b01111111, + 0b01111111, + 0b01011101, + 0b01010101, + 0b01101011, + 0b01111111, + 0b01111111 }; const uint8_t BITMAP_ScanListAll[19] = { - // 'All' symbol - 0b01111111, - 0b01111111, - 0b01000011, - 0b01110101, - 0b01000011, - 0b01111111, - 0b01111111, - 0b01111111, - 0b01000001, - 0b01011111, - 0b01011111, - 0b01111111, - 0b01111111, - 0b01111111, - 0b01000001, - 0b01011111, - 0b01011111, - 0b01111111, - 0b01111111 + // 'All' symbol + 0b01111111, + 0b01111111, + 0b01000011, + 0b01110101, + 0b01000011, + 0b01111111, + 0b01111111, + 0b01111111, + 0b01000001, + 0b01011111, + 0b01011111, + 0b01111111, + 0b01111111, + 0b01111111, + 0b01000001, + 0b01011111, + 0b01011111, + 0b01111111, + 0b01111111 }; const uint8_t BITMAP_compand[6] = { - 0b00000000, - 0b00111100, - 0b01000010, - 0b01000010, - 0b01000010, - 0b00100100 + 0b00000000, + 0b00111100, + 0b01000010, + 0b01000010, + 0b01000010, + 0b00100100 }; const uint8_t BITMAP_Ready[7] = { - 0b00001000, - 0b00010000, - 0b00100000, - 0b00010000, - 0b00001000, - 0b00000100, - 0b00000010, + 0b00001000, + 0b00010000, + 0b00100000, + 0b00010000, + 0b00001000, + 0b00000100, + 0b00000010, }; const uint8_t BITMAP_PowerUser[3] = -{ // 'arrow' symbol - 0b00111110, - 0b00011100, - 0b00001000, +{ // 'arrow' symbol + 0b00111110, + 0b00011100, + 0b00001000, }; #ifndef ENABLE_CUSTOM_MENU_LAYOUT const uint8_t BITMAP_CurrentIndicator[8] = { - 0xFF, - 0xFF, - 0x7E, - 0x7E, - 0x3C, - 0x3C, - 0x18, - 0x18 + 0xFF, + 0xFF, + 0x7E, + 0x7E, + 0x3C, + 0x3C, + 0x18, + 0x18 }; #endif diff --git a/bitmaps.h b/bitmaps.h index 774c7ea1d..51ef41abc 100644 --- a/bitmaps.h +++ b/bitmaps.h @@ -24,7 +24,7 @@ extern const uint8_t BITMAP_USB_C[9]; extern const uint8_t BITMAP_Ready[7]; #ifdef ENABLE_VOX - extern const uint8_t gFontVox[2][6]; + extern const uint8_t gFontVox[2][6]; #endif extern const uint8_t BITMAP_Antenna[5]; @@ -42,7 +42,7 @@ extern const uint8_t BITMAP_PowerUser[3]; extern const uint8_t BITMAP_compand[6]; #ifndef ENABLE_CUSTOM_MENU_LAYOUT - extern const uint8_t BITMAP_CurrentIndicator[8]; + extern const uint8_t BITMAP_CurrentIndicator[8]; #endif #endif diff --git a/board.c b/board.c index 0396d157a..e3db3ca3d 100644 --- a/board.c +++ b/board.c @@ -17,7 +17,7 @@ #include #ifdef ENABLE_FMRADIO - #include "app/fm.h" + #include "app/fm.h" #endif #include "board.h" #include "bsp/dp32g030/gpio.h" @@ -27,7 +27,7 @@ #include "driver/adc.h" #include "driver/backlight.h" #ifdef ENABLE_FMRADIO - #include "driver/bk1080.h" + #include "driver/bk1080.h" #endif #include "driver/crc.h" @@ -41,465 +41,465 @@ #include "misc.h" #include "settings.h" #if defined(ENABLE_OVERLAY) - #include "sram-overlay.h" + #include "sram-overlay.h" #endif #if defined(ENABLE_OVERLAY) - void BOARD_FLASH_Init(void) - { - FLASH_Init(FLASH_READ_MODE_1_CYCLE); - FLASH_ConfigureTrimValues(); - SYSTEM_ConfigureClocks(); + void BOARD_FLASH_Init(void) + { + FLASH_Init(FLASH_READ_MODE_1_CYCLE); + FLASH_ConfigureTrimValues(); + SYSTEM_ConfigureClocks(); - overlay_FLASH_MainClock = 48000000; - overlay_FLASH_ClockMultiplier = 48; + overlay_FLASH_MainClock = 48000000; + overlay_FLASH_ClockMultiplier = 48; - FLASH_Init(FLASH_READ_MODE_2_CYCLE); - } + FLASH_Init(FLASH_READ_MODE_2_CYCLE); + } #endif void BOARD_GPIO_Init(void) { - GPIOA->DIR |= 0 - // A7 = UART1 TX default as OUTPUT from bootloader! - // A8 = UART1 RX default as INPUT from bootloader! - // Key pad + I2C - | GPIO_DIR_10_BITS_OUTPUT - // Key pad + I2C - | GPIO_DIR_11_BITS_OUTPUT - // Key pad + Voice chip - | GPIO_DIR_12_BITS_OUTPUT - // Key pad + Voice chip - | GPIO_DIR_13_BITS_OUTPUT - ; - GPIOA->DIR &= ~(0 - // Key pad - | GPIO_DIR_3_MASK // INPUT - // Key pad - | GPIO_DIR_4_MASK // INPUT - // Key pad - | GPIO_DIR_5_MASK // INPUT - // Key pad - | GPIO_DIR_6_MASK // INPUT - ); - GPIOB->DIR |= 0 - // ST7565 - | GPIO_DIR_9_BITS_OUTPUT - // ST7565 + SWD IO - | GPIO_DIR_11_BITS_OUTPUT - // B14 = SWD_CLK assumed INPUT by default - // BK1080 - | GPIO_DIR_15_BITS_OUTPUT - ; - GPIOC->DIR |= 0 - // BK4819 SCN - | GPIO_DIR_0_BITS_OUTPUT - // BK4819 SCL - | GPIO_DIR_1_BITS_OUTPUT - // BK4819 SDA - | GPIO_DIR_2_BITS_OUTPUT - // Flash light - | GPIO_DIR_3_BITS_OUTPUT - // Speaker - | GPIO_DIR_4_BITS_OUTPUT - ; - GPIOC->DIR &= ~(0 - // PTT button - | GPIO_DIR_5_MASK // INPUT - ); - - #if defined(ENABLE_FMRADIO) - GPIO_SetBit(&GPIOB->DATA, GPIOB_PIN_BK1080); - #endif + GPIOA->DIR |= 0 + // A7 = UART1 TX default as OUTPUT from bootloader! + // A8 = UART1 RX default as INPUT from bootloader! + // Key pad + I2C + | GPIO_DIR_10_BITS_OUTPUT + // Key pad + I2C + | GPIO_DIR_11_BITS_OUTPUT + // Key pad + Voice chip + | GPIO_DIR_12_BITS_OUTPUT + // Key pad + Voice chip + | GPIO_DIR_13_BITS_OUTPUT + ; + GPIOA->DIR &= ~(0 + // Key pad + | GPIO_DIR_3_MASK // INPUT + // Key pad + | GPIO_DIR_4_MASK // INPUT + // Key pad + | GPIO_DIR_5_MASK // INPUT + // Key pad + | GPIO_DIR_6_MASK // INPUT + ); + GPIOB->DIR |= 0 + // ST7565 + | GPIO_DIR_9_BITS_OUTPUT + // ST7565 + SWD IO + | GPIO_DIR_11_BITS_OUTPUT + // B14 = SWD_CLK assumed INPUT by default + // BK1080 + | GPIO_DIR_15_BITS_OUTPUT + ; + GPIOC->DIR |= 0 + // BK4819 SCN + | GPIO_DIR_0_BITS_OUTPUT + // BK4819 SCL + | GPIO_DIR_1_BITS_OUTPUT + // BK4819 SDA + | GPIO_DIR_2_BITS_OUTPUT + // Flash light + | GPIO_DIR_3_BITS_OUTPUT + // Speaker + | GPIO_DIR_4_BITS_OUTPUT + ; + GPIOC->DIR &= ~(0 + // PTT button + | GPIO_DIR_5_MASK // INPUT + ); + + #if defined(ENABLE_FMRADIO) + GPIO_SetBit(&GPIOB->DATA, GPIOB_PIN_BK1080); + #endif } void BOARD_PORTCON_Init(void) { - // PORT A pin selection - - PORTCON_PORTA_SEL0 &= ~(0 - // Key pad - | PORTCON_PORTA_SEL0_A3_MASK - // Key pad - | PORTCON_PORTA_SEL0_A4_MASK - // Key pad - | PORTCON_PORTA_SEL0_A5_MASK - // Key pad - | PORTCON_PORTA_SEL0_A6_MASK - ); - PORTCON_PORTA_SEL0 |= 0 - // Key pad - | PORTCON_PORTA_SEL0_A3_BITS_GPIOA3 - // Key pad - | PORTCON_PORTA_SEL0_A4_BITS_GPIOA4 - // Key pad - | PORTCON_PORTA_SEL0_A5_BITS_GPIOA5 - // Key pad - | PORTCON_PORTA_SEL0_A6_BITS_GPIOA6 - // UART1 TX, wasn't cleared in previous step / relying on default value! - | PORTCON_PORTA_SEL0_A7_BITS_UART1_TX - ; - - PORTCON_PORTA_SEL1 &= ~(0 - // Key pad + I2C - | PORTCON_PORTA_SEL1_A10_MASK - // Key pad + I2C - | PORTCON_PORTA_SEL1_A11_MASK - // Key pad + Voice chip - | PORTCON_PORTA_SEL1_A12_MASK - // Key pad + Voice chip - | PORTCON_PORTA_SEL1_A13_MASK - ); - PORTCON_PORTA_SEL1 |= 0 - // UART1 RX, wasn't cleared in previous step / relying on default value! - | PORTCON_PORTA_SEL1_A8_BITS_UART1_RX - // Battery voltage, wasn't cleared in previous step / relying on default value! - | PORTCON_PORTA_SEL1_A9_BITS_SARADC_CH4 - // Key pad + I2C - | PORTCON_PORTA_SEL1_A10_BITS_GPIOA10 - // Key pad + I2C - | PORTCON_PORTA_SEL1_A11_BITS_GPIOA11 - // Key pad + Voice chip - | PORTCON_PORTA_SEL1_A12_BITS_GPIOA12 - // Key pad + Voice chip - | PORTCON_PORTA_SEL1_A13_BITS_GPIOA13 - // Battery Current, wasn't cleared in previous step / relying on default value! - | PORTCON_PORTA_SEL1_A14_BITS_SARADC_CH9 - ; - - // PORT B pin selection - - PORTCON_PORTB_SEL0 &= ~(0 - // SPI0 SSN - | PORTCON_PORTB_SEL0_B7_MASK - ); - PORTCON_PORTB_SEL0 |= 0 - // SPI0 SSN - | PORTCON_PORTB_SEL0_B7_BITS_SPI0_SSN - ; - - PORTCON_PORTB_SEL1 &= ~(0 - // ST7565 - | PORTCON_PORTB_SEL1_B9_MASK - // ST7565 + SWD IO - | PORTCON_PORTB_SEL1_B11_MASK - // SWD CLK - | PORTCON_PORTB_SEL1_B14_MASK - // BK1080 - | PORTCON_PORTB_SEL1_B15_MASK - ); - PORTCON_PORTB_SEL1 |= 0 - // SPI0 CLK, wasn't cleared in previous step / relying on default value! - | PORTCON_PORTB_SEL1_B8_BITS_SPI0_CLK - // ST7565 - | PORTCON_PORTB_SEL1_B9_BITS_GPIOB9 - // SPI0 MOSI, wasn't cleared in previous step / relying on default value! - | PORTCON_PORTB_SEL1_B10_BITS_SPI0_MOSI + // PORT A pin selection + + PORTCON_PORTA_SEL0 &= ~(0 + // Key pad + | PORTCON_PORTA_SEL0_A3_MASK + // Key pad + | PORTCON_PORTA_SEL0_A4_MASK + // Key pad + | PORTCON_PORTA_SEL0_A5_MASK + // Key pad + | PORTCON_PORTA_SEL0_A6_MASK + ); + PORTCON_PORTA_SEL0 |= 0 + // Key pad + | PORTCON_PORTA_SEL0_A3_BITS_GPIOA3 + // Key pad + | PORTCON_PORTA_SEL0_A4_BITS_GPIOA4 + // Key pad + | PORTCON_PORTA_SEL0_A5_BITS_GPIOA5 + // Key pad + | PORTCON_PORTA_SEL0_A6_BITS_GPIOA6 + // UART1 TX, wasn't cleared in previous step / relying on default value! + | PORTCON_PORTA_SEL0_A7_BITS_UART1_TX + ; + + PORTCON_PORTA_SEL1 &= ~(0 + // Key pad + I2C + | PORTCON_PORTA_SEL1_A10_MASK + // Key pad + I2C + | PORTCON_PORTA_SEL1_A11_MASK + // Key pad + Voice chip + | PORTCON_PORTA_SEL1_A12_MASK + // Key pad + Voice chip + | PORTCON_PORTA_SEL1_A13_MASK + ); + PORTCON_PORTA_SEL1 |= 0 + // UART1 RX, wasn't cleared in previous step / relying on default value! + | PORTCON_PORTA_SEL1_A8_BITS_UART1_RX + // Battery voltage, wasn't cleared in previous step / relying on default value! + | PORTCON_PORTA_SEL1_A9_BITS_SARADC_CH4 + // Key pad + I2C + | PORTCON_PORTA_SEL1_A10_BITS_GPIOA10 + // Key pad + I2C + | PORTCON_PORTA_SEL1_A11_BITS_GPIOA11 + // Key pad + Voice chip + | PORTCON_PORTA_SEL1_A12_BITS_GPIOA12 + // Key pad + Voice chip + | PORTCON_PORTA_SEL1_A13_BITS_GPIOA13 + // Battery Current, wasn't cleared in previous step / relying on default value! + | PORTCON_PORTA_SEL1_A14_BITS_SARADC_CH9 + ; + + // PORT B pin selection + + PORTCON_PORTB_SEL0 &= ~(0 + // SPI0 SSN + | PORTCON_PORTB_SEL0_B7_MASK + ); + PORTCON_PORTB_SEL0 |= 0 + // SPI0 SSN + | PORTCON_PORTB_SEL0_B7_BITS_SPI0_SSN + ; + + PORTCON_PORTB_SEL1 &= ~(0 + // ST7565 + | PORTCON_PORTB_SEL1_B9_MASK + // ST7565 + SWD IO + | PORTCON_PORTB_SEL1_B11_MASK + // SWD CLK + | PORTCON_PORTB_SEL1_B14_MASK + // BK1080 + | PORTCON_PORTB_SEL1_B15_MASK + ); + PORTCON_PORTB_SEL1 |= 0 + // SPI0 CLK, wasn't cleared in previous step / relying on default value! + | PORTCON_PORTB_SEL1_B8_BITS_SPI0_CLK + // ST7565 + | PORTCON_PORTB_SEL1_B9_BITS_GPIOB9 + // SPI0 MOSI, wasn't cleared in previous step / relying on default value! + | PORTCON_PORTB_SEL1_B10_BITS_SPI0_MOSI #if defined(ENABLE_SWD) - // SWD IO - | PORTCON_PORTB_SEL1_B11_BITS_SWDIO - // SWD CLK - | PORTCON_PORTB_SEL1_B14_BITS_SWCLK + // SWD IO + | PORTCON_PORTB_SEL1_B11_BITS_SWDIO + // SWD CLK + | PORTCON_PORTB_SEL1_B14_BITS_SWCLK #else - // ST7565 - | PORTCON_PORTB_SEL1_B11_BITS_GPIOB11 + // ST7565 + | PORTCON_PORTB_SEL1_B11_BITS_GPIOB11 #endif - ; - - // PORT C pin selection - - PORTCON_PORTC_SEL0 &= ~(0 - // BK4819 SCN - | PORTCON_PORTC_SEL0_C0_MASK - // BK4819 SCL - | PORTCON_PORTC_SEL0_C1_MASK - // BK4819 SDA - | PORTCON_PORTC_SEL0_C2_MASK - // Flash light - | PORTCON_PORTC_SEL0_C3_MASK - // Speaker - | PORTCON_PORTC_SEL0_C4_MASK - // PTT button - | PORTCON_PORTC_SEL0_C5_MASK - ); - - // PORT A pin configuration - - PORTCON_PORTA_IE |= 0 - // Keypad - | PORTCON_PORTA_IE_A3_BITS_ENABLE - // Keypad - | PORTCON_PORTA_IE_A4_BITS_ENABLE - // Keypad - | PORTCON_PORTA_IE_A5_BITS_ENABLE - // Keypad - | PORTCON_PORTA_IE_A6_BITS_ENABLE - // A7 = UART1 TX disabled by default - // UART1 RX - | PORTCON_PORTA_IE_A8_BITS_ENABLE - ; - PORTCON_PORTA_IE &= ~(0 - // Keypad + I2C - | PORTCON_PORTA_IE_A10_MASK - // Keypad + I2C - | PORTCON_PORTA_IE_A11_MASK - // Keypad + Voice chip - | PORTCON_PORTA_IE_A12_MASK - // Keypad + Voice chip - | PORTCON_PORTA_IE_A13_MASK - ); - - PORTCON_PORTA_PU |= 0 - // Keypad - | PORTCON_PORTA_PU_A3_BITS_ENABLE - // Keypad - | PORTCON_PORTA_PU_A4_BITS_ENABLE - // Keypad - | PORTCON_PORTA_PU_A5_BITS_ENABLE - // Keypad - | PORTCON_PORTA_PU_A6_BITS_ENABLE - ; - PORTCON_PORTA_PU &= ~(0 - // Keypad + I2C - | PORTCON_PORTA_PU_A10_MASK - // Keypad + I2C - | PORTCON_PORTA_PU_A11_MASK - // Keypad + Voice chip - | PORTCON_PORTA_PU_A12_MASK - // Keypad + Voice chip - | PORTCON_PORTA_PU_A13_MASK - ); - - PORTCON_PORTA_PD &= ~(0 - // Keypad - | PORTCON_PORTA_PD_A3_MASK - // Keypad - | PORTCON_PORTA_PD_A4_MASK - // Keypad - | PORTCON_PORTA_PD_A5_MASK - // Keypad - | PORTCON_PORTA_PD_A6_MASK - // Keypad + I2C - | PORTCON_PORTA_PD_A10_MASK - // Keypad + I2C - | PORTCON_PORTA_PD_A11_MASK - // Keypad + Voice chip - | PORTCON_PORTA_PD_A12_MASK - // Keypad + Voice chip - | PORTCON_PORTA_PD_A13_MASK - ); - - PORTCON_PORTA_OD |= 0 - // Keypad - | PORTCON_PORTA_OD_A3_BITS_ENABLE - // Keypad - | PORTCON_PORTA_OD_A4_BITS_ENABLE - // Keypad - | PORTCON_PORTA_OD_A5_BITS_ENABLE - // Keypad - | PORTCON_PORTA_OD_A6_BITS_ENABLE - ; - PORTCON_PORTA_OD &= ~(0 - // Keypad + I2C - | PORTCON_PORTA_OD_A10_MASK - // Keypad + I2C - | PORTCON_PORTA_OD_A11_MASK - // Keypad + Voice chip - | PORTCON_PORTA_OD_A12_MASK - // Keypad + Voice chip - | PORTCON_PORTA_OD_A13_MASK - ); - - // PORT B pin configuration - - PORTCON_PORTB_IE |= 0 - | PORTCON_PORTB_IE_B14_BITS_ENABLE - ; - PORTCON_PORTB_IE &= ~(0 - // Back light - | PORTCON_PORTB_IE_B6_MASK - // UART1 - | PORTCON_PORTB_IE_B7_MASK - | PORTCON_PORTB_IE_B8_MASK - // ST7565 - | PORTCON_PORTB_IE_B9_MASK - // SPI0 MOSI - | PORTCON_PORTB_IE_B10_MASK + ; + + // PORT C pin selection + + PORTCON_PORTC_SEL0 &= ~(0 + // BK4819 SCN + | PORTCON_PORTC_SEL0_C0_MASK + // BK4819 SCL + | PORTCON_PORTC_SEL0_C1_MASK + // BK4819 SDA + | PORTCON_PORTC_SEL0_C2_MASK + // Flash light + | PORTCON_PORTC_SEL0_C3_MASK + // Speaker + | PORTCON_PORTC_SEL0_C4_MASK + // PTT button + | PORTCON_PORTC_SEL0_C5_MASK + ); + + // PORT A pin configuration + + PORTCON_PORTA_IE |= 0 + // Keypad + | PORTCON_PORTA_IE_A3_BITS_ENABLE + // Keypad + | PORTCON_PORTA_IE_A4_BITS_ENABLE + // Keypad + | PORTCON_PORTA_IE_A5_BITS_ENABLE + // Keypad + | PORTCON_PORTA_IE_A6_BITS_ENABLE + // A7 = UART1 TX disabled by default + // UART1 RX + | PORTCON_PORTA_IE_A8_BITS_ENABLE + ; + PORTCON_PORTA_IE &= ~(0 + // Keypad + I2C + | PORTCON_PORTA_IE_A10_MASK + // Keypad + I2C + | PORTCON_PORTA_IE_A11_MASK + // Keypad + Voice chip + | PORTCON_PORTA_IE_A12_MASK + // Keypad + Voice chip + | PORTCON_PORTA_IE_A13_MASK + ); + + PORTCON_PORTA_PU |= 0 + // Keypad + | PORTCON_PORTA_PU_A3_BITS_ENABLE + // Keypad + | PORTCON_PORTA_PU_A4_BITS_ENABLE + // Keypad + | PORTCON_PORTA_PU_A5_BITS_ENABLE + // Keypad + | PORTCON_PORTA_PU_A6_BITS_ENABLE + ; + PORTCON_PORTA_PU &= ~(0 + // Keypad + I2C + | PORTCON_PORTA_PU_A10_MASK + // Keypad + I2C + | PORTCON_PORTA_PU_A11_MASK + // Keypad + Voice chip + | PORTCON_PORTA_PU_A12_MASK + // Keypad + Voice chip + | PORTCON_PORTA_PU_A13_MASK + ); + + PORTCON_PORTA_PD &= ~(0 + // Keypad + | PORTCON_PORTA_PD_A3_MASK + // Keypad + | PORTCON_PORTA_PD_A4_MASK + // Keypad + | PORTCON_PORTA_PD_A5_MASK + // Keypad + | PORTCON_PORTA_PD_A6_MASK + // Keypad + I2C + | PORTCON_PORTA_PD_A10_MASK + // Keypad + I2C + | PORTCON_PORTA_PD_A11_MASK + // Keypad + Voice chip + | PORTCON_PORTA_PD_A12_MASK + // Keypad + Voice chip + | PORTCON_PORTA_PD_A13_MASK + ); + + PORTCON_PORTA_OD |= 0 + // Keypad + | PORTCON_PORTA_OD_A3_BITS_ENABLE + // Keypad + | PORTCON_PORTA_OD_A4_BITS_ENABLE + // Keypad + | PORTCON_PORTA_OD_A5_BITS_ENABLE + // Keypad + | PORTCON_PORTA_OD_A6_BITS_ENABLE + ; + PORTCON_PORTA_OD &= ~(0 + // Keypad + I2C + | PORTCON_PORTA_OD_A10_MASK + // Keypad + I2C + | PORTCON_PORTA_OD_A11_MASK + // Keypad + Voice chip + | PORTCON_PORTA_OD_A12_MASK + // Keypad + Voice chip + | PORTCON_PORTA_OD_A13_MASK + ); + + // PORT B pin configuration + + PORTCON_PORTB_IE |= 0 + | PORTCON_PORTB_IE_B14_BITS_ENABLE + ; + PORTCON_PORTB_IE &= ~(0 + // Back light + | PORTCON_PORTB_IE_B6_MASK + // UART1 + | PORTCON_PORTB_IE_B7_MASK + | PORTCON_PORTB_IE_B8_MASK + // ST7565 + | PORTCON_PORTB_IE_B9_MASK + // SPI0 MOSI + | PORTCON_PORTB_IE_B10_MASK #if !defined(ENABLE_SWD) - // ST7565 - | PORTCON_PORTB_IE_B11_MASK + // ST7565 + | PORTCON_PORTB_IE_B11_MASK #endif - // BK1080 - | PORTCON_PORTB_IE_B15_MASK - ); - - PORTCON_PORTB_PU &= ~(0 - // Back light - | PORTCON_PORTB_PU_B6_MASK - // ST7565 - | PORTCON_PORTB_PU_B9_MASK - // ST7565 + SWD IO - | PORTCON_PORTB_PU_B11_MASK - // SWD CLK - | PORTCON_PORTB_PU_B14_MASK - // BK1080 - | PORTCON_PORTB_PU_B15_MASK - ); - - PORTCON_PORTB_PD &= ~(0 - // Back light - | PORTCON_PORTB_PD_B6_MASK - // ST7565 - | PORTCON_PORTB_PD_B9_MASK - // ST7565 + SWD IO - | PORTCON_PORTB_PD_B11_MASK - // SWD CLK - | PORTCON_PORTB_PD_B14_MASK - // BK1080 - | PORTCON_PORTB_PD_B15_MASK - ); - - PORTCON_PORTB_OD &= ~(0 - // Back light - | PORTCON_PORTB_OD_B6_MASK - // ST7565 - | PORTCON_PORTB_OD_B9_MASK - // ST7565 + SWD IO - | PORTCON_PORTB_OD_B11_MASK - // BK1080 - | PORTCON_PORTB_OD_B15_MASK - ); - - PORTCON_PORTB_OD |= 0 - // SWD CLK - | PORTCON_PORTB_OD_B14_BITS_ENABLE - ; - - // PORT C pin configuration - - PORTCON_PORTC_IE |= 0 - // PTT button - | PORTCON_PORTC_IE_C5_BITS_ENABLE - ; - PORTCON_PORTC_IE &= ~(0 - // BK4819 SCN - | PORTCON_PORTC_IE_C0_MASK - // BK4819 SCL - | PORTCON_PORTC_IE_C1_MASK - // BK4819 SDA - | PORTCON_PORTC_IE_C2_MASK - // Flash Light - | PORTCON_PORTC_IE_C3_MASK - // Speaker - | PORTCON_PORTC_IE_C4_MASK - ); - - PORTCON_PORTC_PU |= 0 - // PTT button - | PORTCON_PORTC_PU_C5_BITS_ENABLE - ; - PORTCON_PORTC_PU &= ~(0 - // BK4819 SCN - | PORTCON_PORTC_PU_C0_MASK - // BK4819 SCL - | PORTCON_PORTC_PU_C1_MASK - // BK4819 SDA - | PORTCON_PORTC_PU_C2_MASK - // Flash Light - | PORTCON_PORTC_PU_C3_MASK - // Speaker - | PORTCON_PORTC_PU_C4_MASK - ); - - PORTCON_PORTC_PD &= ~(0 - // BK4819 SCN - | PORTCON_PORTC_PD_C0_MASK - // BK4819 SCL - | PORTCON_PORTC_PD_C1_MASK - // BK4819 SDA - | PORTCON_PORTC_PD_C2_MASK - // Flash Light - | PORTCON_PORTC_PD_C3_MASK - // Speaker - | PORTCON_PORTC_PD_C4_MASK - // PTT Button - | PORTCON_PORTC_PD_C5_MASK - ); - - PORTCON_PORTC_OD &= ~(0 - // BK4819 SCN - | PORTCON_PORTC_OD_C0_MASK - // BK4819 SCL - | PORTCON_PORTC_OD_C1_MASK - // BK4819 SDA - | PORTCON_PORTC_OD_C2_MASK - // Flash Light - | PORTCON_PORTC_OD_C3_MASK - // Speaker - | PORTCON_PORTC_OD_C4_MASK - ); - PORTCON_PORTC_OD |= 0 - // BK4819 SCN - | PORTCON_PORTC_OD_C0_BITS_DISABLE - // BK4819 SCL - | PORTCON_PORTC_OD_C1_BITS_DISABLE - // BK4819 SDA - | PORTCON_PORTC_OD_C2_BITS_DISABLE - // Flash Light - | PORTCON_PORTC_OD_C3_BITS_DISABLE - // Speaker - | PORTCON_PORTC_OD_C4_BITS_DISABLE - // PTT button - | PORTCON_PORTC_OD_C5_BITS_ENABLE - ; + // BK1080 + | PORTCON_PORTB_IE_B15_MASK + ); + + PORTCON_PORTB_PU &= ~(0 + // Back light + | PORTCON_PORTB_PU_B6_MASK + // ST7565 + | PORTCON_PORTB_PU_B9_MASK + // ST7565 + SWD IO + | PORTCON_PORTB_PU_B11_MASK + // SWD CLK + | PORTCON_PORTB_PU_B14_MASK + // BK1080 + | PORTCON_PORTB_PU_B15_MASK + ); + + PORTCON_PORTB_PD &= ~(0 + // Back light + | PORTCON_PORTB_PD_B6_MASK + // ST7565 + | PORTCON_PORTB_PD_B9_MASK + // ST7565 + SWD IO + | PORTCON_PORTB_PD_B11_MASK + // SWD CLK + | PORTCON_PORTB_PD_B14_MASK + // BK1080 + | PORTCON_PORTB_PD_B15_MASK + ); + + PORTCON_PORTB_OD &= ~(0 + // Back light + | PORTCON_PORTB_OD_B6_MASK + // ST7565 + | PORTCON_PORTB_OD_B9_MASK + // ST7565 + SWD IO + | PORTCON_PORTB_OD_B11_MASK + // BK1080 + | PORTCON_PORTB_OD_B15_MASK + ); + + PORTCON_PORTB_OD |= 0 + // SWD CLK + | PORTCON_PORTB_OD_B14_BITS_ENABLE + ; + + // PORT C pin configuration + + PORTCON_PORTC_IE |= 0 + // PTT button + | PORTCON_PORTC_IE_C5_BITS_ENABLE + ; + PORTCON_PORTC_IE &= ~(0 + // BK4819 SCN + | PORTCON_PORTC_IE_C0_MASK + // BK4819 SCL + | PORTCON_PORTC_IE_C1_MASK + // BK4819 SDA + | PORTCON_PORTC_IE_C2_MASK + // Flash Light + | PORTCON_PORTC_IE_C3_MASK + // Speaker + | PORTCON_PORTC_IE_C4_MASK + ); + + PORTCON_PORTC_PU |= 0 + // PTT button + | PORTCON_PORTC_PU_C5_BITS_ENABLE + ; + PORTCON_PORTC_PU &= ~(0 + // BK4819 SCN + | PORTCON_PORTC_PU_C0_MASK + // BK4819 SCL + | PORTCON_PORTC_PU_C1_MASK + // BK4819 SDA + | PORTCON_PORTC_PU_C2_MASK + // Flash Light + | PORTCON_PORTC_PU_C3_MASK + // Speaker + | PORTCON_PORTC_PU_C4_MASK + ); + + PORTCON_PORTC_PD &= ~(0 + // BK4819 SCN + | PORTCON_PORTC_PD_C0_MASK + // BK4819 SCL + | PORTCON_PORTC_PD_C1_MASK + // BK4819 SDA + | PORTCON_PORTC_PD_C2_MASK + // Flash Light + | PORTCON_PORTC_PD_C3_MASK + // Speaker + | PORTCON_PORTC_PD_C4_MASK + // PTT Button + | PORTCON_PORTC_PD_C5_MASK + ); + + PORTCON_PORTC_OD &= ~(0 + // BK4819 SCN + | PORTCON_PORTC_OD_C0_MASK + // BK4819 SCL + | PORTCON_PORTC_OD_C1_MASK + // BK4819 SDA + | PORTCON_PORTC_OD_C2_MASK + // Flash Light + | PORTCON_PORTC_OD_C3_MASK + // Speaker + | PORTCON_PORTC_OD_C4_MASK + ); + PORTCON_PORTC_OD |= 0 + // BK4819 SCN + | PORTCON_PORTC_OD_C0_BITS_DISABLE + // BK4819 SCL + | PORTCON_PORTC_OD_C1_BITS_DISABLE + // BK4819 SDA + | PORTCON_PORTC_OD_C2_BITS_DISABLE + // Flash Light + | PORTCON_PORTC_OD_C3_BITS_DISABLE + // Speaker + | PORTCON_PORTC_OD_C4_BITS_DISABLE + // PTT button + | PORTCON_PORTC_OD_C5_BITS_ENABLE + ; } void BOARD_ADC_Init(void) { - ADC_Config_t Config; - - Config.CLK_SEL = SYSCON_CLK_SEL_W_SARADC_SMPL_VALUE_DIV2; - Config.CH_SEL = ADC_CH4 | ADC_CH9; - Config.AVG = SARADC_CFG_AVG_VALUE_8_SAMPLE; - Config.CONT = SARADC_CFG_CONT_VALUE_SINGLE; - Config.MEM_MODE = SARADC_CFG_MEM_MODE_VALUE_CHANNEL; - Config.SMPL_CLK = SARADC_CFG_SMPL_CLK_VALUE_INTERNAL; - Config.SMPL_WIN = SARADC_CFG_SMPL_WIN_VALUE_15_CYCLE; - Config.SMPL_SETUP = SARADC_CFG_SMPL_SETUP_VALUE_1_CYCLE; - Config.ADC_TRIG = SARADC_CFG_ADC_TRIG_VALUE_CPU; - Config.CALIB_KD_VALID = SARADC_CALIB_KD_VALID_VALUE_YES; - Config.CALIB_OFFSET_VALID = SARADC_CALIB_OFFSET_VALID_VALUE_YES; - Config.DMA_EN = SARADC_CFG_DMA_EN_VALUE_DISABLE; - Config.IE_CHx_EOC = SARADC_IE_CHx_EOC_VALUE_NONE; - Config.IE_FIFO_FULL = SARADC_IE_FIFO_FULL_VALUE_DISABLE; - Config.IE_FIFO_HFULL = SARADC_IE_FIFO_HFULL_VALUE_DISABLE; - - ADC_Configure(&Config); - ADC_Enable(); - ADC_SoftReset(); + ADC_Config_t Config; + + Config.CLK_SEL = SYSCON_CLK_SEL_W_SARADC_SMPL_VALUE_DIV2; + Config.CH_SEL = ADC_CH4 | ADC_CH9; + Config.AVG = SARADC_CFG_AVG_VALUE_8_SAMPLE; + Config.CONT = SARADC_CFG_CONT_VALUE_SINGLE; + Config.MEM_MODE = SARADC_CFG_MEM_MODE_VALUE_CHANNEL; + Config.SMPL_CLK = SARADC_CFG_SMPL_CLK_VALUE_INTERNAL; + Config.SMPL_WIN = SARADC_CFG_SMPL_WIN_VALUE_15_CYCLE; + Config.SMPL_SETUP = SARADC_CFG_SMPL_SETUP_VALUE_1_CYCLE; + Config.ADC_TRIG = SARADC_CFG_ADC_TRIG_VALUE_CPU; + Config.CALIB_KD_VALID = SARADC_CALIB_KD_VALID_VALUE_YES; + Config.CALIB_OFFSET_VALID = SARADC_CALIB_OFFSET_VALID_VALUE_YES; + Config.DMA_EN = SARADC_CFG_DMA_EN_VALUE_DISABLE; + Config.IE_CHx_EOC = SARADC_IE_CHx_EOC_VALUE_NONE; + Config.IE_FIFO_FULL = SARADC_IE_FIFO_FULL_VALUE_DISABLE; + Config.IE_FIFO_HFULL = SARADC_IE_FIFO_HFULL_VALUE_DISABLE; + + ADC_Configure(&Config); + ADC_Enable(); + ADC_SoftReset(); } void BOARD_ADC_GetBatteryInfo(uint16_t *pVoltage, uint16_t *pCurrent) { - ADC_Start(); - while (!ADC_CheckEndOfConversion(ADC_CH9)) {} - *pVoltage = ADC_GetValue(ADC_CH4); - *pCurrent = ADC_GetValue(ADC_CH9); + ADC_Start(); + while (!ADC_CheckEndOfConversion(ADC_CH9)) {} + *pVoltage = ADC_GetValue(ADC_CH4); + *pCurrent = ADC_GetValue(ADC_CH9); } void BOARD_Init(void) { - BOARD_PORTCON_Init(); - BOARD_GPIO_Init(); - BACKLIGHT_InitHardware(); - BOARD_ADC_Init(); - ST7565_Init(); + BOARD_PORTCON_Init(); + BOARD_GPIO_Init(); + BACKLIGHT_InitHardware(); + BOARD_ADC_Init(); + ST7565_Init(); #ifdef ENABLE_FMRADIO - BK1080_Init0(); + BK1080_Init0(); #endif #if defined(ENABLE_UART) || defined(ENABLED_AIRCOPY) - CRC_Init(); + CRC_Init(); #endif } diff --git a/dcs.c b/dcs.c index 4615dc513..ba668e81b 100644 --- a/dcs.c +++ b/dcs.c @@ -17,97 +17,97 @@ #include "dcs.h" #ifndef ARRAY_SIZE - #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) + #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) #endif // CTCSS Hz * 10 const uint16_t CTCSS_Options[50] = { - 670, 693, 719, 744, 770, 797, 825, 854, 885, 915, - 948, 974, 1000, 1035, 1072, 1109, 1148, 1188, 1230, 1273, - 1318, 1365, 1413, 1462, 1514, 1567, 1598, 1622, 1655, 1679, - 1713, 1738, 1773, 1799, 1835, 1862, 1899, 1928, 1966, 1995, - 2035, 2065, 2107, 2181, 2257, 2291, 2336, 2418, 2503, 2541 + 670, 693, 719, 744, 770, 797, 825, 854, 885, 915, + 948, 974, 1000, 1035, 1072, 1109, 1148, 1188, 1230, 1273, + 1318, 1365, 1413, 1462, 1514, 1567, 1598, 1622, 1655, 1679, + 1713, 1738, 1773, 1799, 1835, 1862, 1899, 1928, 1966, 1995, + 2035, 2065, 2107, 2181, 2257, 2291, 2336, 2418, 2503, 2541 }; const uint16_t DCS_Options[104] = { - 0x0013, 0x0015, 0x0016, 0x0019, 0x001A, 0x001E, 0x0023, 0x0027, - 0x0029, 0x002B, 0x002C, 0x0035, 0x0039, 0x003A, 0x003B, 0x003C, - 0x004C, 0x004D, 0x004E, 0x0052, 0x0055, 0x0059, 0x005A, 0x005C, - 0x0063, 0x0065, 0x006A, 0x006D, 0x006E, 0x0072, 0x0075, 0x007A, - 0x007C, 0x0085, 0x008A, 0x0093, 0x0095, 0x0096, 0x00A3, 0x00A4, - 0x00A5, 0x00A6, 0x00A9, 0x00AA, 0x00AD, 0x00B1, 0x00B3, 0x00B5, - 0x00B6, 0x00B9, 0x00BC, 0x00C6, 0x00C9, 0x00CD, 0x00D5, 0x00D9, - 0x00DA, 0x00E3, 0x00E6, 0x00E9, 0x00EE, 0x00F4, 0x00F5, 0x00F9, - 0x0109, 0x010A, 0x010B, 0x0113, 0x0119, 0x011A, 0x0125, 0x0126, - 0x012A, 0x012C, 0x012D, 0x0132, 0x0134, 0x0135, 0x0136, 0x0143, - 0x0146, 0x014E, 0x0153, 0x0156, 0x015A, 0x0166, 0x0175, 0x0186, - 0x018A, 0x0194, 0x0197, 0x0199, 0x019A, 0x01AC, 0x01B2, 0x01B4, - 0x01C3, 0x01CA, 0x01D3, 0x01D9, 0x01DA, 0x01DC, 0x01E3, 0x01EC, + 0x0013, 0x0015, 0x0016, 0x0019, 0x001A, 0x001E, 0x0023, 0x0027, + 0x0029, 0x002B, 0x002C, 0x0035, 0x0039, 0x003A, 0x003B, 0x003C, + 0x004C, 0x004D, 0x004E, 0x0052, 0x0055, 0x0059, 0x005A, 0x005C, + 0x0063, 0x0065, 0x006A, 0x006D, 0x006E, 0x0072, 0x0075, 0x007A, + 0x007C, 0x0085, 0x008A, 0x0093, 0x0095, 0x0096, 0x00A3, 0x00A4, + 0x00A5, 0x00A6, 0x00A9, 0x00AA, 0x00AD, 0x00B1, 0x00B3, 0x00B5, + 0x00B6, 0x00B9, 0x00BC, 0x00C6, 0x00C9, 0x00CD, 0x00D5, 0x00D9, + 0x00DA, 0x00E3, 0x00E6, 0x00E9, 0x00EE, 0x00F4, 0x00F5, 0x00F9, + 0x0109, 0x010A, 0x010B, 0x0113, 0x0119, 0x011A, 0x0125, 0x0126, + 0x012A, 0x012C, 0x012D, 0x0132, 0x0134, 0x0135, 0x0136, 0x0143, + 0x0146, 0x014E, 0x0153, 0x0156, 0x015A, 0x0166, 0x0175, 0x0186, + 0x018A, 0x0194, 0x0197, 0x0199, 0x019A, 0x01AC, 0x01B2, 0x01B4, + 0x01C3, 0x01CA, 0x01D3, 0x01D9, 0x01DA, 0x01DC, 0x01E3, 0x01EC, }; static uint32_t DCS_CalculateGolay(uint32_t CodeWord) { - unsigned int i; - uint32_t Word = CodeWord; - for (i = 0; i < 12; i++) - { - Word <<= 1; - if (Word & 0x1000) - Word ^= 0x08EA; - } - return CodeWord | ((Word & 0x0FFE) << 11); + unsigned int i; + uint32_t Word = CodeWord; + for (i = 0; i < 12; i++) + { + Word <<= 1; + if (Word & 0x1000) + Word ^= 0x08EA; + } + return CodeWord | ((Word & 0x0FFE) << 11); } uint32_t DCS_GetGolayCodeWord(DCS_CodeType_t CodeType, uint8_t Option) { - uint32_t Code = DCS_CalculateGolay(DCS_Options[Option] + 0x800U); - if (CodeType == CODE_TYPE_REVERSE_DIGITAL) - Code ^= 0x7FFFFF; - return Code; + uint32_t Code = DCS_CalculateGolay(DCS_Options[Option] + 0x800U); + if (CodeType == CODE_TYPE_REVERSE_DIGITAL) + Code ^= 0x7FFFFF; + return Code; } uint8_t DCS_GetCdcssCode(uint32_t Code) { - unsigned int i; - for (i = 0; i < 23; i++) - { - uint32_t Shift; + unsigned int i; + for (i = 0; i < 23; i++) + { + uint32_t Shift; - if (((Code >> 9) & 0x7U) == 4) - { - unsigned int j; - for (j = 0; j < ARRAY_SIZE(DCS_Options); j++) - if (DCS_Options[j] == (Code & 0x1FF)) - if (DCS_GetGolayCodeWord(2, j) == Code) - return j; - } + if (((Code >> 9) & 0x7U) == 4) + { + unsigned int j; + for (j = 0; j < ARRAY_SIZE(DCS_Options); j++) + if (DCS_Options[j] == (Code & 0x1FF)) + if (DCS_GetGolayCodeWord(2, j) == Code) + return j; + } - Shift = Code >> 1; - if (Code & 1U) - Shift |= 0x400000U; - Code = Shift; - } + Shift = Code >> 1; + if (Code & 1U) + Shift |= 0x400000U; + Code = Shift; + } - return 0xFF; + return 0xFF; } uint8_t DCS_GetCtcssCode(int Code) { - unsigned int i; - uint8_t Result = 0xFF; - int Smallest = ARRAY_SIZE(CTCSS_Options); + unsigned int i; + uint8_t Result = 0xFF; + int Smallest = ARRAY_SIZE(CTCSS_Options); - for (i = 0; i < ARRAY_SIZE(CTCSS_Options); i++) - { - int Delta = Code - CTCSS_Options[i]; - if (Delta < 0) - Delta = -(Code - CTCSS_Options[i]); - if (Smallest > Delta) - { - Smallest = Delta; - Result = i; - } - } + for (i = 0; i < ARRAY_SIZE(CTCSS_Options); i++) + { + int Delta = Code - CTCSS_Options[i]; + if (Delta < 0) + Delta = -(Code - CTCSS_Options[i]); + if (Smallest > Delta) + { + Smallest = Delta; + Result = i; + } + } - return Result; + return Result; } diff --git a/dcs.h b/dcs.h index 873ddb6af..2b4fbdfd0 100644 --- a/dcs.h +++ b/dcs.h @@ -21,17 +21,17 @@ enum DCS_CodeType_t { - CODE_TYPE_OFF = 0, - CODE_TYPE_CONTINUOUS_TONE, - CODE_TYPE_DIGITAL, - CODE_TYPE_REVERSE_DIGITAL + CODE_TYPE_OFF = 0, + CODE_TYPE_CONTINUOUS_TONE, + CODE_TYPE_DIGITAL, + CODE_TYPE_REVERSE_DIGITAL }; typedef enum DCS_CodeType_t DCS_CodeType_t; enum { - CDCSS_POSITIVE_CODE = 1U, - CDCSS_NEGATIVE_CODE = 2U, + CDCSS_POSITIVE_CODE = 1U, + CDCSS_NEGATIVE_CODE = 2U, }; extern const uint16_t CTCSS_Options[50]; diff --git a/debugging.h b/debugging.h index 68e44cbb2..aa0bb692d 100644 --- a/debugging.h +++ b/debugging.h @@ -11,36 +11,36 @@ static inline void LogUart(const char *const str) { - UART_Send(str, strlen(str)); + UART_Send(str, strlen(str)); } static inline void LogUartf(const char* format, ...) { - char buffer[128]; - va_list va; - va_start(va, format); - vsnprintf(buffer, (size_t)-1, format, va); - va_end(va); - UART_Send(buffer, strlen(buffer)); + char buffer[128]; + va_list va; + va_start(va, format); + vsnprintf(buffer, (size_t)-1, format, va); + va_end(va); + UART_Send(buffer, strlen(buffer)); } static inline void LogRegUart(uint16_t reg) { - uint16_t regVal = BK4819_ReadRegister(reg); - char buf[32]; - sprintf(buf, "reg%02X: %04X\n", reg, regVal); - LogUart(buf); + uint16_t regVal = BK4819_ReadRegister(reg); + char buf[32]; + sprintf(buf, "reg%02X: %04X\n", reg, regVal); + LogUart(buf); } static inline void LogPrint() { - uint16_t rssi = BK4819_GetRSSI(); - uint16_t reg7e = BK4819_ReadRegister(0x7E); - char buf[32]; - sprintf(buf, "reg7E: %d %2d %6d %2d %d rssi: %d\n", (reg7e >> 15), - (reg7e >> 12) & 0b111, (reg7e >> 5) & 0b1111111, - (reg7e >> 2) & 0b111, (reg7e >> 0) & 0b11, rssi); - LogUart(buf); + uint16_t rssi = BK4819_GetRSSI(); + uint16_t reg7e = BK4819_ReadRegister(0x7E); + char buf[32]; + sprintf(buf, "reg7E: %d %2d %6d %2d %d rssi: %d\n", (reg7e >> 15), + (reg7e >> 12) & 0b111, (reg7e >> 5) & 0b1111111, + (reg7e >> 2) & 0b111, (reg7e >> 0) & 0b11, rssi); + LogUart(buf); } #endif diff --git a/driver/adc.c b/driver/adc.c index bde01f0c2..531b84d29 100644 --- a/driver/adc.c +++ b/driver/adc.c @@ -22,40 +22,40 @@ uint8_t ADC_GetChannelNumber(ADC_CH_MASK Mask) { - if (Mask & ADC_CH15) return 15U; - if (Mask & ADC_CH14) return 14U; - if (Mask & ADC_CH13) return 13U; - if (Mask & ADC_CH12) return 12U; - if (Mask & ADC_CH11) return 11U; - if (Mask & ADC_CH10) return 10U; - if (Mask & ADC_CH9) return 9U; - if (Mask & ADC_CH8) return 8U; - if (Mask & ADC_CH7) return 7U; - if (Mask & ADC_CH6) return 6U; - if (Mask & ADC_CH5) return 5U; - if (Mask & ADC_CH4) return 4U; - if (Mask & ADC_CH3) return 3U; - if (Mask & ADC_CH2) return 2U; - if (Mask & ADC_CH1) return 1U; - if (Mask & ADC_CH0) return 0U; - - return 0U; + if (Mask & ADC_CH15) return 15U; + if (Mask & ADC_CH14) return 14U; + if (Mask & ADC_CH13) return 13U; + if (Mask & ADC_CH12) return 12U; + if (Mask & ADC_CH11) return 11U; + if (Mask & ADC_CH10) return 10U; + if (Mask & ADC_CH9) return 9U; + if (Mask & ADC_CH8) return 8U; + if (Mask & ADC_CH7) return 7U; + if (Mask & ADC_CH6) return 6U; + if (Mask & ADC_CH5) return 5U; + if (Mask & ADC_CH4) return 4U; + if (Mask & ADC_CH3) return 3U; + if (Mask & ADC_CH2) return 2U; + if (Mask & ADC_CH1) return 1U; + if (Mask & ADC_CH0) return 0U; + + return 0U; } void ADC_Disable(void) { - SARADC_CFG = (SARADC_CFG & ~SARADC_CFG_ADC_EN_MASK) | SARADC_CFG_ADC_EN_BITS_DISABLE; + SARADC_CFG = (SARADC_CFG & ~SARADC_CFG_ADC_EN_MASK) | SARADC_CFG_ADC_EN_BITS_DISABLE; } void ADC_Enable(void) { - SARADC_CFG = (SARADC_CFG & ~SARADC_CFG_ADC_EN_MASK) | SARADC_CFG_ADC_EN_BITS_ENABLE; + SARADC_CFG = (SARADC_CFG & ~SARADC_CFG_ADC_EN_MASK) | SARADC_CFG_ADC_EN_BITS_ENABLE; } void ADC_SoftReset(void) { - SARADC_START = (SARADC_START & ~SARADC_START_SOFT_RESET_MASK) | SARADC_START_SOFT_RESET_BITS_ASSERT; - SARADC_START = (SARADC_START & ~SARADC_START_SOFT_RESET_MASK) | SARADC_START_SOFT_RESET_BITS_DEASSERT; + SARADC_START = (SARADC_START & ~SARADC_START_SOFT_RESET_MASK) | SARADC_START_SOFT_RESET_BITS_ASSERT; + SARADC_START = (SARADC_START & ~SARADC_START_SOFT_RESET_MASK) | SARADC_START_SOFT_RESET_BITS_DEASSERT; } // The firmware thinks W_SARADC_SMPL_CLK_SEL is at [8:7] but the TRM says it's at [10:9] @@ -64,102 +64,102 @@ void ADC_SoftReset(void) uint32_t ADC_GetClockConfig(void) { - uint32_t Value; + uint32_t Value; - Value = SYSCON_CLK_SEL; + Value = SYSCON_CLK_SEL; - Value = 0 - | (Value & ~(SYSCON_CLK_SEL_R_PLL_MASK | FW_R_SARADC_SMPL_MASK)) - | (((Value & SYSCON_CLK_SEL_R_PLL_MASK) >> SYSCON_CLK_SEL_R_PLL_SHIFT) << SYSCON_CLK_SEL_W_PLL_SHIFT) - | (((Value & FW_R_SARADC_SMPL_MASK) >> FW_R_SARADC_SMPL_SHIFT) << SYSCON_CLK_SEL_W_SARADC_SMPL_SHIFT) - ; + Value = 0 + | (Value & ~(SYSCON_CLK_SEL_R_PLL_MASK | FW_R_SARADC_SMPL_MASK)) + | (((Value & SYSCON_CLK_SEL_R_PLL_MASK) >> SYSCON_CLK_SEL_R_PLL_SHIFT) << SYSCON_CLK_SEL_W_PLL_SHIFT) + | (((Value & FW_R_SARADC_SMPL_MASK) >> FW_R_SARADC_SMPL_SHIFT) << SYSCON_CLK_SEL_W_SARADC_SMPL_SHIFT) + ; - return Value; + return Value; } void ADC_Configure(ADC_Config_t *pAdc) { - SYSCON_DEV_CLK_GATE = (SYSCON_DEV_CLK_GATE & ~SYSCON_DEV_CLK_GATE_SARADC_MASK) | SYSCON_DEV_CLK_GATE_SARADC_BITS_ENABLE; - - ADC_Disable(); - - SYSCON_CLK_SEL = (ADC_GetClockConfig() & ~SYSCON_CLK_SEL_W_SARADC_SMPL_MASK) | ((pAdc->CLK_SEL << SYSCON_CLK_SEL_W_SARADC_SMPL_SHIFT) & SYSCON_CLK_SEL_W_SARADC_SMPL_MASK); - - SARADC_CFG = 0 - | (SARADC_CFG & ~(0 - | SARADC_CFG_CH_SEL_MASK - | SARADC_CFG_AVG_MASK - | SARADC_CFG_CONT_MASK - | SARADC_CFG_SMPL_SETUP_MASK - | SARADC_CFG_MEM_MODE_MASK - | SARADC_CFG_SMPL_CLK_MASK - | SARADC_CFG_SMPL_WIN_MASK - | SARADC_CFG_ADC_TRIG_MASK - | SARADC_CFG_DMA_EN_MASK - )) - | ((pAdc->CH_SEL << SARADC_CFG_CH_SEL_SHIFT) & SARADC_CFG_CH_SEL_MASK) - | ((pAdc->AVG << SARADC_CFG_AVG_SHIFT) & SARADC_CFG_AVG_MASK) - | ((pAdc->CONT << SARADC_CFG_CONT_SHIFT) & SARADC_CFG_CONT_MASK) - | ((pAdc->SMPL_SETUP << SARADC_CFG_SMPL_SETUP_SHIFT) & SARADC_CFG_SMPL_SETUP_MASK) - | ((pAdc->MEM_MODE << SARADC_CFG_MEM_MODE_SHIFT) & SARADC_CFG_MEM_MODE_MASK) - | ((pAdc->SMPL_CLK << SARADC_CFG_SMPL_CLK_SHIFT) & SARADC_CFG_SMPL_CLK_MASK) - | ((pAdc->SMPL_WIN << SARADC_CFG_SMPL_WIN_SHIFT) & SARADC_CFG_SMPL_WIN_MASK) - | ((pAdc->ADC_TRIG << SARADC_CFG_ADC_TRIG_SHIFT) & SARADC_CFG_ADC_TRIG_MASK) - | ((pAdc->DMA_EN << SARADC_CFG_DMA_EN_SHIFT) & SARADC_CFG_DMA_EN_MASK) - ; - - SARADC_EXTTRIG_SEL = pAdc->EXTTRIG_SEL; - - if (pAdc->CALIB_OFFSET_VALID) { - SARADC_CALIB_OFFSET = (SARADC_CALIB_OFFSET & ~SARADC_CALIB_OFFSET_VALID_MASK) | SARADC_CALIB_OFFSET_VALID_BITS_YES; - } else { - SARADC_CALIB_OFFSET = (SARADC_CALIB_OFFSET & ~SARADC_CALIB_OFFSET_VALID_MASK) | SARADC_CALIB_OFFSET_VALID_BITS_NO; - } - if (pAdc->CALIB_KD_VALID) { - SARADC_CALIB_KD = (SARADC_CALIB_KD & ~SARADC_CALIB_KD_VALID_MASK) | SARADC_CALIB_KD_VALID_BITS_YES; - } else { - SARADC_CALIB_KD = (SARADC_CALIB_KD & ~SARADC_CALIB_KD_VALID_MASK) | SARADC_CALIB_KD_VALID_BITS_NO; - } - - SARADC_IF = 0xFFFFFFFF; - SARADC_IE = 0 - | (SARADC_IE & ~(0 - | SARADC_IE_CHx_EOC_MASK - | SARADC_IE_FIFO_FULL_MASK - | SARADC_IE_FIFO_HFULL_MASK - )) - | ((pAdc->IE_CHx_EOC << SARADC_IE_CHx_EOC_SHIFT) & SARADC_IE_CHx_EOC_MASK) - | ((pAdc->IE_FIFO_FULL << SARADC_IE_FIFO_FULL_SHIFT) & SARADC_IE_FIFO_FULL_MASK) - | ((pAdc->IE_FIFO_HFULL << SARADC_IE_FIFO_HFULL_SHIFT) & SARADC_IE_FIFO_HFULL_MASK) - ; - - if (SARADC_IE == 0) { - NVIC_DisableIRQ((IRQn_Type)DP32_SARADC_IRQn); - } else { - NVIC_EnableIRQ((IRQn_Type)DP32_SARADC_IRQn); - } + SYSCON_DEV_CLK_GATE = (SYSCON_DEV_CLK_GATE & ~SYSCON_DEV_CLK_GATE_SARADC_MASK) | SYSCON_DEV_CLK_GATE_SARADC_BITS_ENABLE; + + ADC_Disable(); + + SYSCON_CLK_SEL = (ADC_GetClockConfig() & ~SYSCON_CLK_SEL_W_SARADC_SMPL_MASK) | ((pAdc->CLK_SEL << SYSCON_CLK_SEL_W_SARADC_SMPL_SHIFT) & SYSCON_CLK_SEL_W_SARADC_SMPL_MASK); + + SARADC_CFG = 0 + | (SARADC_CFG & ~(0 + | SARADC_CFG_CH_SEL_MASK + | SARADC_CFG_AVG_MASK + | SARADC_CFG_CONT_MASK + | SARADC_CFG_SMPL_SETUP_MASK + | SARADC_CFG_MEM_MODE_MASK + | SARADC_CFG_SMPL_CLK_MASK + | SARADC_CFG_SMPL_WIN_MASK + | SARADC_CFG_ADC_TRIG_MASK + | SARADC_CFG_DMA_EN_MASK + )) + | ((pAdc->CH_SEL << SARADC_CFG_CH_SEL_SHIFT) & SARADC_CFG_CH_SEL_MASK) + | ((pAdc->AVG << SARADC_CFG_AVG_SHIFT) & SARADC_CFG_AVG_MASK) + | ((pAdc->CONT << SARADC_CFG_CONT_SHIFT) & SARADC_CFG_CONT_MASK) + | ((pAdc->SMPL_SETUP << SARADC_CFG_SMPL_SETUP_SHIFT) & SARADC_CFG_SMPL_SETUP_MASK) + | ((pAdc->MEM_MODE << SARADC_CFG_MEM_MODE_SHIFT) & SARADC_CFG_MEM_MODE_MASK) + | ((pAdc->SMPL_CLK << SARADC_CFG_SMPL_CLK_SHIFT) & SARADC_CFG_SMPL_CLK_MASK) + | ((pAdc->SMPL_WIN << SARADC_CFG_SMPL_WIN_SHIFT) & SARADC_CFG_SMPL_WIN_MASK) + | ((pAdc->ADC_TRIG << SARADC_CFG_ADC_TRIG_SHIFT) & SARADC_CFG_ADC_TRIG_MASK) + | ((pAdc->DMA_EN << SARADC_CFG_DMA_EN_SHIFT) & SARADC_CFG_DMA_EN_MASK) + ; + + SARADC_EXTTRIG_SEL = pAdc->EXTTRIG_SEL; + + if (pAdc->CALIB_OFFSET_VALID) { + SARADC_CALIB_OFFSET = (SARADC_CALIB_OFFSET & ~SARADC_CALIB_OFFSET_VALID_MASK) | SARADC_CALIB_OFFSET_VALID_BITS_YES; + } else { + SARADC_CALIB_OFFSET = (SARADC_CALIB_OFFSET & ~SARADC_CALIB_OFFSET_VALID_MASK) | SARADC_CALIB_OFFSET_VALID_BITS_NO; + } + if (pAdc->CALIB_KD_VALID) { + SARADC_CALIB_KD = (SARADC_CALIB_KD & ~SARADC_CALIB_KD_VALID_MASK) | SARADC_CALIB_KD_VALID_BITS_YES; + } else { + SARADC_CALIB_KD = (SARADC_CALIB_KD & ~SARADC_CALIB_KD_VALID_MASK) | SARADC_CALIB_KD_VALID_BITS_NO; + } + + SARADC_IF = 0xFFFFFFFF; + SARADC_IE = 0 + | (SARADC_IE & ~(0 + | SARADC_IE_CHx_EOC_MASK + | SARADC_IE_FIFO_FULL_MASK + | SARADC_IE_FIFO_HFULL_MASK + )) + | ((pAdc->IE_CHx_EOC << SARADC_IE_CHx_EOC_SHIFT) & SARADC_IE_CHx_EOC_MASK) + | ((pAdc->IE_FIFO_FULL << SARADC_IE_FIFO_FULL_SHIFT) & SARADC_IE_FIFO_FULL_MASK) + | ((pAdc->IE_FIFO_HFULL << SARADC_IE_FIFO_HFULL_SHIFT) & SARADC_IE_FIFO_HFULL_MASK) + ; + + if (SARADC_IE == 0) { + NVIC_DisableIRQ((IRQn_Type)DP32_SARADC_IRQn); + } else { + NVIC_EnableIRQ((IRQn_Type)DP32_SARADC_IRQn); + } } void ADC_Start(void) { - SARADC_START = (SARADC_START & ~SARADC_START_START_MASK) | SARADC_START_START_BITS_ENABLE; + SARADC_START = (SARADC_START & ~SARADC_START_START_MASK) | SARADC_START_START_BITS_ENABLE; } bool ADC_CheckEndOfConversion(ADC_CH_MASK Mask) { - volatile ADC_Channel_t *pChannels = (volatile ADC_Channel_t *)&SARADC_CH0; - uint8_t Channel = ADC_GetChannelNumber(Mask); + volatile ADC_Channel_t *pChannels = (volatile ADC_Channel_t *)&SARADC_CH0; + uint8_t Channel = ADC_GetChannelNumber(Mask); - return (pChannels[Channel].STAT & ADC_CHx_STAT_EOC_MASK) >> ADC_CHx_STAT_EOC_SHIFT; + return (pChannels[Channel].STAT & ADC_CHx_STAT_EOC_MASK) >> ADC_CHx_STAT_EOC_SHIFT; } uint16_t ADC_GetValue(ADC_CH_MASK Mask) { - volatile ADC_Channel_t *pChannels = (volatile ADC_Channel_t *)&SARADC_CH0; - uint8_t Channel = ADC_GetChannelNumber(Mask); + volatile ADC_Channel_t *pChannels = (volatile ADC_Channel_t *)&SARADC_CH0; + uint8_t Channel = ADC_GetChannelNumber(Mask); - SARADC_IF = 1 << Channel; // TODO: Or just use 'Mask' + SARADC_IF = 1 << Channel; // TODO: Or just use 'Mask' - return (pChannels[Channel].DATA & ADC_CHx_DATA_DATA_MASK) >> ADC_CHx_DATA_DATA_SHIFT; + return (pChannels[Channel].DATA & ADC_CHx_DATA_DATA_MASK) >> ADC_CHx_DATA_DATA_SHIFT; } diff --git a/driver/adc.h b/driver/adc.h index cd5edc24d..76539f18a 100644 --- a/driver/adc.h +++ b/driver/adc.h @@ -21,44 +21,44 @@ #include enum ADC_CH_MASK { - ADC_CH0 = 0x0001U, - ADC_CH1 = 0x0002U, - ADC_CH2 = 0x0004U, - ADC_CH3 = 0x0008U, - ADC_CH4 = 0x0010U, - ADC_CH5 = 0x0020U, - ADC_CH6 = 0x0040U, - ADC_CH7 = 0x0080U, - ADC_CH8 = 0x0100U, - ADC_CH9 = 0x0200U, - ADC_CH10 = 0x0400U, - ADC_CH11 = 0x0800U, - ADC_CH12 = 0x1000U, - ADC_CH13 = 0x2000U, - ADC_CH14 = 0x4000U, - ADC_CH15 = 0x8000U, + ADC_CH0 = 0x0001U, + ADC_CH1 = 0x0002U, + ADC_CH2 = 0x0004U, + ADC_CH3 = 0x0008U, + ADC_CH4 = 0x0010U, + ADC_CH5 = 0x0020U, + ADC_CH6 = 0x0040U, + ADC_CH7 = 0x0080U, + ADC_CH8 = 0x0100U, + ADC_CH9 = 0x0200U, + ADC_CH10 = 0x0400U, + ADC_CH11 = 0x0800U, + ADC_CH12 = 0x1000U, + ADC_CH13 = 0x2000U, + ADC_CH14 = 0x4000U, + ADC_CH15 = 0x8000U, }; typedef enum ADC_CH_MASK ADC_CH_MASK; typedef struct { - uint16_t EXTTRIG_SEL; - uint16_t IE_CHx_EOC; - ADC_CH_MASK CH_SEL; - uint8_t CLK_SEL; - uint8_t AVG; - uint8_t CONT; - uint8_t MEM_MODE; - uint8_t SMPL_CLK; - uint8_t SMPL_SETUP; - uint8_t SMPL_WIN; - uint8_t ADC_TRIG; - uint8_t DMA_EN; - uint8_t IE_FIFO_HFULL; - uint8_t IE_FIFO_FULL; - bool CALIB_OFFSET_VALID; - bool CALIB_KD_VALID; - uint8_t _pad[1]; + uint16_t EXTTRIG_SEL; + uint16_t IE_CHx_EOC; + ADC_CH_MASK CH_SEL; + uint8_t CLK_SEL; + uint8_t AVG; + uint8_t CONT; + uint8_t MEM_MODE; + uint8_t SMPL_CLK; + uint8_t SMPL_SETUP; + uint8_t SMPL_WIN; + uint8_t ADC_TRIG; + uint8_t DMA_EN; + uint8_t IE_FIFO_HFULL; + uint8_t IE_FIFO_FULL; + bool CALIB_OFFSET_VALID; + bool CALIB_KD_VALID; + uint8_t _pad[1]; } ADC_Config_t; uint8_t ADC_GetChannelNumber(ADC_CH_MASK Mask); diff --git a/driver/aes.c b/driver/aes.c index 6a8b5c0a2..65906af85 100644 --- a/driver/aes.c +++ b/driver/aes.c @@ -21,54 +21,54 @@ static void AES_Setup_ENC_CBC(bool IsDecrypt, const void *pKey, const void *pIv) { - const uint32_t *pK = (const uint32_t *)pKey; - const uint32_t *pI = (const uint32_t *)pIv; + const uint32_t *pK = (const uint32_t *)pKey; + const uint32_t *pI = (const uint32_t *)pIv; - (void)IsDecrypt; // unused - - AES_CR = (AES_CR & ~AES_CR_EN_MASK) | AES_CR_EN_BITS_DISABLE; - AES_CR = AES_CR_CHMOD_BITS_CBC; - AES_KEYR3 = pK[0]; - AES_KEYR2 = pK[1]; - AES_KEYR1 = pK[2]; - AES_KEYR0 = pK[3]; - AES_IVR3 = pI[0]; - AES_IVR2 = pI[1]; - AES_IVR1 = pI[2]; - AES_IVR0 = pI[3]; - AES_CR = (AES_CR & ~AES_CR_EN_MASK) | AES_CR_EN_BITS_ENABLE; + (void)IsDecrypt; // unused + + AES_CR = (AES_CR & ~AES_CR_EN_MASK) | AES_CR_EN_BITS_DISABLE; + AES_CR = AES_CR_CHMOD_BITS_CBC; + AES_KEYR3 = pK[0]; + AES_KEYR2 = pK[1]; + AES_KEYR1 = pK[2]; + AES_KEYR0 = pK[3]; + AES_IVR3 = pI[0]; + AES_IVR2 = pI[1]; + AES_IVR1 = pI[2]; + AES_IVR0 = pI[3]; + AES_CR = (AES_CR & ~AES_CR_EN_MASK) | AES_CR_EN_BITS_ENABLE; } static void AES_Transform(const void *pIn, void *pOut) { - const uint32_t *pI = (const uint32_t *)pIn; - uint32_t *pO = (uint32_t *)pOut; + const uint32_t *pI = (const uint32_t *)pIn; + uint32_t *pO = (uint32_t *)pOut; - AES_DINR = pI[0]; - AES_DINR = pI[1]; - AES_DINR = pI[2]; - AES_DINR = pI[3]; + AES_DINR = pI[0]; + AES_DINR = pI[1]; + AES_DINR = pI[2]; + AES_DINR = pI[3]; - while ((AES_SR & AES_SR_CCF_MASK) == AES_SR_CCF_BITS_NOT_COMPLETE) { - } + while ((AES_SR & AES_SR_CCF_MASK) == AES_SR_CCF_BITS_NOT_COMPLETE) { + } - pO[0] = AES_DOUTR; - pO[1] = AES_DOUTR; - pO[2] = AES_DOUTR; - pO[3] = AES_DOUTR; + pO[0] = AES_DOUTR; + pO[1] = AES_DOUTR; + pO[2] = AES_DOUTR; + pO[3] = AES_DOUTR; - AES_CR |= AES_CR_CCFC_BITS_SET; + AES_CR |= AES_CR_CCFC_BITS_SET; } void AES_Encrypt(const void *pKey, const void *pIv, const void *pIn, void *pOut, uint8_t NumBlocks) { - const uint8_t *pI = (const uint8_t *)pIn; - uint8_t *pO = (uint8_t *)pOut; - uint8_t i; + const uint8_t *pI = (const uint8_t *)pIn; + uint8_t *pO = (uint8_t *)pOut; + uint8_t i; - AES_Setup_ENC_CBC(0, pKey, pIv); - for (i = 0; i < NumBlocks; i++) { - AES_Transform(pI + (i * 16), pO + (i * 16)); - } + AES_Setup_ENC_CBC(0, pKey, pIv); + for (i = 0; i < NumBlocks; i++) { + AES_Transform(pI + (i * 16), pO + (i * 16)); + } } diff --git a/driver/backlight.c b/driver/backlight.c index b6544ed03..8bac46ae1 100644 --- a/driver/backlight.c +++ b/driver/backlight.c @@ -22,9 +22,9 @@ #include "settings.h" #ifdef ENABLE_FEAT_F4HWN - #include "driver/system.h" - #include "audio.h" - #include "misc.h" + #include "driver/system.h" + #include "audio.h" + #include "misc.h" #endif // this is decremented once every 500ms @@ -33,128 +33,128 @@ bool backlightOn; void BACKLIGHT_InitHardware() { - // 48MHz / 94 / 1024 ~ 500Hz - const uint32_t PWM_FREQUENCY_HZ = 25000; - PWM_PLUS0_CLKSRC |= ((48000000 / 1024 / PWM_FREQUENCY_HZ) << 16); - PWM_PLUS0_PERIOD = 1023; - - PORTCON_PORTB_SEL0 &= ~(0 - // Back light - | PORTCON_PORTB_SEL0_B6_MASK - ); - PORTCON_PORTB_SEL0 |= 0 - // Back light PWM - | PORTCON_PORTB_SEL0_B6_BITS_PWMP0_CH0 - ; - - PWM_PLUS0_GEN = - PWMPLUS_GEN_CH0_OE_BITS_ENABLE | - PWMPLUS_GEN_CH0_OUTINV_BITS_ENABLE | - 0; - - PWM_PLUS0_CFG = - PWMPLUS_CFG_CNT_REP_BITS_ENABLE | - PWMPLUS_CFG_COUNTER_EN_BITS_ENABLE | - 0; + // 48MHz / 94 / 1024 ~ 500Hz + const uint32_t PWM_FREQUENCY_HZ = 25000; + PWM_PLUS0_CLKSRC |= ((48000000 / 1024 / PWM_FREQUENCY_HZ) << 16); + PWM_PLUS0_PERIOD = 1023; + + PORTCON_PORTB_SEL0 &= ~(0 + // Back light + | PORTCON_PORTB_SEL0_B6_MASK + ); + PORTCON_PORTB_SEL0 |= 0 + // Back light PWM + | PORTCON_PORTB_SEL0_B6_BITS_PWMP0_CH0 + ; + + PWM_PLUS0_GEN = + PWMPLUS_GEN_CH0_OE_BITS_ENABLE | + PWMPLUS_GEN_CH0_OUTINV_BITS_ENABLE | + 0; + + PWM_PLUS0_CFG = + PWMPLUS_CFG_CNT_REP_BITS_ENABLE | + PWMPLUS_CFG_COUNTER_EN_BITS_ENABLE | + 0; } static void BACKLIGHT_Sound(void) { - if (gEeprom.POWER_ON_DISPLAY_MODE == POWER_ON_DISPLAY_MODE_SOUND || gEeprom.POWER_ON_DISPLAY_MODE == POWER_ON_DISPLAY_MODE_ALL) - { - AUDIO_PlayBeep(BEEP_880HZ_60MS_DOUBLE_BEEP); - AUDIO_PlayBeep(BEEP_880HZ_60MS_DOUBLE_BEEP); - gK5startup = false; - } - else - gK5startup = false; + if (gEeprom.POWER_ON_DISPLAY_MODE == POWER_ON_DISPLAY_MODE_SOUND || gEeprom.POWER_ON_DISPLAY_MODE == POWER_ON_DISPLAY_MODE_ALL) + { + AUDIO_PlayBeep(BEEP_880HZ_60MS_DOUBLE_BEEP); + AUDIO_PlayBeep(BEEP_880HZ_60MS_DOUBLE_BEEP); + gK5startup = false; + } + else + gK5startup = false; } void BACKLIGHT_TurnOn(void) { - #ifdef ENABLE_FEAT_F4HWN - gBacklightBrightnessOld = BACKLIGHT_GetBrightness(); - #endif - - if (gEeprom.BACKLIGHT_TIME == 0) { - BACKLIGHT_TurnOff(); - #ifdef ENABLE_FEAT_F4HWN - if(gK5startup == true) - { - BACKLIGHT_Sound(); - } - #endif - return; - } - - backlightOn = true; + #ifdef ENABLE_FEAT_F4HWN + gBacklightBrightnessOld = BACKLIGHT_GetBrightness(); + #endif + + if (gEeprom.BACKLIGHT_TIME == 0) { + BACKLIGHT_TurnOff(); + #ifdef ENABLE_FEAT_F4HWN + if(gK5startup == true) + { + BACKLIGHT_Sound(); + } + #endif + return; + } + + backlightOn = true; #ifdef ENABLE_FEAT_F4HWN - if(gK5startup == true) { - for(uint8_t i = 0; i <= gEeprom.BACKLIGHT_MAX; i++) - { - BACKLIGHT_SetBrightness(i); - SYSTEM_DelayMs(50); - } - - BACKLIGHT_Sound(); - } - else - { - BACKLIGHT_SetBrightness(gEeprom.BACKLIGHT_MAX); - } + if(gK5startup == true) { + for(uint8_t i = 0; i <= gEeprom.BACKLIGHT_MAX; i++) + { + BACKLIGHT_SetBrightness(i); + SYSTEM_DelayMs(50); + } + + BACKLIGHT_Sound(); + } + else + { + BACKLIGHT_SetBrightness(gEeprom.BACKLIGHT_MAX); + } #else - BACKLIGHT_SetBrightness(gEeprom.BACKLIGHT_MAX); + BACKLIGHT_SetBrightness(gEeprom.BACKLIGHT_MAX); #endif - switch (gEeprom.BACKLIGHT_TIME) { - default: - case 1 ... 60: // 5 sec * value - gBacklightCountdown_500ms = 1 + (gEeprom.BACKLIGHT_TIME * 5) * 2; - break; - case 61: // always on - gBacklightCountdown_500ms = 0; - break; - } + switch (gEeprom.BACKLIGHT_TIME) { + default: + case 1 ... 60: // 5 sec * value + gBacklightCountdown_500ms = 1 + (gEeprom.BACKLIGHT_TIME * 5) * 2; + break; + case 61: // always on + gBacklightCountdown_500ms = 0; + break; + } } void BACKLIGHT_TurnOff() { #ifdef ENABLE_BLMIN_TMP_OFF - register uint8_t tmp; + register uint8_t tmp; - if (gEeprom.BACKLIGHT_MIN_STAT == BLMIN_STAT_ON) - tmp = gEeprom.BACKLIGHT_MIN; - else - tmp = 0; + if (gEeprom.BACKLIGHT_MIN_STAT == BLMIN_STAT_ON) + tmp = gEeprom.BACKLIGHT_MIN; + else + tmp = 0; - BACKLIGHT_SetBrightness(tmp); + BACKLIGHT_SetBrightness(tmp); #else - BACKLIGHT_SetBrightness(gEeprom.BACKLIGHT_MIN); + BACKLIGHT_SetBrightness(gEeprom.BACKLIGHT_MIN); #endif - gBacklightCountdown_500ms = 0; - backlightOn = false; + gBacklightCountdown_500ms = 0; + backlightOn = false; } bool BACKLIGHT_IsOn() { - return backlightOn; + return backlightOn; } static uint8_t currentBrightness; void BACKLIGHT_SetBrightness(uint8_t brigtness) { - const uint8_t value[] = {0, 3, 6, 9, 15, 24, 38, 62, 100, 159, 255}; + const uint8_t value[] = {0, 3, 6, 9, 15, 24, 38, 62, 100, 159, 255}; - currentBrightness = brigtness; - PWM_PLUS0_CH0_COMP = value[brigtness] * 4; - //PWM_PLUS0_CH0_COMP = (1 << brigtness) - 1; - //PWM_PLUS0_SWLOAD = 1; + currentBrightness = brigtness; + PWM_PLUS0_CH0_COMP = value[brigtness] * 4; + //PWM_PLUS0_CH0_COMP = (1 << brigtness) - 1; + //PWM_PLUS0_SWLOAD = 1; } uint8_t BACKLIGHT_GetBrightness(void) { - return currentBrightness; + return currentBrightness; } diff --git a/driver/bk1080-regs.h b/driver/bk1080-regs.h index 49dfdfc1e..8a030f751 100644 --- a/driver/bk1080-regs.h +++ b/driver/bk1080-regs.h @@ -18,40 +18,40 @@ #define BK1080_REGS_H enum BK1080_Register_t { - BK1080_REG_00 = 0x00U, - BK1080_REG_02_POWER_CONFIGURATION = 0x02U, - BK1080_REG_03_CHANNEL = 0x03U, - BK1080_REG_05_SYSTEM_CONFIGURATION2 = 0x05U, - BK1080_REG_07 = 0x07U, - BK1080_REG_10 = 0x0AU, - BK1080_REG_25_INTERNAL = 0x19U, + BK1080_REG_00 = 0x00U, + BK1080_REG_02_POWER_CONFIGURATION = 0x02U, + BK1080_REG_03_CHANNEL = 0x03U, + BK1080_REG_05_SYSTEM_CONFIGURATION2 = 0x05U, + BK1080_REG_07 = 0x07U, + BK1080_REG_10 = 0x0AU, + BK1080_REG_25_INTERNAL = 0x19U, }; typedef enum BK1080_Register_t BK1080_Register_t; // REG 07 -#define BK1080_REG_07_SHIFT_FREQD 4 -#define BK1080_REG_07_SHIFT_SNR 0 +#define BK1080_REG_07_SHIFT_FREQD 4 +#define BK1080_REG_07_SHIFT_SNR 0 -#define BK1080_REG_07_MASK_FREQD (0xFFFU << BK1080_REG_07_SHIFT_FREQD) -#define BK1080_REG_07_MASK_SNR (0x00FU << BK1080_REG_07_SHIFT_SNR) +#define BK1080_REG_07_MASK_FREQD (0xFFFU << BK1080_REG_07_SHIFT_FREQD) +#define BK1080_REG_07_MASK_SNR (0x00FU << BK1080_REG_07_SHIFT_SNR) -#define BK1080_REG_07_GET_FREQD(x) (((x) & BK1080_REG_07_MASK_FREQD) >> BK1080_REG_07_SHIFT_FREQD) -#define BK1080_REG_07_GET_SNR(x) (((x) & BK1080_REG_07_MASK_SNR) >> BK1080_REG_07_SHIFT_SNR) +#define BK1080_REG_07_GET_FREQD(x) (((x) & BK1080_REG_07_MASK_FREQD) >> BK1080_REG_07_SHIFT_FREQD) +#define BK1080_REG_07_GET_SNR(x) (((x) & BK1080_REG_07_MASK_SNR) >> BK1080_REG_07_SHIFT_SNR) // REG 10 -#define BK1080_REG_10_SHIFT_AFCRL 12 -#define BK1080_REG_10_SHIFT_RSSI 0 +#define BK1080_REG_10_SHIFT_AFCRL 12 +#define BK1080_REG_10_SHIFT_RSSI 0 -#define BK1080_REG_10_MASK_AFCRL (0x01U << BK1080_REG_10_SHIFT_AFCRL) -#define BK1080_REG_10_MASK_RSSI (0xFFU << BK1080_REG_10_SHIFT_RSSI) +#define BK1080_REG_10_MASK_AFCRL (0x01U << BK1080_REG_10_SHIFT_AFCRL) +#define BK1080_REG_10_MASK_RSSI (0xFFU << BK1080_REG_10_SHIFT_RSSI) -#define BK1080_REG_10_AFCRL_NOT_RAILED (0U << BK1080_REG_10_SHIFT_AFCRL) -#define BK1080_REG_10_AFCRL_RAILED (1U << BK1080_REG_10_SHIFT_AFCRL) +#define BK1080_REG_10_AFCRL_NOT_RAILED (0U << BK1080_REG_10_SHIFT_AFCRL) +#define BK1080_REG_10_AFCRL_RAILED (1U << BK1080_REG_10_SHIFT_AFCRL) -#define BK1080_REG_10_GET_RSSI(x) (((x) & BK1080_REG_10_MASK_RSSI) >> BK1080_REG_10_SHIFT_RSSI) +#define BK1080_REG_10_GET_RSSI(x) (((x) & BK1080_REG_10_MASK_RSSI) >> BK1080_REG_10_SHIFT_RSSI) #endif diff --git a/driver/bk1080.c b/driver/bk1080.c index b14af1a89..3c8e9218f 100644 --- a/driver/bk1080.c +++ b/driver/bk1080.c @@ -22,16 +22,16 @@ #include "misc.h" #ifndef ARRAY_SIZE - #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) + #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) #endif static const uint16_t BK1080_RegisterTable[] = { - 0x0008, 0x1080, 0x0201, 0x0000, 0x40C0, 0x0A1F, 0x002E, 0x02FF, - 0x5B11, 0x0000, 0x411E, 0x0000, 0xCE00, 0x0000, 0x0000, 0x1000, - 0x3197, 0x0000, 0x13FF, 0x9852, 0x0000, 0x0000, 0x0008, 0x0000, - 0x51E1, 0xA8BC, 0x2645, 0x00E4, 0x1CD8, 0x3A50, 0xEAE0, 0x3000, - 0x0200, 0x0000, + 0x0008, 0x1080, 0x0201, 0x0000, 0x40C0, 0x0A1F, 0x002E, 0x02FF, + 0x5B11, 0x0000, 0x411E, 0x0000, 0xCE00, 0x0000, 0x0000, 0x1000, + 0x3197, 0x0000, 0x13FF, 0x9852, 0x0000, 0x0000, 0x0008, 0x0000, + 0x51E1, 0xA8BC, 0x2645, 0x00E4, 0x1CD8, 0x3A50, 0xEAE0, 0x3000, + 0x0200, 0x0000, }; static bool gIsInitBK1080; @@ -41,104 +41,104 @@ uint16_t BK1080_FrequencyDeviation; void BK1080_Init0(void) { - BK1080_Init(0,0/*,0*/); + BK1080_Init(0,0/*,0*/); } void BK1080_Init(uint16_t freq, uint8_t band/*, uint8_t space*/) { - unsigned int i; + unsigned int i; - if (freq) { - GPIO_ClearBit(&GPIOB->DATA, GPIOB_PIN_BK1080); + if (freq) { + GPIO_ClearBit(&GPIOB->DATA, GPIOB_PIN_BK1080); - if (!gIsInitBK1080) { - for (i = 0; i < ARRAY_SIZE(BK1080_RegisterTable); i++) - BK1080_WriteRegister(i, BK1080_RegisterTable[i]); + if (!gIsInitBK1080) { + for (i = 0; i < ARRAY_SIZE(BK1080_RegisterTable); i++) + BK1080_WriteRegister(i, BK1080_RegisterTable[i]); - SYSTEM_DelayMs(250); + SYSTEM_DelayMs(250); - BK1080_WriteRegister(BK1080_REG_25_INTERNAL, 0xA83C); - BK1080_WriteRegister(BK1080_REG_25_INTERNAL, 0xA8BC); + BK1080_WriteRegister(BK1080_REG_25_INTERNAL, 0xA83C); + BK1080_WriteRegister(BK1080_REG_25_INTERNAL, 0xA8BC); - SYSTEM_DelayMs(60); + SYSTEM_DelayMs(60); - gIsInitBK1080 = true; - } - else { - BK1080_WriteRegister(BK1080_REG_02_POWER_CONFIGURATION, 0x0201); - } + gIsInitBK1080 = true; + } + else { + BK1080_WriteRegister(BK1080_REG_02_POWER_CONFIGURATION, 0x0201); + } - BK1080_WriteRegister(BK1080_REG_05_SYSTEM_CONFIGURATION2, 0x0A1F); - BK1080_SetFrequency(freq, band/*, space*/); - } - else { - BK1080_WriteRegister(BK1080_REG_02_POWER_CONFIGURATION, 0x0241); - GPIO_SetBit(&GPIOB->DATA, GPIOB_PIN_BK1080); - } + BK1080_WriteRegister(BK1080_REG_05_SYSTEM_CONFIGURATION2, 0x0A1F); + BK1080_SetFrequency(freq, band/*, space*/); + } + else { + BK1080_WriteRegister(BK1080_REG_02_POWER_CONFIGURATION, 0x0241); + GPIO_SetBit(&GPIOB->DATA, GPIOB_PIN_BK1080); + } } uint16_t BK1080_ReadRegister(BK1080_Register_t Register) { - uint8_t Value[2]; + uint8_t Value[2]; - I2C_Start(); - I2C_Write(0x80); - I2C_Write((Register << 1) | I2C_READ); - I2C_ReadBuffer(Value, sizeof(Value)); - I2C_Stop(); + I2C_Start(); + I2C_Write(0x80); + I2C_Write((Register << 1) | I2C_READ); + I2C_ReadBuffer(Value, sizeof(Value)); + I2C_Stop(); - return (Value[0] << 8) | Value[1]; + return (Value[0] << 8) | Value[1]; } void BK1080_WriteRegister(BK1080_Register_t Register, uint16_t Value) { - I2C_Start(); - I2C_Write(0x80); - I2C_Write((Register << 1) | I2C_WRITE); - Value = ((Value >> 8) & 0xFF) | ((Value & 0xFF) << 8); - I2C_WriteBuffer(&Value, sizeof(Value)); - I2C_Stop(); + I2C_Start(); + I2C_Write(0x80); + I2C_Write((Register << 1) | I2C_WRITE); + Value = ((Value >> 8) & 0xFF) | ((Value & 0xFF) << 8); + I2C_WriteBuffer(&Value, sizeof(Value)); + I2C_Stop(); } void BK1080_Mute(bool Mute) { - BK1080_WriteRegister(BK1080_REG_02_POWER_CONFIGURATION, Mute ? 0x4201 : 0x0201); + BK1080_WriteRegister(BK1080_REG_02_POWER_CONFIGURATION, Mute ? 0x4201 : 0x0201); } void BK1080_SetFrequency(uint16_t frequency, uint8_t band/*, uint8_t space*/) { - //uint8_t spacings[] = {20,10,5}; - //space %= 3; + //uint8_t spacings[] = {20,10,5}; + //space %= 3; - uint16_t channel = (frequency - BK1080_GetFreqLoLimit(band))/* * 10 / spacings[space]*/; + uint16_t channel = (frequency - BK1080_GetFreqLoLimit(band))/* * 10 / spacings[space]*/; - uint16_t regval = BK1080_ReadRegister(BK1080_REG_05_SYSTEM_CONFIGURATION2); - regval = (regval & ~(0b11 << 6)) | ((band & 0b11) << 6); - //regval = (regval & ~(0b11 << 4)) | ((space & 0b11) << 4); + uint16_t regval = BK1080_ReadRegister(BK1080_REG_05_SYSTEM_CONFIGURATION2); + regval = (regval & ~(0b11 << 6)) | ((band & 0b11) << 6); + //regval = (regval & ~(0b11 << 4)) | ((space & 0b11) << 4); - BK1080_WriteRegister(BK1080_REG_05_SYSTEM_CONFIGURATION2, regval); + BK1080_WriteRegister(BK1080_REG_05_SYSTEM_CONFIGURATION2, regval); - BK1080_WriteRegister(BK1080_REG_03_CHANNEL, channel); - SYSTEM_DelayMs(10); - BK1080_WriteRegister(BK1080_REG_03_CHANNEL, channel | 0x8000); + BK1080_WriteRegister(BK1080_REG_03_CHANNEL, channel); + SYSTEM_DelayMs(10); + BK1080_WriteRegister(BK1080_REG_03_CHANNEL, channel | 0x8000); } void BK1080_GetFrequencyDeviation(uint16_t Frequency) { - BK1080_BaseFrequency = Frequency; - BK1080_FrequencyDeviation = BK1080_ReadRegister(BK1080_REG_07) / 16; + BK1080_BaseFrequency = Frequency; + BK1080_FrequencyDeviation = BK1080_ReadRegister(BK1080_REG_07) / 16; } uint16_t BK1080_GetFreqLoLimit(uint8_t band) { - uint16_t lim[] = {875, 760, 760, 640}; - return lim[band % 4]; + uint16_t lim[] = {875, 760, 760, 640}; + return lim[band % 4]; } uint16_t BK1080_GetFreqHiLimit(uint8_t band) { - band %= 4; - uint16_t lim[] = {1080, 1080, 900, 760}; - return lim[band % 4]; + band %= 4; + uint16_t lim[] = {1080, 1080, 900, 760}; + return lim[band % 4]; } diff --git a/driver/bk4819-regs.h b/driver/bk4819-regs.h index 3b673101e..7c333718e 100644 --- a/driver/bk4819-regs.h +++ b/driver/bk4819-regs.h @@ -32,179 +32,179 @@ static const RegisterSpec afOutRegSpec = {"AF Output Select", 0x47, 8, 0xF, 1}; static const RegisterSpec afDacGainRegSpec = {"AF DAC Gain", 0x48, 0, 0xF, 1}; enum BK4819_REGISTER_t { - BK4819_REG_00 = 0x00U, - BK4819_REG_02 = 0x02U, - BK4819_REG_06 = 0x06U, - BK4819_REG_07 = 0x07U, - BK4819_REG_08 = 0x08U, - BK4819_REG_09 = 0x09U, - BK4819_REG_0B = 0x0BU, - BK4819_REG_0C = 0x0CU, - BK4819_REG_0D = 0x0DU, - BK4819_REG_0E = 0x0EU, - // RX AGC Gain Table[0] - BK4819_REG_10 = 0x10U, - // RX AGC Gain Table[1] - BK4819_REG_11 = 0x11U, - // RX AGC Gain Table[2] - BK4819_REG_12 = 0x12U, - // RX AGC Gain Table[3] - BK4819_REG_13 = 0x13U, - // RX AGC Gain Table[-1] - BK4819_REG_14 = 0x14U, - BK4819_REG_19 = 0x19U, - BK4819_REG_1F = 0x1FU, - BK4819_REG_20 = 0x20U, - BK4819_REG_21 = 0x21U, - BK4819_REG_24 = 0x24U, - BK4819_REG_28 = 0x28U, - BK4819_REG_29 = 0x29U, - BK4819_REG_2B = 0x2BU, - BK4819_REG_30 = 0x30U, - BK4819_REG_31 = 0x31U, - BK4819_REG_32 = 0x32U, - BK4819_REG_33 = 0x33U, - BK4819_REG_36 = 0x36U, - BK4819_REG_37 = 0x37U, - BK4819_REG_38 = 0x38U, - BK4819_REG_39 = 0x39U, - BK4819_REG_3A = 0x3AU, - BK4819_REG_3B = 0x3BU, - BK4819_REG_3C = 0x3CU, - BK4819_REG_3D = 0x3DU, - BK4819_REG_3E = 0x3EU, - BK4819_REG_3F = 0x3FU, - BK4819_REG_43 = 0x43U, - BK4819_REG_46 = 0x46U, - BK4819_REG_47 = 0x47U, - BK4819_REG_48 = 0x48U, - // REG_49<15:14> 0b00; High/Low Lo selection: - // 0X: Auto High/Low Lo - // 10: Low Lo - // 11: High Lo - // REG_49<13:7> 0x50; RF AGC high threshold, 1 dB/LSB - // REG_49<6:0> 0x30; RF AGC low threshold, 1 dB/LSB - BK4819_REG_49 = 0x49U, - BK4819_REG_4D = 0x4DU, - BK4819_REG_4E = 0x4EU, - BK4819_REG_4F = 0x4FU, - BK4819_REG_50 = 0x50U, - BK4819_REG_51 = 0x51U, - BK4819_REG_52 = 0x52U, - BK4819_REG_58 = 0x58U, - BK4819_REG_59 = 0x59U, - BK4819_REG_5A = 0x5AU, - BK4819_REG_5B = 0x5BU, - BK4819_REG_5C = 0x5CU, - BK4819_REG_5D = 0x5DU, - BK4819_REG_5F = 0x5FU, - BK4819_REG_63 = 0x63U, - BK4819_REG_64 = 0x64U, - BK4819_REG_65 = 0x65U, - BK4819_REG_67 = 0x67U, - BK4819_REG_68 = 0x68U, - BK4819_REG_69 = 0x69U, - BK4819_REG_6A = 0x6AU, - BK4819_REG_6F = 0x6FU, - BK4819_REG_70 = 0x70U, - BK4819_REG_71 = 0x71U, - BK4819_REG_72 = 0x72U, - BK4819_REG_78 = 0x78U, - BK4819_REG_79 = 0x79U, - BK4819_REG_7A = 0x7AU, - // REG_7B<15:0> 0xae34 RSSI table - BK4819_REG_7B = 0x7BU, - // REG_7C<15:0> 0x8000 RSSI table - BK4819_REG_7C = 0x7CU, - BK4819_REG_7D = 0x7DU, - // REG_7E<15> 0; AGC fix mode: - // 1: Fix - // 0: Auto - // REG_7E<14:12> 0b011; AGC fix index: - // 011: Max. - // … - // 100: Min. - // REG_7E<5:3> 0b101; DC filter bandwidth for TX (MIC in): - // 000: Bypass DC filter - // REG_7E<2:0> 0b110; DC filter bandwidth for RX (IF in): - // 000: Bypass DC filter - BK4819_REG_7E = 0x7EU, + BK4819_REG_00 = 0x00U, + BK4819_REG_02 = 0x02U, + BK4819_REG_06 = 0x06U, + BK4819_REG_07 = 0x07U, + BK4819_REG_08 = 0x08U, + BK4819_REG_09 = 0x09U, + BK4819_REG_0B = 0x0BU, + BK4819_REG_0C = 0x0CU, + BK4819_REG_0D = 0x0DU, + BK4819_REG_0E = 0x0EU, + // RX AGC Gain Table[0] + BK4819_REG_10 = 0x10U, + // RX AGC Gain Table[1] + BK4819_REG_11 = 0x11U, + // RX AGC Gain Table[2] + BK4819_REG_12 = 0x12U, + // RX AGC Gain Table[3] + BK4819_REG_13 = 0x13U, + // RX AGC Gain Table[-1] + BK4819_REG_14 = 0x14U, + BK4819_REG_19 = 0x19U, + BK4819_REG_1F = 0x1FU, + BK4819_REG_20 = 0x20U, + BK4819_REG_21 = 0x21U, + BK4819_REG_24 = 0x24U, + BK4819_REG_28 = 0x28U, + BK4819_REG_29 = 0x29U, + BK4819_REG_2B = 0x2BU, + BK4819_REG_30 = 0x30U, + BK4819_REG_31 = 0x31U, + BK4819_REG_32 = 0x32U, + BK4819_REG_33 = 0x33U, + BK4819_REG_36 = 0x36U, + BK4819_REG_37 = 0x37U, + BK4819_REG_38 = 0x38U, + BK4819_REG_39 = 0x39U, + BK4819_REG_3A = 0x3AU, + BK4819_REG_3B = 0x3BU, + BK4819_REG_3C = 0x3CU, + BK4819_REG_3D = 0x3DU, + BK4819_REG_3E = 0x3EU, + BK4819_REG_3F = 0x3FU, + BK4819_REG_43 = 0x43U, + BK4819_REG_46 = 0x46U, + BK4819_REG_47 = 0x47U, + BK4819_REG_48 = 0x48U, + // REG_49<15:14> 0b00; High/Low Lo selection: + // 0X: Auto High/Low Lo + // 10: Low Lo + // 11: High Lo + // REG_49<13:7> 0x50; RF AGC high threshold, 1 dB/LSB + // REG_49<6:0> 0x30; RF AGC low threshold, 1 dB/LSB + BK4819_REG_49 = 0x49U, + BK4819_REG_4D = 0x4DU, + BK4819_REG_4E = 0x4EU, + BK4819_REG_4F = 0x4FU, + BK4819_REG_50 = 0x50U, + BK4819_REG_51 = 0x51U, + BK4819_REG_52 = 0x52U, + BK4819_REG_58 = 0x58U, + BK4819_REG_59 = 0x59U, + BK4819_REG_5A = 0x5AU, + BK4819_REG_5B = 0x5BU, + BK4819_REG_5C = 0x5CU, + BK4819_REG_5D = 0x5DU, + BK4819_REG_5F = 0x5FU, + BK4819_REG_63 = 0x63U, + BK4819_REG_64 = 0x64U, + BK4819_REG_65 = 0x65U, + BK4819_REG_67 = 0x67U, + BK4819_REG_68 = 0x68U, + BK4819_REG_69 = 0x69U, + BK4819_REG_6A = 0x6AU, + BK4819_REG_6F = 0x6FU, + BK4819_REG_70 = 0x70U, + BK4819_REG_71 = 0x71U, + BK4819_REG_72 = 0x72U, + BK4819_REG_78 = 0x78U, + BK4819_REG_79 = 0x79U, + BK4819_REG_7A = 0x7AU, + // REG_7B<15:0> 0xae34 RSSI table + BK4819_REG_7B = 0x7BU, + // REG_7C<15:0> 0x8000 RSSI table + BK4819_REG_7C = 0x7CU, + BK4819_REG_7D = 0x7DU, + // REG_7E<15> 0; AGC fix mode: + // 1: Fix + // 0: Auto + // REG_7E<14:12> 0b011; AGC fix index: + // 011: Max. + // … + // 100: Min. + // REG_7E<5:3> 0b101; DC filter bandwidth for TX (MIC in): + // 000: Bypass DC filter + // REG_7E<2:0> 0b110; DC filter bandwidth for RX (IF in): + // 000: Bypass DC filter + BK4819_REG_7E = 0x7EU, }; typedef enum BK4819_REGISTER_t BK4819_REGISTER_t; enum BK4819_GPIO_PIN_t { - BK4819_GPIO0_PIN28_RX_ENABLE = 0, - BK4819_GPIO1_PIN29_PA_ENABLE = 1, - BK4819_GPIO3_PIN31_UHF_LNA = 3, - BK4819_GPIO4_PIN32_VHF_LNA = 4, - BK4819_GPIO5_PIN1_RED = 5, - BK4819_GPIO6_PIN2_GREEN = 6, + BK4819_GPIO0_PIN28_RX_ENABLE = 0, + BK4819_GPIO1_PIN29_PA_ENABLE = 1, + BK4819_GPIO3_PIN31_UHF_LNA = 3, + BK4819_GPIO4_PIN32_VHF_LNA = 4, + BK4819_GPIO5_PIN1_RED = 5, + BK4819_GPIO6_PIN2_GREEN = 6, }; typedef enum BK4819_GPIO_PIN_t BK4819_GPIO_PIN_t; // REG 02 -#define BK4819_REG_02_SHIFT_FSK_TX_FINISHED 15 -#define BK4819_REG_02_SHIFT_FSK_FIFO_ALMOST_EMPTY 14 -#define BK4819_REG_02_SHIFT_FSK_RX_FINISHED 13 -#define BK4819_REG_02_SHIFT_FSK_FIFO_ALMOST_FULL 12 -#define BK4819_REG_02_SHIFT_DTMF_5TONE_FOUND 11 -#define BK4819_REG_02_SHIFT_CxCSS_TAIL 10 -#define BK4819_REG_02_SHIFT_CDCSS_FOUND 9 -#define BK4819_REG_02_SHIFT_CDCSS_LOST 8 -#define BK4819_REG_02_SHIFT_CTCSS_FOUND 7 -#define BK4819_REG_02_SHIFT_CTCSS_LOST 6 -#define BK4819_REG_02_SHIFT_VOX_FOUND 5 -#define BK4819_REG_02_SHIFT_VOX_LOST 4 -#define BK4819_REG_02_SHIFT_SQUELCH_FOUND 3 -#define BK4819_REG_02_SHIFT_SQUELCH_LOST 2 -#define BK4819_REG_02_SHIFT_FSK_RX_SYNC 1 - -#define BK4819_REG_02_MASK_FSK_TX_FINISHED (1U << BK4819_REG_02_SHIFT_FSK_TX) -#define BK4819_REG_02_MASK_FSK_FIFO_ALMOST_EMPTY (1U << BK4819_REG_02_SHIFT_FSK_FIFO_ALMOST_EMPTY) -#define BK4819_REG_02_MASK_FSK_RX_FINISHED (1U << BK4819_REG_02_SHIFT_FSK_RX_FINISHED) -#define BK4819_REG_02_MASK_FSK_FIFO_ALMOST_FULL (1U << BK4819_REG_02_SHIFT_FSK_FIFO_ALMOST_FULL) -#define BK4819_REG_02_MASK_DTMF_5TONE_FOUND (1U << BK4819_REG_02_SHIFT_DTMF_5TONE_FOUND) -#define BK4819_REG_02_MASK_CxCSS_TAIL (1U << BK4819_REG_02_SHIFT_CxCSS_TAIL) -#define BK4819_REG_02_MASK_CDCSS_FOUND (1U << BK4819_REG_02_SHIFT_CDCSS_FOUND) -#define BK4819_REG_02_MASK_CDCSS_LOST (1U << BK4819_REG_02_SHIFT_CDCSS_LOST) -#define BK4819_REG_02_MASK_CTCSS_FOUND (1U << BK4819_REG_02_SHIFT_CTCSS_FOUND) -#define BK4819_REG_02_MASK_CTCSS_LOST (1U << BK4819_REG_02_SHIFT_CTCSS_LOST) -#define BK4819_REG_02_MASK_VOX_FOUND (1U << BK4819_REG_02_SHIFT_VOX_FOUND) -#define BK4819_REG_02_MASK_VOX_LOST (1U << BK4819_REG_02_SHIFT_VOX_LOST) -#define BK4819_REG_02_MASK_SQUELCH_FOUND (1U << BK4819_REG_02_SHIFT_SQUELCH_FOUND) -#define BK4819_REG_02_MASK_SQUELCH_LOST (1U << BK4819_REG_02_SHIFT_SQUELCH_LOST) -#define BK4819_REG_02_MASK_FSK_RX_SYNC (1U << BK4819_REG_02_SHIFT_FSK_RX_SYNC) - -#define BK4819_REG_02_FSK_TX_FINISHED (1U << BK4819_REG_02_SHIFT_FSK_TX_FINISHED) -#define BK4819_REG_02_FSK_FIFO_ALMOST_EMPTY (1U << BK4819_REG_02_SHIFT_FSK_FIFO_ALMOST_EMPTY) -#define BK4819_REG_02_FSK_RX_FINISHED (1U << BK4819_REG_02_SHIFT_FSK_RX_FINISHED) -#define BK4819_REG_02_FSK_FIFO_ALMOST_FULL (1U << BK4819_REG_02_SHIFT_FSK_FIFO_ALMOST_FULL) -#define BK4819_REG_02_DTMF_5TONE_FOUND (1U << BK4819_REG_02_SHIFT_DTMF_5TONE_FOUND) -#define BK4819_REG_02_CxCSS_TAIL (1U << BK4819_REG_02_SHIFT_CxCSS_TAIL) -#define BK4819_REG_02_CDCSS_FOUND (1U << BK4819_REG_02_SHIFT_CDCSS_FOUND) -#define BK4819_REG_02_CDCSS_LOST (1U << BK4819_REG_02_SHIFT_CDCSS_LOST) -#define BK4819_REG_02_CTCSS_FOUND (1U << BK4819_REG_02_SHIFT_CTCSS_FOUND) -#define BK4819_REG_02_CTCSS_LOST (1U << BK4819_REG_02_SHIFT_CTCSS_LOST) -#define BK4819_REG_02_VOX_FOUND (1U << BK4819_REG_02_SHIFT_VOX_FOUND) -#define BK4819_REG_02_VOX_LOST (1U << BK4819_REG_02_SHIFT_VOX_LOST) -#define BK4819_REG_02_SQUELCH_FOUND (1U << BK4819_REG_02_SHIFT_SQUELCH_FOUND) -#define BK4819_REG_02_SQUELCH_LOST (1U << BK4819_REG_02_SHIFT_SQUELCH_LOST) -#define BK4819_REG_02_FSK_RX_SYNC (1U << BK4819_REG_02_SHIFT_FSK_RX_SYNC) +#define BK4819_REG_02_SHIFT_FSK_TX_FINISHED 15 +#define BK4819_REG_02_SHIFT_FSK_FIFO_ALMOST_EMPTY 14 +#define BK4819_REG_02_SHIFT_FSK_RX_FINISHED 13 +#define BK4819_REG_02_SHIFT_FSK_FIFO_ALMOST_FULL 12 +#define BK4819_REG_02_SHIFT_DTMF_5TONE_FOUND 11 +#define BK4819_REG_02_SHIFT_CxCSS_TAIL 10 +#define BK4819_REG_02_SHIFT_CDCSS_FOUND 9 +#define BK4819_REG_02_SHIFT_CDCSS_LOST 8 +#define BK4819_REG_02_SHIFT_CTCSS_FOUND 7 +#define BK4819_REG_02_SHIFT_CTCSS_LOST 6 +#define BK4819_REG_02_SHIFT_VOX_FOUND 5 +#define BK4819_REG_02_SHIFT_VOX_LOST 4 +#define BK4819_REG_02_SHIFT_SQUELCH_FOUND 3 +#define BK4819_REG_02_SHIFT_SQUELCH_LOST 2 +#define BK4819_REG_02_SHIFT_FSK_RX_SYNC 1 + +#define BK4819_REG_02_MASK_FSK_TX_FINISHED (1U << BK4819_REG_02_SHIFT_FSK_TX) +#define BK4819_REG_02_MASK_FSK_FIFO_ALMOST_EMPTY (1U << BK4819_REG_02_SHIFT_FSK_FIFO_ALMOST_EMPTY) +#define BK4819_REG_02_MASK_FSK_RX_FINISHED (1U << BK4819_REG_02_SHIFT_FSK_RX_FINISHED) +#define BK4819_REG_02_MASK_FSK_FIFO_ALMOST_FULL (1U << BK4819_REG_02_SHIFT_FSK_FIFO_ALMOST_FULL) +#define BK4819_REG_02_MASK_DTMF_5TONE_FOUND (1U << BK4819_REG_02_SHIFT_DTMF_5TONE_FOUND) +#define BK4819_REG_02_MASK_CxCSS_TAIL (1U << BK4819_REG_02_SHIFT_CxCSS_TAIL) +#define BK4819_REG_02_MASK_CDCSS_FOUND (1U << BK4819_REG_02_SHIFT_CDCSS_FOUND) +#define BK4819_REG_02_MASK_CDCSS_LOST (1U << BK4819_REG_02_SHIFT_CDCSS_LOST) +#define BK4819_REG_02_MASK_CTCSS_FOUND (1U << BK4819_REG_02_SHIFT_CTCSS_FOUND) +#define BK4819_REG_02_MASK_CTCSS_LOST (1U << BK4819_REG_02_SHIFT_CTCSS_LOST) +#define BK4819_REG_02_MASK_VOX_FOUND (1U << BK4819_REG_02_SHIFT_VOX_FOUND) +#define BK4819_REG_02_MASK_VOX_LOST (1U << BK4819_REG_02_SHIFT_VOX_LOST) +#define BK4819_REG_02_MASK_SQUELCH_FOUND (1U << BK4819_REG_02_SHIFT_SQUELCH_FOUND) +#define BK4819_REG_02_MASK_SQUELCH_LOST (1U << BK4819_REG_02_SHIFT_SQUELCH_LOST) +#define BK4819_REG_02_MASK_FSK_RX_SYNC (1U << BK4819_REG_02_SHIFT_FSK_RX_SYNC) + +#define BK4819_REG_02_FSK_TX_FINISHED (1U << BK4819_REG_02_SHIFT_FSK_TX_FINISHED) +#define BK4819_REG_02_FSK_FIFO_ALMOST_EMPTY (1U << BK4819_REG_02_SHIFT_FSK_FIFO_ALMOST_EMPTY) +#define BK4819_REG_02_FSK_RX_FINISHED (1U << BK4819_REG_02_SHIFT_FSK_RX_FINISHED) +#define BK4819_REG_02_FSK_FIFO_ALMOST_FULL (1U << BK4819_REG_02_SHIFT_FSK_FIFO_ALMOST_FULL) +#define BK4819_REG_02_DTMF_5TONE_FOUND (1U << BK4819_REG_02_SHIFT_DTMF_5TONE_FOUND) +#define BK4819_REG_02_CxCSS_TAIL (1U << BK4819_REG_02_SHIFT_CxCSS_TAIL) +#define BK4819_REG_02_CDCSS_FOUND (1U << BK4819_REG_02_SHIFT_CDCSS_FOUND) +#define BK4819_REG_02_CDCSS_LOST (1U << BK4819_REG_02_SHIFT_CDCSS_LOST) +#define BK4819_REG_02_CTCSS_FOUND (1U << BK4819_REG_02_SHIFT_CTCSS_FOUND) +#define BK4819_REG_02_CTCSS_LOST (1U << BK4819_REG_02_SHIFT_CTCSS_LOST) +#define BK4819_REG_02_VOX_FOUND (1U << BK4819_REG_02_SHIFT_VOX_FOUND) +#define BK4819_REG_02_VOX_LOST (1U << BK4819_REG_02_SHIFT_VOX_LOST) +#define BK4819_REG_02_SQUELCH_FOUND (1U << BK4819_REG_02_SHIFT_SQUELCH_FOUND) +#define BK4819_REG_02_SQUELCH_LOST (1U << BK4819_REG_02_SHIFT_SQUELCH_LOST) +#define BK4819_REG_02_FSK_RX_SYNC (1U << BK4819_REG_02_SHIFT_FSK_RX_SYNC) // REG 07 -#define BK4819_REG_07_SHIFT_FREQUENCY_MODE 13 -#define BK4819_REG_07_SHIFT_FREQUENCY 0 +#define BK4819_REG_07_SHIFT_FREQUENCY_MODE 13 +#define BK4819_REG_07_SHIFT_FREQUENCY 0 -#define BK4819_REG_07_MASK_FREQUENCY_MODE (0x0007U << BK4819_REG_07_SHIFT_FREQUENCY_MODE) -#define BK4819_REG_07_MASK_FREQUENCY (0x1FFFU << BK4819_REG_07_SHIFT_FREQUENCY) +#define BK4819_REG_07_MASK_FREQUENCY_MODE (0x0007U << BK4819_REG_07_SHIFT_FREQUENCY_MODE) +#define BK4819_REG_07_MASK_FREQUENCY (0x1FFFU << BK4819_REG_07_SHIFT_FREQUENCY) -#define BK4819_REG_07_MODE_CTC1 (0U << BK4819_REG_07_SHIFT_FREQUENCY_MODE) -#define BK4819_REG_07_MODE_CTC2 (1U << BK4819_REG_07_SHIFT_FREQUENCY_MODE) -#define BK4819_REG_07_MODE_CDCSS (2U << BK4819_REG_07_SHIFT_FREQUENCY_MODE) +#define BK4819_REG_07_MODE_CTC1 (0U << BK4819_REG_07_SHIFT_FREQUENCY_MODE) +#define BK4819_REG_07_MODE_CTC2 (1U << BK4819_REG_07_SHIFT_FREQUENCY_MODE) +#define BK4819_REG_07_MODE_CDCSS (2U << BK4819_REG_07_SHIFT_FREQUENCY_MODE) // REG 24 @@ -227,100 +227,100 @@ typedef enum BK4819_GPIO_PIN_t BK4819_GPIO_PIN_t; // REG 30 -#define BK4819_REG_30_SHIFT_ENABLE_VCO_CALIB 15 -#define BK4819_REG_30_SHIFT_ENABLE_UNKNOWN 14 -#define BK4819_REG_30_SHIFT_ENABLE_RX_LINK 10 -#define BK4819_REG_30_SHIFT_ENABLE_AF_DAC 9 -#define BK4819_REG_30_SHIFT_ENABLE_DISC_MODE 8 -#define BK4819_REG_30_SHIFT_ENABLE_PLL_VCO 4 -#define BK4819_REG_30_SHIFT_ENABLE_PA_GAIN 3 -#define BK4819_REG_30_SHIFT_ENABLE_MIC_ADC 2 -#define BK4819_REG_30_SHIFT_ENABLE_TX_DSP 1 -#define BK4819_REG_30_SHIFT_ENABLE_RX_DSP 0 - -#define BK4819_REG_30_MASK_ENABLE_VCO_CALIB (0x1U << BK4819_REG_30_SHIFT_ENABLE_VCO_CALIB) -#define BK4819_REG_30_MASK_ENABLE_UNKNOWN (0x1U << BK4819_REG_30_SHIFT_ENABLE_UNKNOWN) -#define BK4819_REG_30_MASK_ENABLE_RX_LINK (0xFU << BK4819_REG_30_SHIFT_ENABLE_RX_LINK) -#define BK4819_REG_30_MASK_ENABLE_AF_DAC (0x1U << BK4819_REG_30_SHIFT_ENABLE_AF_DAC) -#define BK4819_REG_30_MASK_ENABLE_DISC_MODE (0x1U << BK4819_REG_30_SHIFT_ENABLE_DISC_MODE) -#define BK4819_REG_30_MASK_ENABLE_PLL_VCO (0xFU << BK4819_REG_30_SHIFT_ENABLE_PLL_VCO) -#define BK4819_REG_30_MASK_ENABLE_PA_GAIN (0x1U << BK4819_REG_30_SHIFT_ENABLE_PA_GAIN) -#define BK4819_REG_30_MASK_ENABLE_MIC_ADC (0x1U << BK4819_REG_30_SHIFT_ENABLE_MIC_ADC) -#define BK4819_REG_30_MASK_ENABLE_TX_DSP (0x1U << BK4819_REG_30_SHIFT_ENABLE_TX_DSP) -#define BK4819_REG_30_MASK_ENABLE_RX_DSP (0x1U << BK4819_REG_30_SHIFT_ENABLE_RX_DSP) +#define BK4819_REG_30_SHIFT_ENABLE_VCO_CALIB 15 +#define BK4819_REG_30_SHIFT_ENABLE_UNKNOWN 14 +#define BK4819_REG_30_SHIFT_ENABLE_RX_LINK 10 +#define BK4819_REG_30_SHIFT_ENABLE_AF_DAC 9 +#define BK4819_REG_30_SHIFT_ENABLE_DISC_MODE 8 +#define BK4819_REG_30_SHIFT_ENABLE_PLL_VCO 4 +#define BK4819_REG_30_SHIFT_ENABLE_PA_GAIN 3 +#define BK4819_REG_30_SHIFT_ENABLE_MIC_ADC 2 +#define BK4819_REG_30_SHIFT_ENABLE_TX_DSP 1 +#define BK4819_REG_30_SHIFT_ENABLE_RX_DSP 0 + +#define BK4819_REG_30_MASK_ENABLE_VCO_CALIB (0x1U << BK4819_REG_30_SHIFT_ENABLE_VCO_CALIB) +#define BK4819_REG_30_MASK_ENABLE_UNKNOWN (0x1U << BK4819_REG_30_SHIFT_ENABLE_UNKNOWN) +#define BK4819_REG_30_MASK_ENABLE_RX_LINK (0xFU << BK4819_REG_30_SHIFT_ENABLE_RX_LINK) +#define BK4819_REG_30_MASK_ENABLE_AF_DAC (0x1U << BK4819_REG_30_SHIFT_ENABLE_AF_DAC) +#define BK4819_REG_30_MASK_ENABLE_DISC_MODE (0x1U << BK4819_REG_30_SHIFT_ENABLE_DISC_MODE) +#define BK4819_REG_30_MASK_ENABLE_PLL_VCO (0xFU << BK4819_REG_30_SHIFT_ENABLE_PLL_VCO) +#define BK4819_REG_30_MASK_ENABLE_PA_GAIN (0x1U << BK4819_REG_30_SHIFT_ENABLE_PA_GAIN) +#define BK4819_REG_30_MASK_ENABLE_MIC_ADC (0x1U << BK4819_REG_30_SHIFT_ENABLE_MIC_ADC) +#define BK4819_REG_30_MASK_ENABLE_TX_DSP (0x1U << BK4819_REG_30_SHIFT_ENABLE_TX_DSP) +#define BK4819_REG_30_MASK_ENABLE_RX_DSP (0x1U << BK4819_REG_30_SHIFT_ENABLE_RX_DSP) enum { - BK4819_REG_30_ENABLE_VCO_CALIB = (0x1U << BK4819_REG_30_SHIFT_ENABLE_VCO_CALIB), - BK4819_REG_30_DISABLE_VCO_CALIB = (0x0U << BK4819_REG_30_SHIFT_ENABLE_VCO_CALIB), - BK4819_REG_30_ENABLE_UNKNOWN = (0x1U << BK4819_REG_30_SHIFT_ENABLE_UNKNOWN), - BK4819_REG_30_DISABLE_UNKNOWN = (0x0U << BK4819_REG_30_SHIFT_ENABLE_UNKNOWN), - BK4819_REG_30_ENABLE_RX_LINK = (0xFU << BK4819_REG_30_SHIFT_ENABLE_RX_LINK), - BK4819_REG_30_DISABLE_RX_LINK = (0x0U << BK4819_REG_30_SHIFT_ENABLE_RX_LINK), - BK4819_REG_30_ENABLE_AF_DAC = (0x1U << BK4819_REG_30_SHIFT_ENABLE_AF_DAC), - BK4819_REG_30_DISABLE_AF_DAC = (0x0U << BK4819_REG_30_SHIFT_ENABLE_AF_DAC), - BK4819_REG_30_ENABLE_DISC_MODE = (0x1U << BK4819_REG_30_SHIFT_ENABLE_DISC_MODE), - BK4819_REG_30_DISABLE_DISC_MODE = (0x0U << BK4819_REG_30_SHIFT_ENABLE_DISC_MODE), - BK4819_REG_30_ENABLE_PLL_VCO = (0xFU << BK4819_REG_30_SHIFT_ENABLE_PLL_VCO), - BK4819_REG_30_DISABLE_PLL_VCO = (0x0U << BK4819_REG_30_SHIFT_ENABLE_PLL_VCO), - BK4819_REG_30_ENABLE_PA_GAIN = (0x1U << BK4819_REG_30_SHIFT_ENABLE_PA_GAIN), - BK4819_REG_30_DISABLE_PA_GAIN = (0x0U << BK4819_REG_30_SHIFT_ENABLE_PA_GAIN), - BK4819_REG_30_ENABLE_MIC_ADC = (0x1U << BK4819_REG_30_SHIFT_ENABLE_MIC_ADC), - BK4819_REG_30_DISABLE_MIC_ADC = (0x0U << BK4819_REG_30_SHIFT_ENABLE_MIC_ADC), - BK4819_REG_30_ENABLE_TX_DSP = (0x1U << BK4819_REG_30_SHIFT_ENABLE_TX_DSP), - BK4819_REG_30_DISABLE_TX_DSP = (0x0U << BK4819_REG_30_SHIFT_ENABLE_TX_DSP), - BK4819_REG_30_ENABLE_RX_DSP = (0x1U << BK4819_REG_30_SHIFT_ENABLE_RX_DSP), - BK4819_REG_30_DISABLE_RX_DSP = (0x0U << BK4819_REG_30_SHIFT_ENABLE_RX_DSP), + BK4819_REG_30_ENABLE_VCO_CALIB = (0x1U << BK4819_REG_30_SHIFT_ENABLE_VCO_CALIB), + BK4819_REG_30_DISABLE_VCO_CALIB = (0x0U << BK4819_REG_30_SHIFT_ENABLE_VCO_CALIB), + BK4819_REG_30_ENABLE_UNKNOWN = (0x1U << BK4819_REG_30_SHIFT_ENABLE_UNKNOWN), + BK4819_REG_30_DISABLE_UNKNOWN = (0x0U << BK4819_REG_30_SHIFT_ENABLE_UNKNOWN), + BK4819_REG_30_ENABLE_RX_LINK = (0xFU << BK4819_REG_30_SHIFT_ENABLE_RX_LINK), + BK4819_REG_30_DISABLE_RX_LINK = (0x0U << BK4819_REG_30_SHIFT_ENABLE_RX_LINK), + BK4819_REG_30_ENABLE_AF_DAC = (0x1U << BK4819_REG_30_SHIFT_ENABLE_AF_DAC), + BK4819_REG_30_DISABLE_AF_DAC = (0x0U << BK4819_REG_30_SHIFT_ENABLE_AF_DAC), + BK4819_REG_30_ENABLE_DISC_MODE = (0x1U << BK4819_REG_30_SHIFT_ENABLE_DISC_MODE), + BK4819_REG_30_DISABLE_DISC_MODE = (0x0U << BK4819_REG_30_SHIFT_ENABLE_DISC_MODE), + BK4819_REG_30_ENABLE_PLL_VCO = (0xFU << BK4819_REG_30_SHIFT_ENABLE_PLL_VCO), + BK4819_REG_30_DISABLE_PLL_VCO = (0x0U << BK4819_REG_30_SHIFT_ENABLE_PLL_VCO), + BK4819_REG_30_ENABLE_PA_GAIN = (0x1U << BK4819_REG_30_SHIFT_ENABLE_PA_GAIN), + BK4819_REG_30_DISABLE_PA_GAIN = (0x0U << BK4819_REG_30_SHIFT_ENABLE_PA_GAIN), + BK4819_REG_30_ENABLE_MIC_ADC = (0x1U << BK4819_REG_30_SHIFT_ENABLE_MIC_ADC), + BK4819_REG_30_DISABLE_MIC_ADC = (0x0U << BK4819_REG_30_SHIFT_ENABLE_MIC_ADC), + BK4819_REG_30_ENABLE_TX_DSP = (0x1U << BK4819_REG_30_SHIFT_ENABLE_TX_DSP), + BK4819_REG_30_DISABLE_TX_DSP = (0x0U << BK4819_REG_30_SHIFT_ENABLE_TX_DSP), + BK4819_REG_30_ENABLE_RX_DSP = (0x1U << BK4819_REG_30_SHIFT_ENABLE_RX_DSP), + BK4819_REG_30_DISABLE_RX_DSP = (0x0U << BK4819_REG_30_SHIFT_ENABLE_RX_DSP), }; // REG 3F -#define BK4819_REG_3F_SHIFT_FSK_TX_FINISHED 15 -#define BK4819_REG_3F_SHIFT_FSK_FIFO_ALMOST_EMPTY 14 -#define BK4819_REG_3F_SHIFT_FSK_RX_FINISHED 13 -#define BK4819_REG_3F_SHIFT_FSK_FIFO_ALMOST_FULL 12 -#define BK4819_REG_3F_SHIFT_DTMF_5TONE_FOUND 11 -#define BK4819_REG_3F_SHIFT_CxCSS_TAIL 10 -#define BK4819_REG_3F_SHIFT_CDCSS_FOUND 9 -#define BK4819_REG_3F_SHIFT_CDCSS_LOST 8 -#define BK4819_REG_3F_SHIFT_CTCSS_FOUND 7 -#define BK4819_REG_3F_SHIFT_CTCSS_LOST 6 -#define BK4819_REG_3F_SHIFT_VOX_FOUND 5 -#define BK4819_REG_3F_SHIFT_VOX_LOST 4 -#define BK4819_REG_3F_SHIFT_SQUELCH_FOUND 3 -#define BK4819_REG_3F_SHIFT_SQUELCH_LOST 2 -#define BK4819_REG_3F_SHIFT_FSK_RX_SYNC 1 - -#define BK4819_REG_3F_MASK_FSK_TX_FINISHED (1U << BK4819_REG_3F_SHIFT_FSK_TX) -#define BK4819_REG_3F_MASK_FSK_FIFO_ALMOST_EMPTY (1U << BK4819_REG_3F_SHIFT_FSK_FIFO_ALMOST_EMPTY) -#define BK4819_REG_3F_MASK_FSK_RX_FINISHED (1U << BK4819_REG_3F_SHIFT_FSK_RX_FINISHED) -#define BK4819_REG_3F_MASK_FSK_FIFO_ALMOST_FULL (1U << BK4819_REG_3F_SHIFT_FSK_FIFO_ALMOST_FULL) -#define BK4819_REG_3F_MASK_DTMF_5TONE_FOUND (1U << BK4819_REG_3F_SHIFT_DTMF_5TONE_FOUND) -#define BK4819_REG_3F_MASK_CxCSS_TAIL (1U << BK4819_REG_3F_SHIFT_CxCSS_TAIL) -#define BK4819_REG_3F_MASK_CDCSS_FOUND (1U << BK4819_REG_3F_SHIFT_CDCSS_FOUND) -#define BK4819_REG_3F_MASK_CDCSS_LOST (1U << BK4819_REG_3F_SHIFT_CDCSS_LOST) -#define BK4819_REG_3F_MASK_CTCSS_FOUND (1U << BK4819_REG_3F_SHIFT_CTCSS_FOUND) -#define BK4819_REG_3F_MASK_CTCSS_LOST (1U << BK4819_REG_3F_SHIFT_CTCSS_LOST) -#define BK4819_REG_3F_MASK_VOX_FOUND (1U << BK4819_REG_3F_SHIFT_VOX_FOUND) -#define BK4819_REG_3F_MASK_VOX_LOST (1U << BK4819_REG_3F_SHIFT_VOX_LOST) -#define BK4819_REG_3F_MASK_SQUELCH_FOUND (1U << BK4819_REG_3F_SHIFT_SQUELCH_FOUND) -#define BK4819_REG_3F_MASK_SQUELCH_LOST (1U << BK4819_REG_3F_SHIFT_SQUELCH_LOST) -#define BK4819_REG_3F_MASK_FSK_RX_SYNC (1U << BK4819_REG_3F_SHIFT_FSK_RX_SYNC) - -#define BK4819_REG_3F_FSK_TX_FINISHED (1U << BK4819_REG_3F_SHIFT_FSK_TX_FINISHED) -#define BK4819_REG_3F_FSK_FIFO_ALMOST_EMPTY (1U << BK4819_REG_3F_SHIFT_FSK_FIFO_ALMOST_EMPTY) -#define BK4819_REG_3F_FSK_RX_FINISHED (1U << BK4819_REG_3F_SHIFT_FSK_RX_FINISHED) -#define BK4819_REG_3F_FSK_FIFO_ALMOST_FULL (1U << BK4819_REG_3F_SHIFT_FSK_FIFO_ALMOST_FULL) -#define BK4819_REG_3F_DTMF_5TONE_FOUND (1U << BK4819_REG_3F_SHIFT_DTMF_5TONE_FOUND) -#define BK4819_REG_3F_CxCSS_TAIL (1U << BK4819_REG_3F_SHIFT_CxCSS_TAIL) -#define BK4819_REG_3F_CDCSS_FOUND (1U << BK4819_REG_3F_SHIFT_CDCSS_FOUND) -#define BK4819_REG_3F_CDCSS_LOST (1U << BK4819_REG_3F_SHIFT_CDCSS_LOST) -#define BK4819_REG_3F_CTCSS_FOUND (1U << BK4819_REG_3F_SHIFT_CTCSS_FOUND) -#define BK4819_REG_3F_CTCSS_LOST (1U << BK4819_REG_3F_SHIFT_CTCSS_LOST) -#define BK4819_REG_3F_VOX_FOUND (1U << BK4819_REG_3F_SHIFT_VOX_FOUND) -#define BK4819_REG_3F_VOX_LOST (1U << BK4819_REG_3F_SHIFT_VOX_LOST) -#define BK4819_REG_3F_SQUELCH_FOUND (1U << BK4819_REG_3F_SHIFT_SQUELCH_FOUND) -#define BK4819_REG_3F_SQUELCH_LOST (1U << BK4819_REG_3F_SHIFT_SQUELCH_LOST) -#define BK4819_REG_3F_FSK_RX_SYNC (1U << BK4819_REG_3F_SHIFT_FSK_RX_SYNC) +#define BK4819_REG_3F_SHIFT_FSK_TX_FINISHED 15 +#define BK4819_REG_3F_SHIFT_FSK_FIFO_ALMOST_EMPTY 14 +#define BK4819_REG_3F_SHIFT_FSK_RX_FINISHED 13 +#define BK4819_REG_3F_SHIFT_FSK_FIFO_ALMOST_FULL 12 +#define BK4819_REG_3F_SHIFT_DTMF_5TONE_FOUND 11 +#define BK4819_REG_3F_SHIFT_CxCSS_TAIL 10 +#define BK4819_REG_3F_SHIFT_CDCSS_FOUND 9 +#define BK4819_REG_3F_SHIFT_CDCSS_LOST 8 +#define BK4819_REG_3F_SHIFT_CTCSS_FOUND 7 +#define BK4819_REG_3F_SHIFT_CTCSS_LOST 6 +#define BK4819_REG_3F_SHIFT_VOX_FOUND 5 +#define BK4819_REG_3F_SHIFT_VOX_LOST 4 +#define BK4819_REG_3F_SHIFT_SQUELCH_FOUND 3 +#define BK4819_REG_3F_SHIFT_SQUELCH_LOST 2 +#define BK4819_REG_3F_SHIFT_FSK_RX_SYNC 1 + +#define BK4819_REG_3F_MASK_FSK_TX_FINISHED (1U << BK4819_REG_3F_SHIFT_FSK_TX) +#define BK4819_REG_3F_MASK_FSK_FIFO_ALMOST_EMPTY (1U << BK4819_REG_3F_SHIFT_FSK_FIFO_ALMOST_EMPTY) +#define BK4819_REG_3F_MASK_FSK_RX_FINISHED (1U << BK4819_REG_3F_SHIFT_FSK_RX_FINISHED) +#define BK4819_REG_3F_MASK_FSK_FIFO_ALMOST_FULL (1U << BK4819_REG_3F_SHIFT_FSK_FIFO_ALMOST_FULL) +#define BK4819_REG_3F_MASK_DTMF_5TONE_FOUND (1U << BK4819_REG_3F_SHIFT_DTMF_5TONE_FOUND) +#define BK4819_REG_3F_MASK_CxCSS_TAIL (1U << BK4819_REG_3F_SHIFT_CxCSS_TAIL) +#define BK4819_REG_3F_MASK_CDCSS_FOUND (1U << BK4819_REG_3F_SHIFT_CDCSS_FOUND) +#define BK4819_REG_3F_MASK_CDCSS_LOST (1U << BK4819_REG_3F_SHIFT_CDCSS_LOST) +#define BK4819_REG_3F_MASK_CTCSS_FOUND (1U << BK4819_REG_3F_SHIFT_CTCSS_FOUND) +#define BK4819_REG_3F_MASK_CTCSS_LOST (1U << BK4819_REG_3F_SHIFT_CTCSS_LOST) +#define BK4819_REG_3F_MASK_VOX_FOUND (1U << BK4819_REG_3F_SHIFT_VOX_FOUND) +#define BK4819_REG_3F_MASK_VOX_LOST (1U << BK4819_REG_3F_SHIFT_VOX_LOST) +#define BK4819_REG_3F_MASK_SQUELCH_FOUND (1U << BK4819_REG_3F_SHIFT_SQUELCH_FOUND) +#define BK4819_REG_3F_MASK_SQUELCH_LOST (1U << BK4819_REG_3F_SHIFT_SQUELCH_LOST) +#define BK4819_REG_3F_MASK_FSK_RX_SYNC (1U << BK4819_REG_3F_SHIFT_FSK_RX_SYNC) + +#define BK4819_REG_3F_FSK_TX_FINISHED (1U << BK4819_REG_3F_SHIFT_FSK_TX_FINISHED) +#define BK4819_REG_3F_FSK_FIFO_ALMOST_EMPTY (1U << BK4819_REG_3F_SHIFT_FSK_FIFO_ALMOST_EMPTY) +#define BK4819_REG_3F_FSK_RX_FINISHED (1U << BK4819_REG_3F_SHIFT_FSK_RX_FINISHED) +#define BK4819_REG_3F_FSK_FIFO_ALMOST_FULL (1U << BK4819_REG_3F_SHIFT_FSK_FIFO_ALMOST_FULL) +#define BK4819_REG_3F_DTMF_5TONE_FOUND (1U << BK4819_REG_3F_SHIFT_DTMF_5TONE_FOUND) +#define BK4819_REG_3F_CxCSS_TAIL (1U << BK4819_REG_3F_SHIFT_CxCSS_TAIL) +#define BK4819_REG_3F_CDCSS_FOUND (1U << BK4819_REG_3F_SHIFT_CDCSS_FOUND) +#define BK4819_REG_3F_CDCSS_LOST (1U << BK4819_REG_3F_SHIFT_CDCSS_LOST) +#define BK4819_REG_3F_CTCSS_FOUND (1U << BK4819_REG_3F_SHIFT_CTCSS_FOUND) +#define BK4819_REG_3F_CTCSS_LOST (1U << BK4819_REG_3F_SHIFT_CTCSS_LOST) +#define BK4819_REG_3F_VOX_FOUND (1U << BK4819_REG_3F_SHIFT_VOX_FOUND) +#define BK4819_REG_3F_VOX_LOST (1U << BK4819_REG_3F_SHIFT_VOX_LOST) +#define BK4819_REG_3F_SQUELCH_FOUND (1U << BK4819_REG_3F_SHIFT_SQUELCH_FOUND) +#define BK4819_REG_3F_SQUELCH_LOST (1U << BK4819_REG_3F_SHIFT_SQUELCH_LOST) +#define BK4819_REG_3F_FSK_RX_SYNC (1U << BK4819_REG_3F_SHIFT_FSK_RX_SYNC) // REG 51 @@ -345,46 +345,46 @@ enum { #define BK4819_REG_51_MASK_CxCSS_TX_GAIN1 (0x7FU << BK4819_REG_51_SHIFT_CxCSS_TX_GAIN1) enum { - BK4819_REG_51_ENABLE_CxCSS = (1U << BK4819_REG_51_SHIFT_ENABLE_CxCSS), - BK4819_REG_51_DISABLE_CxCSS = (0U << BK4819_REG_51_SHIFT_ENABLE_CxCSS), + BK4819_REG_51_ENABLE_CxCSS = (1U << BK4819_REG_51_SHIFT_ENABLE_CxCSS), + BK4819_REG_51_DISABLE_CxCSS = (0U << BK4819_REG_51_SHIFT_ENABLE_CxCSS), - BK4819_REG_51_GPIO6_PIN2_INPUT = (1U << BK4819_REG_51_SHIFT_GPIO6_PIN2_INPUT), - BK4819_REG_51_GPIO6_PIN2_NORMAL = (0U << BK4819_REG_51_SHIFT_GPIO6_PIN2_INPUT), + BK4819_REG_51_GPIO6_PIN2_INPUT = (1U << BK4819_REG_51_SHIFT_GPIO6_PIN2_INPUT), + BK4819_REG_51_GPIO6_PIN2_NORMAL = (0U << BK4819_REG_51_SHIFT_GPIO6_PIN2_INPUT), - BK4819_REG_51_TX_CDCSS_NEGATIVE = (1U << BK4819_REG_51_SHIFT_TX_CDCSS_POLARITY), - BK4819_REG_51_TX_CDCSS_POSITIVE = (0U << BK4819_REG_51_SHIFT_TX_CDCSS_POLARITY), + BK4819_REG_51_TX_CDCSS_NEGATIVE = (1U << BK4819_REG_51_SHIFT_TX_CDCSS_POLARITY), + BK4819_REG_51_TX_CDCSS_POSITIVE = (0U << BK4819_REG_51_SHIFT_TX_CDCSS_POLARITY), - BK4819_REG_51_MODE_CTCSS = (1U << BK4819_REG_51_SHIFT_CxCSS_MODE), - BK4819_REG_51_MODE_CDCSS = (0U << BK4819_REG_51_SHIFT_CxCSS_MODE), + BK4819_REG_51_MODE_CTCSS = (1U << BK4819_REG_51_SHIFT_CxCSS_MODE), + BK4819_REG_51_MODE_CDCSS = (0U << BK4819_REG_51_SHIFT_CxCSS_MODE), - BK4819_REG_51_CDCSS_24_BIT = (1U << BK4819_REG_51_SHIFT_CDCSS_BIT_WIDTH), - BK4819_REG_51_CDCSS_23_BIT = (0U << BK4819_REG_51_SHIFT_CDCSS_BIT_WIDTH), + BK4819_REG_51_CDCSS_24_BIT = (1U << BK4819_REG_51_SHIFT_CDCSS_BIT_WIDTH), + BK4819_REG_51_CDCSS_23_BIT = (0U << BK4819_REG_51_SHIFT_CDCSS_BIT_WIDTH), - BK4819_REG_51_1050HZ_DETECTION = (1U << BK4819_REG_51_SHIFT_1050HZ_DETECTION), - BK4819_REG_51_1050HZ_NO_DETECTION = (0U << BK4819_REG_51_SHIFT_1050HZ_DETECTION), + BK4819_REG_51_1050HZ_DETECTION = (1U << BK4819_REG_51_SHIFT_1050HZ_DETECTION), + BK4819_REG_51_1050HZ_NO_DETECTION = (0U << BK4819_REG_51_SHIFT_1050HZ_DETECTION), - BK4819_REG_51_AUTO_CDCSS_BW_DISABLE = (1U << BK4819_REG_51_SHIFT_AUTO_CDCSS_BW), - BK4819_REG_51_AUTO_CDCSS_BW_ENABLE = (0U << BK4819_REG_51_SHIFT_AUTO_CDCSS_BW), + BK4819_REG_51_AUTO_CDCSS_BW_DISABLE = (1U << BK4819_REG_51_SHIFT_AUTO_CDCSS_BW), + BK4819_REG_51_AUTO_CDCSS_BW_ENABLE = (0U << BK4819_REG_51_SHIFT_AUTO_CDCSS_BW), - BK4819_REG_51_AUTO_CTCSS_BW_DISABLE = (1U << BK4819_REG_51_SHIFT_AUTO_CTCSS_BW), - BK4819_REG_51_AUTO_CTCSS_BW_ENABLE = (0U << BK4819_REG_51_SHIFT_AUTO_CTCSS_BW), + BK4819_REG_51_AUTO_CTCSS_BW_DISABLE = (1U << BK4819_REG_51_SHIFT_AUTO_CTCSS_BW), + BK4819_REG_51_AUTO_CTCSS_BW_ENABLE = (0U << BK4819_REG_51_SHIFT_AUTO_CTCSS_BW), }; // REG 70 -#define BK4819_REG_70_SHIFT_ENABLE_TONE1 15 -#define BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN 8 -#define BK4819_REG_70_SHIFT_ENABLE_TONE2 7 -#define BK4819_REG_70_SHIFT_TONE2_TUNING_GAIN 0 +#define BK4819_REG_70_SHIFT_ENABLE_TONE1 15 +#define BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN 8 +#define BK4819_REG_70_SHIFT_ENABLE_TONE2 7 +#define BK4819_REG_70_SHIFT_TONE2_TUNING_GAIN 0 -#define BK4819_REG_70_MASK_ENABLE_TONE1 (0x01U << BK4819_REG_70_SHIFT_ENABLE_TONE1) -#define BK4819_REG_70_MASK_TONE1_TUNING_GAIN (0x7FU << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN) -#define BK4819_REG_70_MASK_ENABLE_TONE2 (0x01U << BK4819_REG_70_SHIFT_ENABLE_TONE2) -#define BK4819_REG_70_MASK_TONE2_TUNING_GAIN (0x7FU << BK4819_REG_70_SHIFT_TONE2_TUNING_GAIN) +#define BK4819_REG_70_MASK_ENABLE_TONE1 (0x01U << BK4819_REG_70_SHIFT_ENABLE_TONE1) +#define BK4819_REG_70_MASK_TONE1_TUNING_GAIN (0x7FU << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN) +#define BK4819_REG_70_MASK_ENABLE_TONE2 (0x01U << BK4819_REG_70_SHIFT_ENABLE_TONE2) +#define BK4819_REG_70_MASK_TONE2_TUNING_GAIN (0x7FU << BK4819_REG_70_SHIFT_TONE2_TUNING_GAIN) enum { - BK4819_REG_70_ENABLE_TONE1 = (1U << BK4819_REG_70_SHIFT_ENABLE_TONE1), - BK4819_REG_70_ENABLE_TONE2 = (1U << BK4819_REG_70_SHIFT_ENABLE_TONE2), + BK4819_REG_70_ENABLE_TONE1 = (1U << BK4819_REG_70_SHIFT_ENABLE_TONE1), + BK4819_REG_70_ENABLE_TONE2 = (1U << BK4819_REG_70_SHIFT_ENABLE_TONE2), }; #endif diff --git a/driver/bk4819.c b/driver/bk4819.c index d6390a15b..850193921 100644 --- a/driver/bk4819.c +++ b/driver/bk4819.c @@ -30,7 +30,7 @@ #ifndef ARRAY_SIZE - #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) + #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) #endif static const uint16_t FSK_RogerTable[7] = {0xF1A2, 0x7446, 0x61A4, 0x6544, 0x4E8A, 0xE044, 0xEA84}; @@ -44,743 +44,743 @@ bool gRxIdleMode; __inline uint16_t scale_freq(const uint16_t freq) { -// return (((uint32_t)freq * 1032444u) + 50000u) / 100000u; // with rounding - return (((uint32_t)freq * 1353245u) + (1u << 16)) >> 17; // with rounding +// return (((uint32_t)freq * 1032444u) + 50000u) / 100000u; // with rounding + return (((uint32_t)freq * 1353245u) + (1u << 16)) >> 17; // with rounding } void BK4819_Init(void) { - GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCN); - GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); - GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA); - - BK4819_WriteRegister(BK4819_REG_00, 0x8000); - BK4819_WriteRegister(BK4819_REG_00, 0x0000); - - BK4819_WriteRegister(BK4819_REG_37, 0x1D0F); - BK4819_WriteRegister(BK4819_REG_36, 0x0022); - - BK4819_InitAGC(false); - BK4819_SetAGC(true); - - BK4819_WriteRegister(BK4819_REG_19, 0b0001000001000001); // <15> MIC AGC 1 = disable 0 = enable - - BK4819_WriteRegister(BK4819_REG_7D, 0xE940); - - // REG_48 .. RX AF level - // - // <15:12> 11 ??? 0 to 15 - // - // <11:10> 0 AF Rx Gain-1 - // 0 = 0dB - // 1 = -6dB - // 2 = -12dB - // 3 = -18dB - // - // <9:4> 60 AF Rx Gain-2 -26dB ~ 5.5dB 0.5dB/step - // 63 = max - // 0 = mute - // - // <3:0> 15 AF DAC Gain (after Gain-1 and Gain-2) approx 2dB/step - // 15 = max - // 0 = min - // - BK4819_WriteRegister(BK4819_REG_48, // 0xB3A8); // 1011 00 111010 1000 - (11u << 12) | // ??? 0..15 - ( 0u << 10) | // AF Rx Gain-1 - (58u << 4) | // AF Rx Gain-2 - ( 8u << 0)); // AF DAC Gain (after Gain-1 and Gain-2) + GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCN); + GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); + GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA); + + BK4819_WriteRegister(BK4819_REG_00, 0x8000); + BK4819_WriteRegister(BK4819_REG_00, 0x0000); + + BK4819_WriteRegister(BK4819_REG_37, 0x1D0F); + BK4819_WriteRegister(BK4819_REG_36, 0x0022); + + BK4819_InitAGC(false); + BK4819_SetAGC(true); + + BK4819_WriteRegister(BK4819_REG_19, 0b0001000001000001); // <15> MIC AGC 1 = disable 0 = enable + + BK4819_WriteRegister(BK4819_REG_7D, 0xE940); + + // REG_48 .. RX AF level + // + // <15:12> 11 ??? 0 to 15 + // + // <11:10> 0 AF Rx Gain-1 + // 0 = 0dB + // 1 = -6dB + // 2 = -12dB + // 3 = -18dB + // + // <9:4> 60 AF Rx Gain-2 -26dB ~ 5.5dB 0.5dB/step + // 63 = max + // 0 = mute + // + // <3:0> 15 AF DAC Gain (after Gain-1 and Gain-2) approx 2dB/step + // 15 = max + // 0 = min + // + BK4819_WriteRegister(BK4819_REG_48, // 0xB3A8); // 1011 00 111010 1000 + (11u << 12) | // ??? 0..15 + ( 0u << 10) | // AF Rx Gain-1 + (58u << 4) | // AF Rx Gain-2 + ( 8u << 0)); // AF DAC Gain (after Gain-1 and Gain-2) #if 1 - const uint8_t dtmf_coeffs[] = {111, 107, 103, 98, 80, 71, 58, 44, 65, 55, 37, 23, 228, 203, 181, 159}; - for (unsigned int i = 0; i < ARRAY_SIZE(dtmf_coeffs); i++) - BK4819_WriteRegister(BK4819_REG_09, (i << 12) | dtmf_coeffs[i]); + const uint8_t dtmf_coeffs[] = {111, 107, 103, 98, 80, 71, 58, 44, 65, 55, 37, 23, 228, 203, 181, 159}; + for (unsigned int i = 0; i < ARRAY_SIZE(dtmf_coeffs); i++) + BK4819_WriteRegister(BK4819_REG_09, (i << 12) | dtmf_coeffs[i]); #else - // original code - BK4819_WriteRegister(BK4819_REG_09, 0x006F); // 6F - BK4819_WriteRegister(BK4819_REG_09, 0x106B); // 6B - BK4819_WriteRegister(BK4819_REG_09, 0x2067); // 67 - BK4819_WriteRegister(BK4819_REG_09, 0x3062); // 62 - BK4819_WriteRegister(BK4819_REG_09, 0x4050); // 50 - BK4819_WriteRegister(BK4819_REG_09, 0x5047); // 47 - BK4819_WriteRegister(BK4819_REG_09, 0x603A); // 3A - BK4819_WriteRegister(BK4819_REG_09, 0x702C); // 2C - BK4819_WriteRegister(BK4819_REG_09, 0x8041); // 41 - BK4819_WriteRegister(BK4819_REG_09, 0x9037); // 37 - BK4819_WriteRegister(BK4819_REG_09, 0xA025); // 25 - BK4819_WriteRegister(BK4819_REG_09, 0xB017); // 17 - BK4819_WriteRegister(BK4819_REG_09, 0xC0E4); // E4 - BK4819_WriteRegister(BK4819_REG_09, 0xD0CB); // CB - BK4819_WriteRegister(BK4819_REG_09, 0xE0B5); // B5 - BK4819_WriteRegister(BK4819_REG_09, 0xF09F); // 9F + // original code + BK4819_WriteRegister(BK4819_REG_09, 0x006F); // 6F + BK4819_WriteRegister(BK4819_REG_09, 0x106B); // 6B + BK4819_WriteRegister(BK4819_REG_09, 0x2067); // 67 + BK4819_WriteRegister(BK4819_REG_09, 0x3062); // 62 + BK4819_WriteRegister(BK4819_REG_09, 0x4050); // 50 + BK4819_WriteRegister(BK4819_REG_09, 0x5047); // 47 + BK4819_WriteRegister(BK4819_REG_09, 0x603A); // 3A + BK4819_WriteRegister(BK4819_REG_09, 0x702C); // 2C + BK4819_WriteRegister(BK4819_REG_09, 0x8041); // 41 + BK4819_WriteRegister(BK4819_REG_09, 0x9037); // 37 + BK4819_WriteRegister(BK4819_REG_09, 0xA025); // 25 + BK4819_WriteRegister(BK4819_REG_09, 0xB017); // 17 + BK4819_WriteRegister(BK4819_REG_09, 0xC0E4); // E4 + BK4819_WriteRegister(BK4819_REG_09, 0xD0CB); // CB + BK4819_WriteRegister(BK4819_REG_09, 0xE0B5); // B5 + BK4819_WriteRegister(BK4819_REG_09, 0xF09F); // 9F #endif - BK4819_WriteRegister(BK4819_REG_1F, 0x5454); - BK4819_WriteRegister(BK4819_REG_3E, 0xA037); + BK4819_WriteRegister(BK4819_REG_1F, 0x5454); + BK4819_WriteRegister(BK4819_REG_3E, 0xA037); - gBK4819_GpioOutState = 0x9000; + gBK4819_GpioOutState = 0x9000; - BK4819_WriteRegister(BK4819_REG_33, 0x9000); - BK4819_WriteRegister(BK4819_REG_3F, 0); + BK4819_WriteRegister(BK4819_REG_33, 0x9000); + BK4819_WriteRegister(BK4819_REG_3F, 0); } static uint16_t BK4819_ReadU16(void) { - unsigned int i; - uint16_t Value; + unsigned int i; + uint16_t Value; - PORTCON_PORTC_IE = (PORTCON_PORTC_IE & ~PORTCON_PORTC_IE_C2_MASK) | PORTCON_PORTC_IE_C2_BITS_ENABLE; - GPIOC->DIR = (GPIOC->DIR & ~GPIO_DIR_2_MASK) | GPIO_DIR_2_BITS_INPUT; - SYSTICK_DelayUs(1); - Value = 0; - for (i = 0; i < 16; i++) - { - Value <<= 1; - Value |= GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA); - GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); - SYSTICK_DelayUs(1); - GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); - SYSTICK_DelayUs(1); - } - PORTCON_PORTC_IE = (PORTCON_PORTC_IE & ~PORTCON_PORTC_IE_C2_MASK) | PORTCON_PORTC_IE_C2_BITS_DISABLE; - GPIOC->DIR = (GPIOC->DIR & ~GPIO_DIR_2_MASK) | GPIO_DIR_2_BITS_OUTPUT; + PORTCON_PORTC_IE = (PORTCON_PORTC_IE & ~PORTCON_PORTC_IE_C2_MASK) | PORTCON_PORTC_IE_C2_BITS_ENABLE; + GPIOC->DIR = (GPIOC->DIR & ~GPIO_DIR_2_MASK) | GPIO_DIR_2_BITS_INPUT; + SYSTICK_DelayUs(1); + Value = 0; + for (i = 0; i < 16; i++) + { + Value <<= 1; + Value |= GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA); + GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); + SYSTICK_DelayUs(1); + GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); + SYSTICK_DelayUs(1); + } + PORTCON_PORTC_IE = (PORTCON_PORTC_IE & ~PORTCON_PORTC_IE_C2_MASK) | PORTCON_PORTC_IE_C2_BITS_DISABLE; + GPIOC->DIR = (GPIOC->DIR & ~GPIO_DIR_2_MASK) | GPIO_DIR_2_BITS_OUTPUT; - return Value; + return Value; } uint16_t BK4819_ReadRegister(BK4819_REGISTER_t Register) { - uint16_t Value; + uint16_t Value; - GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCN); - GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); + GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCN); + GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); - SYSTICK_DelayUs(1); + SYSTICK_DelayUs(1); - GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCN); - BK4819_WriteU8(Register | 0x80); - Value = BK4819_ReadU16(); - GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCN); + GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCN); + BK4819_WriteU8(Register | 0x80); + Value = BK4819_ReadU16(); + GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCN); - SYSTICK_DelayUs(1); + SYSTICK_DelayUs(1); - GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); - GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA); + GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); + GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA); - return Value; + return Value; } void BK4819_WriteRegister(BK4819_REGISTER_t Register, uint16_t Data) { - GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCN); - GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); + GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCN); + GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); - SYSTICK_DelayUs(1); + SYSTICK_DelayUs(1); - GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCN); - BK4819_WriteU8(Register); + GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCN); + BK4819_WriteU8(Register); - SYSTICK_DelayUs(1); + SYSTICK_DelayUs(1); - BK4819_WriteU16(Data); + BK4819_WriteU16(Data); - SYSTICK_DelayUs(1); + SYSTICK_DelayUs(1); - GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCN); + GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCN); - SYSTICK_DelayUs(1); + SYSTICK_DelayUs(1); - GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); - GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA); + GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); + GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA); } void BK4819_WriteU8(uint8_t Data) { - unsigned int i; + unsigned int i; - GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); - for (i = 0; i < 8; i++) - { - if ((Data & 0x80) == 0) - GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA); - else - GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA); + GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); + for (i = 0; i < 8; i++) + { + if ((Data & 0x80) == 0) + GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA); + else + GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA); - SYSTICK_DelayUs(1); - GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); - SYSTICK_DelayUs(1); + SYSTICK_DelayUs(1); + GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); + SYSTICK_DelayUs(1); - Data <<= 1; + Data <<= 1; - GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); - SYSTICK_DelayUs(1); - } + GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); + SYSTICK_DelayUs(1); + } } void BK4819_WriteU16(uint16_t Data) { - unsigned int i; + unsigned int i; - GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); - for (i = 0; i < 16; i++) - { - if ((Data & 0x8000) == 0) - GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA); - else - GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA); + GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); + for (i = 0; i < 16; i++) + { + if ((Data & 0x8000) == 0) + GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA); + else + GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SDA); - SYSTICK_DelayUs(1); - GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); + SYSTICK_DelayUs(1); + GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); - Data <<= 1; + Data <<= 1; - SYSTICK_DelayUs(1); - GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); - SYSTICK_DelayUs(1); - } + SYSTICK_DelayUs(1); + GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_BK4819_SCL); + SYSTICK_DelayUs(1); + } } void BK4819_SetAGC(bool enable) { - uint16_t regVal = BK4819_ReadRegister(BK4819_REG_7E); - if(!(regVal & (1 << 15)) == enable) - return; + uint16_t regVal = BK4819_ReadRegister(BK4819_REG_7E); + if(!(regVal & (1 << 15)) == enable) + return; - BK4819_WriteRegister(BK4819_REG_7E, (regVal & ~(1 << 15) & ~(0b111 << 12)) - | (!enable << 15) // 0 AGC fix mode - | (3u << 12) // 3 AGC fix index - ); + BK4819_WriteRegister(BK4819_REG_7E, (regVal & ~(1 << 15) & ~(0b111 << 12)) + | (!enable << 15) // 0 AGC fix mode + | (3u << 12) // 3 AGC fix index + ); - // if(enable) { - // BK4819_WriteRegister(BK4819_REG_7B, 0x8420); - // } - // else { - // BK4819_WriteRegister(BK4819_REG_7B, 0x318C); + // if(enable) { + // BK4819_WriteRegister(BK4819_REG_7B, 0x8420); + // } + // else { + // BK4819_WriteRegister(BK4819_REG_7B, 0x318C); - // BK4819_WriteRegister(BK4819_REG_7C, 0x595E); - // BK4819_WriteRegister(BK4819_REG_20, 0x8DEF); + // BK4819_WriteRegister(BK4819_REG_7C, 0x595E); + // BK4819_WriteRegister(BK4819_REG_20, 0x8DEF); - // for (uint8_t i = 0; i < 8; i++) { - // //BK4819_WriteRegister(BK4819_REG_06, ((i << 13) | 0x2500u) + 0x036u); - // BK4819_WriteRegister(BK4819_REG_06, (i & 7) << 13 | 0x4A << 7 | 0x36); - // } - // } + // for (uint8_t i = 0; i < 8; i++) { + // //BK4819_WriteRegister(BK4819_REG_06, ((i << 13) | 0x2500u) + 0x036u); + // BK4819_WriteRegister(BK4819_REG_06, (i & 7) << 13 | 0x4A << 7 | 0x36); + // } + // } } void BK4819_InitAGC(bool amModulation) { - // REG_10, REG_11, REG_12 REG_13, REG_14 - // - // Rx AGC Gain Table[]. (Index Max->Min is 3,2,1,0,-1) - // - // <15:10> ??? - // - // <9:8> LNA Gain Short - // 3 = 0dB <<< 1o11 read from spectrum reference manual - // 2 = -24dB -19 -11 - // 1 = -30dB -24 -16 - // 0 = -33dB -28 -19 - // - // <7:5> LNA Gain - // 7 = 0dB - // 6 = -2dB - // 5 = -4dB - // 4 = -6dB - // 3 = -9dB - // 2 = -14dB <<< - // 1 = -19dB - // 0 = -24dB - // - // <4:3> MIXER Gain - // 3 = 0dB <<< - // 2 = -3dB - // 1 = -6dB - // 0 = -8dB - // - // <2:0> PGA Gain - // 7 = 0dB - // 6 = -3dB <<< - // 5 = -6dB - // 4 = -9dB - // 3 = -15dB - // 2 = -21dB - // 1 = -27dB - // 0 = -33dB - // - - BK4819_WriteRegister(BK4819_REG_13, 0x03BE); // 0x03BE / 000000 11 101 11 110 / -7dB - BK4819_WriteRegister(BK4819_REG_12, 0x037B); // 0x037B / 000000 11 011 11 011 / -24dB - BK4819_WriteRegister(BK4819_REG_11, 0x027B); // 0x027B / 000000 10 011 11 011 / -43dB - BK4819_WriteRegister(BK4819_REG_10, 0x007A); // 0x007A / 000000 00 011 11 010 / -58dB - if(amModulation) { - BK4819_WriteRegister(BK4819_REG_14, 0x0000); - BK4819_WriteRegister(BK4819_REG_49, (0 << 14) | (50 << 7) | (32 << 0)); - } - else{ - BK4819_WriteRegister(BK4819_REG_14, 0x0019); // 0x0019 / 000000 00 000 11 001 / -79dB - BK4819_WriteRegister(BK4819_REG_49, (0 << 14) | (84 << 7) | (56 << 0)); //0x2A38 / 00 1010100 0111000 / 84, 56 - } - - BK4819_WriteRegister(BK4819_REG_7B, 0x8420); + // REG_10, REG_11, REG_12 REG_13, REG_14 + // + // Rx AGC Gain Table[]. (Index Max->Min is 3,2,1,0,-1) + // + // <15:10> ??? + // + // <9:8> LNA Gain Short + // 3 = 0dB <<< 1o11 read from spectrum reference manual + // 2 = -24dB -19 -11 + // 1 = -30dB -24 -16 + // 0 = -33dB -28 -19 + // + // <7:5> LNA Gain + // 7 = 0dB + // 6 = -2dB + // 5 = -4dB + // 4 = -6dB + // 3 = -9dB + // 2 = -14dB <<< + // 1 = -19dB + // 0 = -24dB + // + // <4:3> MIXER Gain + // 3 = 0dB <<< + // 2 = -3dB + // 1 = -6dB + // 0 = -8dB + // + // <2:0> PGA Gain + // 7 = 0dB + // 6 = -3dB <<< + // 5 = -6dB + // 4 = -9dB + // 3 = -15dB + // 2 = -21dB + // 1 = -27dB + // 0 = -33dB + // + + BK4819_WriteRegister(BK4819_REG_13, 0x03BE); // 0x03BE / 000000 11 101 11 110 / -7dB + BK4819_WriteRegister(BK4819_REG_12, 0x037B); // 0x037B / 000000 11 011 11 011 / -24dB + BK4819_WriteRegister(BK4819_REG_11, 0x027B); // 0x027B / 000000 10 011 11 011 / -43dB + BK4819_WriteRegister(BK4819_REG_10, 0x007A); // 0x007A / 000000 00 011 11 010 / -58dB + if(amModulation) { + BK4819_WriteRegister(BK4819_REG_14, 0x0000); + BK4819_WriteRegister(BK4819_REG_49, (0 << 14) | (50 << 7) | (32 << 0)); + } + else{ + BK4819_WriteRegister(BK4819_REG_14, 0x0019); // 0x0019 / 000000 00 000 11 001 / -79dB + BK4819_WriteRegister(BK4819_REG_49, (0 << 14) | (84 << 7) | (56 << 0)); //0x2A38 / 00 1010100 0111000 / 84, 56 + } + + BK4819_WriteRegister(BK4819_REG_7B, 0x8420); } int8_t BK4819_GetRxGain_dB(void) { - union { - struct { - uint16_t pga:3; - uint16_t mixer:2; - uint16_t lna:3; - uint16_t lnaS:2; - }; - uint16_t __raw; - } agcGainReg; - - union { - struct { - uint16_t _ : 5; - uint16_t agcSigStrength : 7; - int16_t gainIdx : 3; - uint16_t agcEnab : 1; - }; - uint16_t __raw; - } reg7e; - - reg7e.__raw = BK4819_ReadRegister(BK4819_REG_7E); - uint8_t gainAddr = reg7e.gainIdx < 0 ? BK4819_REG_14 : BK4819_REG_10 + reg7e.gainIdx; - agcGainReg.__raw = BK4819_ReadRegister(gainAddr); - int8_t lnaShortTab[] = {-28, -24, -19, 0}; - int8_t lnaTab[] = {-24, -19, -14, -9, -6, -4, -2, 0}; - int8_t mixerTab[] = {-8, -6, -3, 0}; - int8_t pgaTab[] = {-33, -27, -21, -15, -9, -6, -3, 0}; - return lnaShortTab[agcGainReg.lnaS] + lnaTab[agcGainReg.lna] + mixerTab[agcGainReg.mixer] + pgaTab[agcGainReg.pga]; + union { + struct { + uint16_t pga:3; + uint16_t mixer:2; + uint16_t lna:3; + uint16_t lnaS:2; + }; + uint16_t __raw; + } agcGainReg; + + union { + struct { + uint16_t _ : 5; + uint16_t agcSigStrength : 7; + int16_t gainIdx : 3; + uint16_t agcEnab : 1; + }; + uint16_t __raw; + } reg7e; + + reg7e.__raw = BK4819_ReadRegister(BK4819_REG_7E); + uint8_t gainAddr = reg7e.gainIdx < 0 ? BK4819_REG_14 : BK4819_REG_10 + reg7e.gainIdx; + agcGainReg.__raw = BK4819_ReadRegister(gainAddr); + int8_t lnaShortTab[] = {-28, -24, -19, 0}; + int8_t lnaTab[] = {-24, -19, -14, -9, -6, -4, -2, 0}; + int8_t mixerTab[] = {-8, -6, -3, 0}; + int8_t pgaTab[] = {-33, -27, -21, -15, -9, -6, -3, 0}; + return lnaShortTab[agcGainReg.lnaS] + lnaTab[agcGainReg.lna] + mixerTab[agcGainReg.mixer] + pgaTab[agcGainReg.pga]; } int16_t BK4819_GetRSSI_dBm(void) { - uint16_t rssi = BK4819_GetRSSI(); - return (rssi / 2) - 160;// - BK4819_GetRxGain_dB(); + uint16_t rssi = BK4819_GetRSSI(); + return (rssi / 2) - 160;// - BK4819_GetRxGain_dB(); } void BK4819_ToggleGpioOut(BK4819_GPIO_PIN_t Pin, bool bSet) { - if (bSet) - gBK4819_GpioOutState |= (0x40u >> Pin); - else - gBK4819_GpioOutState &= ~(0x40u >> Pin); + if (bSet) + gBK4819_GpioOutState |= (0x40u >> Pin); + else + gBK4819_GpioOutState &= ~(0x40u >> Pin); - BK4819_WriteRegister(BK4819_REG_33, gBK4819_GpioOutState); + BK4819_WriteRegister(BK4819_REG_33, gBK4819_GpioOutState); } void BK4819_SetCDCSSCodeWord(uint32_t CodeWord) { - // REG_51 - // - // <15> 0 - // 1 = Enable TxCTCSS/CDCSS - // 0 = Disable - // - // <14> 0 - // 1 = GPIO0Input for CDCSS - // 0 = Normal Mode (for BK4819 v3) - // - // <13> 0 - // 1 = Transmit negative CDCSS code - // 0 = Transmit positive CDCSS code - // - // <12> 0 CTCSS/CDCSS mode selection - // 1 = CTCSS - // 0 = CDCSS - // - // <11> 0 CDCSS 24/23bit selection - // 1 = 24bit - // 0 = 23bit - // - // <10> 0 1050HzDetectionMode - // 1 = 1050/4 Detect Enable, CTC1 should be set to 1050/4 Hz - // - // <9> 0 Auto CDCSS Bw Mode - // 1 = Disable - // 0 = Enable - // - // <8> 0 Auto CTCSS Bw Mode - // 0 = Enable - // 1 = Disable - // - // <6:0> 0 CTCSS/CDCSS Tx Gain1 Tuning - // 0 = min - // 127 = max - - // Enable CDCSS - // Transmit positive CDCSS code - // CDCSS Mode - // CDCSS 23bit - // Enable Auto CDCSS Bw Mode - // Enable Auto CTCSS Bw Mode - // CTCSS/CDCSS Tx Gain1 Tuning = 51 - // - BK4819_WriteRegister(BK4819_REG_51, - BK4819_REG_51_ENABLE_CxCSS | - BK4819_REG_51_GPIO6_PIN2_NORMAL | - BK4819_REG_51_TX_CDCSS_POSITIVE | - BK4819_REG_51_MODE_CDCSS | - BK4819_REG_51_CDCSS_23_BIT | - BK4819_REG_51_1050HZ_NO_DETECTION | - BK4819_REG_51_AUTO_CDCSS_BW_ENABLE | - BK4819_REG_51_AUTO_CTCSS_BW_ENABLE | - (51u << BK4819_REG_51_SHIFT_CxCSS_TX_GAIN1)); - - // REG_07 <15:0> - // - // When <13> = 0 for CTC1 - // <12:0> = CTC1 frequency control word = - // freq(Hz) * 20.64888 for XTAL 13M/26M or - // freq(Hz) * 20.97152 for XTAL 12.8M/19.2M/25.6M/38.4M - // - // When <13> = 1 for CTC2 (Tail 55Hz Rx detection) - // <12:0> = CTC2 (should below 100Hz) frequency control word = - // 25391 / freq(Hz) for XTAL 13M/26M or - // 25000 / freq(Hz) for XTAL 12.8M/19.2M/25.6M/38.4M - // - // When <13> = 2 for CDCSS 134.4Hz - // <12:0> = CDCSS baud rate frequency (134.4Hz) control word = - // freq(Hz) * 20.64888 for XTAL 13M/26M or - // freq(Hz) * 20.97152 for XTAL 12.8M/19.2M/25.6M/38.4M - // - BK4819_WriteRegister(BK4819_REG_07, BK4819_REG_07_MODE_CTC1 | 2775u); - - // REG_08 <15:0> <15> = 1 for CDCSS high 12bit - // <15> = 0 for CDCSS low 12bit - // <11:0> = CDCSShigh/low 12bit code - // - BK4819_WriteRegister(BK4819_REG_08, (0u << 15) | ((CodeWord >> 0) & 0x0FFF)); // LS 12-bits - BK4819_WriteRegister(BK4819_REG_08, (1u << 15) | ((CodeWord >> 12) & 0x0FFF)); // MS 12-bits + // REG_51 + // + // <15> 0 + // 1 = Enable TxCTCSS/CDCSS + // 0 = Disable + // + // <14> 0 + // 1 = GPIO0Input for CDCSS + // 0 = Normal Mode (for BK4819 v3) + // + // <13> 0 + // 1 = Transmit negative CDCSS code + // 0 = Transmit positive CDCSS code + // + // <12> 0 CTCSS/CDCSS mode selection + // 1 = CTCSS + // 0 = CDCSS + // + // <11> 0 CDCSS 24/23bit selection + // 1 = 24bit + // 0 = 23bit + // + // <10> 0 1050HzDetectionMode + // 1 = 1050/4 Detect Enable, CTC1 should be set to 1050/4 Hz + // + // <9> 0 Auto CDCSS Bw Mode + // 1 = Disable + // 0 = Enable + // + // <8> 0 Auto CTCSS Bw Mode + // 0 = Enable + // 1 = Disable + // + // <6:0> 0 CTCSS/CDCSS Tx Gain1 Tuning + // 0 = min + // 127 = max + + // Enable CDCSS + // Transmit positive CDCSS code + // CDCSS Mode + // CDCSS 23bit + // Enable Auto CDCSS Bw Mode + // Enable Auto CTCSS Bw Mode + // CTCSS/CDCSS Tx Gain1 Tuning = 51 + // + BK4819_WriteRegister(BK4819_REG_51, + BK4819_REG_51_ENABLE_CxCSS | + BK4819_REG_51_GPIO6_PIN2_NORMAL | + BK4819_REG_51_TX_CDCSS_POSITIVE | + BK4819_REG_51_MODE_CDCSS | + BK4819_REG_51_CDCSS_23_BIT | + BK4819_REG_51_1050HZ_NO_DETECTION | + BK4819_REG_51_AUTO_CDCSS_BW_ENABLE | + BK4819_REG_51_AUTO_CTCSS_BW_ENABLE | + (51u << BK4819_REG_51_SHIFT_CxCSS_TX_GAIN1)); + + // REG_07 <15:0> + // + // When <13> = 0 for CTC1 + // <12:0> = CTC1 frequency control word = + // freq(Hz) * 20.64888 for XTAL 13M/26M or + // freq(Hz) * 20.97152 for XTAL 12.8M/19.2M/25.6M/38.4M + // + // When <13> = 1 for CTC2 (Tail 55Hz Rx detection) + // <12:0> = CTC2 (should below 100Hz) frequency control word = + // 25391 / freq(Hz) for XTAL 13M/26M or + // 25000 / freq(Hz) for XTAL 12.8M/19.2M/25.6M/38.4M + // + // When <13> = 2 for CDCSS 134.4Hz + // <12:0> = CDCSS baud rate frequency (134.4Hz) control word = + // freq(Hz) * 20.64888 for XTAL 13M/26M or + // freq(Hz) * 20.97152 for XTAL 12.8M/19.2M/25.6M/38.4M + // + BK4819_WriteRegister(BK4819_REG_07, BK4819_REG_07_MODE_CTC1 | 2775u); + + // REG_08 <15:0> <15> = 1 for CDCSS high 12bit + // <15> = 0 for CDCSS low 12bit + // <11:0> = CDCSShigh/low 12bit code + // + BK4819_WriteRegister(BK4819_REG_08, (0u << 15) | ((CodeWord >> 0) & 0x0FFF)); // LS 12-bits + BK4819_WriteRegister(BK4819_REG_08, (1u << 15) | ((CodeWord >> 12) & 0x0FFF)); // MS 12-bits } void BK4819_SetCTCSSFrequency(uint32_t FreqControlWord) { - // REG_51 <15> 0 1 = Enable TxCTCSS/CDCSS 0 = Disable - // REG_51 <14> 0 1 = GPIO0Input for CDCSS 0 = Normal Mode.(for BK4819v3) - // REG_51 <13> 0 1 = Transmit negative CDCSS code 0 = Transmit positive CDCSScode - // REG_51 <12> 0 CTCSS/CDCSS mode selection 1 = CTCSS 0 = CDCSS - // REG_51 <11> 0 CDCSS 24/23bit selection 1 = 24bit 0 = 23bit - // REG_51 <10> 0 1050HzDetectionMode 1 = 1050/4 Detect Enable, CTC1 should be set to 1050/4 Hz - // REG_51 <9> 0 Auto CDCSS Bw Mode 1 = Disable 0 = Enable. - // REG_51 <8> 0 Auto CTCSS Bw Mode 0 = Enable 1 = Disable - // REG_51 <6:0> 0 CTCSS/CDCSS Tx Gain1 Tuning 0 = min 127 = max - - uint16_t Config; - if (FreqControlWord == 2625) - { // Enables 1050Hz detection mode - // Enable TxCTCSS - // CTCSS Mode - // 1050/4 Detect Enable - // Enable Auto CDCSS Bw Mode - // Enable Auto CTCSS Bw Mode - // CTCSS/CDCSS Tx Gain1 Tuning = 74 - // - Config = 0x944A; // 1 0 0 1 0 1 0 0 0 1001010 - } - else - { // Enable TxCTCSS - // CTCSS Mode - // Enable Auto CDCSS Bw Mode - // Enable Auto CTCSS Bw Mode - // CTCSS/CDCSS Tx Gain1 Tuning = 74 - // - Config = 0x904A; // 1 0 0 1 0 0 0 0 0 1001010 - } - BK4819_WriteRegister(BK4819_REG_51, Config); - - // REG_07 <15:0> - // - // When <13> = 0 for CTC1 - // <12:0> = CTC1 frequency control word = - // freq(Hz) * 20.64888 for XTAL 13M/26M or - // freq(Hz) * 20.97152 for XTAL 12.8M/19.2M/25.6M/38.4M - // - // When <13> = 1 for CTC2 (Tail RX detection) - // <12:0> = CTC2 (should below 100Hz) frequency control word = - // 25391 / freq(Hz) for XTAL 13M/26M or - // 25000 / freq(Hz) for XTAL 12.8M/19.2M/25.6M/38.4M - // - // When <13> = 2 for CDCSS 134.4Hz - // <12:0> = CDCSS baud rate frequency (134.4Hz) control word = - // freq(Hz) * 20.64888 for XTAL 13M/26M or - // freq(Hz) * 20.97152 for XTAL 12.8M/19.2M/25.6M/38.4M - // - BK4819_WriteRegister(BK4819_REG_07, BK4819_REG_07_MODE_CTC1 | (((FreqControlWord * 206488u) + 50000u) / 100000u)); // with rounding + // REG_51 <15> 0 1 = Enable TxCTCSS/CDCSS 0 = Disable + // REG_51 <14> 0 1 = GPIO0Input for CDCSS 0 = Normal Mode.(for BK4819v3) + // REG_51 <13> 0 1 = Transmit negative CDCSS code 0 = Transmit positive CDCSScode + // REG_51 <12> 0 CTCSS/CDCSS mode selection 1 = CTCSS 0 = CDCSS + // REG_51 <11> 0 CDCSS 24/23bit selection 1 = 24bit 0 = 23bit + // REG_51 <10> 0 1050HzDetectionMode 1 = 1050/4 Detect Enable, CTC1 should be set to 1050/4 Hz + // REG_51 <9> 0 Auto CDCSS Bw Mode 1 = Disable 0 = Enable. + // REG_51 <8> 0 Auto CTCSS Bw Mode 0 = Enable 1 = Disable + // REG_51 <6:0> 0 CTCSS/CDCSS Tx Gain1 Tuning 0 = min 127 = max + + uint16_t Config; + if (FreqControlWord == 2625) + { // Enables 1050Hz detection mode + // Enable TxCTCSS + // CTCSS Mode + // 1050/4 Detect Enable + // Enable Auto CDCSS Bw Mode + // Enable Auto CTCSS Bw Mode + // CTCSS/CDCSS Tx Gain1 Tuning = 74 + // + Config = 0x944A; // 1 0 0 1 0 1 0 0 0 1001010 + } + else + { // Enable TxCTCSS + // CTCSS Mode + // Enable Auto CDCSS Bw Mode + // Enable Auto CTCSS Bw Mode + // CTCSS/CDCSS Tx Gain1 Tuning = 74 + // + Config = 0x904A; // 1 0 0 1 0 0 0 0 0 1001010 + } + BK4819_WriteRegister(BK4819_REG_51, Config); + + // REG_07 <15:0> + // + // When <13> = 0 for CTC1 + // <12:0> = CTC1 frequency control word = + // freq(Hz) * 20.64888 for XTAL 13M/26M or + // freq(Hz) * 20.97152 for XTAL 12.8M/19.2M/25.6M/38.4M + // + // When <13> = 1 for CTC2 (Tail RX detection) + // <12:0> = CTC2 (should below 100Hz) frequency control word = + // 25391 / freq(Hz) for XTAL 13M/26M or + // 25000 / freq(Hz) for XTAL 12.8M/19.2M/25.6M/38.4M + // + // When <13> = 2 for CDCSS 134.4Hz + // <12:0> = CDCSS baud rate frequency (134.4Hz) control word = + // freq(Hz) * 20.64888 for XTAL 13M/26M or + // freq(Hz) * 20.97152 for XTAL 12.8M/19.2M/25.6M/38.4M + // + BK4819_WriteRegister(BK4819_REG_07, BK4819_REG_07_MODE_CTC1 | (((FreqControlWord * 206488u) + 50000u) / 100000u)); // with rounding } // freq_10Hz is CTCSS Hz * 10 void BK4819_SetTailDetection(const uint32_t freq_10Hz) { - // REG_07 <15:0> - // - // When <13> = 0 for CTC1 - // <12:0> = CTC1 frequency control word = - // freq(Hz) * 20.64888 for XTAL 13M/26M or - // freq(Hz) * 20.97152 for XTAL 12.8M/19.2M/25.6M/38.4M - // - // When <13> = 1 for CTC2 (Tail RX detection) - // <12:0> = CTC2 (should below 100Hz) frequency control word = - // 25391 / freq(Hz) for XTAL 13M/26M or - // 25000 / freq(Hz) for XTAL 12.8M/19.2M/25.6M/38.4M - // - // When <13> = 2 for CDCSS 134.4Hz - // <12:0> = CDCSS baud rate frequency (134.4Hz) control word = - // freq(Hz) * 20.64888 for XTAL 13M/26M or - // freq(Hz) * 20.97152 for XTAL 12.8M/19.2M/25.6M/38.4M - // - BK4819_WriteRegister(BK4819_REG_07, BK4819_REG_07_MODE_CTC2 | ((253910 + (freq_10Hz / 2)) / freq_10Hz)); // with rounding + // REG_07 <15:0> + // + // When <13> = 0 for CTC1 + // <12:0> = CTC1 frequency control word = + // freq(Hz) * 20.64888 for XTAL 13M/26M or + // freq(Hz) * 20.97152 for XTAL 12.8M/19.2M/25.6M/38.4M + // + // When <13> = 1 for CTC2 (Tail RX detection) + // <12:0> = CTC2 (should below 100Hz) frequency control word = + // 25391 / freq(Hz) for XTAL 13M/26M or + // 25000 / freq(Hz) for XTAL 12.8M/19.2M/25.6M/38.4M + // + // When <13> = 2 for CDCSS 134.4Hz + // <12:0> = CDCSS baud rate frequency (134.4Hz) control word = + // freq(Hz) * 20.64888 for XTAL 13M/26M or + // freq(Hz) * 20.97152 for XTAL 12.8M/19.2M/25.6M/38.4M + // + BK4819_WriteRegister(BK4819_REG_07, BK4819_REG_07_MODE_CTC2 | ((253910 + (freq_10Hz / 2)) / freq_10Hz)); // with rounding } void BK4819_EnableVox(uint16_t VoxEnableThreshold, uint16_t VoxDisableThreshold) { - //VOX Algorithm - //if (voxamp>VoxEnableThreshold) VOX = 1; - //else - //if (voxampVoxEnableThreshold) VOX = 1; + //else + //if (voxamp 0 ??? - // - // <14:12> 4 RF filter bandwidth - // 0 = 1.7 kHz - // 1 = 2.0 kHz - // 2 = 2.5 kHz - // 3 = 3.0 kHz - // 4 = 3.75 kHz - // 5 = 4.0 kHz - // 6 = 4.25 kHz - // 7 = 4.5 kHz - // if <5> == 1, RF filter bandwidth * 2 - // - // <11:9> 0 RF filter bandwidth when signal is weak - // 0 = 1.7 kHz - // 1 = 2.0 kHz - // 2 = 2.5 kHz - // 3 = 3.0 kHz - // 4 = 3.75 kHz - // 5 = 4.0 kHz - // 6 = 4.25 kHz - // 7 = 4.5 kHz - // if <5> == 1, RF filter bandwidth * 2 - // - // <8:6> 1 AFTxLPF2 filter Band Width - // 1 = 2.5 kHz (for 12.5k channel space) - // 2 = 2.75 kHz - // 0 = 3.0 kHz (for 25k channel space) - // 3 = 3.5 kHz - // 4 = 4.5 kHz - // 5 = 4.25 kHz - // 6 = 4.0 kHz - // 7 = 3.75 kHz - // - // <5:4> 0 BW Mode Selection - // 0 = 12.5k - // 1 = 6.25k - // 2 = 25k/20k - // - // <3> 1 ??? - // - // <2> 0 Gain after FM Demodulation - // 0 = 0dB - // 1 = 6dB - // - // <1:0> 0 ??? - - uint16_t val = 0; - switch (Bandwidth) - { - default: - case BK4819_FILTER_BW_WIDE: // 25kHz - val = (4u << 12) | // *3 RF filter bandwidth - (6u << 6) | // *0 AFTxLPF2 filter Band Width - (2u << 4) | // 2 BW Mode Selection - (1u << 3) | // 1 - (0u << 2); // 0 Gain after FM Demodulation - - if (weak_no_different) { - // make the RX bandwidth the same with weak signals - val |= (4u << 9); // *0 RF filter bandwidth when signal is weak - } else { - /// with weak RX signals the RX bandwidth is reduced - val |= (2u << 9); // *0 RF filter bandwidth when signal is weak - } - - break; - - case BK4819_FILTER_BW_NARROW: // 12.5kHz - val = (4u << 12) | // *4 RF filter bandwidth - (0u << 6) | // *1 AFTxLPF2 filter Band Width - (0u << 4) | // 0 BW Mode Selection - (1u << 3) | // 1 - (0u << 2); // 0 Gain after FM Demodulation - - if (weak_no_different) { - val |= (4u << 9); // *0 RF filter bandwidth when signal is weak - } else { - val |= (2u << 9); - } - - break; - - case BK4819_FILTER_BW_NARROWER: // 6.25kHz - val = (3u << 12) | // 3 RF filter bandwidth - (3u << 9) | // *0 RF filter bandwidth when signal is weak - (1u << 6) | // 1 AFTxLPF2 filter Band Width - (1u << 4) | // 1 BW Mode Selection - (1u << 3) | // 1 - (0u << 2); // 0 Gain after FM Demodulation - - if (weak_no_different) { - val |= (3u << 9); - } else { - val |= (0u << 9); // 0 RF filter bandwidth when signal is weak - } - break; - } - - BK4819_WriteRegister(BK4819_REG_43, val); + // REG_43 + // <15> 0 ??? + // + // <14:12> 4 RF filter bandwidth + // 0 = 1.7 kHz + // 1 = 2.0 kHz + // 2 = 2.5 kHz + // 3 = 3.0 kHz + // 4 = 3.75 kHz + // 5 = 4.0 kHz + // 6 = 4.25 kHz + // 7 = 4.5 kHz + // if <5> == 1, RF filter bandwidth * 2 + // + // <11:9> 0 RF filter bandwidth when signal is weak + // 0 = 1.7 kHz + // 1 = 2.0 kHz + // 2 = 2.5 kHz + // 3 = 3.0 kHz + // 4 = 3.75 kHz + // 5 = 4.0 kHz + // 6 = 4.25 kHz + // 7 = 4.5 kHz + // if <5> == 1, RF filter bandwidth * 2 + // + // <8:6> 1 AFTxLPF2 filter Band Width + // 1 = 2.5 kHz (for 12.5k channel space) + // 2 = 2.75 kHz + // 0 = 3.0 kHz (for 25k channel space) + // 3 = 3.5 kHz + // 4 = 4.5 kHz + // 5 = 4.25 kHz + // 6 = 4.0 kHz + // 7 = 3.75 kHz + // + // <5:4> 0 BW Mode Selection + // 0 = 12.5k + // 1 = 6.25k + // 2 = 25k/20k + // + // <3> 1 ??? + // + // <2> 0 Gain after FM Demodulation + // 0 = 0dB + // 1 = 6dB + // + // <1:0> 0 ??? + + uint16_t val = 0; + switch (Bandwidth) + { + default: + case BK4819_FILTER_BW_WIDE: // 25kHz + val = (4u << 12) | // *3 RF filter bandwidth + (6u << 6) | // *0 AFTxLPF2 filter Band Width + (2u << 4) | // 2 BW Mode Selection + (1u << 3) | // 1 + (0u << 2); // 0 Gain after FM Demodulation + + if (weak_no_different) { + // make the RX bandwidth the same with weak signals + val |= (4u << 9); // *0 RF filter bandwidth when signal is weak + } else { + /// with weak RX signals the RX bandwidth is reduced + val |= (2u << 9); // *0 RF filter bandwidth when signal is weak + } + + break; + + case BK4819_FILTER_BW_NARROW: // 12.5kHz + val = (4u << 12) | // *4 RF filter bandwidth + (0u << 6) | // *1 AFTxLPF2 filter Band Width + (0u << 4) | // 0 BW Mode Selection + (1u << 3) | // 1 + (0u << 2); // 0 Gain after FM Demodulation + + if (weak_no_different) { + val |= (4u << 9); // *0 RF filter bandwidth when signal is weak + } else { + val |= (2u << 9); + } + + break; + + case BK4819_FILTER_BW_NARROWER: // 6.25kHz + val = (3u << 12) | // 3 RF filter bandwidth + (3u << 9) | // *0 RF filter bandwidth when signal is weak + (1u << 6) | // 1 AFTxLPF2 filter Band Width + (1u << 4) | // 1 BW Mode Selection + (1u << 3) | // 1 + (0u << 2); // 0 Gain after FM Demodulation + + if (weak_no_different) { + val |= (3u << 9); + } else { + val |= (0u << 9); // 0 RF filter bandwidth when signal is weak + } + break; + } + + BK4819_WriteRegister(BK4819_REG_43, val); } void BK4819_SetupPowerAmplifier(const uint8_t bias, const uint32_t frequency) { - // REG_36 <15:8> 0 PA Bias output 0 ~ 3.2V - // 255 = 3.2V - // 0 = 0V - // - // REG_36 <7> 0 - // 1 = Enable PA-CTL output - // 0 = Disable (Output 0 V) - // - // REG_36 <5:3> 7 PA gain 1 tuning - // 7 = max - // 0 = min - // - // REG_36 <2:0> 7 PA gain 2 tuning - // 7 = max - // 0 = min - // - // 280MHz g1=1 g2=0 (-14.9dBm), g1=4 g2=2 (0.13dBm) - const uint8_t gain = (frequency < 28000000) ? (1u << 3) | (0u << 0) : (4u << 3) | (2u << 0); - const uint8_t enable = 1; - BK4819_WriteRegister(BK4819_REG_36, (bias << 8) | (enable << 7) | (gain << 0)); + // REG_36 <15:8> 0 PA Bias output 0 ~ 3.2V + // 255 = 3.2V + // 0 = 0V + // + // REG_36 <7> 0 + // 1 = Enable PA-CTL output + // 0 = Disable (Output 0 V) + // + // REG_36 <5:3> 7 PA gain 1 tuning + // 7 = max + // 0 = min + // + // REG_36 <2:0> 7 PA gain 2 tuning + // 7 = max + // 0 = min + // + // 280MHz g1=1 g2=0 (-14.9dBm), g1=4 g2=2 (0.13dBm) + const uint8_t gain = (frequency < 28000000) ? (1u << 3) | (0u << 0) : (4u << 3) | (2u << 0); + const uint8_t enable = 1; + BK4819_WriteRegister(BK4819_REG_36, (bias << 8) | (enable << 7) | (gain << 0)); } void BK4819_SetFrequency(uint32_t Frequency) { - BK4819_WriteRegister(BK4819_REG_38, (Frequency >> 0) & 0xFFFF); - BK4819_WriteRegister(BK4819_REG_39, (Frequency >> 16) & 0xFFFF); + BK4819_WriteRegister(BK4819_REG_38, (Frequency >> 0) & 0xFFFF); + BK4819_WriteRegister(BK4819_REG_39, (Frequency >> 16) & 0xFFFF); } void BK4819_SetupSquelch( - uint8_t SquelchOpenRSSIThresh, - uint8_t SquelchCloseRSSIThresh, - uint8_t SquelchOpenNoiseThresh, - uint8_t SquelchCloseNoiseThresh, - uint8_t SquelchCloseGlitchThresh, - uint8_t SquelchOpenGlitchThresh) -{ - // REG_70 - // - // <15> 0 Enable TONE1 - // 1 = Enable - // 0 = Disable - // - // <14:8> 0 TONE1 tuning gain - // 0 ~ 127 - // - // <7> 0 Enable TONE2 - // 1 = Enable - // 0 = Disable - // - // <6:0> 0 TONE2/FSK tuning gain - // 0 ~ 127 - // - BK4819_WriteRegister(BK4819_REG_70, 0); - - // Glitch threshold for Squelch = close - // - // 0 ~ 255 - // - BK4819_WriteRegister(BK4819_REG_4D, 0xA000 | SquelchCloseGlitchThresh); - - // REG_4E - // - // <15:14> 1 ??? - // - // <13:11> 5 Squelch = open Delay Setting - // 0 ~ 7 - // - // <10:9> 7 Squelch = close Delay Setting - // 0 ~ 3 - // - // <8> 0 ??? - // - // <7:0> 8 Glitch threshold for Squelch = open - // 0 ~ 255 - // - BK4819_WriteRegister(BK4819_REG_4E, // 01 101 11 1 00000000 - - // original (*) - (1u << 14) | // 1 ??? - (5u << 11) | // *5 squelch = open delay .. 0 ~ 7 - (6u << 9) | // *3 squelch = close delay .. 0 ~ 3 - SquelchOpenGlitchThresh); // 0 ~ 255 - - - // REG_4F - // - // <14:8> 47 Ex-noise threshold for Squelch = close - // 0 ~ 127 - // - // <7> ??? - // - // <6:0> 46 Ex-noise threshold for Squelch = open - // 0 ~ 127 - // - BK4819_WriteRegister(BK4819_REG_4F, ((uint16_t)SquelchCloseNoiseThresh << 8) | SquelchOpenNoiseThresh); - - // REG_78 - // - // <15:8> 72 RSSI threshold for Squelch = open 0.5dB/step - // - // <7:0> 70 RSSI threshold for Squelch = close 0.5dB/step - // - BK4819_WriteRegister(BK4819_REG_78, ((uint16_t)SquelchOpenRSSIThresh << 8) | SquelchCloseRSSIThresh); - - BK4819_SetAF(BK4819_AF_MUTE); - - BK4819_RX_TurnOn(); + uint8_t SquelchOpenRSSIThresh, + uint8_t SquelchCloseRSSIThresh, + uint8_t SquelchOpenNoiseThresh, + uint8_t SquelchCloseNoiseThresh, + uint8_t SquelchCloseGlitchThresh, + uint8_t SquelchOpenGlitchThresh) +{ + // REG_70 + // + // <15> 0 Enable TONE1 + // 1 = Enable + // 0 = Disable + // + // <14:8> 0 TONE1 tuning gain + // 0 ~ 127 + // + // <7> 0 Enable TONE2 + // 1 = Enable + // 0 = Disable + // + // <6:0> 0 TONE2/FSK tuning gain + // 0 ~ 127 + // + BK4819_WriteRegister(BK4819_REG_70, 0); + + // Glitch threshold for Squelch = close + // + // 0 ~ 255 + // + BK4819_WriteRegister(BK4819_REG_4D, 0xA000 | SquelchCloseGlitchThresh); + + // REG_4E + // + // <15:14> 1 ??? + // + // <13:11> 5 Squelch = open Delay Setting + // 0 ~ 7 + // + // <10:9> 7 Squelch = close Delay Setting + // 0 ~ 3 + // + // <8> 0 ??? + // + // <7:0> 8 Glitch threshold for Squelch = open + // 0 ~ 255 + // + BK4819_WriteRegister(BK4819_REG_4E, // 01 101 11 1 00000000 + + // original (*) + (1u << 14) | // 1 ??? + (5u << 11) | // *5 squelch = open delay .. 0 ~ 7 + (6u << 9) | // *3 squelch = close delay .. 0 ~ 3 + SquelchOpenGlitchThresh); // 0 ~ 255 + + + // REG_4F + // + // <14:8> 47 Ex-noise threshold for Squelch = close + // 0 ~ 127 + // + // <7> ??? + // + // <6:0> 46 Ex-noise threshold for Squelch = open + // 0 ~ 127 + // + BK4819_WriteRegister(BK4819_REG_4F, ((uint16_t)SquelchCloseNoiseThresh << 8) | SquelchOpenNoiseThresh); + + // REG_78 + // + // <15:8> 72 RSSI threshold for Squelch = open 0.5dB/step + // + // <7:0> 70 RSSI threshold for Squelch = close 0.5dB/step + // + BK4819_WriteRegister(BK4819_REG_78, ((uint16_t)SquelchOpenRSSIThresh << 8) | SquelchCloseRSSIThresh); + + BK4819_SetAF(BK4819_AF_MUTE); + + BK4819_RX_TurnOn(); } void BK4819_SetAF(BK4819_AF_Type_t AF) { - // AF Output Inverse Mode = Inverse - // Undocumented bits 0x2040 - // -// BK4819_WriteRegister(BK4819_REG_47, 0x6040 | (AF << 8)); - BK4819_WriteRegister(BK4819_REG_47, (6u << 12) | (AF << 8) | (1u << 6)); + // AF Output Inverse Mode = Inverse + // Undocumented bits 0x2040 + // +// BK4819_WriteRegister(BK4819_REG_47, 0x6040 | (AF << 8)); + BK4819_WriteRegister(BK4819_REG_47, (6u << 12) | (AF << 8) | (1u << 6)); } void BK4819_SetRegValue(RegisterSpec s, uint16_t v) { @@ -791,1029 +791,1029 @@ void BK4819_SetRegValue(RegisterSpec s, uint16_t v) { void BK4819_RX_TurnOn(void) { - // DSP Voltage Setting = 1 - // ANA LDO = 2.7v - // VCO LDO = 2.7v - // RF LDO = 2.7v - // PLL LDO = 2.7v - // ANA LDO bypass - // VCO LDO bypass - // RF LDO bypass - // PLL LDO bypass - // Reserved bit is 1 instead of 0 - // Enable DSP - // Enable XTAL - // Enable Band Gap - // - BK4819_WriteRegister(BK4819_REG_37, 0x1F0F); // 0001111100001111 - - // Turn off everything - BK4819_WriteRegister(BK4819_REG_30, 0); - - - BK4819_WriteRegister(BK4819_REG_30, - BK4819_REG_30_ENABLE_VCO_CALIB | - BK4819_REG_30_DISABLE_UNKNOWN | - BK4819_REG_30_ENABLE_RX_LINK | - BK4819_REG_30_ENABLE_AF_DAC | - BK4819_REG_30_ENABLE_DISC_MODE | - BK4819_REG_30_ENABLE_PLL_VCO | - BK4819_REG_30_DISABLE_PA_GAIN | - BK4819_REG_30_DISABLE_MIC_ADC | - BK4819_REG_30_DISABLE_TX_DSP | - BK4819_REG_30_ENABLE_RX_DSP ); + // DSP Voltage Setting = 1 + // ANA LDO = 2.7v + // VCO LDO = 2.7v + // RF LDO = 2.7v + // PLL LDO = 2.7v + // ANA LDO bypass + // VCO LDO bypass + // RF LDO bypass + // PLL LDO bypass + // Reserved bit is 1 instead of 0 + // Enable DSP + // Enable XTAL + // Enable Band Gap + // + BK4819_WriteRegister(BK4819_REG_37, 0x1F0F); // 0001111100001111 + + // Turn off everything + BK4819_WriteRegister(BK4819_REG_30, 0); + + + BK4819_WriteRegister(BK4819_REG_30, + BK4819_REG_30_ENABLE_VCO_CALIB | + BK4819_REG_30_DISABLE_UNKNOWN | + BK4819_REG_30_ENABLE_RX_LINK | + BK4819_REG_30_ENABLE_AF_DAC | + BK4819_REG_30_ENABLE_DISC_MODE | + BK4819_REG_30_ENABLE_PLL_VCO | + BK4819_REG_30_DISABLE_PA_GAIN | + BK4819_REG_30_DISABLE_MIC_ADC | + BK4819_REG_30_DISABLE_TX_DSP | + BK4819_REG_30_ENABLE_RX_DSP ); } void BK4819_PickRXFilterPathBasedOnFrequency(uint32_t Frequency) { - if (Frequency < 28000000) - { // VHF - BK4819_ToggleGpioOut(BK4819_GPIO4_PIN32_VHF_LNA, true); - BK4819_ToggleGpioOut(BK4819_GPIO3_PIN31_UHF_LNA, false); - } - else - if (Frequency == 0xFFFFFFFF) - { // OFF - BK4819_ToggleGpioOut(BK4819_GPIO4_PIN32_VHF_LNA, false); - BK4819_ToggleGpioOut(BK4819_GPIO3_PIN31_UHF_LNA, false); - } - else - { // UHF - BK4819_ToggleGpioOut(BK4819_GPIO4_PIN32_VHF_LNA, false); - BK4819_ToggleGpioOut(BK4819_GPIO3_PIN31_UHF_LNA, true); - } + if (Frequency < 28000000) + { // VHF + BK4819_ToggleGpioOut(BK4819_GPIO4_PIN32_VHF_LNA, true); + BK4819_ToggleGpioOut(BK4819_GPIO3_PIN31_UHF_LNA, false); + } + else + if (Frequency == 0xFFFFFFFF) + { // OFF + BK4819_ToggleGpioOut(BK4819_GPIO4_PIN32_VHF_LNA, false); + BK4819_ToggleGpioOut(BK4819_GPIO3_PIN31_UHF_LNA, false); + } + else + { // UHF + BK4819_ToggleGpioOut(BK4819_GPIO4_PIN32_VHF_LNA, false); + BK4819_ToggleGpioOut(BK4819_GPIO3_PIN31_UHF_LNA, true); + } } void BK4819_DisableScramble(void) { - const uint16_t Value = BK4819_ReadRegister(BK4819_REG_31); - BK4819_WriteRegister(BK4819_REG_31, Value & ~(1u << 1)); + const uint16_t Value = BK4819_ReadRegister(BK4819_REG_31); + BK4819_WriteRegister(BK4819_REG_31, Value & ~(1u << 1)); } void BK4819_EnableScramble(uint8_t Type) { - const uint16_t Value = BK4819_ReadRegister(BK4819_REG_31); - BK4819_WriteRegister(BK4819_REG_31, Value | (1u << 1)); + const uint16_t Value = BK4819_ReadRegister(BK4819_REG_31); + BK4819_WriteRegister(BK4819_REG_31, Value | (1u << 1)); - BK4819_WriteRegister(BK4819_REG_71, 0x68DC + (Type * 1032)); // 0110 1000 1101 1100 + BK4819_WriteRegister(BK4819_REG_71, 0x68DC + (Type * 1032)); // 0110 1000 1101 1100 } bool BK4819_CompanderEnabled(void) { - return (BK4819_ReadRegister(BK4819_REG_31) & (1u << 3)) ? true : false; + return (BK4819_ReadRegister(BK4819_REG_31) & (1u << 3)) ? true : false; } void BK4819_SetCompander(const unsigned int mode) { - // mode 0 .. OFF - // mode 1 .. TX - // mode 2 .. RX - // mode 3 .. TX and RX - - const uint16_t r31 = BK4819_ReadRegister(BK4819_REG_31); - - if (mode == 0) - { // disable - BK4819_WriteRegister(BK4819_REG_31, r31 & ~(1u << 3)); - return; - } - - // REG_29 - // - // <15:14> 10 Compress (AF Tx) Ratio - // 00 = Disable - // 01 = 1.333:1 - // 10 = 2:1 - // 11 = 4:1 - // - // <13:7> 86 Compress (AF Tx) 0 dB point (dB) - // - // <6:0> 64 Compress (AF Tx) noise point (dB) - // - const uint16_t compress_ratio = (mode == 1 || mode >= 3) ? 2 : 0; // 2:1 - const uint16_t compress_0dB = 86; - const uint16_t compress_noise_dB = 64; -// AB40 10 1010110 1000000 - BK4819_WriteRegister(BK4819_REG_29, // (BK4819_ReadRegister(BK4819_REG_29) & ~(3u << 14)) | (compress_ratio << 14)); - (compress_ratio << 14) | - (compress_0dB << 7) | - (compress_noise_dB << 0)); - - // REG_28 - // - // <15:14> 01 Expander (AF Rx) Ratio - // 00 = Disable - // 01 = 1:2 - // 10 = 1:3 - // 11 = 1:4 - // - // <13:7> 86 Expander (AF Rx) 0 dB point (dB) - // - // <6:0> 56 Expander (AF Rx) noise point (dB) - // - const uint16_t expand_ratio = (mode >= 2) ? 1 : 0; // 1:2 - const uint16_t expand_0dB = 86; - const uint16_t expand_noise_dB = 56; -// 6B38 01 1010110 0111000 - BK4819_WriteRegister(BK4819_REG_28, // (BK4819_ReadRegister(BK4819_REG_28) & ~(3u << 14)) | (expand_ratio << 14)); - (expand_ratio << 14) | - (expand_0dB << 7) | - (expand_noise_dB << 0)); - - // enable - BK4819_WriteRegister(BK4819_REG_31, r31 | (1u << 3)); + // mode 0 .. OFF + // mode 1 .. TX + // mode 2 .. RX + // mode 3 .. TX and RX + + const uint16_t r31 = BK4819_ReadRegister(BK4819_REG_31); + + if (mode == 0) + { // disable + BK4819_WriteRegister(BK4819_REG_31, r31 & ~(1u << 3)); + return; + } + + // REG_29 + // + // <15:14> 10 Compress (AF Tx) Ratio + // 00 = Disable + // 01 = 1.333:1 + // 10 = 2:1 + // 11 = 4:1 + // + // <13:7> 86 Compress (AF Tx) 0 dB point (dB) + // + // <6:0> 64 Compress (AF Tx) noise point (dB) + // + const uint16_t compress_ratio = (mode == 1 || mode >= 3) ? 2 : 0; // 2:1 + const uint16_t compress_0dB = 86; + const uint16_t compress_noise_dB = 64; +// AB40 10 1010110 1000000 + BK4819_WriteRegister(BK4819_REG_29, // (BK4819_ReadRegister(BK4819_REG_29) & ~(3u << 14)) | (compress_ratio << 14)); + (compress_ratio << 14) | + (compress_0dB << 7) | + (compress_noise_dB << 0)); + + // REG_28 + // + // <15:14> 01 Expander (AF Rx) Ratio + // 00 = Disable + // 01 = 1:2 + // 10 = 1:3 + // 11 = 1:4 + // + // <13:7> 86 Expander (AF Rx) 0 dB point (dB) + // + // <6:0> 56 Expander (AF Rx) noise point (dB) + // + const uint16_t expand_ratio = (mode >= 2) ? 1 : 0; // 1:2 + const uint16_t expand_0dB = 86; + const uint16_t expand_noise_dB = 56; +// 6B38 01 1010110 0111000 + BK4819_WriteRegister(BK4819_REG_28, // (BK4819_ReadRegister(BK4819_REG_28) & ~(3u << 14)) | (expand_ratio << 14)); + (expand_ratio << 14) | + (expand_0dB << 7) | + (expand_noise_dB << 0)); + + // enable + BK4819_WriteRegister(BK4819_REG_31, r31 | (1u << 3)); } void BK4819_DisableVox(void) { - const uint16_t Value = BK4819_ReadRegister(BK4819_REG_31); - BK4819_WriteRegister(BK4819_REG_31, Value & 0xFFFB); + const uint16_t Value = BK4819_ReadRegister(BK4819_REG_31); + BK4819_WriteRegister(BK4819_REG_31, Value & 0xFFFB); } void BK4819_DisableDTMF(void) { - BK4819_WriteRegister(BK4819_REG_24, 0); + BK4819_WriteRegister(BK4819_REG_24, 0); } void BK4819_EnableDTMF(void) { - // no idea what this does - BK4819_WriteRegister(BK4819_REG_21, 0x06D8); // 0000 0110 1101 1000 - - // REG_24 - // - // <15> 1 ??? - // - // <14:7> 24 Threshold - // - // <6> 1 ??? - // - // <5> 0 DTMF/SelCall enable - // 1 = Enable - // 0 = Disable - // - // <4> 1 DTMF or SelCall detection mode - // 1 = for DTMF - // 0 = for SelCall - // - // <3:0> 14 Max symbol number for SelCall detection - // -// const uint16_t threshold = 24; // default, but doesn't decode non-QS radios - const uint16_t threshold = 130; // but 128 ~ 247 does - BK4819_WriteRegister(BK4819_REG_24, // 1 00011000 1 1 1 1110 - (1u << BK4819_REG_24_SHIFT_UNKNOWN_15) | - (threshold << BK4819_REG_24_SHIFT_THRESHOLD) | // 0 ~ 255 - (1u << BK4819_REG_24_SHIFT_UNKNOWN_6) | - BK4819_REG_24_ENABLE | - BK4819_REG_24_SELECT_DTMF | - (15u << BK4819_REG_24_SHIFT_MAX_SYMBOLS)); // 0 ~ 15 + // no idea what this does + BK4819_WriteRegister(BK4819_REG_21, 0x06D8); // 0000 0110 1101 1000 + + // REG_24 + // + // <15> 1 ??? + // + // <14:7> 24 Threshold + // + // <6> 1 ??? + // + // <5> 0 DTMF/SelCall enable + // 1 = Enable + // 0 = Disable + // + // <4> 1 DTMF or SelCall detection mode + // 1 = for DTMF + // 0 = for SelCall + // + // <3:0> 14 Max symbol number for SelCall detection + // +// const uint16_t threshold = 24; // default, but doesn't decode non-QS radios + const uint16_t threshold = 130; // but 128 ~ 247 does + BK4819_WriteRegister(BK4819_REG_24, // 1 00011000 1 1 1 1110 + (1u << BK4819_REG_24_SHIFT_UNKNOWN_15) | + (threshold << BK4819_REG_24_SHIFT_THRESHOLD) | // 0 ~ 255 + (1u << BK4819_REG_24_SHIFT_UNKNOWN_6) | + BK4819_REG_24_ENABLE | + BK4819_REG_24_SELECT_DTMF | + (15u << BK4819_REG_24_SHIFT_MAX_SYMBOLS)); // 0 ~ 15 } void BK4819_PlayTone(uint16_t Frequency, bool bTuningGainSwitch) { - uint16_t ToneConfig = BK4819_REG_70_ENABLE_TONE1; + uint16_t ToneConfig = BK4819_REG_70_ENABLE_TONE1; - BK4819_EnterTxMute(); - BK4819_SetAF(BK4819_AF_BEEP); + BK4819_EnterTxMute(); + BK4819_SetAF(BK4819_AF_BEEP); - if (bTuningGainSwitch == 0) - ToneConfig |= 96u << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN; - else - ToneConfig |= 28u << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN; - BK4819_WriteRegister(BK4819_REG_70, ToneConfig); + if (bTuningGainSwitch == 0) + ToneConfig |= 96u << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN; + else + ToneConfig |= 28u << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN; + BK4819_WriteRegister(BK4819_REG_70, ToneConfig); - BK4819_WriteRegister(BK4819_REG_30, 0); - BK4819_WriteRegister(BK4819_REG_30, BK4819_REG_30_ENABLE_AF_DAC | BK4819_REG_30_ENABLE_DISC_MODE | BK4819_REG_30_ENABLE_TX_DSP); + BK4819_WriteRegister(BK4819_REG_30, 0); + BK4819_WriteRegister(BK4819_REG_30, BK4819_REG_30_ENABLE_AF_DAC | BK4819_REG_30_ENABLE_DISC_MODE | BK4819_REG_30_ENABLE_TX_DSP); - BK4819_WriteRegister(BK4819_REG_71, scale_freq(Frequency)); + BK4819_WriteRegister(BK4819_REG_71, scale_freq(Frequency)); } // level 0 ~ 127 void BK4819_PlaySingleTone(const unsigned int tone_Hz, const unsigned int delay, const unsigned int level, const bool play_speaker) { - BK4819_EnterTxMute(); + BK4819_EnterTxMute(); - if (play_speaker) - { - AUDIO_AudioPathOn(); - BK4819_SetAF(BK4819_AF_BEEP); - } - else - BK4819_SetAF(BK4819_AF_MUTE); + if (play_speaker) + { + AUDIO_AudioPathOn(); + BK4819_SetAF(BK4819_AF_BEEP); + } + else + BK4819_SetAF(BK4819_AF_MUTE); - BK4819_WriteRegister(BK4819_REG_70, BK4819_REG_70_ENABLE_TONE1 | ((level & 0x7f) << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN)); + BK4819_WriteRegister(BK4819_REG_70, BK4819_REG_70_ENABLE_TONE1 | ((level & 0x7f) << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN)); - BK4819_EnableTXLink(); - SYSTEM_DelayMs(50); + BK4819_EnableTXLink(); + SYSTEM_DelayMs(50); - BK4819_WriteRegister(BK4819_REG_71, scale_freq(tone_Hz)); + BK4819_WriteRegister(BK4819_REG_71, scale_freq(tone_Hz)); - BK4819_ExitTxMute(); - SYSTEM_DelayMs(delay); - BK4819_EnterTxMute(); + BK4819_ExitTxMute(); + SYSTEM_DelayMs(delay); + BK4819_EnterTxMute(); - if (play_speaker) - { - AUDIO_AudioPathOff(); - BK4819_SetAF(BK4819_AF_MUTE); - } + if (play_speaker) + { + AUDIO_AudioPathOff(); + BK4819_SetAF(BK4819_AF_MUTE); + } - BK4819_WriteRegister(BK4819_REG_70, 0x0000); - BK4819_WriteRegister(BK4819_REG_30, 0xC1FE); - BK4819_ExitTxMute(); + BK4819_WriteRegister(BK4819_REG_70, 0x0000); + BK4819_WriteRegister(BK4819_REG_30, 0xC1FE); + BK4819_ExitTxMute(); } void BK4819_EnterTxMute(void) { - BK4819_WriteRegister(BK4819_REG_50, 0xBB20); + BK4819_WriteRegister(BK4819_REG_50, 0xBB20); } void BK4819_ExitTxMute(void) { - BK4819_WriteRegister(BK4819_REG_50, 0x3B20); + BK4819_WriteRegister(BK4819_REG_50, 0x3B20); } void BK4819_Sleep(void) { - BK4819_WriteRegister(BK4819_REG_30, 0); - BK4819_WriteRegister(BK4819_REG_37, 0x1D00); + BK4819_WriteRegister(BK4819_REG_30, 0); + BK4819_WriteRegister(BK4819_REG_37, 0x1D00); } void BK4819_TurnsOffTones_TurnsOnRX(void) { - BK4819_WriteRegister(BK4819_REG_70, 0); - BK4819_SetAF(BK4819_AF_MUTE); + BK4819_WriteRegister(BK4819_REG_70, 0); + BK4819_SetAF(BK4819_AF_MUTE); - BK4819_ExitTxMute(); + BK4819_ExitTxMute(); - BK4819_WriteRegister(BK4819_REG_30, 0); - BK4819_WriteRegister(BK4819_REG_30, - BK4819_REG_30_ENABLE_VCO_CALIB | - BK4819_REG_30_ENABLE_RX_LINK | - BK4819_REG_30_ENABLE_AF_DAC | - BK4819_REG_30_ENABLE_DISC_MODE | - BK4819_REG_30_ENABLE_PLL_VCO | - BK4819_REG_30_ENABLE_RX_DSP); + BK4819_WriteRegister(BK4819_REG_30, 0); + BK4819_WriteRegister(BK4819_REG_30, + BK4819_REG_30_ENABLE_VCO_CALIB | + BK4819_REG_30_ENABLE_RX_LINK | + BK4819_REG_30_ENABLE_AF_DAC | + BK4819_REG_30_ENABLE_DISC_MODE | + BK4819_REG_30_ENABLE_PLL_VCO | + BK4819_REG_30_ENABLE_RX_DSP); } #ifdef ENABLE_AIRCOPY - void BK4819_SetupAircopy(void) - { - BK4819_WriteRegister(BK4819_REG_70, 0x00E0); // Enable Tone2, tuning gain 48 - BK4819_WriteRegister(BK4819_REG_72, 0x3065); // Tone2 baudrate 1200 - BK4819_WriteRegister(BK4819_REG_58, 0x00C1); // FSK Enable, FSK 1.2K RX Bandwidth, Preamble 0xAA or 0x55, RX Gain 0, RX Mode - // (FSK1.2K, FSK2.4K Rx and NOAA SAME Rx), TX Mode FSK 1.2K and FSK 2.4K Tx - BK4819_WriteRegister(BK4819_REG_5C, 0x5665); // Enable CRC among other things we don't know yet - BK4819_WriteRegister(BK4819_REG_5D, 0x4700); // FSK Data Length 72 Bytes (0xabcd + 2 byte length + 64 byte payload + 2 byte CRC + 0xdcba) - } + void BK4819_SetupAircopy(void) + { + BK4819_WriteRegister(BK4819_REG_70, 0x00E0); // Enable Tone2, tuning gain 48 + BK4819_WriteRegister(BK4819_REG_72, 0x3065); // Tone2 baudrate 1200 + BK4819_WriteRegister(BK4819_REG_58, 0x00C1); // FSK Enable, FSK 1.2K RX Bandwidth, Preamble 0xAA or 0x55, RX Gain 0, RX Mode + // (FSK1.2K, FSK2.4K Rx and NOAA SAME Rx), TX Mode FSK 1.2K and FSK 2.4K Tx + BK4819_WriteRegister(BK4819_REG_5C, 0x5665); // Enable CRC among other things we don't know yet + BK4819_WriteRegister(BK4819_REG_5D, 0x4700); // FSK Data Length 72 Bytes (0xabcd + 2 byte length + 64 byte payload + 2 byte CRC + 0xdcba) + } #endif void BK4819_ResetFSK(void) { - BK4819_WriteRegister(BK4819_REG_3F, 0x0000); // Disable interrupts - BK4819_WriteRegister(BK4819_REG_59, 0x0068); // Sync length 4 bytes, 7 byte preamble + BK4819_WriteRegister(BK4819_REG_3F, 0x0000); // Disable interrupts + BK4819_WriteRegister(BK4819_REG_59, 0x0068); // Sync length 4 bytes, 7 byte preamble - SYSTEM_DelayMs(30); + SYSTEM_DelayMs(30); - BK4819_Idle(); + BK4819_Idle(); } void BK4819_Idle(void) { - BK4819_WriteRegister(BK4819_REG_30, 0x0000); + BK4819_WriteRegister(BK4819_REG_30, 0x0000); } void BK4819_ExitBypass(void) { - BK4819_SetAF(BK4819_AF_MUTE); - - // REG_7E - // - // <15> 0 AGC fix mode - // 1 = fix - // 0 = auto - // - // <14:12> 3 AGC fix index - // 3 ( 3) = max - // 2 ( 2) - // 1 ( 1) - // 0 ( 0) - // 7 (-1) - // 6 (-2) - // 5 (-3) - // 4 (-4) = min - // - // <11:6> 0 ??? - // - // <5:3> 5 DC filter band width for Tx (MIC In) - // 0 ~ 7 - // 0 = bypass DC filter - // - // <2:0> 6 DC filter band width for Rx (I.F In) - // 0 ~ 7 - // 0 = bypass DC filter - // - - uint16_t regVal = BK4819_ReadRegister(BK4819_REG_7E); - - // 0x302E / 0 011 000000 101 110 - BK4819_WriteRegister(BK4819_REG_7E, (regVal & ~(0b111 << 3)) - - | (5u << 3) // 5 DC Filter band width for Tx (MIC In) - - ); + BK4819_SetAF(BK4819_AF_MUTE); + + // REG_7E + // + // <15> 0 AGC fix mode + // 1 = fix + // 0 = auto + // + // <14:12> 3 AGC fix index + // 3 ( 3) = max + // 2 ( 2) + // 1 ( 1) + // 0 ( 0) + // 7 (-1) + // 6 (-2) + // 5 (-3) + // 4 (-4) = min + // + // <11:6> 0 ??? + // + // <5:3> 5 DC filter band width for Tx (MIC In) + // 0 ~ 7 + // 0 = bypass DC filter + // + // <2:0> 6 DC filter band width for Rx (I.F In) + // 0 ~ 7 + // 0 = bypass DC filter + // + + uint16_t regVal = BK4819_ReadRegister(BK4819_REG_7E); + + // 0x302E / 0 011 000000 101 110 + BK4819_WriteRegister(BK4819_REG_7E, (regVal & ~(0b111 << 3)) + + | (5u << 3) // 5 DC Filter band width for Tx (MIC In) + + ); } void BK4819_PrepareTransmit(void) { - BK4819_ExitBypass(); - BK4819_ExitTxMute(); - BK4819_TxOn_Beep(); + BK4819_ExitBypass(); + BK4819_ExitTxMute(); + BK4819_TxOn_Beep(); } void BK4819_TxOn_Beep(void) { - BK4819_WriteRegister(BK4819_REG_37, 0x1D0F); - BK4819_WriteRegister(BK4819_REG_52, 0x028F); - BK4819_WriteRegister(BK4819_REG_30, 0x0000); - BK4819_WriteRegister(BK4819_REG_30, 0xC1FE); + BK4819_WriteRegister(BK4819_REG_37, 0x1D0F); + BK4819_WriteRegister(BK4819_REG_52, 0x028F); + BK4819_WriteRegister(BK4819_REG_30, 0x0000); + BK4819_WriteRegister(BK4819_REG_30, 0xC1FE); } void BK4819_ExitSubAu(void) { - // REG_51 - // - // <15> 0 - // 1 = Enable TxCTCSS/CDCSS - // 0 = Disable - // - // <14> 0 - // 1 = GPIO0Input for CDCSS - // 0 = Normal Mode (for BK4819 v3) - // - // <13> 0 - // 1 = Transmit negative CDCSS code - // 0 = Transmit positive CDCSS code - // - // <12> 0 CTCSS/CDCSS mode selection - // 1 = CTCSS - // 0 = CDCSS - // - // <11> 0 CDCSS 24/23bit selection - // 1 = 24bit - // 0 = 23bit - // - // <10> 0 1050HzDetectionMode - // 1 = 1050/4 Detect Enable, CTC1 should be set to 1050/4 Hz - // - // <9> 0 Auto CDCSS Bw Mode - // 1 = Disable - // 0 = Enable - // - // <8> 0 Auto CTCSS Bw Mode - // 0 = Enable - // 1 = Disable - // - // <6:0> 0 CTCSS/CDCSS Tx Gain1 Tuning - // 0 = min - // 127 = max - // - BK4819_WriteRegister(BK4819_REG_51, 0x0000); + // REG_51 + // + // <15> 0 + // 1 = Enable TxCTCSS/CDCSS + // 0 = Disable + // + // <14> 0 + // 1 = GPIO0Input for CDCSS + // 0 = Normal Mode (for BK4819 v3) + // + // <13> 0 + // 1 = Transmit negative CDCSS code + // 0 = Transmit positive CDCSS code + // + // <12> 0 CTCSS/CDCSS mode selection + // 1 = CTCSS + // 0 = CDCSS + // + // <11> 0 CDCSS 24/23bit selection + // 1 = 24bit + // 0 = 23bit + // + // <10> 0 1050HzDetectionMode + // 1 = 1050/4 Detect Enable, CTC1 should be set to 1050/4 Hz + // + // <9> 0 Auto CDCSS Bw Mode + // 1 = Disable + // 0 = Enable + // + // <8> 0 Auto CTCSS Bw Mode + // 0 = Enable + // 1 = Disable + // + // <6:0> 0 CTCSS/CDCSS Tx Gain1 Tuning + // 0 = min + // 127 = max + // + BK4819_WriteRegister(BK4819_REG_51, 0x0000); } void BK4819_Conditional_RX_TurnOn_and_GPIO6_Enable(void) { - if (gRxIdleMode) - { - BK4819_ToggleGpioOut(BK4819_GPIO0_PIN28_RX_ENABLE, true); - BK4819_RX_TurnOn(); - } + if (gRxIdleMode) + { + BK4819_ToggleGpioOut(BK4819_GPIO0_PIN28_RX_ENABLE, true); + BK4819_RX_TurnOn(); + } } void BK4819_EnterDTMF_TX(bool bLocalLoopback) { - BK4819_EnableDTMF(); - BK4819_EnterTxMute(); - BK4819_SetAF(bLocalLoopback ? BK4819_AF_BEEP : BK4819_AF_MUTE); + BK4819_EnableDTMF(); + BK4819_EnterTxMute(); + BK4819_SetAF(bLocalLoopback ? BK4819_AF_BEEP : BK4819_AF_MUTE); - BK4819_WriteRegister(BK4819_REG_70, - BK4819_REG_70_MASK_ENABLE_TONE1 | - (DTMF_TONE1_GAIN << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN) | - BK4819_REG_70_MASK_ENABLE_TONE2 | - (DTMF_TONE2_GAIN << BK4819_REG_70_SHIFT_TONE2_TUNING_GAIN)); + BK4819_WriteRegister(BK4819_REG_70, + BK4819_REG_70_MASK_ENABLE_TONE1 | + (DTMF_TONE1_GAIN << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN) | + BK4819_REG_70_MASK_ENABLE_TONE2 | + (DTMF_TONE2_GAIN << BK4819_REG_70_SHIFT_TONE2_TUNING_GAIN)); - BK4819_EnableTXLink(); + BK4819_EnableTXLink(); } void BK4819_ExitDTMF_TX(bool bKeep) { - BK4819_EnterTxMute(); - BK4819_SetAF(BK4819_AF_MUTE); - BK4819_WriteRegister(BK4819_REG_70, 0x0000); - BK4819_DisableDTMF(); - BK4819_WriteRegister(BK4819_REG_30, 0xC1FE); - if (!bKeep) - BK4819_ExitTxMute(); + BK4819_EnterTxMute(); + BK4819_SetAF(BK4819_AF_MUTE); + BK4819_WriteRegister(BK4819_REG_70, 0x0000); + BK4819_DisableDTMF(); + BK4819_WriteRegister(BK4819_REG_30, 0xC1FE); + if (!bKeep) + BK4819_ExitTxMute(); } void BK4819_EnableTXLink(void) { - BK4819_WriteRegister(BK4819_REG_30, - BK4819_REG_30_ENABLE_VCO_CALIB | - BK4819_REG_30_ENABLE_UNKNOWN | - BK4819_REG_30_DISABLE_RX_LINK | - BK4819_REG_30_ENABLE_AF_DAC | - BK4819_REG_30_ENABLE_DISC_MODE | - BK4819_REG_30_ENABLE_PLL_VCO | - BK4819_REG_30_ENABLE_PA_GAIN | - BK4819_REG_30_DISABLE_MIC_ADC | - BK4819_REG_30_ENABLE_TX_DSP | - BK4819_REG_30_DISABLE_RX_DSP); + BK4819_WriteRegister(BK4819_REG_30, + BK4819_REG_30_ENABLE_VCO_CALIB | + BK4819_REG_30_ENABLE_UNKNOWN | + BK4819_REG_30_DISABLE_RX_LINK | + BK4819_REG_30_ENABLE_AF_DAC | + BK4819_REG_30_ENABLE_DISC_MODE | + BK4819_REG_30_ENABLE_PLL_VCO | + BK4819_REG_30_ENABLE_PA_GAIN | + BK4819_REG_30_DISABLE_MIC_ADC | + BK4819_REG_30_ENABLE_TX_DSP | + BK4819_REG_30_DISABLE_RX_DSP); } void BK4819_PlayDTMF(char Code) { - struct DTMF_TonePair { - uint16_t tone1; - uint16_t tone2; - }; - - const struct DTMF_TonePair tones[] = { - {941, 1336}, - {697, 1209}, - {697, 1336}, - {697, 1477}, - {770, 1209}, - {770, 1336}, - {770, 1477}, - {852, 1209}, - {852, 1336}, - {852, 1477}, - {697, 1633}, - {770, 1633}, - {852, 1633}, - {941, 1633}, - {941, 1209}, - {941, 1477}, - }; - - - const struct DTMF_TonePair *pSelectedTone = NULL; - switch (Code) - { - case '0'...'9': pSelectedTone = &tones[0 + Code - '0']; break; - case 'A'...'D': pSelectedTone = &tones[10 + Code - 'A']; break; - case '*': pSelectedTone = &tones[14]; break; - case '#': pSelectedTone = &tones[15]; break; - default: pSelectedTone = NULL; - } - - if (pSelectedTone) { - BK4819_WriteRegister(BK4819_REG_71, (((uint32_t)pSelectedTone->tone1 * 103244) + 5000) / 10000); // with rounding - BK4819_WriteRegister(BK4819_REG_72, (((uint32_t)pSelectedTone->tone2 * 103244) + 5000) / 10000); // with rounding - } + struct DTMF_TonePair { + uint16_t tone1; + uint16_t tone2; + }; + + const struct DTMF_TonePair tones[] = { + {941, 1336}, + {697, 1209}, + {697, 1336}, + {697, 1477}, + {770, 1209}, + {770, 1336}, + {770, 1477}, + {852, 1209}, + {852, 1336}, + {852, 1477}, + {697, 1633}, + {770, 1633}, + {852, 1633}, + {941, 1633}, + {941, 1209}, + {941, 1477}, + }; + + + const struct DTMF_TonePair *pSelectedTone = NULL; + switch (Code) + { + case '0'...'9': pSelectedTone = &tones[0 + Code - '0']; break; + case 'A'...'D': pSelectedTone = &tones[10 + Code - 'A']; break; + case '*': pSelectedTone = &tones[14]; break; + case '#': pSelectedTone = &tones[15]; break; + default: pSelectedTone = NULL; + } + + if (pSelectedTone) { + BK4819_WriteRegister(BK4819_REG_71, (((uint32_t)pSelectedTone->tone1 * 103244) + 5000) / 10000); // with rounding + BK4819_WriteRegister(BK4819_REG_72, (((uint32_t)pSelectedTone->tone2 * 103244) + 5000) / 10000); // with rounding + } } void BK4819_PlayDTMFString(const char *pString, bool bDelayFirst, uint16_t FirstCodePersistTime, uint16_t HashCodePersistTime, uint16_t CodePersistTime, uint16_t CodeInternalTime) { - unsigned int i; - - if (pString == NULL) - return; - - for (i = 0; pString[i]; i++) - { - uint16_t Delay; - BK4819_PlayDTMF(pString[i]); - BK4819_ExitTxMute(); - if (bDelayFirst && i == 0) - Delay = FirstCodePersistTime; - else - if (pString[i] == '*' || pString[i] == '#') - Delay = HashCodePersistTime; - else - Delay = CodePersistTime; - SYSTEM_DelayMs(Delay); - BK4819_EnterTxMute(); - SYSTEM_DelayMs(CodeInternalTime); - } + unsigned int i; + + if (pString == NULL) + return; + + for (i = 0; pString[i]; i++) + { + uint16_t Delay; + BK4819_PlayDTMF(pString[i]); + BK4819_ExitTxMute(); + if (bDelayFirst && i == 0) + Delay = FirstCodePersistTime; + else + if (pString[i] == '*' || pString[i] == '#') + Delay = HashCodePersistTime; + else + Delay = CodePersistTime; + SYSTEM_DelayMs(Delay); + BK4819_EnterTxMute(); + SYSTEM_DelayMs(CodeInternalTime); + } } void BK4819_TransmitTone(bool bLocalLoopback, uint32_t Frequency) { - BK4819_EnterTxMute(); + BK4819_EnterTxMute(); - // REG_70 - // - // <15> 0 Enable TONE1 - // 1 = Enable - // 0 = Disable - // - // <14:8> 0 TONE1 tuning gain - // 0 ~ 127 - // - // <7> 0 Enable TONE2 - // 1 = Enable - // 0 = Disable - // - // <6:0> 0 TONE2/FSK amplitude - // 0 ~ 127 - // - // set the tone amplitude - // - BK4819_WriteRegister(BK4819_REG_70, BK4819_REG_70_MASK_ENABLE_TONE1 | (66u << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN)); + // REG_70 + // + // <15> 0 Enable TONE1 + // 1 = Enable + // 0 = Disable + // + // <14:8> 0 TONE1 tuning gain + // 0 ~ 127 + // + // <7> 0 Enable TONE2 + // 1 = Enable + // 0 = Disable + // + // <6:0> 0 TONE2/FSK amplitude + // 0 ~ 127 + // + // set the tone amplitude + // + BK4819_WriteRegister(BK4819_REG_70, BK4819_REG_70_MASK_ENABLE_TONE1 | (66u << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN)); - BK4819_WriteRegister(BK4819_REG_71, scale_freq(Frequency)); + BK4819_WriteRegister(BK4819_REG_71, scale_freq(Frequency)); - BK4819_SetAF(bLocalLoopback ? BK4819_AF_BEEP : BK4819_AF_MUTE); + BK4819_SetAF(bLocalLoopback ? BK4819_AF_BEEP : BK4819_AF_MUTE); - BK4819_EnableTXLink(); + BK4819_EnableTXLink(); - SYSTEM_DelayMs(50); + SYSTEM_DelayMs(50); - BK4819_ExitTxMute(); + BK4819_ExitTxMute(); } void BK4819_GenTail(uint8_t Tail) { - // REG_52 - // - // <15> 0 Enable 120/180/240 degree shift CTCSS or 134.4Hz Tail when CDCSS mode - // 0 = Normal - // 1 = Enable - // - // <14:13> 0 CTCSS tail mode selection (only valid when REG_52 <15> = 1) - // 00 = for 134.4Hz CTCSS Tail when CDCSS mode - // 01 = CTCSS0 120° phase shift - // 10 = CTCSS0 180° phase shift - // 11 = CTCSS0 240° phase shift - // - // <12> 0 CTCSSDetectionThreshold Mode - // 1 = ~0.1% - // 0 = 0.1 Hz - // - // <11:6> 0x0A CTCSS found detect threshold - // - // <5:0> 0x0F CTCSS lost detect threshold - - // REG_07 <15:0> - // - // When <13> = 0 for CTC1 - // <12:0> = CTC1 frequency control word = - // freq(Hz) * 20.64888 for XTAL 13M/26M or - // freq(Hz) * 20.97152 for XTAL 12.8M/19.2M/25.6M/38.4M - // - // When <13> = 1 for CTC2 (Tail 55Hz Rx detection) - // <12:0> = CTC2 (should below 100Hz) frequency control word = - // 25391 / freq(Hz) for XTAL 13M/26M or - // 25000 / freq(Hz) for XTAL 12.8M/19.2M/25.6M/38.4M - // - // When <13> = 2 for CDCSS 134.4Hz - // <12:0> = CDCSS baud rate frequency (134.4Hz) control word = - // freq(Hz) * 20.64888 for XTAL 13M/26M or - // freq(Hz)*20.97152 for XTAL 12.8M/19.2M/25.6M/38.4M - - switch (Tail) - { - case 0: // 134.4Hz CTCSS Tail - BK4819_WriteRegister(BK4819_REG_52, 0x828F); // 1 00 0 001010 001111 - break; - case 1: // 120° phase shift - BK4819_WriteRegister(BK4819_REG_52, 0xA28F); // 1 01 0 001010 001111 - break; - case 2: // 180° phase shift - BK4819_WriteRegister(BK4819_REG_52, 0xC28F); // 1 10 0 001010 001111 - break; - case 3: // 240° phase shift - BK4819_WriteRegister(BK4819_REG_52, 0xE28F); // 1 11 0 001010 001111 - break; - case 4: // 55Hz tone freq - BK4819_WriteRegister(BK4819_REG_07, 0x046f); // 0 00 0 010001 101111 - break; - } + // REG_52 + // + // <15> 0 Enable 120/180/240 degree shift CTCSS or 134.4Hz Tail when CDCSS mode + // 0 = Normal + // 1 = Enable + // + // <14:13> 0 CTCSS tail mode selection (only valid when REG_52 <15> = 1) + // 00 = for 134.4Hz CTCSS Tail when CDCSS mode + // 01 = CTCSS0 120° phase shift + // 10 = CTCSS0 180° phase shift + // 11 = CTCSS0 240° phase shift + // + // <12> 0 CTCSSDetectionThreshold Mode + // 1 = ~0.1% + // 0 = 0.1 Hz + // + // <11:6> 0x0A CTCSS found detect threshold + // + // <5:0> 0x0F CTCSS lost detect threshold + + // REG_07 <15:0> + // + // When <13> = 0 for CTC1 + // <12:0> = CTC1 frequency control word = + // freq(Hz) * 20.64888 for XTAL 13M/26M or + // freq(Hz) * 20.97152 for XTAL 12.8M/19.2M/25.6M/38.4M + // + // When <13> = 1 for CTC2 (Tail 55Hz Rx detection) + // <12:0> = CTC2 (should below 100Hz) frequency control word = + // 25391 / freq(Hz) for XTAL 13M/26M or + // 25000 / freq(Hz) for XTAL 12.8M/19.2M/25.6M/38.4M + // + // When <13> = 2 for CDCSS 134.4Hz + // <12:0> = CDCSS baud rate frequency (134.4Hz) control word = + // freq(Hz) * 20.64888 for XTAL 13M/26M or + // freq(Hz)*20.97152 for XTAL 12.8M/19.2M/25.6M/38.4M + + switch (Tail) + { + case 0: // 134.4Hz CTCSS Tail + BK4819_WriteRegister(BK4819_REG_52, 0x828F); // 1 00 0 001010 001111 + break; + case 1: // 120° phase shift + BK4819_WriteRegister(BK4819_REG_52, 0xA28F); // 1 01 0 001010 001111 + break; + case 2: // 180° phase shift + BK4819_WriteRegister(BK4819_REG_52, 0xC28F); // 1 10 0 001010 001111 + break; + case 3: // 240° phase shift + BK4819_WriteRegister(BK4819_REG_52, 0xE28F); // 1 11 0 001010 001111 + break; + case 4: // 55Hz tone freq + BK4819_WriteRegister(BK4819_REG_07, 0x046f); // 0 00 0 010001 101111 + break; + } } void BK4819_PlayCDCSSTail(void) { - BK4819_GenTail(0); // CTC134 - BK4819_WriteRegister(BK4819_REG_51, 0x804A); // 1 0 0 0 0 0 0 0 0 1001010 + BK4819_GenTail(0); // CTC134 + BK4819_WriteRegister(BK4819_REG_51, 0x804A); // 1 0 0 0 0 0 0 0 0 1001010 } void BK4819_PlayCTCSSTail(void) { - #ifdef ENABLE_CTCSS_TAIL_PHASE_SHIFT - BK4819_GenTail(2); // 180° phase shift - #else - BK4819_GenTail(4); // 55Hz tone freq - #endif - - // REG_51 - // - // <15> 0 - // 1 = Enable TxCTCSS/CDCSS - // 0 = Disable - // - // <14> 0 - // 1 = GPIO0Input for CDCSS - // 0 = Normal Mode (for BK4819 v3) - // - // <13> 0 - // 1 = Transmit negative CDCSS code - // 0 = Transmit positive CDCSS code - // - // <12> 0 CTCSS/CDCSS mode selection - // 1 = CTCSS - // 0 = CDCSS - // - // <11> 0 CDCSS 24/23bit selection - // 1 = 24bit - // 0 = 23bit - // - // <10> 0 1050HzDetectionMode - // 1 = 1050/4 Detect Enable, CTC1 should be set to 1050/4 Hz - // - // <9> 0 Auto CDCSS Bw Mode - // 1 = Disable - // 0 = Enable - // - // <8> 0 Auto CTCSS Bw Mode - // 0 = Enable - // 1 = Disable - // - // <6:0> 0 CTCSS/CDCSS Tx Gain1 Tuning - // 0 = min - // 127 = max - - BK4819_WriteRegister(BK4819_REG_51, 0x904A); // 1 0 0 1 0 0 0 0 0 1001010 + #ifdef ENABLE_CTCSS_TAIL_PHASE_SHIFT + BK4819_GenTail(2); // 180° phase shift + #else + BK4819_GenTail(4); // 55Hz tone freq + #endif + + // REG_51 + // + // <15> 0 + // 1 = Enable TxCTCSS/CDCSS + // 0 = Disable + // + // <14> 0 + // 1 = GPIO0Input for CDCSS + // 0 = Normal Mode (for BK4819 v3) + // + // <13> 0 + // 1 = Transmit negative CDCSS code + // 0 = Transmit positive CDCSS code + // + // <12> 0 CTCSS/CDCSS mode selection + // 1 = CTCSS + // 0 = CDCSS + // + // <11> 0 CDCSS 24/23bit selection + // 1 = 24bit + // 0 = 23bit + // + // <10> 0 1050HzDetectionMode + // 1 = 1050/4 Detect Enable, CTC1 should be set to 1050/4 Hz + // + // <9> 0 Auto CDCSS Bw Mode + // 1 = Disable + // 0 = Enable + // + // <8> 0 Auto CTCSS Bw Mode + // 0 = Enable + // 1 = Disable + // + // <6:0> 0 CTCSS/CDCSS Tx Gain1 Tuning + // 0 = min + // 127 = max + + BK4819_WriteRegister(BK4819_REG_51, 0x904A); // 1 0 0 1 0 0 0 0 0 1001010 } uint16_t BK4819_GetRSSI(void) { - return BK4819_ReadRegister(BK4819_REG_67) & 0x01FF; + return BK4819_ReadRegister(BK4819_REG_67) & 0x01FF; } uint8_t BK4819_GetGlitchIndicator(void) { - return BK4819_ReadRegister(BK4819_REG_63) & 0x00FF; + return BK4819_ReadRegister(BK4819_REG_63) & 0x00FF; } uint8_t BK4819_GetExNoiceIndicator(void) { - return BK4819_ReadRegister(BK4819_REG_65) & 0x007F; + return BK4819_ReadRegister(BK4819_REG_65) & 0x007F; } uint16_t BK4819_GetVoiceAmplitudeOut(void) { - return BK4819_ReadRegister(BK4819_REG_64); + return BK4819_ReadRegister(BK4819_REG_64); } uint8_t BK4819_GetAfTxRx(void) { - return BK4819_ReadRegister(BK4819_REG_6F) & 0x003F; + return BK4819_ReadRegister(BK4819_REG_6F) & 0x003F; } bool BK4819_GetFrequencyScanResult(uint32_t *pFrequency) { - const uint16_t High = BK4819_ReadRegister(BK4819_REG_0D); - const bool Finished = (High & 0x8000) == 0; - if (Finished) - { - const uint16_t Low = BK4819_ReadRegister(BK4819_REG_0E); - *pFrequency = (uint32_t)((High & 0x7FF) << 16) | Low; - } - return Finished; + const uint16_t High = BK4819_ReadRegister(BK4819_REG_0D); + const bool Finished = (High & 0x8000) == 0; + if (Finished) + { + const uint16_t Low = BK4819_ReadRegister(BK4819_REG_0E); + *pFrequency = (uint32_t)((High & 0x7FF) << 16) | Low; + } + return Finished; } BK4819_CssScanResult_t BK4819_GetCxCSSScanResult(uint32_t *pCdcssFreq, uint16_t *pCtcssFreq) { - uint16_t Low; - uint16_t High = BK4819_ReadRegister(BK4819_REG_69); + uint16_t Low; + uint16_t High = BK4819_ReadRegister(BK4819_REG_69); - if ((High & 0x8000) == 0) - { - Low = BK4819_ReadRegister(BK4819_REG_6A); - *pCdcssFreq = ((High & 0xFFF) << 12) | (Low & 0xFFF); - return BK4819_CSS_RESULT_CDCSS; - } + if ((High & 0x8000) == 0) + { + Low = BK4819_ReadRegister(BK4819_REG_6A); + *pCdcssFreq = ((High & 0xFFF) << 12) | (Low & 0xFFF); + return BK4819_CSS_RESULT_CDCSS; + } - Low = BK4819_ReadRegister(BK4819_REG_68); + Low = BK4819_ReadRegister(BK4819_REG_68); - if ((Low & 0x8000) == 0) - { - *pCtcssFreq = ((Low & 0x1FFF) * 4843) / 10000; - return BK4819_CSS_RESULT_CTCSS; - } + if ((Low & 0x8000) == 0) + { + *pCtcssFreq = ((Low & 0x1FFF) * 4843) / 10000; + return BK4819_CSS_RESULT_CTCSS; + } - return BK4819_CSS_RESULT_NOT_FOUND; + return BK4819_CSS_RESULT_NOT_FOUND; } void BK4819_DisableFrequencyScan(void) { - // REG_32 - // - // <15:14> 0 frequency scan time - // 0 = 0.2 sec - // 1 = 0.4 sec - // 2 = 0.8 sec - // 3 = 1.6 sec - // - // <13:1> ??? - // - // <0> 0 frequency scan enable - // 1 = enable - // 0 = disable - // - BK4819_WriteRegister(BK4819_REG_32, // 0x0244); // 00 0000100100010 0 - ( 0u << 14) | // 0 frequency scan Time - (290u << 1) | // ??? - ( 0u << 0)); // 0 frequency scan enable + // REG_32 + // + // <15:14> 0 frequency scan time + // 0 = 0.2 sec + // 1 = 0.4 sec + // 2 = 0.8 sec + // 3 = 1.6 sec + // + // <13:1> ??? + // + // <0> 0 frequency scan enable + // 1 = enable + // 0 = disable + // + BK4819_WriteRegister(BK4819_REG_32, // 0x0244); // 00 0000100100010 0 + ( 0u << 14) | // 0 frequency scan Time + (290u << 1) | // ??? + ( 0u << 0)); // 0 frequency scan enable } void BK4819_EnableFrequencyScan(void) { - // REG_32 - // - // <15:14> 0 frequency scan time - // 0 = 0.2 sec - // 1 = 0.4 sec - // 2 = 0.8 sec - // 3 = 1.6 sec - // - // <13:1> ??? - // - // <0> 0 frequency scan enable - // 1 = enable - // 0 = disable - // - BK4819_WriteRegister(BK4819_REG_32, // 0x0245); // 00 0000100100010 1 - ( 0u << 14) | // 0 frequency scan time - (290u << 1) | // ??? - ( 1u << 0)); // 1 frequency scan enable + // REG_32 + // + // <15:14> 0 frequency scan time + // 0 = 0.2 sec + // 1 = 0.4 sec + // 2 = 0.8 sec + // 3 = 1.6 sec + // + // <13:1> ??? + // + // <0> 0 frequency scan enable + // 1 = enable + // 0 = disable + // + BK4819_WriteRegister(BK4819_REG_32, // 0x0245); // 00 0000100100010 1 + ( 0u << 14) | // 0 frequency scan time + (290u << 1) | // ??? + ( 1u << 0)); // 1 frequency scan enable } void BK4819_SetScanFrequency(uint32_t Frequency) { - BK4819_SetFrequency(Frequency); - - // REG_51 - // - // <15> 0 - // 1 = Enable TxCTCSS/CDCSS - // 0 = Disable - // - // <14> 0 - // 1 = GPIO0Input for CDCSS - // 0 = Normal Mode (for BK4819 v3) - // - // <13> 0 - // 1 = Transmit negative CDCSS code - // 0 = Transmit positive CDCSS code - // - // <12> 0 CTCSS/CDCSS mode selection - // 1 = CTCSS - // 0 = CDCSS - // - // <11> 0 CDCSS 24/23bit selection - // 1 = 24bit - // 0 = 23bit - // - // <10> 0 1050HzDetectionMode - // 1 = 1050/4 Detect Enable, CTC1 should be set to 1050/4 Hz - // - // <9> 0 Auto CDCSS Bw Mode - // 1 = Disable - // 0 = Enable - // - // <8> 0 Auto CTCSS Bw Mode - // 0 = Enable - // 1 = Disable - // - // <6:0> 0 CTCSS/CDCSS Tx Gain1 Tuning - // 0 = min - // 127 = max - // - BK4819_WriteRegister(BK4819_REG_51, - BK4819_REG_51_DISABLE_CxCSS | - BK4819_REG_51_GPIO6_PIN2_NORMAL | - BK4819_REG_51_TX_CDCSS_POSITIVE | - BK4819_REG_51_MODE_CDCSS | - BK4819_REG_51_CDCSS_23_BIT | - BK4819_REG_51_1050HZ_NO_DETECTION | - BK4819_REG_51_AUTO_CDCSS_BW_DISABLE | - BK4819_REG_51_AUTO_CTCSS_BW_DISABLE); - - BK4819_RX_TurnOn(); + BK4819_SetFrequency(Frequency); + + // REG_51 + // + // <15> 0 + // 1 = Enable TxCTCSS/CDCSS + // 0 = Disable + // + // <14> 0 + // 1 = GPIO0Input for CDCSS + // 0 = Normal Mode (for BK4819 v3) + // + // <13> 0 + // 1 = Transmit negative CDCSS code + // 0 = Transmit positive CDCSS code + // + // <12> 0 CTCSS/CDCSS mode selection + // 1 = CTCSS + // 0 = CDCSS + // + // <11> 0 CDCSS 24/23bit selection + // 1 = 24bit + // 0 = 23bit + // + // <10> 0 1050HzDetectionMode + // 1 = 1050/4 Detect Enable, CTC1 should be set to 1050/4 Hz + // + // <9> 0 Auto CDCSS Bw Mode + // 1 = Disable + // 0 = Enable + // + // <8> 0 Auto CTCSS Bw Mode + // 0 = Enable + // 1 = Disable + // + // <6:0> 0 CTCSS/CDCSS Tx Gain1 Tuning + // 0 = min + // 127 = max + // + BK4819_WriteRegister(BK4819_REG_51, + BK4819_REG_51_DISABLE_CxCSS | + BK4819_REG_51_GPIO6_PIN2_NORMAL | + BK4819_REG_51_TX_CDCSS_POSITIVE | + BK4819_REG_51_MODE_CDCSS | + BK4819_REG_51_CDCSS_23_BIT | + BK4819_REG_51_1050HZ_NO_DETECTION | + BK4819_REG_51_AUTO_CDCSS_BW_DISABLE | + BK4819_REG_51_AUTO_CTCSS_BW_DISABLE); + + BK4819_RX_TurnOn(); } void BK4819_Disable(void) { - BK4819_WriteRegister(BK4819_REG_30, 0); + BK4819_WriteRegister(BK4819_REG_30, 0); } void BK4819_StopScan(void) { - BK4819_DisableFrequencyScan(); - BK4819_Disable(); + BK4819_DisableFrequencyScan(); + BK4819_Disable(); } uint8_t BK4819_GetDTMF_5TONE_Code(void) { - return (BK4819_ReadRegister(BK4819_REG_0B) >> 8) & 0x0F; + return (BK4819_ReadRegister(BK4819_REG_0B) >> 8) & 0x0F; } uint8_t BK4819_GetCDCSSCodeType(void) { - return (BK4819_ReadRegister(BK4819_REG_0C) >> 14) & 3u; + return (BK4819_ReadRegister(BK4819_REG_0C) >> 14) & 3u; } uint8_t BK4819_GetCTCShift(void) { - return (BK4819_ReadRegister(BK4819_REG_0C) >> 12) & 3u; + return (BK4819_ReadRegister(BK4819_REG_0C) >> 12) & 3u; } uint8_t BK4819_GetCTCType(void) { - return (BK4819_ReadRegister(BK4819_REG_0C) >> 10) & 3u; + return (BK4819_ReadRegister(BK4819_REG_0C) >> 10) & 3u; } void BK4819_SendFSKData(uint16_t *pData) { - unsigned int i; - uint8_t Timeout = 200; + unsigned int i; + uint8_t Timeout = 200; - SYSTEM_DelayMs(20); + SYSTEM_DelayMs(20); - BK4819_WriteRegister(BK4819_REG_3F, BK4819_REG_3F_FSK_TX_FINISHED); - BK4819_WriteRegister(BK4819_REG_59, 0x8068); - BK4819_WriteRegister(BK4819_REG_59, 0x0068); + BK4819_WriteRegister(BK4819_REG_3F, BK4819_REG_3F_FSK_TX_FINISHED); + BK4819_WriteRegister(BK4819_REG_59, 0x8068); + BK4819_WriteRegister(BK4819_REG_59, 0x0068); - for (i = 0; i < 36; i++) - BK4819_WriteRegister(BK4819_REG_5F, pData[i]); + for (i = 0; i < 36; i++) + BK4819_WriteRegister(BK4819_REG_5F, pData[i]); - SYSTEM_DelayMs(20); + SYSTEM_DelayMs(20); - BK4819_WriteRegister(BK4819_REG_59, 0x2868); + BK4819_WriteRegister(BK4819_REG_59, 0x2868); - while (Timeout-- && (BK4819_ReadRegister(BK4819_REG_0C) & 1u) == 0) - SYSTEM_DelayMs(5); + while (Timeout-- && (BK4819_ReadRegister(BK4819_REG_0C) & 1u) == 0) + SYSTEM_DelayMs(5); - BK4819_WriteRegister(BK4819_REG_02, 0); + BK4819_WriteRegister(BK4819_REG_02, 0); - SYSTEM_DelayMs(20); + SYSTEM_DelayMs(20); - BK4819_ResetFSK(); + BK4819_ResetFSK(); } void BK4819_PrepareFSKReceive(void) { - BK4819_ResetFSK(); - BK4819_WriteRegister(BK4819_REG_02, 0); - BK4819_WriteRegister(BK4819_REG_3F, 0); - BK4819_RX_TurnOn(); - BK4819_WriteRegister(BK4819_REG_3F, 0 | BK4819_REG_3F_FSK_RX_FINISHED | BK4819_REG_3F_FSK_FIFO_ALMOST_FULL); + BK4819_ResetFSK(); + BK4819_WriteRegister(BK4819_REG_02, 0); + BK4819_WriteRegister(BK4819_REG_3F, 0); + BK4819_RX_TurnOn(); + BK4819_WriteRegister(BK4819_REG_3F, 0 | BK4819_REG_3F_FSK_RX_FINISHED | BK4819_REG_3F_FSK_FIFO_ALMOST_FULL); - // Clear RX FIFO - // FSK Preamble Length 7 bytes - // FSK SyncLength Selection - BK4819_WriteRegister(BK4819_REG_59, 0x4068); + // Clear RX FIFO + // FSK Preamble Length 7 bytes + // FSK SyncLength Selection + BK4819_WriteRegister(BK4819_REG_59, 0x4068); - // Enable FSK Scramble - // Enable FSK RX - // FSK Preamble Length 7 bytes - // FSK SyncLength Selection - BK4819_WriteRegister(BK4819_REG_59, 0x3068); + // Enable FSK Scramble + // Enable FSK RX + // FSK Preamble Length 7 bytes + // FSK SyncLength Selection + BK4819_WriteRegister(BK4819_REG_59, 0x3068); } static void BK4819_PlayRogerNormal(void) { - #if 0 - const uint32_t tone1_Hz = 500; - const uint32_t tone2_Hz = 700; - #else - // motorola type - const uint32_t tone1_Hz = 1540; - const uint32_t tone2_Hz = 1310; - #endif + #if 0 + const uint32_t tone1_Hz = 500; + const uint32_t tone2_Hz = 700; + #else + // motorola type + const uint32_t tone1_Hz = 1540; + const uint32_t tone2_Hz = 1310; + #endif - BK4819_EnterTxMute(); - BK4819_SetAF(BK4819_AF_MUTE); + BK4819_EnterTxMute(); + BK4819_SetAF(BK4819_AF_MUTE); - BK4819_WriteRegister(BK4819_REG_70, BK4819_REG_70_ENABLE_TONE1 | (66u << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN)); + BK4819_WriteRegister(BK4819_REG_70, BK4819_REG_70_ENABLE_TONE1 | (66u << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN)); - BK4819_EnableTXLink(); - SYSTEM_DelayMs(50); + BK4819_EnableTXLink(); + SYSTEM_DelayMs(50); - BK4819_WriteRegister(BK4819_REG_71, scale_freq(tone1_Hz)); + BK4819_WriteRegister(BK4819_REG_71, scale_freq(tone1_Hz)); - BK4819_ExitTxMute(); - SYSTEM_DelayMs(80); - BK4819_EnterTxMute(); + BK4819_ExitTxMute(); + SYSTEM_DelayMs(80); + BK4819_EnterTxMute(); - BK4819_WriteRegister(BK4819_REG_71, scale_freq(tone2_Hz)); + BK4819_WriteRegister(BK4819_REG_71, scale_freq(tone2_Hz)); - BK4819_ExitTxMute(); - SYSTEM_DelayMs(80); - BK4819_EnterTxMute(); + BK4819_ExitTxMute(); + SYSTEM_DelayMs(80); + BK4819_EnterTxMute(); - BK4819_WriteRegister(BK4819_REG_70, 0x0000); - BK4819_WriteRegister(BK4819_REG_30, 0xC1FE); // 1 1 0000 0 1 1111 1 1 1 0 + BK4819_WriteRegister(BK4819_REG_70, 0x0000); + BK4819_WriteRegister(BK4819_REG_30, 0xC1FE); // 1 1 0000 0 1 1111 1 1 1 0 } void BK4819_PlayRogerMDC(void) { - struct reg_value { - BK4819_REGISTER_t reg; - uint16_t value; - }; + struct reg_value { + BK4819_REGISTER_t reg; + uint16_t value; + }; - struct reg_value RogerMDC_Configuration [] = { - { BK4819_REG_58, 0x37C3 }, // FSK Enable, - // RX Bandwidth FFSK 1200/1800 - // 0xAA or 0x55 Preamble - // 11 RX Gain, - // 101 RX Mode - // TX FFSK 1200/1800 - { BK4819_REG_72, 0x3065 }, // Set Tone-2 to 1200Hz - { BK4819_REG_70, 0x00E0 }, // Enable Tone-2 and Set Tone2 Gain - { BK4819_REG_5D, 0x0D00 }, // Set FSK data length to 13 bytes - { BK4819_REG_59, 0x8068 }, // 4 byte sync length, 6 byte preamble, clear TX FIFO - { BK4819_REG_59, 0x0068 }, // Same, but clear TX FIFO is now unset (clearing done) - { BK4819_REG_5A, 0x5555 }, // First two sync bytes - { BK4819_REG_5B, 0x55AA }, // End of sync bytes. Total 4 bytes: 555555aa - { BK4819_REG_5C, 0xAA30 }, // Disable CRC - }; + struct reg_value RogerMDC_Configuration [] = { + { BK4819_REG_58, 0x37C3 }, // FSK Enable, + // RX Bandwidth FFSK 1200/1800 + // 0xAA or 0x55 Preamble + // 11 RX Gain, + // 101 RX Mode + // TX FFSK 1200/1800 + { BK4819_REG_72, 0x3065 }, // Set Tone-2 to 1200Hz + { BK4819_REG_70, 0x00E0 }, // Enable Tone-2 and Set Tone2 Gain + { BK4819_REG_5D, 0x0D00 }, // Set FSK data length to 13 bytes + { BK4819_REG_59, 0x8068 }, // 4 byte sync length, 6 byte preamble, clear TX FIFO + { BK4819_REG_59, 0x0068 }, // Same, but clear TX FIFO is now unset (clearing done) + { BK4819_REG_5A, 0x5555 }, // First two sync bytes + { BK4819_REG_5B, 0x55AA }, // End of sync bytes. Total 4 bytes: 555555aa + { BK4819_REG_5C, 0xAA30 }, // Disable CRC + }; - BK4819_SetAF(BK4819_AF_MUTE); + BK4819_SetAF(BK4819_AF_MUTE); - for (unsigned int i = 0; i < ARRAY_SIZE(RogerMDC_Configuration); i++) { - BK4819_WriteRegister(RogerMDC_Configuration[i].reg, RogerMDC_Configuration[i].value); - } + for (unsigned int i = 0; i < ARRAY_SIZE(RogerMDC_Configuration); i++) { + BK4819_WriteRegister(RogerMDC_Configuration[i].reg, RogerMDC_Configuration[i].value); + } - // Send the data from the roger table - for (unsigned int i = 0; i < ARRAY_SIZE(FSK_RogerTable); i++) { - BK4819_WriteRegister(BK4819_REG_5F, FSK_RogerTable[i]); - } + // Send the data from the roger table + for (unsigned int i = 0; i < ARRAY_SIZE(FSK_RogerTable); i++) { + BK4819_WriteRegister(BK4819_REG_5F, FSK_RogerTable[i]); + } - SYSTEM_DelayMs(20); + SYSTEM_DelayMs(20); - // 4 sync bytes, 6 byte preamble, Enable FSK TX - BK4819_WriteRegister(BK4819_REG_59, 0x0868); + // 4 sync bytes, 6 byte preamble, Enable FSK TX + BK4819_WriteRegister(BK4819_REG_59, 0x0868); - SYSTEM_DelayMs(180); + SYSTEM_DelayMs(180); - // Stop FSK TX, reset Tone-2, disable FSK - BK4819_WriteRegister(BK4819_REG_59, 0x0068); - BK4819_WriteRegister(BK4819_REG_70, 0x0000); - BK4819_WriteRegister(BK4819_REG_58, 0x0000); + // Stop FSK TX, reset Tone-2, disable FSK + BK4819_WriteRegister(BK4819_REG_59, 0x0068); + BK4819_WriteRegister(BK4819_REG_70, 0x0000); + BK4819_WriteRegister(BK4819_REG_58, 0x0000); } void BK4819_PlayRoger(void) { - if (gEeprom.ROGER == ROGER_MODE_ROGER) { - BK4819_PlayRogerNormal(); - } else if (gEeprom.ROGER == ROGER_MODE_MDC) { - BK4819_PlayRogerMDC(); - } + if (gEeprom.ROGER == ROGER_MODE_ROGER) { + BK4819_PlayRogerNormal(); + } else if (gEeprom.ROGER == ROGER_MODE_MDC) { + BK4819_PlayRogerMDC(); + } } void BK4819_Enable_AfDac_DiscMode_TxDsp(void) { - BK4819_WriteRegister(BK4819_REG_30, 0x0000); - BK4819_WriteRegister(BK4819_REG_30, 0x0302); + BK4819_WriteRegister(BK4819_REG_30, 0x0000); + BK4819_WriteRegister(BK4819_REG_30, 0x0302); } void BK4819_GetVoxAmp(uint16_t *pResult) { - *pResult = BK4819_ReadRegister(BK4819_REG_64) & 0x7FFF; + *pResult = BK4819_ReadRegister(BK4819_REG_64) & 0x7FFF; } void BK4819_SetScrambleFrequencyControlWord(uint32_t Frequency) { - BK4819_WriteRegister(BK4819_REG_71, scale_freq(Frequency)); + BK4819_WriteRegister(BK4819_REG_71, scale_freq(Frequency)); } void BK4819_PlayDTMFEx(bool bLocalLoopback, char Code) { - BK4819_EnableDTMF(); - BK4819_EnterTxMute(); + BK4819_EnableDTMF(); + BK4819_EnterTxMute(); - BK4819_SetAF(bLocalLoopback ? BK4819_AF_BEEP : BK4819_AF_MUTE); + BK4819_SetAF(bLocalLoopback ? BK4819_AF_BEEP : BK4819_AF_MUTE); - BK4819_WriteRegister(BK4819_REG_70, - BK4819_REG_70_MASK_ENABLE_TONE1 | - (DTMF_TONE1_GAIN << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN) | - BK4819_REG_70_MASK_ENABLE_TONE2 | - (DTMF_TONE2_GAIN << BK4819_REG_70_SHIFT_TONE2_TUNING_GAIN)); + BK4819_WriteRegister(BK4819_REG_70, + BK4819_REG_70_MASK_ENABLE_TONE1 | + (DTMF_TONE1_GAIN << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN) | + BK4819_REG_70_MASK_ENABLE_TONE2 | + (DTMF_TONE2_GAIN << BK4819_REG_70_SHIFT_TONE2_TUNING_GAIN)); - BK4819_EnableTXLink(); + BK4819_EnableTXLink(); - SYSTEM_DelayMs(50); + SYSTEM_DelayMs(50); - BK4819_PlayDTMF(Code); + BK4819_PlayDTMF(Code); - BK4819_ExitTxMute(); + BK4819_ExitTxMute(); } diff --git a/driver/bk4819.h b/driver/bk4819.h index 1a6d06efd..b700377f2 100644 --- a/driver/bk4819.h +++ b/driver/bk4819.h @@ -24,40 +24,40 @@ enum BK4819_AF_Type_t { - BK4819_AF_MUTE = 0u, // - BK4819_AF_FM = 1u, // FM - BK4819_AF_ALAM = 2u, // - BK4819_AF_BEEP = 3u, // - BK4819_AF_BASEBAND1 = 4u, // RAW - BK4819_AF_BASEBAND2 = 5u, // USB - BK4819_AF_CTCO = 6u, // strange LF audio .. maybe the CTCSS LF line ? - BK4819_AF_AM = 7u, // AM - BK4819_AF_FSKO = 8u, // nothing - BK4819_AF_UNKNOWN3 = 9u, // BYP - BK4819_AF_UNKNOWN4 = 10u, // nothing at all - BK4819_AF_UNKNOWN5 = 11u, // distorted - BK4819_AF_UNKNOWN6 = 12u, // distorted - BK4819_AF_UNKNOWN7 = 13u, // interesting - BK4819_AF_UNKNOWN8 = 14u, // interesting - BK4819_AF_UNKNOWN9 = 15u // not a lot + BK4819_AF_MUTE = 0u, // + BK4819_AF_FM = 1u, // FM + BK4819_AF_ALAM = 2u, // + BK4819_AF_BEEP = 3u, // + BK4819_AF_BASEBAND1 = 4u, // RAW + BK4819_AF_BASEBAND2 = 5u, // USB + BK4819_AF_CTCO = 6u, // strange LF audio .. maybe the CTCSS LF line ? + BK4819_AF_AM = 7u, // AM + BK4819_AF_FSKO = 8u, // nothing + BK4819_AF_UNKNOWN3 = 9u, // BYP + BK4819_AF_UNKNOWN4 = 10u, // nothing at all + BK4819_AF_UNKNOWN5 = 11u, // distorted + BK4819_AF_UNKNOWN6 = 12u, // distorted + BK4819_AF_UNKNOWN7 = 13u, // interesting + BK4819_AF_UNKNOWN8 = 14u, // interesting + BK4819_AF_UNKNOWN9 = 15u // not a lot }; typedef enum BK4819_AF_Type_t BK4819_AF_Type_t; enum BK4819_FilterBandwidth_t { - BK4819_FILTER_BW_WIDE = 0, - BK4819_FILTER_BW_NARROW, - BK4819_FILTER_BW_NARROWER + BK4819_FILTER_BW_WIDE = 0, + BK4819_FILTER_BW_NARROW, + BK4819_FILTER_BW_NARROWER }; typedef enum BK4819_FilterBandwidth_t BK4819_FilterBandwidth_t; enum BK4819_CssScanResult_t { - BK4819_CSS_RESULT_NOT_FOUND = 0, - BK4819_CSS_RESULT_CTCSS, - BK4819_CSS_RESULT_CDCSS + BK4819_CSS_RESULT_NOT_FOUND = 0, + BK4819_CSS_RESULT_CTCSS, + BK4819_CSS_RESULT_CDCSS }; typedef enum BK4819_CssScanResult_t BK4819_CssScanResult_t; @@ -85,12 +85,12 @@ void BK4819_SetFilterBandwidth(const BK4819_FilterBandwidth_t Bandwidth, con void BK4819_SetupPowerAmplifier(const uint8_t bias, const uint32_t frequency); void BK4819_SetFrequency(uint32_t Frequency); void BK4819_SetupSquelch( - uint8_t SquelchOpenRSSIThresh, - uint8_t SquelchCloseRSSIThresh, - uint8_t SquelchOpenNoiseThresh, - uint8_t SquelchCloseNoiseThresh, - uint8_t SquelchCloseGlitchThresh, - uint8_t SquelchOpenGlitchThresh); + uint8_t SquelchOpenRSSIThresh, + uint8_t SquelchCloseRSSIThresh, + uint8_t SquelchOpenNoiseThresh, + uint8_t SquelchCloseNoiseThresh, + uint8_t SquelchCloseGlitchThresh, + uint8_t SquelchOpenGlitchThresh); void BK4819_SetAF(BK4819_AF_Type_t AF); void BK4819_RX_TurnOn(void); @@ -111,7 +111,7 @@ void BK4819_ExitTxMute(void); void BK4819_Sleep(void); void BK4819_TurnsOffTones_TurnsOnRX(void); #ifdef ENABLE_AIRCOPY - void BK4819_SetupAircopy(void); + void BK4819_SetupAircopy(void); #endif void BK4819_ResetFSK(void); void BK4819_Idle(void); diff --git a/driver/crc.c b/driver/crc.c index 6acb966de..d3fd2af3d 100644 --- a/driver/crc.c +++ b/driver/crc.c @@ -19,31 +19,31 @@ void CRC_Init(void) { - CRC_CR = 0 - | CRC_CR_CRC_EN_BITS_DISABLE - | CRC_CR_INPUT_REV_BITS_NORMAL - | CRC_CR_INPUT_INV_BITS_NORMAL - | CRC_CR_OUTPUT_REV_BITS_NORMAL - | CRC_CR_OUTPUT_INV_BITS_NORMAL - | CRC_CR_DATA_WIDTH_BITS_8 - | CRC_CR_CRC_SEL_BITS_CRC_16_CCITT - ; - CRC_IV = 0; + CRC_CR = 0 + | CRC_CR_CRC_EN_BITS_DISABLE + | CRC_CR_INPUT_REV_BITS_NORMAL + | CRC_CR_INPUT_INV_BITS_NORMAL + | CRC_CR_OUTPUT_REV_BITS_NORMAL + | CRC_CR_OUTPUT_INV_BITS_NORMAL + | CRC_CR_DATA_WIDTH_BITS_8 + | CRC_CR_CRC_SEL_BITS_CRC_16_CCITT + ; + CRC_IV = 0; } uint16_t CRC_Calculate(const void *pBuffer, uint16_t Size) { - const uint8_t *pData = (const uint8_t *)pBuffer; - uint16_t i, Crc; + const uint8_t *pData = (const uint8_t *)pBuffer; + uint16_t i, Crc; - CRC_CR = (CRC_CR & ~CRC_CR_CRC_EN_MASK) | CRC_CR_CRC_EN_BITS_ENABLE; + CRC_CR = (CRC_CR & ~CRC_CR_CRC_EN_MASK) | CRC_CR_CRC_EN_BITS_ENABLE; - for (i = 0; i < Size; i++) { - CRC_DATAIN = pData[i]; - } - Crc = (uint16_t)CRC_DATAOUT; + for (i = 0; i < Size; i++) { + CRC_DATAIN = pData[i]; + } + Crc = (uint16_t)CRC_DATAOUT; - CRC_CR = (CRC_CR & ~CRC_CR_CRC_EN_MASK) | CRC_CR_CRC_EN_BITS_DISABLE; + CRC_CR = (CRC_CR & ~CRC_CR_CRC_EN_MASK) | CRC_CR_CRC_EN_BITS_DISABLE; - return Crc; + return Crc; } diff --git a/driver/eeprom.c b/driver/eeprom.c index 07cca2ed1..4357f658d 100644 --- a/driver/eeprom.c +++ b/driver/eeprom.c @@ -23,41 +23,41 @@ void EEPROM_ReadBuffer(uint16_t Address, void *pBuffer, uint8_t Size) { - I2C_Start(); + I2C_Start(); - I2C_Write(0xA0); + I2C_Write(0xA0); - I2C_Write((Address >> 8) & 0xFF); - I2C_Write((Address >> 0) & 0xFF); + I2C_Write((Address >> 8) & 0xFF); + I2C_Write((Address >> 0) & 0xFF); - I2C_Start(); + I2C_Start(); - I2C_Write(0xA1); + I2C_Write(0xA1); - I2C_ReadBuffer(pBuffer, Size); + I2C_ReadBuffer(pBuffer, Size); - I2C_Stop(); + I2C_Stop(); } void EEPROM_WriteBuffer(uint16_t Address, const void *pBuffer) { - if (pBuffer == NULL || Address >= 0x2000) - return; + if (pBuffer == NULL || Address >= 0x2000) + return; - uint8_t buffer[8]; - EEPROM_ReadBuffer(Address, buffer, 8); - if (memcmp(pBuffer, buffer, 8) == 0) { - return; - } + uint8_t buffer[8]; + EEPROM_ReadBuffer(Address, buffer, 8); + if (memcmp(pBuffer, buffer, 8) == 0) { + return; + } - I2C_Start(); - I2C_Write(0xA0); - I2C_Write((Address >> 8) & 0xFF); - I2C_Write((Address >> 0) & 0xFF); - I2C_WriteBuffer(pBuffer, 8); - I2C_Stop(); + I2C_Start(); + I2C_Write(0xA0); + I2C_Write((Address >> 8) & 0xFF); + I2C_Write((Address >> 0) & 0xFF); + I2C_WriteBuffer(pBuffer, 8); + I2C_Stop(); - // give the EEPROM time to burn the data in (apparently takes 5ms) - SYSTEM_DelayMs(8); + // give the EEPROM time to burn the data in (apparently takes 5ms) + SYSTEM_DelayMs(8); } diff --git a/driver/flash.c b/driver/flash.c index aa4116d46..8f0cf6690 100644 --- a/driver/flash.c +++ b/driver/flash.c @@ -19,15 +19,15 @@ void FLASH_Init(FLASH_READ_MODE ReadMode) { - overlay_FLASH_Init(ReadMode); + overlay_FLASH_Init(ReadMode); } void FLASH_ConfigureTrimValues(void) { - overlay_FLASH_ConfigureTrimValues(); + overlay_FLASH_ConfigureTrimValues(); } uint32_t FLASH_ReadNvrWord(uint32_t Address) { - return overlay_FLASH_ReadNvrWord(Address); + return overlay_FLASH_ReadNvrWord(Address); } diff --git a/driver/flash.h b/driver/flash.h index 794716376..b827c4c57 100644 --- a/driver/flash.h +++ b/driver/flash.h @@ -20,33 +20,33 @@ #include "bsp/dp32g030/flash.h" enum FLASH_READ_MODE { - FLASH_READ_MODE_1_CYCLE = FLASH_CFG_READ_MD_VALUE_1_CYCLE, - FLASH_READ_MODE_2_CYCLE = FLASH_CFG_READ_MD_VALUE_2_CYCLE, + FLASH_READ_MODE_1_CYCLE = FLASH_CFG_READ_MD_VALUE_1_CYCLE, + FLASH_READ_MODE_2_CYCLE = FLASH_CFG_READ_MD_VALUE_2_CYCLE, }; typedef enum FLASH_READ_MODE FLASH_READ_MODE; enum FLASH_MASK_SELECTION { - FLASH_MASK_SELECTION_NONE = FLASH_MASK_SEL_VALUE_NONE, - FLASH_MASK_SELECTION_2KB = FLASH_MASK_SEL_VALUE_2KB, - FLASH_MASK_SELECTION_4KB = FLASH_MASK_SEL_VALUE_4KB, - FLASH_MASK_SELECTION_8KB = FLASH_MASK_SEL_VALUE_8KB, + FLASH_MASK_SELECTION_NONE = FLASH_MASK_SEL_VALUE_NONE, + FLASH_MASK_SELECTION_2KB = FLASH_MASK_SEL_VALUE_2KB, + FLASH_MASK_SELECTION_4KB = FLASH_MASK_SEL_VALUE_4KB, + FLASH_MASK_SELECTION_8KB = FLASH_MASK_SEL_VALUE_8KB, }; typedef enum FLASH_MASK_SELECTION FLASH_MASK_SELECTION; enum FLASH_MODE { - FLASH_MODE_READ_AHB = FLASH_CFG_MODE_VALUE_READ_AHB, - FLASH_MODE_PROGRAM = FLASH_CFG_MODE_VALUE_PROGRAM, - FLASH_MODE_ERASE = FLASH_CFG_MODE_VALUE_ERASE, - FLASH_MODE_READ_APB = FLASH_CFG_MODE_VALUE_READ_APB, + FLASH_MODE_READ_AHB = FLASH_CFG_MODE_VALUE_READ_AHB, + FLASH_MODE_PROGRAM = FLASH_CFG_MODE_VALUE_PROGRAM, + FLASH_MODE_ERASE = FLASH_CFG_MODE_VALUE_ERASE, + FLASH_MODE_READ_APB = FLASH_CFG_MODE_VALUE_READ_APB, }; typedef enum FLASH_MODE FLASH_MODE; enum FLASH_AREA { - FLASH_AREA_MAIN = FLASH_CFG_NVR_SEL_VALUE_MAIN, - FLASH_AREA_NVR = FLASH_CFG_NVR_SEL_VALUE_NVR, + FLASH_AREA_MAIN = FLASH_CFG_NVR_SEL_VALUE_MAIN, + FLASH_AREA_NVR = FLASH_CFG_NVR_SEL_VALUE_NVR, }; typedef enum FLASH_AREA FLASH_AREA; diff --git a/driver/gpio.h b/driver/gpio.h index 4de7e8b13..54883929d 100644 --- a/driver/gpio.h +++ b/driver/gpio.h @@ -20,58 +20,58 @@ #include enum GPIOA_PINS { - GPIOA_PIN_KEYBOARD_0 = 3, - GPIOA_PIN_KEYBOARD_1 = 4, - GPIOA_PIN_KEYBOARD_2 = 5, - GPIOA_PIN_KEYBOARD_3 = 6, - GPIOA_PIN_KEYBOARD_4 = 10, // Shared with I2C! - GPIOA_PIN_KEYBOARD_5 = 11, // Shared with I2C! - GPIOA_PIN_KEYBOARD_6 = 12, // Shared with voice chip! - GPIOA_PIN_KEYBOARD_7 = 13, // Shared with voice chip! - - GPIOA_PIN_I2C_SCL = 10, // Shared with keyboard! - GPIOA_PIN_I2C_SDA = 11, // Shared with keyboard! - - GPIOA_PIN_VOICE_0 = 12, // Shared with keyboard! - GPIOA_PIN_VOICE_1 = 13 // Shared with keyboard! + GPIOA_PIN_KEYBOARD_0 = 3, + GPIOA_PIN_KEYBOARD_1 = 4, + GPIOA_PIN_KEYBOARD_2 = 5, + GPIOA_PIN_KEYBOARD_3 = 6, + GPIOA_PIN_KEYBOARD_4 = 10, // Shared with I2C! + GPIOA_PIN_KEYBOARD_5 = 11, // Shared with I2C! + GPIOA_PIN_KEYBOARD_6 = 12, // Shared with voice chip! + GPIOA_PIN_KEYBOARD_7 = 13, // Shared with voice chip! + + GPIOA_PIN_I2C_SCL = 10, // Shared with keyboard! + GPIOA_PIN_I2C_SDA = 11, // Shared with keyboard! + + GPIOA_PIN_VOICE_0 = 12, // Shared with keyboard! + GPIOA_PIN_VOICE_1 = 13 // Shared with keyboard! }; enum GPIOB_PINS { - GPIOB_PIN_BACKLIGHT = 6, + GPIOB_PIN_BACKLIGHT = 6, - GPIOB_PIN_ST7565_A0 = 9, - GPIOB_PIN_ST7565_RES = 11, // Shared with SWD! + GPIOB_PIN_ST7565_A0 = 9, + GPIOB_PIN_ST7565_RES = 11, // Shared with SWD! - GPIOB_PIN_SWD_IO = 11, // Shared with ST7565! - GPIOB_PIN_SWD_CLK = 14, + GPIOB_PIN_SWD_IO = 11, // Shared with ST7565! + GPIOB_PIN_SWD_CLK = 14, - GPIOB_PIN_BK1080 = 15 + GPIOB_PIN_BK1080 = 15 }; enum GPIOC_PINS { - GPIOC_PIN_BK4819_SCN = 0, - GPIOC_PIN_BK4819_SCL = 1, - GPIOC_PIN_BK4819_SDA = 2, + GPIOC_PIN_BK4819_SCN = 0, + GPIOC_PIN_BK4819_SCL = 1, + GPIOC_PIN_BK4819_SDA = 2, - GPIOC_PIN_FLASHLIGHT = 3, - GPIOC_PIN_AUDIO_PATH = 4, - GPIOC_PIN_PTT = 5 + GPIOC_PIN_FLASHLIGHT = 3, + GPIOC_PIN_AUDIO_PATH = 4, + GPIOC_PIN_PTT = 5 }; static inline void GPIO_ClearBit(volatile uint32_t *pReg, uint8_t Bit) { - *pReg &= ~(1U << Bit); + *pReg &= ~(1U << Bit); } static inline uint8_t GPIO_CheckBit(volatile uint32_t *pReg, uint8_t Bit) { - return (*pReg >> Bit) & 1U; + return (*pReg >> Bit) & 1U; } static inline void GPIO_FlipBit(volatile uint32_t *pReg, uint8_t Bit) { - *pReg ^= 1U << Bit; + *pReg ^= 1U << Bit; } static inline void GPIO_SetBit(volatile uint32_t *pReg, uint8_t Bit) { - *pReg |= 1U << Bit; + *pReg |= 1U << Bit; } #endif diff --git a/driver/i2c.c b/driver/i2c.c index 620036440..9b80c239f 100644 --- a/driver/i2c.c +++ b/driver/i2c.c @@ -22,143 +22,143 @@ void I2C_Start(void) { - GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA); - SYSTICK_DelayUs(1); - GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL); - SYSTICK_DelayUs(1); - GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA); - SYSTICK_DelayUs(1); - GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL); - SYSTICK_DelayUs(1); + GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA); + SYSTICK_DelayUs(1); + GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL); + SYSTICK_DelayUs(1); + GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA); + SYSTICK_DelayUs(1); + GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL); + SYSTICK_DelayUs(1); } void I2C_Stop(void) { - GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA); - SYSTICK_DelayUs(1); - GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL); - SYSTICK_DelayUs(1); - GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL); - SYSTICK_DelayUs(1); - GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA); - SYSTICK_DelayUs(1); + GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA); + SYSTICK_DelayUs(1); + GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL); + SYSTICK_DelayUs(1); + GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL); + SYSTICK_DelayUs(1); + GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA); + SYSTICK_DelayUs(1); } uint8_t I2C_Read(bool bFinal) { - uint8_t i, Data; - - PORTCON_PORTA_IE |= PORTCON_PORTA_IE_A11_BITS_ENABLE; - PORTCON_PORTA_OD &= ~PORTCON_PORTA_OD_A11_MASK; - GPIOA->DIR &= ~GPIO_DIR_11_MASK; - - Data = 0; - for (i = 0; i < 8; i++) { - GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL); - SYSTICK_DelayUs(1); - GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL); - SYSTICK_DelayUs(1); - Data <<= 1; - SYSTICK_DelayUs(1); - if (GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA)) { - Data |= 1U; - } - GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL); - SYSTICK_DelayUs(1); - } - - PORTCON_PORTA_IE &= ~PORTCON_PORTA_IE_A11_MASK; - PORTCON_PORTA_OD |= PORTCON_PORTA_OD_A11_BITS_ENABLE; - GPIOA->DIR |= GPIO_DIR_11_BITS_OUTPUT; - GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL); - SYSTICK_DelayUs(1); - if (bFinal) { - GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA); - } else { - GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA); - } - SYSTICK_DelayUs(1); - GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL); - SYSTICK_DelayUs(1); - GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL); - SYSTICK_DelayUs(1); - - return Data; + uint8_t i, Data; + + PORTCON_PORTA_IE |= PORTCON_PORTA_IE_A11_BITS_ENABLE; + PORTCON_PORTA_OD &= ~PORTCON_PORTA_OD_A11_MASK; + GPIOA->DIR &= ~GPIO_DIR_11_MASK; + + Data = 0; + for (i = 0; i < 8; i++) { + GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL); + SYSTICK_DelayUs(1); + GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL); + SYSTICK_DelayUs(1); + Data <<= 1; + SYSTICK_DelayUs(1); + if (GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA)) { + Data |= 1U; + } + GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL); + SYSTICK_DelayUs(1); + } + + PORTCON_PORTA_IE &= ~PORTCON_PORTA_IE_A11_MASK; + PORTCON_PORTA_OD |= PORTCON_PORTA_OD_A11_BITS_ENABLE; + GPIOA->DIR |= GPIO_DIR_11_BITS_OUTPUT; + GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL); + SYSTICK_DelayUs(1); + if (bFinal) { + GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA); + } else { + GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA); + } + SYSTICK_DelayUs(1); + GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL); + SYSTICK_DelayUs(1); + GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL); + SYSTICK_DelayUs(1); + + return Data; } int I2C_Write(uint8_t Data) { - uint8_t i; - int ret = -1; - - GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL); - SYSTICK_DelayUs(1); - for (i = 0; i < 8; i++) { - if ((Data & 0x80) == 0) { - GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA); - } else { - GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA); - } - Data <<= 1; - SYSTICK_DelayUs(1); - GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL); - SYSTICK_DelayUs(1); - GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL); - SYSTICK_DelayUs(1); - } - - PORTCON_PORTA_IE |= PORTCON_PORTA_IE_A11_BITS_ENABLE; - PORTCON_PORTA_OD &= ~PORTCON_PORTA_OD_A11_MASK; - GPIOA->DIR &= ~GPIO_DIR_11_MASK; - GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA); - SYSTICK_DelayUs(1); - GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL); - SYSTICK_DelayUs(1); - - for (i = 0; i < 255; i++) { - if (GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA) == 0) { - ret = 0; - break; - } - } - - GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL); - SYSTICK_DelayUs(1); - PORTCON_PORTA_IE &= ~PORTCON_PORTA_IE_A11_MASK; - PORTCON_PORTA_OD |= PORTCON_PORTA_OD_A11_BITS_ENABLE; - GPIOA->DIR |= GPIO_DIR_11_BITS_OUTPUT; - GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA); - - return ret; + uint8_t i; + int ret = -1; + + GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL); + SYSTICK_DelayUs(1); + for (i = 0; i < 8; i++) { + if ((Data & 0x80) == 0) { + GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA); + } else { + GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA); + } + Data <<= 1; + SYSTICK_DelayUs(1); + GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL); + SYSTICK_DelayUs(1); + GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL); + SYSTICK_DelayUs(1); + } + + PORTCON_PORTA_IE |= PORTCON_PORTA_IE_A11_BITS_ENABLE; + PORTCON_PORTA_OD &= ~PORTCON_PORTA_OD_A11_MASK; + GPIOA->DIR &= ~GPIO_DIR_11_MASK; + GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA); + SYSTICK_DelayUs(1); + GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL); + SYSTICK_DelayUs(1); + + for (i = 0; i < 255; i++) { + if (GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA) == 0) { + ret = 0; + break; + } + } + + GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL); + SYSTICK_DelayUs(1); + PORTCON_PORTA_IE &= ~PORTCON_PORTA_IE_A11_MASK; + PORTCON_PORTA_OD |= PORTCON_PORTA_OD_A11_BITS_ENABLE; + GPIOA->DIR |= GPIO_DIR_11_BITS_OUTPUT; + GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA); + + return ret; } int I2C_ReadBuffer(void *pBuffer, uint8_t Size) { - uint8_t *pData = (uint8_t *)pBuffer; - uint8_t i; + uint8_t *pData = (uint8_t *)pBuffer; + uint8_t i; - for (i = 0; i < Size - 1; i++) { - SYSTICK_DelayUs(1); - pData[i] = I2C_Read(false); - } + for (i = 0; i < Size - 1; i++) { + SYSTICK_DelayUs(1); + pData[i] = I2C_Read(false); + } - SYSTICK_DelayUs(1); - pData[i] = I2C_Read(true); + SYSTICK_DelayUs(1); + pData[i] = I2C_Read(true); - return Size; + return Size; } int I2C_WriteBuffer(const void *pBuffer, uint8_t Size) { - const uint8_t *pData = (const uint8_t *)pBuffer; - uint8_t i; + const uint8_t *pData = (const uint8_t *)pBuffer; + uint8_t i; - for (i = 0; i < Size; i++) { - if (I2C_Write(*pData++) < 0) { - return -1; - } - } + for (i = 0; i < Size; i++) { + if (I2C_Write(*pData++) < 0) { + return -1; + } + } - return 0; + return 0; } diff --git a/driver/i2c.h b/driver/i2c.h index f4dbbbb83..42e4403fa 100644 --- a/driver/i2c.h +++ b/driver/i2c.h @@ -21,8 +21,8 @@ #include enum { - I2C_WRITE = 0U, - I2C_READ = 1U, + I2C_WRITE = 0U, + I2C_READ = 1U, }; void I2C_Start(void); diff --git a/driver/keyboard.c b/driver/keyboard.c index 0a39b9465..bc553813f 100644 --- a/driver/keyboard.c +++ b/driver/keyboard.c @@ -29,125 +29,125 @@ bool gWasFKeyPressed = false; static const struct { - // Using a 16 bit pre-calculated shift and invert is cheaper - // than using 8 bit and doing shift and invert in code. - uint16_t set_to_zero_mask; + // Using a 16 bit pre-calculated shift and invert is cheaper + // than using 8 bit and doing shift and invert in code. + uint16_t set_to_zero_mask; - // We are very fortunate. - // The key and pin defines fit together in a single u8, making this very efficient - struct { - KEY_Code_t key : 5; - uint8_t pin : 3; // Pin 6 is highest - } pins[4]; + // We are very fortunate. + // The key and pin defines fit together in a single u8, making this very efficient + struct { + KEY_Code_t key : 5; + uint8_t pin : 3; // Pin 6 is highest + } pins[4]; } keyboard[] = { - { // Zero row - // Set to zero to handle special case of nothing pulled down - .set_to_zero_mask = 0xffff, - .pins = { - { .key = KEY_SIDE1, .pin = GPIOA_PIN_KEYBOARD_0}, - { .key = KEY_SIDE2, .pin = GPIOA_PIN_KEYBOARD_1}, - - // Duplicate to fill the array with valid values - { .key = KEY_INVALID, .pin = GPIOA_PIN_KEYBOARD_1}, - { .key = KEY_INVALID, .pin = GPIOA_PIN_KEYBOARD_1} - } - }, - { // First row - .set_to_zero_mask = ~(1u << GPIOA_PIN_KEYBOARD_4) & 0xffff, - .pins = { - { .key = KEY_MENU, .pin = GPIOA_PIN_KEYBOARD_0}, - { .key = KEY_1, .pin = GPIOA_PIN_KEYBOARD_1}, - { .key = KEY_4, .pin = GPIOA_PIN_KEYBOARD_2}, - { .key = KEY_7, .pin = GPIOA_PIN_KEYBOARD_3} - } - }, - { // Second row - .set_to_zero_mask = ~(1u << GPIOA_PIN_KEYBOARD_5) & 0xffff, - .pins = { - { .key = KEY_UP, .pin = GPIOA_PIN_KEYBOARD_0}, - { .key = KEY_2 , .pin = GPIOA_PIN_KEYBOARD_1}, - { .key = KEY_5 , .pin = GPIOA_PIN_KEYBOARD_2}, - { .key = KEY_8 , .pin = GPIOA_PIN_KEYBOARD_3} - } - }, - { // Third row - .set_to_zero_mask = ~(1u << GPIOA_PIN_KEYBOARD_6) & 0xffff, - .pins = { - { .key = KEY_DOWN, .pin = GPIOA_PIN_KEYBOARD_0}, - { .key = KEY_3 , .pin = GPIOA_PIN_KEYBOARD_1}, - { .key = KEY_6 , .pin = GPIOA_PIN_KEYBOARD_2}, - { .key = KEY_9 , .pin = GPIOA_PIN_KEYBOARD_3} - } - }, - { // Fourth row - .set_to_zero_mask = ~(1u << GPIOA_PIN_KEYBOARD_7) & 0xffff, - .pins = { - { .key = KEY_EXIT, .pin = GPIOA_PIN_KEYBOARD_0}, - { .key = KEY_STAR, .pin = GPIOA_PIN_KEYBOARD_1}, - { .key = KEY_0 , .pin = GPIOA_PIN_KEYBOARD_2}, - { .key = KEY_F , .pin = GPIOA_PIN_KEYBOARD_3} - } - } + { // Zero row + // Set to zero to handle special case of nothing pulled down + .set_to_zero_mask = 0xffff, + .pins = { + { .key = KEY_SIDE1, .pin = GPIOA_PIN_KEYBOARD_0}, + { .key = KEY_SIDE2, .pin = GPIOA_PIN_KEYBOARD_1}, + + // Duplicate to fill the array with valid values + { .key = KEY_INVALID, .pin = GPIOA_PIN_KEYBOARD_1}, + { .key = KEY_INVALID, .pin = GPIOA_PIN_KEYBOARD_1} + } + }, + { // First row + .set_to_zero_mask = ~(1u << GPIOA_PIN_KEYBOARD_4) & 0xffff, + .pins = { + { .key = KEY_MENU, .pin = GPIOA_PIN_KEYBOARD_0}, + { .key = KEY_1, .pin = GPIOA_PIN_KEYBOARD_1}, + { .key = KEY_4, .pin = GPIOA_PIN_KEYBOARD_2}, + { .key = KEY_7, .pin = GPIOA_PIN_KEYBOARD_3} + } + }, + { // Second row + .set_to_zero_mask = ~(1u << GPIOA_PIN_KEYBOARD_5) & 0xffff, + .pins = { + { .key = KEY_UP, .pin = GPIOA_PIN_KEYBOARD_0}, + { .key = KEY_2 , .pin = GPIOA_PIN_KEYBOARD_1}, + { .key = KEY_5 , .pin = GPIOA_PIN_KEYBOARD_2}, + { .key = KEY_8 , .pin = GPIOA_PIN_KEYBOARD_3} + } + }, + { // Third row + .set_to_zero_mask = ~(1u << GPIOA_PIN_KEYBOARD_6) & 0xffff, + .pins = { + { .key = KEY_DOWN, .pin = GPIOA_PIN_KEYBOARD_0}, + { .key = KEY_3 , .pin = GPIOA_PIN_KEYBOARD_1}, + { .key = KEY_6 , .pin = GPIOA_PIN_KEYBOARD_2}, + { .key = KEY_9 , .pin = GPIOA_PIN_KEYBOARD_3} + } + }, + { // Fourth row + .set_to_zero_mask = ~(1u << GPIOA_PIN_KEYBOARD_7) & 0xffff, + .pins = { + { .key = KEY_EXIT, .pin = GPIOA_PIN_KEYBOARD_0}, + { .key = KEY_STAR, .pin = GPIOA_PIN_KEYBOARD_1}, + { .key = KEY_0 , .pin = GPIOA_PIN_KEYBOARD_2}, + { .key = KEY_F , .pin = GPIOA_PIN_KEYBOARD_3} + } + } }; KEY_Code_t KEYBOARD_Poll(void) { - KEY_Code_t Key = KEY_INVALID; - -// if (!GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT)) -// return KEY_PTT; - - // ***************** - - for (unsigned int j = 0; j < ARRAY_SIZE(keyboard); j++) - { - uint16_t reg; - unsigned int i; - unsigned int k; - - // Set all high - GPIOA->DATA |= 1u << GPIOA_PIN_KEYBOARD_4 | - 1u << GPIOA_PIN_KEYBOARD_5 | - 1u << GPIOA_PIN_KEYBOARD_6 | - 1u << GPIOA_PIN_KEYBOARD_7; - - // Clear the pin we are selecting - GPIOA->DATA &= keyboard[j].set_to_zero_mask; - - // Read all 4 GPIO pins at once .. with de-noise, max of 8 sample loops - for (i = 0, k = 0, reg = 0; i < 3 && k < 8; i++, k++) { - SYSTICK_DelayUs(1); - uint16_t reg2 = GPIOA->DATA; - i *= reg == reg2; - reg = reg2; - } - - if (i < 3) - break; // noise is too bad - - for (unsigned int i = 0; i < ARRAY_SIZE(keyboard[j].pins); i++) - { - const uint16_t mask = 1u << keyboard[j].pins[i].pin; - if (!(reg & mask)) - { - Key = keyboard[j].pins[i].key; - break; - } - } - - if (Key != KEY_INVALID) - break; - } - - // Create I2C stop condition since we might have toggled I2C pins - // This leaves GPIOA_PIN_KEYBOARD_4 and GPIOA_PIN_KEYBOARD_5 high - I2C_Stop(); - - // Reset VOICE pins - GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_6); - GPIO_SetBit( &GPIOA->DATA, GPIOA_PIN_KEYBOARD_7); - - return Key; + KEY_Code_t Key = KEY_INVALID; + +// if (!GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT)) +// return KEY_PTT; + + // ***************** + + for (unsigned int j = 0; j < ARRAY_SIZE(keyboard); j++) + { + uint16_t reg; + unsigned int i; + unsigned int k; + + // Set all high + GPIOA->DATA |= 1u << GPIOA_PIN_KEYBOARD_4 | + 1u << GPIOA_PIN_KEYBOARD_5 | + 1u << GPIOA_PIN_KEYBOARD_6 | + 1u << GPIOA_PIN_KEYBOARD_7; + + // Clear the pin we are selecting + GPIOA->DATA &= keyboard[j].set_to_zero_mask; + + // Read all 4 GPIO pins at once .. with de-noise, max of 8 sample loops + for (i = 0, k = 0, reg = 0; i < 3 && k < 8; i++, k++) { + SYSTICK_DelayUs(1); + uint16_t reg2 = GPIOA->DATA; + i *= reg == reg2; + reg = reg2; + } + + if (i < 3) + break; // noise is too bad + + for (unsigned int i = 0; i < ARRAY_SIZE(keyboard[j].pins); i++) + { + const uint16_t mask = 1u << keyboard[j].pins[i].pin; + if (!(reg & mask)) + { + Key = keyboard[j].pins[i].key; + break; + } + } + + if (Key != KEY_INVALID) + break; + } + + // Create I2C stop condition since we might have toggled I2C pins + // This leaves GPIOA_PIN_KEYBOARD_4 and GPIOA_PIN_KEYBOARD_5 high + I2C_Stop(); + + // Reset VOICE pins + GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_6); + GPIO_SetBit( &GPIOA->DATA, GPIOA_PIN_KEYBOARD_7); + + return Key; } diff --git a/driver/keyboard.h b/driver/keyboard.h index 5a7d83986..5a0184454 100644 --- a/driver/keyboard.h +++ b/driver/keyboard.h @@ -22,26 +22,26 @@ #include enum KEY_Code_e { - KEY_0 = 0, // 0 - KEY_1, // 1 - KEY_2, // 2 - KEY_3, // 3 - KEY_4, // 4 - KEY_5, // 5 - KEY_6, // 6 - KEY_7, // 7 - KEY_8, // 8 - KEY_9, // 9 - KEY_MENU, // A - KEY_UP, // B - KEY_DOWN, // C - KEY_EXIT, // D - KEY_STAR, // * - KEY_F, // # - KEY_PTT, // - KEY_SIDE2, // - KEY_SIDE1, // - KEY_INVALID // + KEY_0 = 0, // 0 + KEY_1, // 1 + KEY_2, // 2 + KEY_3, // 3 + KEY_4, // 4 + KEY_5, // 5 + KEY_6, // 6 + KEY_7, // 7 + KEY_8, // 8 + KEY_9, // 9 + KEY_MENU, // A + KEY_UP, // B + KEY_DOWN, // C + KEY_EXIT, // D + KEY_STAR, // * + KEY_F, // # + KEY_PTT, // + KEY_SIDE2, // + KEY_SIDE1, // + KEY_INVALID // }; typedef enum KEY_Code_e KEY_Code_t; diff --git a/driver/spi.c b/driver/spi.c index 4a1a279d3..b7926359a 100644 --- a/driver/spi.c +++ b/driver/spi.c @@ -22,95 +22,95 @@ void SPI0_Init(void) { - SPI_Config_t Config; - - SPI_Disable(&SPI0->CR); - - Config.TXFIFO_EMPTY = 0; - Config.RXFIFO_HFULL = 0; - Config.RXFIFO_FULL = 0; - Config.RXFIFO_OVF = 0; - Config.MSTR = 1; - Config.SPR = 2; - Config.CPHA = 1; - Config.CPOL = 1; - Config.LSB = 0; - Config.TF_CLR = 0; - Config.RF_CLR = 0; - Config.TXFIFO_HFULL = 0; - SPI_Configure(SPI0, &Config); - - SPI_Enable(&SPI0->CR); + SPI_Config_t Config; + + SPI_Disable(&SPI0->CR); + + Config.TXFIFO_EMPTY = 0; + Config.RXFIFO_HFULL = 0; + Config.RXFIFO_FULL = 0; + Config.RXFIFO_OVF = 0; + Config.MSTR = 1; + Config.SPR = 2; + Config.CPHA = 1; + Config.CPOL = 1; + Config.LSB = 0; + Config.TF_CLR = 0; + Config.RF_CLR = 0; + Config.TXFIFO_HFULL = 0; + SPI_Configure(SPI0, &Config); + + SPI_Enable(&SPI0->CR); } void SPI_WaitForUndocumentedTxFifoStatusBit(void) { - uint32_t Timeout; - - Timeout = 0; - do { - // Undocumented bit! - if ((SPI0->IF & 0x20) == 0) { - break; - } - Timeout++; - } while (Timeout <= 100000); + uint32_t Timeout; + + Timeout = 0; + do { + // Undocumented bit! + if ((SPI0->IF & 0x20) == 0) { + break; + } + Timeout++; + } while (Timeout <= 100000); } void SPI_Disable(volatile uint32_t *pCR) { - *pCR = (*pCR & ~SPI_CR_SPE_MASK) | SPI_CR_SPE_BITS_DISABLE; + *pCR = (*pCR & ~SPI_CR_SPE_MASK) | SPI_CR_SPE_BITS_DISABLE; } void SPI_Configure(volatile SPI_Port_t *pPort, SPI_Config_t *pConfig) { - if (pPort == SPI0) { - SYSCON_DEV_CLK_GATE = (SYSCON_DEV_CLK_GATE & ~SYSCON_DEV_CLK_GATE_SPI0_MASK) | SYSCON_DEV_CLK_GATE_SPI0_BITS_ENABLE; - } else if (pPort == SPI1) { - SYSCON_DEV_CLK_GATE = (SYSCON_DEV_CLK_GATE & ~SYSCON_DEV_CLK_GATE_SPI1_MASK) | SYSCON_DEV_CLK_GATE_SPI1_BITS_ENABLE; - } - - SPI_Disable(&pPort->CR); - - pPort->CR = 0 - | (pPort->CR & ~(SPI_CR_SPR_MASK | SPI_CR_CPHA_MASK | SPI_CR_CPOL_MASK | SPI_CR_MSTR_MASK | SPI_CR_LSB_MASK | SPI_CR_RF_CLR_MASK)) - | ((pConfig->SPR << SPI_CR_SPR_SHIFT) & SPI_CR_SPR_MASK) - | ((pConfig->CPHA << SPI_CR_CPHA_SHIFT) & SPI_CR_CPHA_MASK) - | ((pConfig->CPOL << SPI_CR_CPOL_SHIFT) & SPI_CR_CPOL_MASK) - | ((pConfig->MSTR << SPI_CR_MSTR_SHIFT) & SPI_CR_MSTR_MASK) - | ((pConfig->LSB << SPI_CR_LSB_SHIFT) & SPI_CR_LSB_MASK) - | ((pConfig->RF_CLR << SPI_CR_RF_CLR_SHIFT) & SPI_CR_RF_CLR_MASK) - | ((pConfig->TF_CLR << SPI_CR_TF_CLR_SHIFT) & SPI_CR_TF_CLR_MASK) - ; - - pPort->IE = 0 - | ((pConfig->RXFIFO_OVF << SPI_IE_RXFIFO_OVF_SHIFT) & SPI_IE_RXFIFO_OVF_MASK) - | ((pConfig->RXFIFO_FULL << SPI_IE_RXFIFO_FULL_SHIFT) & SPI_IE_RXFIFO_FULL_MASK) - | ((pConfig->RXFIFO_HFULL << SPI_IE_RXFIFO_HFULL_SHIFT) & SPI_IE_RXFIFO_HFULL_MASK) - | ((pConfig->TXFIFO_EMPTY << SPI_IE_TXFIFO_EMPTY_SHIFT) & SPI_IE_TXFIFO_EMPTY_MASK) - | ((pConfig->TXFIFO_HFULL << SPI_IE_TXFIFO_HFULL_SHIFT) & SPI_IE_TXFIFO_HFULL_MASK) - ; - - if (pPort->IE) { - if (pPort == SPI0) { - NVIC_EnableIRQ((IRQn_Type)DP32_SPI0_IRQn); - } else if (pPort == SPI1) { - NVIC_EnableIRQ((IRQn_Type)DP32_SPI1_IRQn); - } - } + if (pPort == SPI0) { + SYSCON_DEV_CLK_GATE = (SYSCON_DEV_CLK_GATE & ~SYSCON_DEV_CLK_GATE_SPI0_MASK) | SYSCON_DEV_CLK_GATE_SPI0_BITS_ENABLE; + } else if (pPort == SPI1) { + SYSCON_DEV_CLK_GATE = (SYSCON_DEV_CLK_GATE & ~SYSCON_DEV_CLK_GATE_SPI1_MASK) | SYSCON_DEV_CLK_GATE_SPI1_BITS_ENABLE; + } + + SPI_Disable(&pPort->CR); + + pPort->CR = 0 + | (pPort->CR & ~(SPI_CR_SPR_MASK | SPI_CR_CPHA_MASK | SPI_CR_CPOL_MASK | SPI_CR_MSTR_MASK | SPI_CR_LSB_MASK | SPI_CR_RF_CLR_MASK)) + | ((pConfig->SPR << SPI_CR_SPR_SHIFT) & SPI_CR_SPR_MASK) + | ((pConfig->CPHA << SPI_CR_CPHA_SHIFT) & SPI_CR_CPHA_MASK) + | ((pConfig->CPOL << SPI_CR_CPOL_SHIFT) & SPI_CR_CPOL_MASK) + | ((pConfig->MSTR << SPI_CR_MSTR_SHIFT) & SPI_CR_MSTR_MASK) + | ((pConfig->LSB << SPI_CR_LSB_SHIFT) & SPI_CR_LSB_MASK) + | ((pConfig->RF_CLR << SPI_CR_RF_CLR_SHIFT) & SPI_CR_RF_CLR_MASK) + | ((pConfig->TF_CLR << SPI_CR_TF_CLR_SHIFT) & SPI_CR_TF_CLR_MASK) + ; + + pPort->IE = 0 + | ((pConfig->RXFIFO_OVF << SPI_IE_RXFIFO_OVF_SHIFT) & SPI_IE_RXFIFO_OVF_MASK) + | ((pConfig->RXFIFO_FULL << SPI_IE_RXFIFO_FULL_SHIFT) & SPI_IE_RXFIFO_FULL_MASK) + | ((pConfig->RXFIFO_HFULL << SPI_IE_RXFIFO_HFULL_SHIFT) & SPI_IE_RXFIFO_HFULL_MASK) + | ((pConfig->TXFIFO_EMPTY << SPI_IE_TXFIFO_EMPTY_SHIFT) & SPI_IE_TXFIFO_EMPTY_MASK) + | ((pConfig->TXFIFO_HFULL << SPI_IE_TXFIFO_HFULL_SHIFT) & SPI_IE_TXFIFO_HFULL_MASK) + ; + + if (pPort->IE) { + if (pPort == SPI0) { + NVIC_EnableIRQ((IRQn_Type)DP32_SPI0_IRQn); + } else if (pPort == SPI1) { + NVIC_EnableIRQ((IRQn_Type)DP32_SPI1_IRQn); + } + } } void SPI_ToggleMasterMode(volatile uint32_t *pCR, bool bIsMaster) { - if (bIsMaster) { - *pCR = (*pCR & ~SPI_CR_MSR_SSN_MASK) | SPI_CR_MSR_SSN_BITS_ENABLE; - } else { - *pCR = (*pCR & ~SPI_CR_MSR_SSN_MASK) | SPI_CR_MSR_SSN_BITS_DISABLE; - } + if (bIsMaster) { + *pCR = (*pCR & ~SPI_CR_MSR_SSN_MASK) | SPI_CR_MSR_SSN_BITS_ENABLE; + } else { + *pCR = (*pCR & ~SPI_CR_MSR_SSN_MASK) | SPI_CR_MSR_SSN_BITS_DISABLE; + } } void SPI_Enable(volatile uint32_t *pCR) { - *pCR = (*pCR & ~SPI_CR_SPE_MASK) | SPI_CR_SPE_BITS_ENABLE; + *pCR = (*pCR & ~SPI_CR_SPE_MASK) | SPI_CR_SPE_BITS_ENABLE; } diff --git a/driver/spi.h b/driver/spi.h index a3cc8a440..e94f5e53a 100644 --- a/driver/spi.h +++ b/driver/spi.h @@ -21,18 +21,18 @@ #include typedef struct { - uint8_t MSTR; - uint8_t SPR; - uint8_t CPHA; - uint8_t CPOL; - uint8_t LSB; - uint8_t TF_CLR; - uint8_t RF_CLR; - uint8_t TXFIFO_HFULL; - uint8_t TXFIFO_EMPTY; - uint8_t RXFIFO_HFULL; - uint8_t RXFIFO_FULL; - uint8_t RXFIFO_OVF; + uint8_t MSTR; + uint8_t SPR; + uint8_t CPHA; + uint8_t CPOL; + uint8_t LSB; + uint8_t TF_CLR; + uint8_t RF_CLR; + uint8_t TXFIFO_HFULL; + uint8_t TXFIFO_EMPTY; + uint8_t RXFIFO_HFULL; + uint8_t RXFIFO_FULL; + uint8_t RXFIFO_OVF; } SPI_Config_t; void SPI0_Init(void); diff --git a/driver/st7565.c b/driver/st7565.c index af17e2472..4e008f3f6 100644 --- a/driver/st7565.c +++ b/driver/st7565.c @@ -29,104 +29,104 @@ uint8_t gStatusLine[LCD_WIDTH]; uint8_t gFrameBuffer[FRAME_LINES][LCD_WIDTH]; static void DrawLine(uint8_t column, uint8_t line, const uint8_t * lineBuffer, unsigned size_defVal) -{ - ST7565_SelectColumnAndLine(column + 4, line); - GPIO_SetBit(&GPIOB->DATA, GPIOB_PIN_ST7565_A0); - for (unsigned i = 0; i < size_defVal; i++) { - while ((SPI0->FIFOST & SPI_FIFOST_TFF_MASK) != SPI_FIFOST_TFF_BITS_NOT_FULL) {} - SPI0->WDR = lineBuffer ? lineBuffer[i] : size_defVal; - } - SPI_WaitForUndocumentedTxFifoStatusBit(); +{ + ST7565_SelectColumnAndLine(column + 4, line); + GPIO_SetBit(&GPIOB->DATA, GPIOB_PIN_ST7565_A0); + for (unsigned i = 0; i < size_defVal; i++) { + while ((SPI0->FIFOST & SPI_FIFOST_TFF_MASK) != SPI_FIFOST_TFF_BITS_NOT_FULL) {} + SPI0->WDR = lineBuffer ? lineBuffer[i] : size_defVal; + } + SPI_WaitForUndocumentedTxFifoStatusBit(); } void ST7565_DrawLine(const unsigned int Column, const unsigned int Line, const uint8_t *pBitmap, const unsigned int Size) { - SPI_ToggleMasterMode(&SPI0->CR, false); - DrawLine(Column, Line, pBitmap, Size); - SPI_ToggleMasterMode(&SPI0->CR, true); + SPI_ToggleMasterMode(&SPI0->CR, false); + DrawLine(Column, Line, pBitmap, Size); + SPI_ToggleMasterMode(&SPI0->CR, true); } #ifdef ENABLE_FEAT_F4HWN - // Optimization - // - // ST7565_BlitScreen(0) = ST7565_BlitStatusLine() - // ST7565_BlitScreen(1..7) = ST7565_BlitLine() - // ST7565_BlitScreen(8) = ST7565_BlitFullScreen() - // - - static void ST7565_BlitScreen(uint8_t line) - { - SPI_ToggleMasterMode(&SPI0->CR, false); - ST7565_WriteByte(0x40); - - if(line == 0) - { - DrawLine(0, 0, gStatusLine, LCD_WIDTH); - } - else if(line <= FRAME_LINES) - { - DrawLine(0, line, gFrameBuffer[line - 1], LCD_WIDTH); - } - else - { - for (line = 1; line <= FRAME_LINES; line++) { - DrawLine(0, line, gFrameBuffer[line - 1], LCD_WIDTH); - } - } - - SPI_ToggleMasterMode(&SPI0->CR, true); - } - - void ST7565_BlitFullScreen(void) - { - ST7565_BlitScreen(8); - } - - void ST7565_BlitLine(unsigned line) - { - ST7565_BlitScreen(line + 1); - } - - void ST7565_BlitStatusLine(void) - { - ST7565_BlitScreen(0); - } + // Optimization + // + // ST7565_BlitScreen(0) = ST7565_BlitStatusLine() + // ST7565_BlitScreen(1..7) = ST7565_BlitLine() + // ST7565_BlitScreen(8) = ST7565_BlitFullScreen() + // + + static void ST7565_BlitScreen(uint8_t line) + { + SPI_ToggleMasterMode(&SPI0->CR, false); + ST7565_WriteByte(0x40); + + if(line == 0) + { + DrawLine(0, 0, gStatusLine, LCD_WIDTH); + } + else if(line <= FRAME_LINES) + { + DrawLine(0, line, gFrameBuffer[line - 1], LCD_WIDTH); + } + else + { + for (line = 1; line <= FRAME_LINES; line++) { + DrawLine(0, line, gFrameBuffer[line - 1], LCD_WIDTH); + } + } + + SPI_ToggleMasterMode(&SPI0->CR, true); + } + + void ST7565_BlitFullScreen(void) + { + ST7565_BlitScreen(8); + } + + void ST7565_BlitLine(unsigned line) + { + ST7565_BlitScreen(line + 1); + } + + void ST7565_BlitStatusLine(void) + { + ST7565_BlitScreen(0); + } #else - void ST7565_BlitFullScreen(void) - { - SPI_ToggleMasterMode(&SPI0->CR, false); - ST7565_WriteByte(0x40); - for (unsigned line = 0; line < FRAME_LINES; line++) { - DrawLine(0, line+1, gFrameBuffer[line], LCD_WIDTH); - } - SPI_ToggleMasterMode(&SPI0->CR, true); - } - - void ST7565_BlitLine(unsigned line) - { - SPI_ToggleMasterMode(&SPI0->CR, false); - ST7565_WriteByte(0x40); // start line ? - DrawLine(0, line+1, gFrameBuffer[line], LCD_WIDTH); - SPI_ToggleMasterMode(&SPI0->CR, true); - } - - void ST7565_BlitStatusLine(void) - { // the top small text line on the display - SPI_ToggleMasterMode(&SPI0->CR, false); - ST7565_WriteByte(0x40); // start line ? - DrawLine(0, 0, gStatusLine, LCD_WIDTH); - SPI_ToggleMasterMode(&SPI0->CR, true); - } + void ST7565_BlitFullScreen(void) + { + SPI_ToggleMasterMode(&SPI0->CR, false); + ST7565_WriteByte(0x40); + for (unsigned line = 0; line < FRAME_LINES; line++) { + DrawLine(0, line+1, gFrameBuffer[line], LCD_WIDTH); + } + SPI_ToggleMasterMode(&SPI0->CR, true); + } + + void ST7565_BlitLine(unsigned line) + { + SPI_ToggleMasterMode(&SPI0->CR, false); + ST7565_WriteByte(0x40); // start line ? + DrawLine(0, line+1, gFrameBuffer[line], LCD_WIDTH); + SPI_ToggleMasterMode(&SPI0->CR, true); + } + + void ST7565_BlitStatusLine(void) + { // the top small text line on the display + SPI_ToggleMasterMode(&SPI0->CR, false); + ST7565_WriteByte(0x40); // start line ? + DrawLine(0, 0, gStatusLine, LCD_WIDTH); + SPI_ToggleMasterMode(&SPI0->CR, true); + } #endif void ST7565_FillScreen(uint8_t value) { - SPI_ToggleMasterMode(&SPI0->CR, false); - for (unsigned i = 0; i < 8; i++) { - DrawLine(0, i, NULL, value); - } - SPI_ToggleMasterMode(&SPI0->CR, true); + SPI_ToggleMasterMode(&SPI0->CR, false); + for (unsigned i = 0; i < 8; i++) { + DrawLine(0, i, NULL, value); + } + SPI_ToggleMasterMode(&SPI0->CR, true); } // Software reset @@ -179,121 +179,121 @@ const uint8_t ST7565_CMD_SET_START_LINE = 0x40; const uint8_t ST7565_CMD_DISPLAY_ON_OFF = 0xAE; uint8_t cmds[] = { - ST7565_CMD_BIAS_SELECT | 0, // Select bias setting: 1/9 - ST7565_CMD_COM_DIRECTION | (0 << 3), // Set output direction of COM: normal - ST7565_CMD_SEG_DIRECTION | 1, // Set scan direction of SEG: reverse - ST7565_CMD_INVERSE_DISPLAY | 0, // Inverse Display: false - ST7565_CMD_ALL_PIXEL_ON | 0, // All Pixel ON: false - normal display - ST7565_CMD_REGULATION_RATIO | (4 << 0), // Regulation Ratio 5.0 - - ST7565_CMD_SET_EV, // Set contrast - 31, - - ST7565_CMD_POWER_CIRCUIT | 0b111, // Built-in power circuit ON/OFF: VB=1 VR=1 VF=1 - ST7565_CMD_SET_START_LINE | 0, // Set Start Line: 0 - ST7565_CMD_DISPLAY_ON_OFF | 1, // Display ON/OFF: ON + ST7565_CMD_BIAS_SELECT | 0, // Select bias setting: 1/9 + ST7565_CMD_COM_DIRECTION | (0 << 3), // Set output direction of COM: normal + ST7565_CMD_SEG_DIRECTION | 1, // Set scan direction of SEG: reverse + ST7565_CMD_INVERSE_DISPLAY | 0, // Inverse Display: false + ST7565_CMD_ALL_PIXEL_ON | 0, // All Pixel ON: false - normal display + ST7565_CMD_REGULATION_RATIO | (4 << 0), // Regulation Ratio 5.0 + + ST7565_CMD_SET_EV, // Set contrast + 31, + + ST7565_CMD_POWER_CIRCUIT | 0b111, // Built-in power circuit ON/OFF: VB=1 VR=1 VF=1 + ST7565_CMD_SET_START_LINE | 0, // Set Start Line: 0 + ST7565_CMD_DISPLAY_ON_OFF | 1, // Display ON/OFF: ON }; #ifdef ENABLE_FEAT_F4HWN - static void ST7565_Cmd(uint8_t i) - { - switch(i) { - case 3: - ST7565_WriteByte(ST7565_CMD_INVERSE_DISPLAY | gSetting_set_inv); - break; - case 7: - ST7565_WriteByte(21 + gSetting_set_ctr); - break; - default: - ST7565_WriteByte(cmds[i]); - } - } - - void ST7565_ContrastAndInv(void) - { - SPI_ToggleMasterMode(&SPI0->CR, false); - ST7565_WriteByte(ST7565_CMD_SOFTWARE_RESET); // software reset - - for(uint8_t i = 0; i < 8; i++) - { - ST7565_Cmd(i); - } - } + static void ST7565_Cmd(uint8_t i) + { + switch(i) { + case 3: + ST7565_WriteByte(ST7565_CMD_INVERSE_DISPLAY | gSetting_set_inv); + break; + case 7: + ST7565_WriteByte(21 + gSetting_set_ctr); + break; + default: + ST7565_WriteByte(cmds[i]); + } + } + + void ST7565_ContrastAndInv(void) + { + SPI_ToggleMasterMode(&SPI0->CR, false); + ST7565_WriteByte(ST7565_CMD_SOFTWARE_RESET); // software reset + + for(uint8_t i = 0; i < 8; i++) + { + ST7565_Cmd(i); + } + } #endif - + void ST7565_Init(void) { - SPI0_Init(); - ST7565_HardwareReset(); - SPI_ToggleMasterMode(&SPI0->CR, false); - ST7565_WriteByte(ST7565_CMD_SOFTWARE_RESET); // software reset - SYSTEM_DelayMs(120); - - for(uint8_t i = 0; i < 8; i++) - { + SPI0_Init(); + ST7565_HardwareReset(); + SPI_ToggleMasterMode(&SPI0->CR, false); + ST7565_WriteByte(ST7565_CMD_SOFTWARE_RESET); // software reset + SYSTEM_DelayMs(120); + + for(uint8_t i = 0; i < 8; i++) + { #ifdef ENABLE_FEAT_F4HWN - ST7565_Cmd(i); + ST7565_Cmd(i); #else - ST7565_WriteByte(cmds[i]); + ST7565_WriteByte(cmds[i]); #endif - } + } - ST7565_WriteByte(ST7565_CMD_POWER_CIRCUIT | 0b011); // VB=0 VR=1 VF=1 - SYSTEM_DelayMs(1); - ST7565_WriteByte(ST7565_CMD_POWER_CIRCUIT | 0b110); // VB=1 VR=1 VF=0 - SYSTEM_DelayMs(1); + ST7565_WriteByte(ST7565_CMD_POWER_CIRCUIT | 0b011); // VB=0 VR=1 VF=1 + SYSTEM_DelayMs(1); + ST7565_WriteByte(ST7565_CMD_POWER_CIRCUIT | 0b110); // VB=1 VR=1 VF=0 + SYSTEM_DelayMs(1); - for(uint8_t i = 0; i < 4; i++) // why 4 times? - ST7565_WriteByte(ST7565_CMD_POWER_CIRCUIT | 0b111); // VB=1 VR=1 VF=1 + for(uint8_t i = 0; i < 4; i++) // why 4 times? + ST7565_WriteByte(ST7565_CMD_POWER_CIRCUIT | 0b111); // VB=1 VR=1 VF=1 - SYSTEM_DelayMs(40); - - ST7565_WriteByte(ST7565_CMD_SET_START_LINE | 0); // line 0 - ST7565_WriteByte(ST7565_CMD_DISPLAY_ON_OFF | 1); // D=1 - SPI_WaitForUndocumentedTxFifoStatusBit(); - SPI_ToggleMasterMode(&SPI0->CR, true); + SYSTEM_DelayMs(40); + + ST7565_WriteByte(ST7565_CMD_SET_START_LINE | 0); // line 0 + ST7565_WriteByte(ST7565_CMD_DISPLAY_ON_OFF | 1); // D=1 + SPI_WaitForUndocumentedTxFifoStatusBit(); + SPI_ToggleMasterMode(&SPI0->CR, true); - ST7565_FillScreen(0x00); + ST7565_FillScreen(0x00); } void ST7565_FixInterfGlitch(void) { - SPI_ToggleMasterMode(&SPI0->CR, false); - for(uint8_t i = 0; i < ARRAY_SIZE(cmds); i++) + SPI_ToggleMasterMode(&SPI0->CR, false); + for(uint8_t i = 0; i < ARRAY_SIZE(cmds); i++) #ifdef ENABLE_FEAT_F4HWN - ST7565_Cmd(i); + ST7565_Cmd(i); #else - ST7565_WriteByte(cmds[i]); + ST7565_WriteByte(cmds[i]); #endif - SPI_WaitForUndocumentedTxFifoStatusBit(); - SPI_ToggleMasterMode(&SPI0->CR, true); + SPI_WaitForUndocumentedTxFifoStatusBit(); + SPI_ToggleMasterMode(&SPI0->CR, true); } void ST7565_HardwareReset(void) { - GPIO_SetBit(&GPIOB->DATA, GPIOB_PIN_ST7565_RES); - SYSTEM_DelayMs(1); - GPIO_ClearBit(&GPIOB->DATA, GPIOB_PIN_ST7565_RES); - SYSTEM_DelayMs(20); - GPIO_SetBit(&GPIOB->DATA, GPIOB_PIN_ST7565_RES); - SYSTEM_DelayMs(120); + GPIO_SetBit(&GPIOB->DATA, GPIOB_PIN_ST7565_RES); + SYSTEM_DelayMs(1); + GPIO_ClearBit(&GPIOB->DATA, GPIOB_PIN_ST7565_RES); + SYSTEM_DelayMs(20); + GPIO_SetBit(&GPIOB->DATA, GPIOB_PIN_ST7565_RES); + SYSTEM_DelayMs(120); } void ST7565_SelectColumnAndLine(uint8_t Column, uint8_t Line) { - GPIO_ClearBit(&GPIOB->DATA, GPIOB_PIN_ST7565_A0); - while ((SPI0->FIFOST & SPI_FIFOST_TFF_MASK) != SPI_FIFOST_TFF_BITS_NOT_FULL) {} - SPI0->WDR = Line + 176; - while ((SPI0->FIFOST & SPI_FIFOST_TFF_MASK) != SPI_FIFOST_TFF_BITS_NOT_FULL) {} - SPI0->WDR = ((Column >> 4) & 0x0F) | 0x10; - while ((SPI0->FIFOST & SPI_FIFOST_TFF_MASK) != SPI_FIFOST_TFF_BITS_NOT_FULL) {} - SPI0->WDR = ((Column >> 0) & 0x0F); - SPI_WaitForUndocumentedTxFifoStatusBit(); + GPIO_ClearBit(&GPIOB->DATA, GPIOB_PIN_ST7565_A0); + while ((SPI0->FIFOST & SPI_FIFOST_TFF_MASK) != SPI_FIFOST_TFF_BITS_NOT_FULL) {} + SPI0->WDR = Line + 176; + while ((SPI0->FIFOST & SPI_FIFOST_TFF_MASK) != SPI_FIFOST_TFF_BITS_NOT_FULL) {} + SPI0->WDR = ((Column >> 4) & 0x0F) | 0x10; + while ((SPI0->FIFOST & SPI_FIFOST_TFF_MASK) != SPI_FIFOST_TFF_BITS_NOT_FULL) {} + SPI0->WDR = ((Column >> 0) & 0x0F); + SPI_WaitForUndocumentedTxFifoStatusBit(); } void ST7565_WriteByte(uint8_t Value) { - GPIO_ClearBit(&GPIOB->DATA, GPIOB_PIN_ST7565_A0); - while ((SPI0->FIFOST & SPI_FIFOST_TFF_MASK) != SPI_FIFOST_TFF_BITS_NOT_FULL) {} - SPI0->WDR = Value; + GPIO_ClearBit(&GPIOB->DATA, GPIOB_PIN_ST7565_A0); + while ((SPI0->FIFOST & SPI_FIFOST_TFF_MASK) != SPI_FIFOST_TFF_BITS_NOT_FULL) {} + SPI0->WDR = Value; } diff --git a/driver/st7565.h b/driver/st7565.h index b5ec79c00..80b43e1fd 100644 --- a/driver/st7565.h +++ b/driver/st7565.h @@ -39,7 +39,7 @@ void ST7565_SelectColumnAndLine(uint8_t Column, uint8_t Line); void ST7565_WriteByte(uint8_t Value); #ifdef ENABLE_FEAT_F4HWN - void ST7565_ContrastAndInv(void); + void ST7565_ContrastAndInv(void); #endif #endif diff --git a/driver/system.c b/driver/system.c index 813ddec26..e9f16f758 100644 --- a/driver/system.c +++ b/driver/system.c @@ -21,17 +21,17 @@ void SYSTEM_DelayMs(uint32_t Delay) { - SYSTICK_DelayUs(Delay * 1000); + SYSTICK_DelayUs(Delay * 1000); } void SYSTEM_ConfigureClocks(void) { - // Set source clock from external crystal - PMU_SRC_CFG = (PMU_SRC_CFG & ~(PMU_SRC_CFG_RCHF_SEL_MASK | PMU_SRC_CFG_RCHF_EN_MASK)) | PMU_SRC_CFG_RCHF_SEL_BITS_48MHZ | PMU_SRC_CFG_RCHF_EN_BITS_ENABLE; + // Set source clock from external crystal + PMU_SRC_CFG = (PMU_SRC_CFG & ~(PMU_SRC_CFG_RCHF_SEL_MASK | PMU_SRC_CFG_RCHF_EN_MASK)) | PMU_SRC_CFG_RCHF_SEL_BITS_48MHZ | PMU_SRC_CFG_RCHF_EN_BITS_ENABLE; - // Divide by 2 - SYSCON_CLK_SEL = SYSCON_CLK_SEL_DIV_BITS_2; + // Divide by 2 + SYSCON_CLK_SEL = SYSCON_CLK_SEL_DIV_BITS_2; - // Disable division clock gate - SYSCON_DIV_CLK_GATE = (SYSCON_DIV_CLK_GATE & ~SYSCON_DIV_CLK_GATE_DIV_CLK_GATE_MASK) | SYSCON_DIV_CLK_GATE_DIV_CLK_GATE_BITS_DISABLE; + // Disable division clock gate + SYSCON_DIV_CLK_GATE = (SYSCON_DIV_CLK_GATE & ~SYSCON_DIV_CLK_GATE_DIV_CLK_GATE_MASK) | SYSCON_DIV_CLK_GATE_DIV_CLK_GATE_BITS_DISABLE; } diff --git a/driver/systick.c b/driver/systick.c index c7cbed32a..ff8182c38 100644 --- a/driver/systick.c +++ b/driver/systick.c @@ -23,27 +23,27 @@ static uint32_t gTickMultiplier; void SYSTICK_Init(void) { - SysTick_Config(480000); - gTickMultiplier = 48; + SysTick_Config(480000); + gTickMultiplier = 48; } void SYSTICK_DelayUs(uint32_t Delay) { - const uint32_t ticks = Delay * gTickMultiplier; - uint32_t elapsed_ticks = 0; - uint32_t Start = SysTick->LOAD; - uint32_t Previous = SysTick->VAL; - do { - uint32_t Current; + const uint32_t ticks = Delay * gTickMultiplier; + uint32_t elapsed_ticks = 0; + uint32_t Start = SysTick->LOAD; + uint32_t Previous = SysTick->VAL; + do { + uint32_t Current; - do { - Current = SysTick->VAL; - } while (Current == Previous); + do { + Current = SysTick->VAL; + } while (Current == Previous); - uint32_t Delta = ((Current < Previous) ? - Current : Start - Current); + uint32_t Delta = ((Current < Previous) ? - Current : Start - Current); - elapsed_ticks += Delta + Previous; + elapsed_ticks += Delta + Previous; - Previous = Current; - } while (elapsed_ticks < ticks); + Previous = Current; + } while (elapsed_ticks < ticks); } diff --git a/driver/uart.c b/driver/uart.c index cb97d94d9..5ea744c43 100644 --- a/driver/uart.c +++ b/driver/uart.c @@ -25,80 +25,80 @@ uint8_t UART_DMA_Buffer[256]; void UART_Init(void) { - uint32_t Delta; - uint32_t Positive; - uint32_t Frequency; + uint32_t Delta; + uint32_t Positive; + uint32_t Frequency; - UART1->CTRL = (UART1->CTRL & ~UART_CTRL_UARTEN_MASK) | UART_CTRL_UARTEN_BITS_DISABLE; - Delta = SYSCON_RC_FREQ_DELTA; - Positive = (Delta & SYSCON_RC_FREQ_DELTA_RCHF_SIG_MASK) >> SYSCON_RC_FREQ_DELTA_RCHF_SIG_SHIFT; - Frequency = (Delta & SYSCON_RC_FREQ_DELTA_RCHF_DELTA_MASK) >> SYSCON_RC_FREQ_DELTA_RCHF_DELTA_SHIFT; - if (Positive) { - Frequency += 48000000U; - } else { - Frequency = 48000000U - Frequency; - } + UART1->CTRL = (UART1->CTRL & ~UART_CTRL_UARTEN_MASK) | UART_CTRL_UARTEN_BITS_DISABLE; + Delta = SYSCON_RC_FREQ_DELTA; + Positive = (Delta & SYSCON_RC_FREQ_DELTA_RCHF_SIG_MASK) >> SYSCON_RC_FREQ_DELTA_RCHF_SIG_SHIFT; + Frequency = (Delta & SYSCON_RC_FREQ_DELTA_RCHF_DELTA_MASK) >> SYSCON_RC_FREQ_DELTA_RCHF_DELTA_SHIFT; + if (Positive) { + Frequency += 48000000U; + } else { + Frequency = 48000000U - Frequency; + } - UART1->BAUD = Frequency / 39053U; - UART1->CTRL = UART_CTRL_RXEN_BITS_ENABLE | UART_CTRL_TXEN_BITS_ENABLE | UART_CTRL_RXDMAEN_BITS_ENABLE; - UART1->RXTO = 4; - UART1->FC = 0; - UART1->FIFO = UART_FIFO_RF_LEVEL_BITS_8_BYTE | UART_FIFO_RF_CLR_BITS_ENABLE | UART_FIFO_TF_CLR_BITS_ENABLE; - UART1->IE = 0; + UART1->BAUD = Frequency / 39053U; + UART1->CTRL = UART_CTRL_RXEN_BITS_ENABLE | UART_CTRL_TXEN_BITS_ENABLE | UART_CTRL_RXDMAEN_BITS_ENABLE; + UART1->RXTO = 4; + UART1->FC = 0; + UART1->FIFO = UART_FIFO_RF_LEVEL_BITS_8_BYTE | UART_FIFO_RF_CLR_BITS_ENABLE | UART_FIFO_TF_CLR_BITS_ENABLE; + UART1->IE = 0; - DMA_CTR = (DMA_CTR & ~DMA_CTR_DMAEN_MASK) | DMA_CTR_DMAEN_BITS_DISABLE; + DMA_CTR = (DMA_CTR & ~DMA_CTR_DMAEN_MASK) | DMA_CTR_DMAEN_BITS_DISABLE; - DMA_CH0->MSADDR = (uint32_t)(uintptr_t)&UART1->RDR; - DMA_CH0->MDADDR = (uint32_t)(uintptr_t)UART_DMA_Buffer; - DMA_CH0->MOD = 0 - // Source - | DMA_CH_MOD_MS_ADDMOD_BITS_NONE - | DMA_CH_MOD_MS_SIZE_BITS_8BIT - | DMA_CH_MOD_MS_SEL_BITS_HSREQ_MS1 - // Destination - | DMA_CH_MOD_MD_ADDMOD_BITS_INCREMENT - | DMA_CH_MOD_MD_SIZE_BITS_8BIT - | DMA_CH_MOD_MD_SEL_BITS_SRAM - ; - DMA_INTEN = 0; - DMA_INTST = 0 - | DMA_INTST_CH0_TC_INTST_BITS_SET - | DMA_INTST_CH1_TC_INTST_BITS_SET - | DMA_INTST_CH2_TC_INTST_BITS_SET - | DMA_INTST_CH3_TC_INTST_BITS_SET - | DMA_INTST_CH0_THC_INTST_BITS_SET - | DMA_INTST_CH1_THC_INTST_BITS_SET - | DMA_INTST_CH2_THC_INTST_BITS_SET - | DMA_INTST_CH3_THC_INTST_BITS_SET - ; - DMA_CH0->CTR = 0 - | DMA_CH_CTR_CH_EN_BITS_ENABLE - | ((0xFF << DMA_CH_CTR_LENGTH_SHIFT) & DMA_CH_CTR_LENGTH_MASK) - | DMA_CH_CTR_LOOP_BITS_ENABLE - | DMA_CH_CTR_PRI_BITS_MEDIUM - ; - UART1->IF = UART_IF_RXTO_BITS_SET; + DMA_CH0->MSADDR = (uint32_t)(uintptr_t)&UART1->RDR; + DMA_CH0->MDADDR = (uint32_t)(uintptr_t)UART_DMA_Buffer; + DMA_CH0->MOD = 0 + // Source + | DMA_CH_MOD_MS_ADDMOD_BITS_NONE + | DMA_CH_MOD_MS_SIZE_BITS_8BIT + | DMA_CH_MOD_MS_SEL_BITS_HSREQ_MS1 + // Destination + | DMA_CH_MOD_MD_ADDMOD_BITS_INCREMENT + | DMA_CH_MOD_MD_SIZE_BITS_8BIT + | DMA_CH_MOD_MD_SEL_BITS_SRAM + ; + DMA_INTEN = 0; + DMA_INTST = 0 + | DMA_INTST_CH0_TC_INTST_BITS_SET + | DMA_INTST_CH1_TC_INTST_BITS_SET + | DMA_INTST_CH2_TC_INTST_BITS_SET + | DMA_INTST_CH3_TC_INTST_BITS_SET + | DMA_INTST_CH0_THC_INTST_BITS_SET + | DMA_INTST_CH1_THC_INTST_BITS_SET + | DMA_INTST_CH2_THC_INTST_BITS_SET + | DMA_INTST_CH3_THC_INTST_BITS_SET + ; + DMA_CH0->CTR = 0 + | DMA_CH_CTR_CH_EN_BITS_ENABLE + | ((0xFF << DMA_CH_CTR_LENGTH_SHIFT) & DMA_CH_CTR_LENGTH_MASK) + | DMA_CH_CTR_LOOP_BITS_ENABLE + | DMA_CH_CTR_PRI_BITS_MEDIUM + ; + UART1->IF = UART_IF_RXTO_BITS_SET; - DMA_CTR = (DMA_CTR & ~DMA_CTR_DMAEN_MASK) | DMA_CTR_DMAEN_BITS_ENABLE; + DMA_CTR = (DMA_CTR & ~DMA_CTR_DMAEN_MASK) | DMA_CTR_DMAEN_BITS_ENABLE; - UART1->CTRL |= UART_CTRL_UARTEN_BITS_ENABLE; + UART1->CTRL |= UART_CTRL_UARTEN_BITS_ENABLE; } void UART_Send(const void *pBuffer, uint32_t Size) { - const uint8_t *pData = (const uint8_t *)pBuffer; - uint32_t i; + const uint8_t *pData = (const uint8_t *)pBuffer; + uint32_t i; - for (i = 0; i < Size; i++) { - UART1->TDR = pData[i]; - while ((UART1->IF & UART_IF_TXFIFO_FULL_MASK) != UART_IF_TXFIFO_FULL_BITS_NOT_SET) { - } - } + for (i = 0; i < Size; i++) { + UART1->TDR = pData[i]; + while ((UART1->IF & UART_IF_TXFIFO_FULL_MASK) != UART_IF_TXFIFO_FULL_BITS_NOT_SET) { + } + } } void UART_LogSend(const void *pBuffer, uint32_t Size) { - if (UART_IsLogEnabled) { - UART_Send(pBuffer, Size); - } + if (UART_IsLogEnabled) { + UART_Send(pBuffer, Size); + } } diff --git a/font.c b/font.c index 67252dc02..4b2732f77 100644 --- a/font.c +++ b/font.c @@ -22,633 +22,633 @@ const uint8_t gFontBig[95 - 1][16 - 2] = { #if 0 // {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // , 0x00}, // ' ' - {0x00, 0x00, 0x70, 0xF8, 0xF8, 0x70, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x1B, 0x1B, 0x00, 0x00}, // , 0x00}, // '!' - {0x00, 0x1E, 0x3E, 0x00, 0x00, 0x3E, 0x1E, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // , 0x00}, // '"' - {0x40, 0xF0, 0xF0, 0x40, 0xF0, 0xF0, 0x40, /*0x00,*/ 0x04, 0x1F, 0x1F, 0x04, 0x1F, 0x1F, 0x04}, // , 0x00}, // '#' - {0x70, 0xF8, 0x88, 0x8F, 0x8F, 0x98, 0x30, /*0x00,*/ 0x06, 0x0C, 0x08, 0x38, 0x38, 0x0F, 0x07}, // , 0x00}, // '$' - {0x60, 0x60, 0x00, 0x00, 0x80, 0xC0, 0x60, /*0x00,*/ 0x18, 0x0C, 0x06, 0x03, 0x01, 0x18, 0x18}, // , 0x00}, // '%' - {0x00, 0xB0, 0xF8, 0xC8, 0x78, 0xB0, 0x80, /*0x00,*/ 0x0F, 0x1F, 0x10, 0x11, 0x0F, 0x1F, 0x10}, // , 0x00}, // '&' - {0x00, 0x20, 0x3E, 0x1E, 0x00, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // , 0x00}, // ''' - {0x00, 0x00, 0xE0, 0xF0, 0x18, 0x08, 0x00, /*0x00,*/ 0x00, 0x00, 0x07, 0x0F, 0x18, 0x10, 0x00}, // , 0x00}, // '(' - {0x00, 0x00, 0x08, 0x18, 0xF0, 0xE0, 0x00, /*0x00,*/ 0x00, 0x00, 0x10, 0x18, 0x0F, 0x07, 0x00}, // , 0x00}, // ')' - {0x00, 0x40, 0xC0, 0x80, 0x80, 0xC0, 0x40, /*0x00,*/ 0x01, 0x05, 0x07, 0x03, 0x03, 0x07, 0x05}, // , 0x01}, // '*' - {0x00, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, /*0x00,*/ 0x00, 0x01, 0x01, 0x07, 0x07, 0x01, 0x01}, // , 0x00}, // '+' - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x20, 0x3C, 0x1C, 0x00, 0x00}, // , 0x00}, // ',' - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x00,*/ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, // , 0x00}, // '-' - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00}, // , 0x00}, // '.' - {0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0x60, /*0x00,*/ 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00, 0x00}, // , 0x00}, // '/' - {0xF0, 0xF8, 0x08, 0x88, 0x48, 0xF8, 0xF0, /*0x00,*/ 0x0F, 0x1F, 0x12, 0x11, 0x10, 0x1F, 0x0F}, // , 0x00}, // '0' - {0x00, 0x20, 0x30, 0xF8, 0xF8, 0x00, 0x00, /*0x00,*/ 0x00, 0x10, 0x10, 0x1F, 0x1F, 0x10, 0x10}, // , 0x00}, // '1' - {0x10, 0x18, 0x08, 0x88, 0xC8, 0x78, 0x30, /*0x00,*/ 0x1C, 0x1E, 0x13, 0x11, 0x10, 0x18, 0x18}, // , 0x00}, // '2' - {0x10, 0x18, 0x88, 0x88, 0x88, 0xF8, 0x70, /*0x00,*/ 0x08, 0x18, 0x10, 0x10, 0x10, 0x1F, 0x0F}, // , 0x00}, // '3' - {0x80, 0xC0, 0x60, 0x30, 0xF8, 0xF8, 0x00, /*0x00,*/ 0x01, 0x01, 0x01, 0x11, 0x1F, 0x1F, 0x11}, // , 0x00}, // '4' - {0xF8, 0xF8, 0x88, 0x88, 0x88, 0x88, 0x08, /*0x00,*/ 0x08, 0x18, 0x10, 0x10, 0x11, 0x1F, 0x0F}, // , 0x00}, // '5' - {0xE0, 0xF0, 0x98, 0x88, 0x88, 0x80, 0x00, /*0x00,*/ 0x0F, 0x1F, 0x10, 0x10, 0x10, 0x1F, 0x0F}, // , 0x00}, // '6' - {0x18, 0x18, 0x08, 0x08, 0x88, 0xF8, 0x78, /*0x00,*/ 0x00, 0x00, 0x1E, 0x1F, 0x01, 0x00, 0x00}, // , 0x00}, // '7' - {0x70, 0xF8, 0x88, 0x88, 0x88, 0xF8, 0x70, /*0x00,*/ 0x0F, 0x1F, 0x10, 0x10, 0x10, 0x1F, 0x0F}, // , 0x00}, // '8' - {0x70, 0xF8, 0x88, 0x88, 0x88, 0xF8, 0xF0, /*0x00,*/ 0x00, 0x10, 0x10, 0x10, 0x18, 0x0F, 0x07}, // , 0x00}, // '9' - {0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00, 0x00}, // , 0x00}, // ':' - {0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x10, 0x1C, 0x0C, 0x00, 0x00}, // , 0x00}, // ';' - {0x00, 0x00, 0x80, 0xC0, 0x60, 0x30, 0x10, /*0x00,*/ 0x00, 0x01, 0x03, 0x06, 0x0C, 0x18, 0x10}, // , 0x00}, // '<' - {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /*0x00,*/ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04}, // , 0x00}, // '=' - {0x00, 0x10, 0x30, 0x60, 0xC0, 0x80, 0x00, /*0x00,*/ 0x00, 0x10, 0x18, 0x0C, 0x06, 0x03, 0x01}, // , 0x00}, // '>' - {0x30, 0x38, 0x08, 0x88, 0xC8, 0x78, 0x30, /*0x00,*/ 0x00, 0x00, 0x00, 0x1B, 0x1B, 0x00, 0x00}, // , 0x00}, // '?' - {0xE0, 0xF0, 0x10, 0x90, 0x90, 0xF0, 0xE0, /*0x00,*/ 0x0F, 0x1F, 0x10, 0x17, 0x17, 0x17, 0x03}, // , 0x00}, // '@' - {0xC0, 0xE0, 0x30, 0x18, 0x30, 0xE0, 0xC0, /*0x00,*/ 0x1F, 0x1F, 0x01, 0x01, 0x01, 0x1F, 0x1F}, // , 0x00}, // 'A' - {0x08, 0xF8, 0xF8, 0x88, 0x88, 0xF8, 0x70, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x10, 0x10, 0x1F, 0x0F}, // , 0x00}, // 'B' - {0xE0, 0xF0, 0x18, 0x08, 0x08, 0x18, 0x30, /*0x00,*/ 0x07, 0x0F, 0x18, 0x10, 0x10, 0x18, 0x0C}, // , 0x00}, // 'C' - {0x08, 0xF8, 0xF8, 0x08, 0x18, 0xF0, 0xE0, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x10, 0x18, 0x0F, 0x07}, // , 0x00}, // 'D' - {0x08, 0xF8, 0xF8, 0x88, 0xC8, 0x18, 0x38, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x10, 0x11, 0x18, 0x1C}, // , 0x00}, // 'E' - {0x08, 0xF8, 0xF8, 0x88, 0xC8, 0x18, 0x38, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x10, 0x01, 0x00, 0x00}, // , 0x00}, // 'F' - {0xE0, 0xF0, 0x18, 0x08, 0x08, 0x18, 0x30, /*0x00,*/ 0x07, 0x0F, 0x18, 0x11, 0x11, 0x0F, 0x1F}, // , 0x00}, // 'G' - {0xF8, 0xF8, 0x80, 0x80, 0x80, 0xF8, 0xF8, /*0x00,*/ 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x1F}, // , 0x00}, // 'H' - {0x00, 0x00, 0x08, 0xF8, 0xF8, 0x08, 0x00, /*0x00,*/ 0x00, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x00}, // , 0x00}, // 'I' - {0x00, 0x00, 0x00, 0x08, 0xF8, 0xF8, 0x08, /*0x00,*/ 0x0E, 0x1E, 0x10, 0x10, 0x1F, 0x0F, 0x00}, // , 0x00}, // 'J' - {0x08, 0xF8, 0xF8, 0x80, 0xE0, 0x78, 0x18, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x01, 0x03, 0x1E, 0x1C}, // , 0x00}, // 'K' - {0x08, 0xF8, 0xF8, 0x08, 0x00, 0x00, 0x00, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x10, 0x10, 0x18, 0x1C}, // , 0x00}, // 'L' - {0xF8, 0xF8, 0x70, 0xE0, 0x70, 0xF8, 0xF8, /*0x00,*/ 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x1F}, // , 0x00}, // 'M' - {0xF8, 0xF8, 0x70, 0xE0, 0xC0, 0xF8, 0xF8, /*0x00,*/ 0x1F, 0x1F, 0x00, 0x00, 0x01, 0x1F, 0x1F}, // , 0x00}, // 'N' - {0xE0, 0xF0, 0x18, 0x08, 0x18, 0xF0, 0xE0, /*0x00,*/ 0x07, 0x0F, 0x18, 0x10, 0x18, 0x0F, 0x07}, // , 0x00}, // 'O' - {0x08, 0xF8, 0xF8, 0x88, 0x88, 0xF8, 0x70, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x10, 0x00, 0x00, 0x00}, // , 0x00}, // 'P' - {0xF0, 0xF8, 0x08, 0x08, 0x08, 0xF8, 0xF0, /*0x00,*/ 0x0F, 0x1F, 0x10, 0x1C, 0x78, 0x7F, 0x4F}, // , 0x00}, // 'Q' - {0x08, 0xF8, 0xF8, 0x88, 0x88, 0xF8, 0x70, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x00, 0x01, 0x1F, 0x1E}, // , 0x00}, // 'R' - {0x30, 0x78, 0xC8, 0x88, 0x88, 0x38, 0x30, /*0x00,*/ 0x0C, 0x1C, 0x10, 0x10, 0x11, 0x1F, 0x0E}, // , 0x00}, // 'S' - {0x00, 0x38, 0x18, 0xF8, 0xF8, 0x18, 0x38, /*0x00,*/ 0x00, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x00}, // , 0x00}, // 'T' - {0xF8, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0xF8, /*0x00,*/ 0x0F, 0x1F, 0x10, 0x10, 0x10, 0x1F, 0x0F}, // , 0x00}, // 'U' - {0xF8, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0xF8, /*0x00,*/ 0x03, 0x07, 0x0C, 0x18, 0x0C, 0x07, 0x03}, // , 0x00}, // 'V' - {0xF8, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0xF8, /*0x00,*/ 0x07, 0x1F, 0x1C, 0x07, 0x1C, 0x1F, 0x07}, // , 0x00}, // 'W' - {0x18, 0x78, 0xE0, 0x80, 0xE0, 0x78, 0x18, /*0x00,*/ 0x18, 0x1E, 0x07, 0x01, 0x07, 0x1E, 0x18}, // , 0x00}, // 'X' - {0x00, 0x78, 0xF8, 0x80, 0x80, 0xF8, 0x78, /*0x00,*/ 0x00, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x00}, // , 0x00}, // 'Y' - {0x38, 0x18, 0x08, 0x88, 0xC8, 0x78, 0x38, /*0x00,*/ 0x1C, 0x1E, 0x13, 0x11, 0x10, 0x18, 0x1C}, // , 0x00}, // 'Z' - {0x00, 0x00, 0xF8, 0xF8, 0x08, 0x08, 0x00, /*0x00,*/ 0x00, 0x00, 0x1F, 0x1F, 0x10, 0x10, 0x00}, // , 0x00}, // '[' - {0x70, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x01, 0x03, 0x07, 0x0E, 0x1C}, // , 0x00}, // '"\' - {0x00, 0x00, 0x08, 0x08, 0xF8, 0xF8, 0x00, /*0x00,*/ 0x00, 0x00, 0x10, 0x10, 0x1F, 0x1F, 0x00}, // , 0x00}, // ']' - {0x10, 0x18, 0x0E, 0x07, 0x0E, 0x18, 0x10, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // , 0x00}, // '^' - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x00,*/ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40}, // , 0x40}, // '_' - {0x00, 0x00, 0x07, 0x0F, 0x08, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // , 0x00}, // '`' - {0x00, 0x40, 0x40, 0x40, 0xC0, 0x80, 0x00, /*0x00,*/ 0x0E, 0x1F, 0x11, 0x11, 0x0F, 0x1F, 0x10}, // , 0x00}, // 'a' - {0x08, 0xF8, 0xF8, 0x40, 0xC0, 0x80, 0x00, /*0x00,*/ 0x10, 0x1F, 0x0F, 0x10, 0x10, 0x1F, 0x0F}, // , 0x00}, // 'b' - {0x80, 0xC0, 0x40, 0x40, 0x40, 0xC0, 0x80, /*0x00,*/ 0x0F, 0x1F, 0x10, 0x10, 0x10, 0x18, 0x08}, // , 0x00}, // 'c' - {0x00, 0x80, 0xC0, 0x48, 0xF8, 0xF8, 0x00, /*0x00,*/ 0x0F, 0x1F, 0x10, 0x10, 0x0F, 0x1F, 0x10}, // , 0x00}, // 'd' - {0x80, 0xC0, 0x40, 0x40, 0x40, 0xC0, 0x80, /*0x00,*/ 0x0F, 0x1F, 0x11, 0x11, 0x11, 0x19, 0x09}, // , 0x00}, // 'e' - {0x80, 0xF0, 0xF8, 0x88, 0x18, 0x30, 0x00, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x10, 0x00, 0x00, 0x00}, // , 0x00}, // 'f' - {0x80, 0xC0, 0x40, 0x40, 0x80, 0xC0, 0x40, /*0x00,*/ 0x4F, 0xDF, 0x90, 0x90, 0xFF, 0x7F, 0x00}, // , 0x00}, // 'g' - {0x08, 0xF8, 0xF8, 0x80, 0x40, 0xC0, 0x80, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x00, 0x00, 0x1F, 0x1F}, // , 0x00}, // 'h' - {0x00, 0x00, 0x40, 0xD8, 0xD8, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x00}, // , 0x00}, // 'i' - {0x00, 0x00, 0x00, 0x00, 0x40, 0xD8, 0xD8, /*0x00,*/ 0x00, 0x60, 0xE0, 0x80, 0x80, 0xFF, 0x7F}, // , 0x00}, // 'j' - {0x08, 0xF8, 0xF8, 0x00, 0x80, 0xC0, 0x40, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x03, 0x07, 0x1C, 0x18}, // , 0x00}, // 'k' - {0x00, 0x00, 0x08, 0xF8, 0xF8, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x00}, // , 0x00}, // 'l' - {0xC0, 0xC0, 0xC0, 0x80, 0xC0, 0xC0, 0x80, /*0x00,*/ 0x1F, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x1F}, // , 0x00}, // 'm' - {0x40, 0xC0, 0x80, 0x40, 0x40, 0xC0, 0x80, /*0x00,*/ 0x00, 0x1F, 0x1F, 0x00, 0x00, 0x1F, 0x1F}, // , 0x00}, // 'n' - {0x80, 0xC0, 0x40, 0x40, 0x40, 0xC0, 0x80, /*0x00,*/ 0x0F, 0x1F, 0x10, 0x10, 0x10, 0x1F, 0x0F}, // , 0x00}, // 'o' - {0x40, 0xC0, 0x80, 0x40, 0x40, 0xC0, 0x80, /*0x00,*/ 0x80, 0xFF, 0xFF, 0x90, 0x10, 0x1F, 0x0F}, // , 0x00}, // 'p' - {0x80, 0xC0, 0x40, 0x40, 0x80, 0xC0, 0x40, /*0x00,*/ 0x0F, 0x1F, 0x10, 0x90, 0xFF, 0xFF, 0x80}, // , 0x00}, // 'q' - {0x40, 0xC0, 0x80, 0xC0, 0x40, 0xC0, 0x80, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x10, 0x00, 0x00, 0x01}, // , 0x00}, // 'r' - {0x80, 0xC0, 0x40, 0x40, 0x40, 0xC0, 0x80, /*0x00,*/ 0x08, 0x19, 0x13, 0x12, 0x16, 0x1C, 0x08}, // , 0x00}, // 's' - {0x40, 0x40, 0xF0, 0xF8, 0x40, 0x40, 0x00, /*0x00,*/ 0x00, 0x00, 0x0F, 0x1F, 0x10, 0x18, 0x08}, // , 0x00}, // 't' - {0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, /*0x00,*/ 0x0F, 0x1F, 0x10, 0x10, 0x0F, 0x1F, 0x10}, // , 0x00}, // 'u' - {0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, /*0x00,*/ 0x00, 0x07, 0x0F, 0x18, 0x18, 0x0F, 0x07}, // , 0x00}, // 'v' - {0xC0, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0xC0, /*0x00,*/ 0x0F, 0x1F, 0x18, 0x0E, 0x18, 0x1F, 0x0F}, // , 0x00}, // 'w' - {0x40, 0xC0, 0x80, 0x00, 0x80, 0xC0, 0x40, /*0x00,*/ 0x10, 0x18, 0x0F, 0x07, 0x0F, 0x18, 0x10}, // , 0x00}, // 'x' - {0xC0, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0xC0, /*0x00,*/ 0x8F, 0x9F, 0x90, 0x90, 0xD0, 0x7F, 0x3F}, // , 0x00}, // 'y' - {0xC0, 0xC0, 0x40, 0x40, 0xC0, 0xC0, 0x40, /*0x00,*/ 0x18, 0x1C, 0x16, 0x13, 0x11, 0x18, 0x18}, // , 0x00}, // 'z' - {0x00, 0x80, 0x80, 0xF0, 0x78, 0x08, 0x08, /*0x00,*/ 0x00, 0x00, 0x00, 0x0F, 0x1F, 0x10, 0x10}, // , 0x00}, // '{' - {0x00, 0x00, 0x00, 0x78, 0x78, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x00, 0x00}, // , 0x00}, // '|' - {0x00, 0x08, 0x08, 0x78, 0xF0, 0x80, 0x80, /*0x00,*/ 0x00, 0x10, 0x10, 0x1F, 0x0F, 0x00, 0x00}, // , 0x00}, // '}' - {0x10, 0x18, 0x08, 0x18, 0x10, 0x18, 0x08, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // , 0x00} // '->' + {0x00, 0x00, 0x70, 0xF8, 0xF8, 0x70, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x1B, 0x1B, 0x00, 0x00}, // , 0x00}, // '!' + {0x00, 0x1E, 0x3E, 0x00, 0x00, 0x3E, 0x1E, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // , 0x00}, // '"' + {0x40, 0xF0, 0xF0, 0x40, 0xF0, 0xF0, 0x40, /*0x00,*/ 0x04, 0x1F, 0x1F, 0x04, 0x1F, 0x1F, 0x04}, // , 0x00}, // '#' + {0x70, 0xF8, 0x88, 0x8F, 0x8F, 0x98, 0x30, /*0x00,*/ 0x06, 0x0C, 0x08, 0x38, 0x38, 0x0F, 0x07}, // , 0x00}, // '$' + {0x60, 0x60, 0x00, 0x00, 0x80, 0xC0, 0x60, /*0x00,*/ 0x18, 0x0C, 0x06, 0x03, 0x01, 0x18, 0x18}, // , 0x00}, // '%' + {0x00, 0xB0, 0xF8, 0xC8, 0x78, 0xB0, 0x80, /*0x00,*/ 0x0F, 0x1F, 0x10, 0x11, 0x0F, 0x1F, 0x10}, // , 0x00}, // '&' + {0x00, 0x20, 0x3E, 0x1E, 0x00, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // , 0x00}, // ''' + {0x00, 0x00, 0xE0, 0xF0, 0x18, 0x08, 0x00, /*0x00,*/ 0x00, 0x00, 0x07, 0x0F, 0x18, 0x10, 0x00}, // , 0x00}, // '(' + {0x00, 0x00, 0x08, 0x18, 0xF0, 0xE0, 0x00, /*0x00,*/ 0x00, 0x00, 0x10, 0x18, 0x0F, 0x07, 0x00}, // , 0x00}, // ')' + {0x00, 0x40, 0xC0, 0x80, 0x80, 0xC0, 0x40, /*0x00,*/ 0x01, 0x05, 0x07, 0x03, 0x03, 0x07, 0x05}, // , 0x01}, // '*' + {0x00, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, /*0x00,*/ 0x00, 0x01, 0x01, 0x07, 0x07, 0x01, 0x01}, // , 0x00}, // '+' + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x20, 0x3C, 0x1C, 0x00, 0x00}, // , 0x00}, // ',' + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x00,*/ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, // , 0x00}, // '-' + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00}, // , 0x00}, // '.' + {0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0x60, /*0x00,*/ 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00, 0x00}, // , 0x00}, // '/' + {0xF0, 0xF8, 0x08, 0x88, 0x48, 0xF8, 0xF0, /*0x00,*/ 0x0F, 0x1F, 0x12, 0x11, 0x10, 0x1F, 0x0F}, // , 0x00}, // '0' + {0x00, 0x20, 0x30, 0xF8, 0xF8, 0x00, 0x00, /*0x00,*/ 0x00, 0x10, 0x10, 0x1F, 0x1F, 0x10, 0x10}, // , 0x00}, // '1' + {0x10, 0x18, 0x08, 0x88, 0xC8, 0x78, 0x30, /*0x00,*/ 0x1C, 0x1E, 0x13, 0x11, 0x10, 0x18, 0x18}, // , 0x00}, // '2' + {0x10, 0x18, 0x88, 0x88, 0x88, 0xF8, 0x70, /*0x00,*/ 0x08, 0x18, 0x10, 0x10, 0x10, 0x1F, 0x0F}, // , 0x00}, // '3' + {0x80, 0xC0, 0x60, 0x30, 0xF8, 0xF8, 0x00, /*0x00,*/ 0x01, 0x01, 0x01, 0x11, 0x1F, 0x1F, 0x11}, // , 0x00}, // '4' + {0xF8, 0xF8, 0x88, 0x88, 0x88, 0x88, 0x08, /*0x00,*/ 0x08, 0x18, 0x10, 0x10, 0x11, 0x1F, 0x0F}, // , 0x00}, // '5' + {0xE0, 0xF0, 0x98, 0x88, 0x88, 0x80, 0x00, /*0x00,*/ 0x0F, 0x1F, 0x10, 0x10, 0x10, 0x1F, 0x0F}, // , 0x00}, // '6' + {0x18, 0x18, 0x08, 0x08, 0x88, 0xF8, 0x78, /*0x00,*/ 0x00, 0x00, 0x1E, 0x1F, 0x01, 0x00, 0x00}, // , 0x00}, // '7' + {0x70, 0xF8, 0x88, 0x88, 0x88, 0xF8, 0x70, /*0x00,*/ 0x0F, 0x1F, 0x10, 0x10, 0x10, 0x1F, 0x0F}, // , 0x00}, // '8' + {0x70, 0xF8, 0x88, 0x88, 0x88, 0xF8, 0xF0, /*0x00,*/ 0x00, 0x10, 0x10, 0x10, 0x18, 0x0F, 0x07}, // , 0x00}, // '9' + {0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00, 0x00}, // , 0x00}, // ':' + {0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x10, 0x1C, 0x0C, 0x00, 0x00}, // , 0x00}, // ';' + {0x00, 0x00, 0x80, 0xC0, 0x60, 0x30, 0x10, /*0x00,*/ 0x00, 0x01, 0x03, 0x06, 0x0C, 0x18, 0x10}, // , 0x00}, // '<' + {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /*0x00,*/ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04}, // , 0x00}, // '=' + {0x00, 0x10, 0x30, 0x60, 0xC0, 0x80, 0x00, /*0x00,*/ 0x00, 0x10, 0x18, 0x0C, 0x06, 0x03, 0x01}, // , 0x00}, // '>' + {0x30, 0x38, 0x08, 0x88, 0xC8, 0x78, 0x30, /*0x00,*/ 0x00, 0x00, 0x00, 0x1B, 0x1B, 0x00, 0x00}, // , 0x00}, // '?' + {0xE0, 0xF0, 0x10, 0x90, 0x90, 0xF0, 0xE0, /*0x00,*/ 0x0F, 0x1F, 0x10, 0x17, 0x17, 0x17, 0x03}, // , 0x00}, // '@' + {0xC0, 0xE0, 0x30, 0x18, 0x30, 0xE0, 0xC0, /*0x00,*/ 0x1F, 0x1F, 0x01, 0x01, 0x01, 0x1F, 0x1F}, // , 0x00}, // 'A' + {0x08, 0xF8, 0xF8, 0x88, 0x88, 0xF8, 0x70, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x10, 0x10, 0x1F, 0x0F}, // , 0x00}, // 'B' + {0xE0, 0xF0, 0x18, 0x08, 0x08, 0x18, 0x30, /*0x00,*/ 0x07, 0x0F, 0x18, 0x10, 0x10, 0x18, 0x0C}, // , 0x00}, // 'C' + {0x08, 0xF8, 0xF8, 0x08, 0x18, 0xF0, 0xE0, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x10, 0x18, 0x0F, 0x07}, // , 0x00}, // 'D' + {0x08, 0xF8, 0xF8, 0x88, 0xC8, 0x18, 0x38, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x10, 0x11, 0x18, 0x1C}, // , 0x00}, // 'E' + {0x08, 0xF8, 0xF8, 0x88, 0xC8, 0x18, 0x38, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x10, 0x01, 0x00, 0x00}, // , 0x00}, // 'F' + {0xE0, 0xF0, 0x18, 0x08, 0x08, 0x18, 0x30, /*0x00,*/ 0x07, 0x0F, 0x18, 0x11, 0x11, 0x0F, 0x1F}, // , 0x00}, // 'G' + {0xF8, 0xF8, 0x80, 0x80, 0x80, 0xF8, 0xF8, /*0x00,*/ 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x1F}, // , 0x00}, // 'H' + {0x00, 0x00, 0x08, 0xF8, 0xF8, 0x08, 0x00, /*0x00,*/ 0x00, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x00}, // , 0x00}, // 'I' + {0x00, 0x00, 0x00, 0x08, 0xF8, 0xF8, 0x08, /*0x00,*/ 0x0E, 0x1E, 0x10, 0x10, 0x1F, 0x0F, 0x00}, // , 0x00}, // 'J' + {0x08, 0xF8, 0xF8, 0x80, 0xE0, 0x78, 0x18, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x01, 0x03, 0x1E, 0x1C}, // , 0x00}, // 'K' + {0x08, 0xF8, 0xF8, 0x08, 0x00, 0x00, 0x00, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x10, 0x10, 0x18, 0x1C}, // , 0x00}, // 'L' + {0xF8, 0xF8, 0x70, 0xE0, 0x70, 0xF8, 0xF8, /*0x00,*/ 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x1F}, // , 0x00}, // 'M' + {0xF8, 0xF8, 0x70, 0xE0, 0xC0, 0xF8, 0xF8, /*0x00,*/ 0x1F, 0x1F, 0x00, 0x00, 0x01, 0x1F, 0x1F}, // , 0x00}, // 'N' + {0xE0, 0xF0, 0x18, 0x08, 0x18, 0xF0, 0xE0, /*0x00,*/ 0x07, 0x0F, 0x18, 0x10, 0x18, 0x0F, 0x07}, // , 0x00}, // 'O' + {0x08, 0xF8, 0xF8, 0x88, 0x88, 0xF8, 0x70, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x10, 0x00, 0x00, 0x00}, // , 0x00}, // 'P' + {0xF0, 0xF8, 0x08, 0x08, 0x08, 0xF8, 0xF0, /*0x00,*/ 0x0F, 0x1F, 0x10, 0x1C, 0x78, 0x7F, 0x4F}, // , 0x00}, // 'Q' + {0x08, 0xF8, 0xF8, 0x88, 0x88, 0xF8, 0x70, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x00, 0x01, 0x1F, 0x1E}, // , 0x00}, // 'R' + {0x30, 0x78, 0xC8, 0x88, 0x88, 0x38, 0x30, /*0x00,*/ 0x0C, 0x1C, 0x10, 0x10, 0x11, 0x1F, 0x0E}, // , 0x00}, // 'S' + {0x00, 0x38, 0x18, 0xF8, 0xF8, 0x18, 0x38, /*0x00,*/ 0x00, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x00}, // , 0x00}, // 'T' + {0xF8, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0xF8, /*0x00,*/ 0x0F, 0x1F, 0x10, 0x10, 0x10, 0x1F, 0x0F}, // , 0x00}, // 'U' + {0xF8, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0xF8, /*0x00,*/ 0x03, 0x07, 0x0C, 0x18, 0x0C, 0x07, 0x03}, // , 0x00}, // 'V' + {0xF8, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0xF8, /*0x00,*/ 0x07, 0x1F, 0x1C, 0x07, 0x1C, 0x1F, 0x07}, // , 0x00}, // 'W' + {0x18, 0x78, 0xE0, 0x80, 0xE0, 0x78, 0x18, /*0x00,*/ 0x18, 0x1E, 0x07, 0x01, 0x07, 0x1E, 0x18}, // , 0x00}, // 'X' + {0x00, 0x78, 0xF8, 0x80, 0x80, 0xF8, 0x78, /*0x00,*/ 0x00, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x00}, // , 0x00}, // 'Y' + {0x38, 0x18, 0x08, 0x88, 0xC8, 0x78, 0x38, /*0x00,*/ 0x1C, 0x1E, 0x13, 0x11, 0x10, 0x18, 0x1C}, // , 0x00}, // 'Z' + {0x00, 0x00, 0xF8, 0xF8, 0x08, 0x08, 0x00, /*0x00,*/ 0x00, 0x00, 0x1F, 0x1F, 0x10, 0x10, 0x00}, // , 0x00}, // '[' + {0x70, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x01, 0x03, 0x07, 0x0E, 0x1C}, // , 0x00}, // '"\' + {0x00, 0x00, 0x08, 0x08, 0xF8, 0xF8, 0x00, /*0x00,*/ 0x00, 0x00, 0x10, 0x10, 0x1F, 0x1F, 0x00}, // , 0x00}, // ']' + {0x10, 0x18, 0x0E, 0x07, 0x0E, 0x18, 0x10, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // , 0x00}, // '^' + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x00,*/ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40}, // , 0x40}, // '_' + {0x00, 0x00, 0x07, 0x0F, 0x08, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // , 0x00}, // '`' + {0x00, 0x40, 0x40, 0x40, 0xC0, 0x80, 0x00, /*0x00,*/ 0x0E, 0x1F, 0x11, 0x11, 0x0F, 0x1F, 0x10}, // , 0x00}, // 'a' + {0x08, 0xF8, 0xF8, 0x40, 0xC0, 0x80, 0x00, /*0x00,*/ 0x10, 0x1F, 0x0F, 0x10, 0x10, 0x1F, 0x0F}, // , 0x00}, // 'b' + {0x80, 0xC0, 0x40, 0x40, 0x40, 0xC0, 0x80, /*0x00,*/ 0x0F, 0x1F, 0x10, 0x10, 0x10, 0x18, 0x08}, // , 0x00}, // 'c' + {0x00, 0x80, 0xC0, 0x48, 0xF8, 0xF8, 0x00, /*0x00,*/ 0x0F, 0x1F, 0x10, 0x10, 0x0F, 0x1F, 0x10}, // , 0x00}, // 'd' + {0x80, 0xC0, 0x40, 0x40, 0x40, 0xC0, 0x80, /*0x00,*/ 0x0F, 0x1F, 0x11, 0x11, 0x11, 0x19, 0x09}, // , 0x00}, // 'e' + {0x80, 0xF0, 0xF8, 0x88, 0x18, 0x30, 0x00, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x10, 0x00, 0x00, 0x00}, // , 0x00}, // 'f' + {0x80, 0xC0, 0x40, 0x40, 0x80, 0xC0, 0x40, /*0x00,*/ 0x4F, 0xDF, 0x90, 0x90, 0xFF, 0x7F, 0x00}, // , 0x00}, // 'g' + {0x08, 0xF8, 0xF8, 0x80, 0x40, 0xC0, 0x80, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x00, 0x00, 0x1F, 0x1F}, // , 0x00}, // 'h' + {0x00, 0x00, 0x40, 0xD8, 0xD8, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x00}, // , 0x00}, // 'i' + {0x00, 0x00, 0x00, 0x00, 0x40, 0xD8, 0xD8, /*0x00,*/ 0x00, 0x60, 0xE0, 0x80, 0x80, 0xFF, 0x7F}, // , 0x00}, // 'j' + {0x08, 0xF8, 0xF8, 0x00, 0x80, 0xC0, 0x40, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x03, 0x07, 0x1C, 0x18}, // , 0x00}, // 'k' + {0x00, 0x00, 0x08, 0xF8, 0xF8, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x00}, // , 0x00}, // 'l' + {0xC0, 0xC0, 0xC0, 0x80, 0xC0, 0xC0, 0x80, /*0x00,*/ 0x1F, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x1F}, // , 0x00}, // 'm' + {0x40, 0xC0, 0x80, 0x40, 0x40, 0xC0, 0x80, /*0x00,*/ 0x00, 0x1F, 0x1F, 0x00, 0x00, 0x1F, 0x1F}, // , 0x00}, // 'n' + {0x80, 0xC0, 0x40, 0x40, 0x40, 0xC0, 0x80, /*0x00,*/ 0x0F, 0x1F, 0x10, 0x10, 0x10, 0x1F, 0x0F}, // , 0x00}, // 'o' + {0x40, 0xC0, 0x80, 0x40, 0x40, 0xC0, 0x80, /*0x00,*/ 0x80, 0xFF, 0xFF, 0x90, 0x10, 0x1F, 0x0F}, // , 0x00}, // 'p' + {0x80, 0xC0, 0x40, 0x40, 0x80, 0xC0, 0x40, /*0x00,*/ 0x0F, 0x1F, 0x10, 0x90, 0xFF, 0xFF, 0x80}, // , 0x00}, // 'q' + {0x40, 0xC0, 0x80, 0xC0, 0x40, 0xC0, 0x80, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x10, 0x00, 0x00, 0x01}, // , 0x00}, // 'r' + {0x80, 0xC0, 0x40, 0x40, 0x40, 0xC0, 0x80, /*0x00,*/ 0x08, 0x19, 0x13, 0x12, 0x16, 0x1C, 0x08}, // , 0x00}, // 's' + {0x40, 0x40, 0xF0, 0xF8, 0x40, 0x40, 0x00, /*0x00,*/ 0x00, 0x00, 0x0F, 0x1F, 0x10, 0x18, 0x08}, // , 0x00}, // 't' + {0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, /*0x00,*/ 0x0F, 0x1F, 0x10, 0x10, 0x0F, 0x1F, 0x10}, // , 0x00}, // 'u' + {0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, /*0x00,*/ 0x00, 0x07, 0x0F, 0x18, 0x18, 0x0F, 0x07}, // , 0x00}, // 'v' + {0xC0, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0xC0, /*0x00,*/ 0x0F, 0x1F, 0x18, 0x0E, 0x18, 0x1F, 0x0F}, // , 0x00}, // 'w' + {0x40, 0xC0, 0x80, 0x00, 0x80, 0xC0, 0x40, /*0x00,*/ 0x10, 0x18, 0x0F, 0x07, 0x0F, 0x18, 0x10}, // , 0x00}, // 'x' + {0xC0, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0xC0, /*0x00,*/ 0x8F, 0x9F, 0x90, 0x90, 0xD0, 0x7F, 0x3F}, // , 0x00}, // 'y' + {0xC0, 0xC0, 0x40, 0x40, 0xC0, 0xC0, 0x40, /*0x00,*/ 0x18, 0x1C, 0x16, 0x13, 0x11, 0x18, 0x18}, // , 0x00}, // 'z' + {0x00, 0x80, 0x80, 0xF0, 0x78, 0x08, 0x08, /*0x00,*/ 0x00, 0x00, 0x00, 0x0F, 0x1F, 0x10, 0x10}, // , 0x00}, // '{' + {0x00, 0x00, 0x00, 0x78, 0x78, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x00, 0x00}, // , 0x00}, // '|' + {0x00, 0x08, 0x08, 0x78, 0xF0, 0x80, 0x80, /*0x00,*/ 0x00, 0x10, 0x10, 0x1F, 0x0F, 0x00, 0x00}, // , 0x00}, // '}' + {0x10, 0x18, 0x08, 0x18, 0x10, 0x18, 0x08, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // , 0x00} // '->' #else // {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // ' ' - {0x00, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x00, 0x00}, // '!' - {0x00, 0x0F, 0x1F, 0x00, 0x00, 0x1F, 0x0F, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // '"' - {0x20, 0xF8, 0xF8, 0x20, 0xF8, 0xF8, 0x20, /*0x00,*/ 0x02, 0x0F, 0x0F, 0x02, 0x0F, 0x0F, 0x02}, // '#' - {0x70, 0xF8, 0x88, 0x8E, 0x8E, 0x98, 0x10, /*0x00,*/ 0x04, 0x0C, 0x08, 0x38, 0x38, 0x0F, 0x07}, // '$' - {0x30, 0x30, 0x00, 0x80, 0xC0, 0x60, 0x30, /*0x00,*/ 0x0C, 0x06, 0x03, 0x01, 0x00, 0x0C, 0x0C}, // '%' - {0x80, 0xD8, 0x7C, 0xE4, 0xBC, 0xD8, 0x40, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x07, 0x0F, 0x08}, // '&' - {0x00, 0x10, 0x1F, 0x0F, 0x00, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // ''' - {0x00, 0x00, 0xF0, 0xF8, 0x0C, 0x04, 0x00, /*0x00,*/ 0x00, 0x00, 0x03, 0x07, 0x0C, 0x08, 0x00}, // '(' - {0x00, 0x00, 0x04, 0x0C, 0xF8, 0xF0, 0x00, /*0x00,*/ 0x00, 0x00, 0x08, 0x0C, 0x07, 0x03, 0x00}, // ')' - {0x00, 0x80, 0xA0, 0xE0, 0xC0, 0xE0, 0xA0, /*0x80,*/ 0x00, 0x00, 0x02, 0x03, 0x01, 0x03, 0x02}, // '*' - {0x00, 0x80, 0x80, 0xE0, 0xE0, 0x80, 0x80, /*0x00,*/ 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00}, // '+' - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x10, 0x1E, 0x0E, 0x00, 0x00}, // ',' - {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // '-' - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00, 0x00}, // '.' - {0x00, 0x00, 0x00, 0x80, 0xC0, 0x60, 0x30, /*0x00,*/ 0x0C, 0x06, 0x03, 0x01, 0x00, 0x00, 0x00}, // '/' - {0xF8, 0xFC, 0x04, 0x04, 0x04, 0xFC, 0xF8, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x0F, 0x07}, // '0' - {0x00, 0x10, 0x18, 0xFC, 0xFC, 0x00, 0x00, /*0x00,*/ 0x00, 0x08, 0x08, 0x0F, 0x0F, 0x08, 0x08}, // '1' - {0x18, 0x1C, 0x04, 0x84, 0xC4, 0x7C, 0x38, /*0x00,*/ 0x0C, 0x0E, 0x0B, 0x09, 0x08, 0x08, 0x08}, // '2' - {0x18, 0x1C, 0x44, 0x44, 0x44, 0xFC, 0xB8, /*0x00,*/ 0x06, 0x0E, 0x08, 0x08, 0x08, 0x0F, 0x07}, // '3' - {0x80, 0xC0, 0x60, 0x30, 0x18, 0xFC, 0xFC, /*0x00,*/ 0x01, 0x01, 0x01, 0x01, 0x01, 0x0F, 0x0F}, // '4' - {0x7C, 0x7C, 0x44, 0x44, 0x44, 0xC4, 0x84, /*0x00,*/ 0x04, 0x0C, 0x08, 0x08, 0x08, 0x0F, 0x07}, // '5' - {0xF0, 0xF8, 0x4C, 0x44, 0x44, 0xC4, 0x80, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x0F, 0x07}, // '6' - {0x04, 0x04, 0x04, 0x84, 0xE4, 0x7C, 0x1C, /*0x00,*/ 0x00, 0x00, 0x0E, 0x0F, 0x01, 0x00, 0x00}, // '7' - {0xB8, 0xFC, 0x44, 0x44, 0x44, 0xFC, 0xB8, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x0F, 0x07}, // '8' - {0x78, 0xFC, 0x84, 0x84, 0x84, 0xFC, 0xF8, /*0x00,*/ 0x00, 0x08, 0x08, 0x08, 0x0C, 0x07, 0x03}, // '9' - {0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00}, // ':' - {0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x08, 0x0E, 0x06, 0x00, 0x00}, // ';' - {0x00, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x08, /*0x00,*/ 0x00, 0x00, 0x01, 0x03, 0x06, 0x0C, 0x08}, // '<' - {0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /*0x00,*/ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02}, // '=' - {0x00, 0x08, 0x18, 0x30, 0x60, 0xC0, 0x80, /*0x00,*/ 0x00, 0x08, 0x0C, 0x06, 0x03, 0x01, 0x00}, // '>' - {0x38, 0x3C, 0x04, 0x84, 0xC4, 0x7C, 0x38, /*0x00,*/ 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x00, 0x00}, // '?' - {0xF0, 0xF8, 0x08, 0xC8, 0xC8, 0xF8, 0xF0, /*0x00,*/ 0x07, 0x0F, 0x08, 0x0B, 0x0B, 0x0B, 0x01}, // '@' - {0xF8, 0xFC, 0x84, 0x84, 0x84, 0xFC, 0xF8, /*0x00,*/ 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F}, // 'A' - {0xFC, 0xFC, 0x44, 0x44, 0x44, 0xFC, 0xB8, /*0x00,*/ 0x0F, 0x0F, 0x08, 0x08, 0x08, 0x0F, 0x07}, // 'B' - {0xF8, 0xFC, 0x04, 0x04, 0x04, 0x1C, 0x18, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x0E, 0x06}, // 'C' - {0xFC, 0xFC, 0x04, 0x04, 0x0C, 0xF8, 0xF0, /*0x00,*/ 0x0F, 0x0F, 0x08, 0x08, 0x0C, 0x07, 0x03}, // 'D' - {0xFC, 0xFC, 0x44, 0x44, 0x44, 0x04, 0x04, /*0x00,*/ 0x0F, 0x0F, 0x08, 0x08, 0x08, 0x08, 0x08}, // 'E' - {0xFC, 0xFC, 0x44, 0x44, 0x44, 0x04, 0x04, /*0x00,*/ 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00}, // 'F' - {0xF8, 0xFC, 0x04, 0x84, 0x84, 0x9C, 0x98, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x0F, 0x07}, // 'G' - {0xFC, 0xFC, 0x40, 0x40, 0x40, 0xFC, 0xFC, /*0x00,*/ 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F}, // 'H' - {0x00, 0x00, 0x04, 0xFC, 0xFC, 0x04, 0x00, /*0x00,*/ 0x00, 0x00, 0x08, 0x0F, 0x0F, 0x08, 0x00}, // 'I' - {0x00, 0x00, 0x00, 0x04, 0xFC, 0xFC, 0x04, /*0x00,*/ 0x06, 0x0E, 0x08, 0x08, 0x0F, 0x07, 0x00}, // 'J' - {0xFC, 0xFC, 0xE0, 0x30, 0x18, 0x0C, 0x04, /*0x00,*/ 0x0F, 0x0F, 0x01, 0x03, 0x06, 0x0C, 0x08}, // 'K' - {0xFC, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x00,*/ 0x0F, 0x0F, 0x08, 0x08, 0x08, 0x08, 0x08}, // 'L' - {0xFC, 0xFC, 0x18, 0x70, 0x18, 0xFC, 0xFC, /*0x00,*/ 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F}, // 'M' - {0xFC, 0xFC, 0x60, 0xC0, 0x80, 0xFC, 0xFC, /*0x00,*/ 0x0F, 0x0F, 0x00, 0x00, 0x01, 0x0F, 0x0F}, // 'N' - {0xF8, 0xFC, 0x04, 0x04, 0x04, 0xFC, 0xF8, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x0F, 0x07}, // 'O' - {0xFC, 0xFC, 0x84, 0x84, 0x84, 0xFC, 0x78, /*0x00,*/ 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00}, // 'P' - {0xF8, 0xFC, 0x04, 0x04, 0x04, 0xFC, 0xF8, /*0x00,*/ 0x07, 0x0F, 0x08, 0x0C, 0x0C, 0x1F, 0x17}, // 'Q' - {0xFC, 0xFC, 0x84, 0x84, 0x84, 0xFC, 0x78, /*0x00,*/ 0x0F, 0x0F, 0x01, 0x03, 0x06, 0x0C, 0x08}, // 'R' - {0x38, 0x7C, 0x44, 0x44, 0x44, 0xCC, 0x88, /*0x00,*/ 0x06, 0x0E, 0x08, 0x08, 0x08, 0x0F, 0x07}, // 'S' - {0x00, 0x04, 0x04, 0xFC, 0xFC, 0x04, 0x04, /*0x00,*/ 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00}, // 'T' - {0xFC, 0xFC, 0x00, 0x00, 0x00, 0xFC, 0xFC, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x0F, 0x07}, // 'U' - {0x7C, 0xFC, 0x80, 0x00, 0x80, 0xFC, 0x7C, /*0x00,*/ 0x00, 0x03, 0x0F, 0x0C, 0x0F, 0x03, 0x00}, // 'V' - {0xFC, 0xFC, 0x00, 0x80, 0x00, 0xFC, 0xFC, /*0x00,*/ 0x0F, 0x0F, 0x06, 0x03, 0x06, 0x0F, 0x0F}, // 'W' - {0x0C, 0x3C, 0xF0, 0xC0, 0xF0, 0x3C, 0x0C, /*0x00,*/ 0x0C, 0x0F, 0x03, 0x00, 0x03, 0x0F, 0x0C}, // 'X' - {0x00, 0x3C, 0x7C, 0xC0, 0xC0, 0x7C, 0x3C, /*0x00,*/ 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00}, // 'Y' - {0x04, 0x04, 0x84, 0xC4, 0x64, 0x3C, 0x1C, /*0x00,*/ 0x0E, 0x0F, 0x09, 0x08, 0x08, 0x08, 0x08}, // 'Z' - {0x00, 0x00, 0xFC, 0xFC, 0x04, 0x04, 0x00, /*0x00,*/ 0x00, 0x00, 0x0F, 0x0F, 0x08, 0x08, 0x00}, // '[' - {0x38, 0x70, 0xE0, 0xC0, 0x80, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x0E}, // '"\' - {0x00, 0x00, 0x04, 0x04, 0xFC, 0xFC, 0x00, /*0x00,*/ 0x00, 0x00, 0x08, 0x08, 0x0F, 0x0F, 0x00}, // ']' - {0x08, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x08, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // '^' - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x00,*/ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}, // '_' - {0x00, 0x00, 0x03, 0x07, 0x04, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // '`' - {0x00, 0xA0, 0xA0, 0xA0, 0xA0, 0xE0, 0xC0, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x0F, 0x0F}, // 'a' - {0xFC, 0xFC, 0x20, 0x20, 0x20, 0xE0, 0xC0, /*0x00,*/ 0x0F, 0x0F, 0x08, 0x08, 0x08, 0x0F, 0x07}, // 'b' - {0xC0, 0xE0, 0x20, 0x20, 0x20, 0x60, 0x40, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x0C, 0x04}, // 'c' - {0xC0, 0xE0, 0x20, 0x20, 0x20, 0xFC, 0xFC, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x0F, 0x0F}, // 'd' - {0xC0, 0xE0, 0x20, 0x20, 0x20, 0xE0, 0xC0, /*0x00,*/ 0x07, 0x0F, 0x09, 0x09, 0x09, 0x09, 0x01}, // 'e' - {0x20, 0x20, 0xF8, 0xFC, 0x24, 0x24, 0x04, /*0x00,*/ 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00}, // 'f' - {0xC0, 0xE0, 0x20, 0x20, 0x20, 0xE0, 0xE0, /*0x00,*/ 0x07, 0x4F, 0x48, 0x48, 0x48, 0x7F, 0x3F}, // 'g' - {0xFC, 0xFC, 0x20, 0x20, 0x20, 0xE0, 0xC0, /*0x00,*/ 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F}, // 'h' - {0x00, 0x00, 0x20, 0xEC, 0xEC, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x08, 0x0F, 0x0F, 0x08, 0x00}, // 'i' - {0x00, 0x00, 0x00, 0x00, 0x20, 0xEC, 0xEC, /*0x00,*/ 0x00, 0x30, 0x70, 0x40, 0x40, 0x7F, 0x3F}, // 'j' - {0xFC, 0xFC, 0x00, 0x80, 0xC0, 0x60, 0x20, /*0x00,*/ 0x0F, 0x0F, 0x01, 0x03, 0x06, 0x0C, 0x08}, // 'k' - {0x00, 0x00, 0x04, 0xFC, 0xFC, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x08, 0x0F, 0x0F, 0x08, 0x00}, // 'l' - {0xE0, 0xE0, 0x20, 0xE0, 0x20, 0xE0, 0xC0, /*0x00,*/ 0x0F, 0x0F, 0x00, 0x0F, 0x00, 0x0F, 0x0F}, // 'm' - {0xE0, 0xE0, 0x20, 0x20, 0x20, 0xE0, 0xC0, /*0x00,*/ 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F}, // 'n' - {0xC0, 0xE0, 0x20, 0x20, 0x20, 0xE0, 0xC0, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x0F, 0x07}, // 'o' - {0xE0, 0xE0, 0x20, 0x20, 0x20, 0xE0, 0xC0, /*0x00,*/ 0x7F, 0x7F, 0x08, 0x08, 0x08, 0x0F, 0x07}, // 'p' - {0xC0, 0xE0, 0x20, 0x20, 0x20, 0xE0, 0xE0, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x7F, 0x7F}, // 'q' - {0xE0, 0xE0, 0x60, 0x20, 0x20, 0x20, 0x20, /*0x00,*/ 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00}, // 'r' - {0xC0, 0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, /*0x00,*/ 0x08, 0x09, 0x09, 0x09, 0x09, 0x0F, 0x06}, // 's' - {0x20, 0x20, 0xFC, 0xFC, 0x20, 0x20, 0x00, /*0x00,*/ 0x00, 0x00, 0x07, 0x0F, 0x08, 0x08, 0x08}, // 't' - {0xE0, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0xE0, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x0F, 0x0F}, // 'u' - {0xE0, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0xE0, /*0x00,*/ 0x00, 0x03, 0x0F, 0x0C, 0x0F, 0x03, 0x00}, // 'v' - {0xE0, 0xE0, 0x00, 0x80, 0x00, 0xE0, 0xE0, /*0x00,*/ 0x07, 0x0F, 0x08, 0x0F, 0x08, 0x0F, 0x07}, // 'w' - {0x60, 0xE0, 0x80, 0x00, 0x80, 0xE0, 0x60, /*0x00,*/ 0x0C, 0x0E, 0x03, 0x01, 0x03, 0x0E, 0x0C}, // 'x' - {0xE0, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0xE0, /*0x00,*/ 0x07, 0x4F, 0x48, 0x48, 0x48, 0x7F, 0x3F}, // 'y' - {0x20, 0x20, 0x20, 0xA0, 0xE0, 0x60, 0x20, /*0x00,*/ 0x0C, 0x0E, 0x0B, 0x09, 0x08, 0x08, 0x08}, // 'z' - {0x00, 0x00, 0x40, 0xF8, 0xBC, 0x04, 0x04, /*0x00,*/ 0x00, 0x00, 0x00, 0x07, 0x0F, 0x08, 0x08}, // '{' - {0x00, 0x00, 0x00, 0xBC, 0xBC, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00}, // '|' - {0x00, 0x04, 0x04, 0xBC, 0xF8, 0x40, 0x00, /*0x00,*/ 0x00, 0x08, 0x08, 0x0F, 0x07, 0x00, 0x00}, // '}' - {0x08, 0x0C, 0x04, 0x0C, 0x08, 0x0C, 0x04, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // '->' + {0x00, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x00, 0x00}, // '!' + {0x00, 0x0F, 0x1F, 0x00, 0x00, 0x1F, 0x0F, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // '"' + {0x20, 0xF8, 0xF8, 0x20, 0xF8, 0xF8, 0x20, /*0x00,*/ 0x02, 0x0F, 0x0F, 0x02, 0x0F, 0x0F, 0x02}, // '#' + {0x70, 0xF8, 0x88, 0x8E, 0x8E, 0x98, 0x10, /*0x00,*/ 0x04, 0x0C, 0x08, 0x38, 0x38, 0x0F, 0x07}, // '$' + {0x30, 0x30, 0x00, 0x80, 0xC0, 0x60, 0x30, /*0x00,*/ 0x0C, 0x06, 0x03, 0x01, 0x00, 0x0C, 0x0C}, // '%' + {0x80, 0xD8, 0x7C, 0xE4, 0xBC, 0xD8, 0x40, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x07, 0x0F, 0x08}, // '&' + {0x00, 0x10, 0x1F, 0x0F, 0x00, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // ''' + {0x00, 0x00, 0xF0, 0xF8, 0x0C, 0x04, 0x00, /*0x00,*/ 0x00, 0x00, 0x03, 0x07, 0x0C, 0x08, 0x00}, // '(' + {0x00, 0x00, 0x04, 0x0C, 0xF8, 0xF0, 0x00, /*0x00,*/ 0x00, 0x00, 0x08, 0x0C, 0x07, 0x03, 0x00}, // ')' + {0x00, 0x80, 0xA0, 0xE0, 0xC0, 0xE0, 0xA0, /*0x80,*/ 0x00, 0x00, 0x02, 0x03, 0x01, 0x03, 0x02}, // '*' + {0x00, 0x80, 0x80, 0xE0, 0xE0, 0x80, 0x80, /*0x00,*/ 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00}, // '+' + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x10, 0x1E, 0x0E, 0x00, 0x00}, // ',' + {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // '-' + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00, 0x00}, // '.' + {0x00, 0x00, 0x00, 0x80, 0xC0, 0x60, 0x30, /*0x00,*/ 0x0C, 0x06, 0x03, 0x01, 0x00, 0x00, 0x00}, // '/' + {0xF8, 0xFC, 0x04, 0x04, 0x04, 0xFC, 0xF8, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x0F, 0x07}, // '0' + {0x00, 0x10, 0x18, 0xFC, 0xFC, 0x00, 0x00, /*0x00,*/ 0x00, 0x08, 0x08, 0x0F, 0x0F, 0x08, 0x08}, // '1' + {0x18, 0x1C, 0x04, 0x84, 0xC4, 0x7C, 0x38, /*0x00,*/ 0x0C, 0x0E, 0x0B, 0x09, 0x08, 0x08, 0x08}, // '2' + {0x18, 0x1C, 0x44, 0x44, 0x44, 0xFC, 0xB8, /*0x00,*/ 0x06, 0x0E, 0x08, 0x08, 0x08, 0x0F, 0x07}, // '3' + {0x80, 0xC0, 0x60, 0x30, 0x18, 0xFC, 0xFC, /*0x00,*/ 0x01, 0x01, 0x01, 0x01, 0x01, 0x0F, 0x0F}, // '4' + {0x7C, 0x7C, 0x44, 0x44, 0x44, 0xC4, 0x84, /*0x00,*/ 0x04, 0x0C, 0x08, 0x08, 0x08, 0x0F, 0x07}, // '5' + {0xF0, 0xF8, 0x4C, 0x44, 0x44, 0xC4, 0x80, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x0F, 0x07}, // '6' + {0x04, 0x04, 0x04, 0x84, 0xE4, 0x7C, 0x1C, /*0x00,*/ 0x00, 0x00, 0x0E, 0x0F, 0x01, 0x00, 0x00}, // '7' + {0xB8, 0xFC, 0x44, 0x44, 0x44, 0xFC, 0xB8, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x0F, 0x07}, // '8' + {0x78, 0xFC, 0x84, 0x84, 0x84, 0xFC, 0xF8, /*0x00,*/ 0x00, 0x08, 0x08, 0x08, 0x0C, 0x07, 0x03}, // '9' + {0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00}, // ':' + {0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x08, 0x0E, 0x06, 0x00, 0x00}, // ';' + {0x00, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x08, /*0x00,*/ 0x00, 0x00, 0x01, 0x03, 0x06, 0x0C, 0x08}, // '<' + {0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /*0x00,*/ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02}, // '=' + {0x00, 0x08, 0x18, 0x30, 0x60, 0xC0, 0x80, /*0x00,*/ 0x00, 0x08, 0x0C, 0x06, 0x03, 0x01, 0x00}, // '>' + {0x38, 0x3C, 0x04, 0x84, 0xC4, 0x7C, 0x38, /*0x00,*/ 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x00, 0x00}, // '?' + {0xF0, 0xF8, 0x08, 0xC8, 0xC8, 0xF8, 0xF0, /*0x00,*/ 0x07, 0x0F, 0x08, 0x0B, 0x0B, 0x0B, 0x01}, // '@' + {0xF8, 0xFC, 0x84, 0x84, 0x84, 0xFC, 0xF8, /*0x00,*/ 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F}, // 'A' + {0xFC, 0xFC, 0x44, 0x44, 0x44, 0xFC, 0xB8, /*0x00,*/ 0x0F, 0x0F, 0x08, 0x08, 0x08, 0x0F, 0x07}, // 'B' + {0xF8, 0xFC, 0x04, 0x04, 0x04, 0x1C, 0x18, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x0E, 0x06}, // 'C' + {0xFC, 0xFC, 0x04, 0x04, 0x0C, 0xF8, 0xF0, /*0x00,*/ 0x0F, 0x0F, 0x08, 0x08, 0x0C, 0x07, 0x03}, // 'D' + {0xFC, 0xFC, 0x44, 0x44, 0x44, 0x04, 0x04, /*0x00,*/ 0x0F, 0x0F, 0x08, 0x08, 0x08, 0x08, 0x08}, // 'E' + {0xFC, 0xFC, 0x44, 0x44, 0x44, 0x04, 0x04, /*0x00,*/ 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00}, // 'F' + {0xF8, 0xFC, 0x04, 0x84, 0x84, 0x9C, 0x98, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x0F, 0x07}, // 'G' + {0xFC, 0xFC, 0x40, 0x40, 0x40, 0xFC, 0xFC, /*0x00,*/ 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F}, // 'H' + {0x00, 0x00, 0x04, 0xFC, 0xFC, 0x04, 0x00, /*0x00,*/ 0x00, 0x00, 0x08, 0x0F, 0x0F, 0x08, 0x00}, // 'I' + {0x00, 0x00, 0x00, 0x04, 0xFC, 0xFC, 0x04, /*0x00,*/ 0x06, 0x0E, 0x08, 0x08, 0x0F, 0x07, 0x00}, // 'J' + {0xFC, 0xFC, 0xE0, 0x30, 0x18, 0x0C, 0x04, /*0x00,*/ 0x0F, 0x0F, 0x01, 0x03, 0x06, 0x0C, 0x08}, // 'K' + {0xFC, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x00,*/ 0x0F, 0x0F, 0x08, 0x08, 0x08, 0x08, 0x08}, // 'L' + {0xFC, 0xFC, 0x18, 0x70, 0x18, 0xFC, 0xFC, /*0x00,*/ 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F}, // 'M' + {0xFC, 0xFC, 0x60, 0xC0, 0x80, 0xFC, 0xFC, /*0x00,*/ 0x0F, 0x0F, 0x00, 0x00, 0x01, 0x0F, 0x0F}, // 'N' + {0xF8, 0xFC, 0x04, 0x04, 0x04, 0xFC, 0xF8, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x0F, 0x07}, // 'O' + {0xFC, 0xFC, 0x84, 0x84, 0x84, 0xFC, 0x78, /*0x00,*/ 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00}, // 'P' + {0xF8, 0xFC, 0x04, 0x04, 0x04, 0xFC, 0xF8, /*0x00,*/ 0x07, 0x0F, 0x08, 0x0C, 0x0C, 0x1F, 0x17}, // 'Q' + {0xFC, 0xFC, 0x84, 0x84, 0x84, 0xFC, 0x78, /*0x00,*/ 0x0F, 0x0F, 0x01, 0x03, 0x06, 0x0C, 0x08}, // 'R' + {0x38, 0x7C, 0x44, 0x44, 0x44, 0xCC, 0x88, /*0x00,*/ 0x06, 0x0E, 0x08, 0x08, 0x08, 0x0F, 0x07}, // 'S' + {0x00, 0x04, 0x04, 0xFC, 0xFC, 0x04, 0x04, /*0x00,*/ 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00}, // 'T' + {0xFC, 0xFC, 0x00, 0x00, 0x00, 0xFC, 0xFC, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x0F, 0x07}, // 'U' + {0x7C, 0xFC, 0x80, 0x00, 0x80, 0xFC, 0x7C, /*0x00,*/ 0x00, 0x03, 0x0F, 0x0C, 0x0F, 0x03, 0x00}, // 'V' + {0xFC, 0xFC, 0x00, 0x80, 0x00, 0xFC, 0xFC, /*0x00,*/ 0x0F, 0x0F, 0x06, 0x03, 0x06, 0x0F, 0x0F}, // 'W' + {0x0C, 0x3C, 0xF0, 0xC0, 0xF0, 0x3C, 0x0C, /*0x00,*/ 0x0C, 0x0F, 0x03, 0x00, 0x03, 0x0F, 0x0C}, // 'X' + {0x00, 0x3C, 0x7C, 0xC0, 0xC0, 0x7C, 0x3C, /*0x00,*/ 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00}, // 'Y' + {0x04, 0x04, 0x84, 0xC4, 0x64, 0x3C, 0x1C, /*0x00,*/ 0x0E, 0x0F, 0x09, 0x08, 0x08, 0x08, 0x08}, // 'Z' + {0x00, 0x00, 0xFC, 0xFC, 0x04, 0x04, 0x00, /*0x00,*/ 0x00, 0x00, 0x0F, 0x0F, 0x08, 0x08, 0x00}, // '[' + {0x38, 0x70, 0xE0, 0xC0, 0x80, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x0E}, // '"\' + {0x00, 0x00, 0x04, 0x04, 0xFC, 0xFC, 0x00, /*0x00,*/ 0x00, 0x00, 0x08, 0x08, 0x0F, 0x0F, 0x00}, // ']' + {0x08, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x08, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // '^' + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x00,*/ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}, // '_' + {0x00, 0x00, 0x03, 0x07, 0x04, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // '`' + {0x00, 0xA0, 0xA0, 0xA0, 0xA0, 0xE0, 0xC0, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x0F, 0x0F}, // 'a' + {0xFC, 0xFC, 0x20, 0x20, 0x20, 0xE0, 0xC0, /*0x00,*/ 0x0F, 0x0F, 0x08, 0x08, 0x08, 0x0F, 0x07}, // 'b' + {0xC0, 0xE0, 0x20, 0x20, 0x20, 0x60, 0x40, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x0C, 0x04}, // 'c' + {0xC0, 0xE0, 0x20, 0x20, 0x20, 0xFC, 0xFC, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x0F, 0x0F}, // 'd' + {0xC0, 0xE0, 0x20, 0x20, 0x20, 0xE0, 0xC0, /*0x00,*/ 0x07, 0x0F, 0x09, 0x09, 0x09, 0x09, 0x01}, // 'e' + {0x20, 0x20, 0xF8, 0xFC, 0x24, 0x24, 0x04, /*0x00,*/ 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00}, // 'f' + {0xC0, 0xE0, 0x20, 0x20, 0x20, 0xE0, 0xE0, /*0x00,*/ 0x07, 0x4F, 0x48, 0x48, 0x48, 0x7F, 0x3F}, // 'g' + {0xFC, 0xFC, 0x20, 0x20, 0x20, 0xE0, 0xC0, /*0x00,*/ 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F}, // 'h' + {0x00, 0x00, 0x20, 0xEC, 0xEC, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x08, 0x0F, 0x0F, 0x08, 0x00}, // 'i' + {0x00, 0x00, 0x00, 0x00, 0x20, 0xEC, 0xEC, /*0x00,*/ 0x00, 0x30, 0x70, 0x40, 0x40, 0x7F, 0x3F}, // 'j' + {0xFC, 0xFC, 0x00, 0x80, 0xC0, 0x60, 0x20, /*0x00,*/ 0x0F, 0x0F, 0x01, 0x03, 0x06, 0x0C, 0x08}, // 'k' + {0x00, 0x00, 0x04, 0xFC, 0xFC, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x08, 0x0F, 0x0F, 0x08, 0x00}, // 'l' + {0xE0, 0xE0, 0x20, 0xE0, 0x20, 0xE0, 0xC0, /*0x00,*/ 0x0F, 0x0F, 0x00, 0x0F, 0x00, 0x0F, 0x0F}, // 'm' + {0xE0, 0xE0, 0x20, 0x20, 0x20, 0xE0, 0xC0, /*0x00,*/ 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F}, // 'n' + {0xC0, 0xE0, 0x20, 0x20, 0x20, 0xE0, 0xC0, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x0F, 0x07}, // 'o' + {0xE0, 0xE0, 0x20, 0x20, 0x20, 0xE0, 0xC0, /*0x00,*/ 0x7F, 0x7F, 0x08, 0x08, 0x08, 0x0F, 0x07}, // 'p' + {0xC0, 0xE0, 0x20, 0x20, 0x20, 0xE0, 0xE0, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x7F, 0x7F}, // 'q' + {0xE0, 0xE0, 0x60, 0x20, 0x20, 0x20, 0x20, /*0x00,*/ 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00}, // 'r' + {0xC0, 0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, /*0x00,*/ 0x08, 0x09, 0x09, 0x09, 0x09, 0x0F, 0x06}, // 's' + {0x20, 0x20, 0xFC, 0xFC, 0x20, 0x20, 0x00, /*0x00,*/ 0x00, 0x00, 0x07, 0x0F, 0x08, 0x08, 0x08}, // 't' + {0xE0, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0xE0, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x0F, 0x0F}, // 'u' + {0xE0, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0xE0, /*0x00,*/ 0x00, 0x03, 0x0F, 0x0C, 0x0F, 0x03, 0x00}, // 'v' + {0xE0, 0xE0, 0x00, 0x80, 0x00, 0xE0, 0xE0, /*0x00,*/ 0x07, 0x0F, 0x08, 0x0F, 0x08, 0x0F, 0x07}, // 'w' + {0x60, 0xE0, 0x80, 0x00, 0x80, 0xE0, 0x60, /*0x00,*/ 0x0C, 0x0E, 0x03, 0x01, 0x03, 0x0E, 0x0C}, // 'x' + {0xE0, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0xE0, /*0x00,*/ 0x07, 0x4F, 0x48, 0x48, 0x48, 0x7F, 0x3F}, // 'y' + {0x20, 0x20, 0x20, 0xA0, 0xE0, 0x60, 0x20, /*0x00,*/ 0x0C, 0x0E, 0x0B, 0x09, 0x08, 0x08, 0x08}, // 'z' + {0x00, 0x00, 0x40, 0xF8, 0xBC, 0x04, 0x04, /*0x00,*/ 0x00, 0x00, 0x00, 0x07, 0x0F, 0x08, 0x08}, // '{' + {0x00, 0x00, 0x00, 0xBC, 0xBC, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00}, // '|' + {0x00, 0x04, 0x04, 0xBC, 0xF8, 0x40, 0x00, /*0x00,*/ 0x00, 0x08, 0x08, 0x0F, 0x07, 0x00, 0x00}, // '}' + {0x08, 0x0C, 0x04, 0x0C, 0x08, 0x0C, 0x04, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // '->' #endif }; #if 0 - // original font - const uint8_t gFontBigDigits[11][26] = - { - {0x00, 0xC0, 0xF0, 0xF8, 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1C, 0xF8, 0xF0, 0xE0, 0x00, 0x07, 0x1F, 0x3F, 0x78, 0x60, 0x60, 0x60, 0x60, 0x70, 0x3F, 0x1F, 0x0F}, - {0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0xFC, 0xFC, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x7F, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x10, 0x38, 0x38, 0x1C, 0x0C, 0x0C, 0x0C, 0x0C, 0xFC, 0xF8, 0xF0, 0x00, 0x00, 0x70, 0x78, 0x7C, 0x7C, 0x6E, 0x66, 0x67, 0x67, 0x63, 0x61, 0x60, 0x00}, - {0x00, 0x10, 0x18, 0x18, 0x9C, 0x8C, 0x8C, 0x8C, 0x8C, 0xCC, 0xF8, 0xF8, 0x70, 0x00, 0x30, 0x30, 0x30, 0x71, 0x61, 0x61, 0x61, 0x61, 0x71, 0x3F, 0x3F, 0x1E}, - {0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0x70, 0x38, 0xFC, 0xFC, 0xFC, 0x00, 0x00, 0x1C, 0x1E, 0x1F, 0x1F, 0x19, 0x18, 0x18, 0x18, 0x7F, 0x7F, 0x7F, 0x18}, - {0x00, 0x00, 0xFC, 0xFC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x8C, 0x0C, 0x00, 0x00, 0x18, 0x30, 0x70, 0x60, 0x60, 0x60, 0x60, 0x71, 0x7B, 0x3F, 0x1F}, - {0x00, 0xC0, 0xF0, 0xF8, 0x38, 0x9C, 0x8C, 0x8C, 0x8C, 0x8C, 0x9C, 0x38, 0x30, 0x00, 0x0F, 0x1F, 0x3F, 0x73, 0x61, 0x61, 0x61, 0x61, 0x73, 0x33, 0x3F, 0x1E}, - {0x00, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x8C, 0xEC, 0xFC, 0x3C, 0x1C, 0x00, 0x00, 0x00, 0x40, 0x60, 0x78, 0x7C, 0x1F, 0x07, 0x03, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x78, 0xF8, 0xDC, 0x8C, 0x8C, 0x8C, 0x8C, 0xDC, 0xF8, 0x78, 0x00, 0x00, 0x1E, 0x3F, 0x3F, 0x73, 0x61, 0x61, 0x61, 0x61, 0x73, 0x3F, 0x3F, 0x1E}, - {0x00, 0xF0, 0xF8, 0xB8, 0x1C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1C, 0xB8, 0xF0, 0xE0, 0x00, 0x11, 0x33, 0x77, 0x67, 0x66, 0x66, 0x66, 0x76, 0x33, 0x3F, 0x1F, 0x07}, - {0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00} - }; + // original font + const uint8_t gFontBigDigits[11][26] = + { + {0x00, 0xC0, 0xF0, 0xF8, 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1C, 0xF8, 0xF0, 0xE0, 0x00, 0x07, 0x1F, 0x3F, 0x78, 0x60, 0x60, 0x60, 0x60, 0x70, 0x3F, 0x1F, 0x0F}, + {0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0xFC, 0xFC, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x7F, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x10, 0x38, 0x38, 0x1C, 0x0C, 0x0C, 0x0C, 0x0C, 0xFC, 0xF8, 0xF0, 0x00, 0x00, 0x70, 0x78, 0x7C, 0x7C, 0x6E, 0x66, 0x67, 0x67, 0x63, 0x61, 0x60, 0x00}, + {0x00, 0x10, 0x18, 0x18, 0x9C, 0x8C, 0x8C, 0x8C, 0x8C, 0xCC, 0xF8, 0xF8, 0x70, 0x00, 0x30, 0x30, 0x30, 0x71, 0x61, 0x61, 0x61, 0x61, 0x71, 0x3F, 0x3F, 0x1E}, + {0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0x70, 0x38, 0xFC, 0xFC, 0xFC, 0x00, 0x00, 0x1C, 0x1E, 0x1F, 0x1F, 0x19, 0x18, 0x18, 0x18, 0x7F, 0x7F, 0x7F, 0x18}, + {0x00, 0x00, 0xFC, 0xFC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x8C, 0x0C, 0x00, 0x00, 0x18, 0x30, 0x70, 0x60, 0x60, 0x60, 0x60, 0x71, 0x7B, 0x3F, 0x1F}, + {0x00, 0xC0, 0xF0, 0xF8, 0x38, 0x9C, 0x8C, 0x8C, 0x8C, 0x8C, 0x9C, 0x38, 0x30, 0x00, 0x0F, 0x1F, 0x3F, 0x73, 0x61, 0x61, 0x61, 0x61, 0x73, 0x33, 0x3F, 0x1E}, + {0x00, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x8C, 0xEC, 0xFC, 0x3C, 0x1C, 0x00, 0x00, 0x00, 0x40, 0x60, 0x78, 0x7C, 0x1F, 0x07, 0x03, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x78, 0xF8, 0xDC, 0x8C, 0x8C, 0x8C, 0x8C, 0xDC, 0xF8, 0x78, 0x00, 0x00, 0x1E, 0x3F, 0x3F, 0x73, 0x61, 0x61, 0x61, 0x61, 0x73, 0x3F, 0x3F, 0x1E}, + {0x00, 0xF0, 0xF8, 0xB8, 0x1C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1C, 0xB8, 0xF0, 0xE0, 0x00, 0x11, 0x33, 0x77, 0x67, 0x66, 0x66, 0x66, 0x76, 0x33, 0x3F, 0x1F, 0x07}, + {0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00} + }; - // 6 Empty columns removed + // 6 Empty columns removed #elif 0 - // VCR font - const uint8_t gFontBigDigits[11][26 - 6] = - { - {/*0x00, 0x00,*/ 0xF8, 0xFC, 0x06, 0x86, 0xC6, 0xE6, 0xF6, 0x76, 0xFC, 0xF8, /*0x00,*/ /*0x00, 0x00,*/ 0x1F, 0x3F, 0x77, 0x67, 0x63, 0x61, 0x60, 0x70, 0x3F, 0x1F, /*0x00*/}, - {/*0x00, 0x00,*/ 0x00, 0x00, 0x18, 0x1C, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, /*0x00,*/ /*0x00, 0x00,*/ 0x00, 0x00, 0x60, 0x60, 0x7F, 0x7F, 0x60, 0x60, 0x00, 0x00, /*0x00*/}, - {/*0x00, 0x00,*/ 0x18, 0x1C, 0x86, 0x86, 0x86, 0x86, 0x86, 0xC6, 0xFC, 0x78, /*0x00,*/ /*0x00, 0x00,*/ 0x7E, 0x7F, 0x63, 0x61, 0x61, 0x61, 0x61, 0x61, 0x60, 0x60, /*0x00*/}, - {/*0x00, 0x00,*/ 0x18, 0x1C, 0x06, 0x06, 0x86, 0x86, 0x86, 0xC6, 0xFC, 0x78, /*0x00,*/ /*0x00, 0x00,*/ 0x18, 0x38, 0x70, 0x60, 0x61, 0x61, 0x61, 0x73, 0x3F, 0x1E, /*0x00*/}, - {/*0x00, 0x00,*/ 0x80, 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0xFE, 0xFE, 0x00, 0x00, /*0x00,*/ /*0x00, 0x00,*/ 0x07, 0x07, 0x06, 0x06, 0x06, 0x06, 0x7F, 0x7F, 0x06, 0x06, /*0x00*/}, - {/*0x00, 0x00,*/ 0x7E, 0x7E, 0x66, 0x66, 0x66, 0x66, 0x66, 0xE6, 0xC6, 0x86, /*0x00,*/ /*0x00, 0x00,*/ 0x18, 0x38, 0x70, 0x60, 0x60, 0x60, 0x60, 0x70, 0x3F, 0x1F, /*0x00*/}, - {/*0x00, 0x00,*/ 0xF8, 0xFC, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x1C, 0x18, /*0x00,*/ /*0x00, 0x00,*/ 0x1F, 0x3F, 0x71, 0x61, 0x61, 0x61, 0x61, 0x73, 0x3F, 0x1E, /*0x00*/}, - {/*0x00, 0x00,*/ 0x06, 0x06, 0x06, 0x06, 0x06, 0x86, 0xC6, 0xE6, 0x7E, 0x3E, /*0x00,*/ /*0x00, 0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x01, 0x00, 0x00, 0x00, /*0x00*/}, - {/*0x00, 0x00,*/ 0x78, 0xFC, 0xC6, 0x86, 0x86, 0x86, 0x86, 0xC6, 0xFC, 0x78, /*0x00,*/ /*0x00, 0x00,*/ 0x1E, 0x3F, 0x73, 0x61, 0x61, 0x61, 0x61, 0x73, 0x3F, 0x1E, /*0x00*/}, - {/*0x00, 0x00,*/ 0x78, 0xFC, 0xC6, 0x86, 0x86, 0x86, 0x86, 0x86, 0xFC, 0xF8, /*0x00,*/ /*0x00, 0x00,*/ 0x18, 0x38, 0x71, 0x61, 0x61, 0x61, 0x61, 0x71, 0x3F, 0x1F, /*0x00*/}, - {/*0x00, 0x00,*/ 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, /*0x00,*/ /*0x00, 0x00,*/ 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, /*0x00*/} - }; + // VCR font + const uint8_t gFontBigDigits[11][26 - 6] = + { + {/*0x00, 0x00,*/ 0xF8, 0xFC, 0x06, 0x86, 0xC6, 0xE6, 0xF6, 0x76, 0xFC, 0xF8, /*0x00,*/ /*0x00, 0x00,*/ 0x1F, 0x3F, 0x77, 0x67, 0x63, 0x61, 0x60, 0x70, 0x3F, 0x1F, /*0x00*/}, + {/*0x00, 0x00,*/ 0x00, 0x00, 0x18, 0x1C, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, /*0x00,*/ /*0x00, 0x00,*/ 0x00, 0x00, 0x60, 0x60, 0x7F, 0x7F, 0x60, 0x60, 0x00, 0x00, /*0x00*/}, + {/*0x00, 0x00,*/ 0x18, 0x1C, 0x86, 0x86, 0x86, 0x86, 0x86, 0xC6, 0xFC, 0x78, /*0x00,*/ /*0x00, 0x00,*/ 0x7E, 0x7F, 0x63, 0x61, 0x61, 0x61, 0x61, 0x61, 0x60, 0x60, /*0x00*/}, + {/*0x00, 0x00,*/ 0x18, 0x1C, 0x06, 0x06, 0x86, 0x86, 0x86, 0xC6, 0xFC, 0x78, /*0x00,*/ /*0x00, 0x00,*/ 0x18, 0x38, 0x70, 0x60, 0x61, 0x61, 0x61, 0x73, 0x3F, 0x1E, /*0x00*/}, + {/*0x00, 0x00,*/ 0x80, 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0xFE, 0xFE, 0x00, 0x00, /*0x00,*/ /*0x00, 0x00,*/ 0x07, 0x07, 0x06, 0x06, 0x06, 0x06, 0x7F, 0x7F, 0x06, 0x06, /*0x00*/}, + {/*0x00, 0x00,*/ 0x7E, 0x7E, 0x66, 0x66, 0x66, 0x66, 0x66, 0xE6, 0xC6, 0x86, /*0x00,*/ /*0x00, 0x00,*/ 0x18, 0x38, 0x70, 0x60, 0x60, 0x60, 0x60, 0x70, 0x3F, 0x1F, /*0x00*/}, + {/*0x00, 0x00,*/ 0xF8, 0xFC, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x1C, 0x18, /*0x00,*/ /*0x00, 0x00,*/ 0x1F, 0x3F, 0x71, 0x61, 0x61, 0x61, 0x61, 0x73, 0x3F, 0x1E, /*0x00*/}, + {/*0x00, 0x00,*/ 0x06, 0x06, 0x06, 0x06, 0x06, 0x86, 0xC6, 0xE6, 0x7E, 0x3E, /*0x00,*/ /*0x00, 0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x01, 0x00, 0x00, 0x00, /*0x00*/}, + {/*0x00, 0x00,*/ 0x78, 0xFC, 0xC6, 0x86, 0x86, 0x86, 0x86, 0xC6, 0xFC, 0x78, /*0x00,*/ /*0x00, 0x00,*/ 0x1E, 0x3F, 0x73, 0x61, 0x61, 0x61, 0x61, 0x73, 0x3F, 0x1E, /*0x00*/}, + {/*0x00, 0x00,*/ 0x78, 0xFC, 0xC6, 0x86, 0x86, 0x86, 0x86, 0x86, 0xFC, 0xF8, /*0x00,*/ /*0x00, 0x00,*/ 0x18, 0x38, 0x71, 0x61, 0x61, 0x61, 0x61, 0x71, 0x3F, 0x1F, /*0x00*/}, + {/*0x00, 0x00,*/ 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, /*0x00,*/ /*0x00, 0x00,*/ 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, /*0x00*/} + }; #else - // Terminus font + // Terminus font - const uint8_t gFontBigDigits[11][26 - 6] = - { - {/*0x00, 0x00,*/ 0xFC, 0xFE, 0xFE, 0x06, 0x06, 0x06, 0x06, 0xFE, 0xFE, 0xFC, /*0x00,*/ /*0x00, 0x00,*/ 0x3F, 0x7F, 0x7F, 0x60, 0x60, 0x60, 0x60, 0x7F, 0x7F, 0x3F, /*0x00*/}, - {/*0x00, 0x00,*/ 0x00, 0x00, 0x18, 0x1C, 0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x00, /*0x00,*/ /*0x00, 0x00,*/ 0x00, 0x00, 0x60, 0x60, 0x7F, 0x7F, 0x7F, 0x60, 0x60, 0x00, /*0x00*/}, - {/*0x00, 0x00,*/ 0x1C, 0x1E, 0x1E, 0x06, 0x06, 0x06, 0x86, 0xFE, 0xFE, 0x7C, /*0x00,*/ /*0x00, 0x00,*/ 0x60, 0x70, 0x78, 0x7C, 0x6E, 0x67, 0x63, 0x61, 0x60, 0x60, /*0x00*/}, - {/*0x00, 0x00,*/ 0x0C, 0x0E, 0x0E, 0x86, 0x86, 0x86, 0x86, 0xFE, 0xFE, 0x7C, /*0x00,*/ /*0x00, 0x00,*/ 0x30, 0x70, 0x70, 0x61, 0x61, 0x61, 0x61, 0x7F, 0x7F, 0x3E, /*0x00*/}, - {/*0x00, 0x00,*/ 0x80, 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0xFE, 0xFE, 0xFE, /*0x00,*/ /*0x00, 0x00,*/ 0x0F, 0x0F, 0x0F, 0x0C, 0x0C, 0x0C, 0x0C, 0x7F, 0x7F, 0x7F, /*0x00*/}, - {/*0x00, 0x00,*/ 0xFE, 0xFE, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x86, /*0x00,*/ /*0x00, 0x00,*/ 0x30, 0x70, 0x70, 0x60, 0x60, 0x60, 0x60, 0x7F, 0x7F, 0x3F, /*0x00*/}, - {/*0x00, 0x00,*/ 0xF8, 0xFC, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x80, /*0x00,*/ /*0x00, 0x00,*/ 0x3F, 0x7F, 0x7F, 0x60, 0x60, 0x60, 0x60, 0x7F, 0x7F, 0x3F, /*0x00*/}, - {/*0x00, 0x00,*/ 0x0E, 0x0E, 0x0E, 0x06, 0x06, 0x86, 0xE6, 0xFE, 0x7E, 0x1E, /*0x00,*/ /*0x00, 0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x7C, 0x7F, 0x7F, 0x03, 0x00, 0x00, /*0x00*/}, - {/*0x00, 0x00,*/ 0x7C, 0xFE, 0xFE, 0x86, 0x86, 0x86, 0x86, 0xFE, 0xFE, 0x7C, /*0x00,*/ /*0x00, 0x00,*/ 0x3F, 0x7F, 0x7F, 0x61, 0x61, 0x61, 0x61, 0x7F, 0x7F, 0x3F, /*0x00*/}, - {/*0x00, 0x00,*/ 0xFC, 0xFE, 0xFE, 0x06, 0x06, 0x06, 0x06, 0xFE, 0xFE, 0xFC, /*0x00,*/ /*0x00, 0x00,*/ 0x01, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x7F, 0x3F, 0x1F, /*0x00*/}, - {/*0x00, 0x00,*/ 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, /*0x00,*/ /*0x00, 0x00,*/ 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, /*0x00*/} - }; + const uint8_t gFontBigDigits[11][26 - 6] = + { + {/*0x00, 0x00,*/ 0xFC, 0xFE, 0xFE, 0x06, 0x06, 0x06, 0x06, 0xFE, 0xFE, 0xFC, /*0x00,*/ /*0x00, 0x00,*/ 0x3F, 0x7F, 0x7F, 0x60, 0x60, 0x60, 0x60, 0x7F, 0x7F, 0x3F, /*0x00*/}, + {/*0x00, 0x00,*/ 0x00, 0x00, 0x18, 0x1C, 0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x00, /*0x00,*/ /*0x00, 0x00,*/ 0x00, 0x00, 0x60, 0x60, 0x7F, 0x7F, 0x7F, 0x60, 0x60, 0x00, /*0x00*/}, + {/*0x00, 0x00,*/ 0x1C, 0x1E, 0x1E, 0x06, 0x06, 0x06, 0x86, 0xFE, 0xFE, 0x7C, /*0x00,*/ /*0x00, 0x00,*/ 0x60, 0x70, 0x78, 0x7C, 0x6E, 0x67, 0x63, 0x61, 0x60, 0x60, /*0x00*/}, + {/*0x00, 0x00,*/ 0x0C, 0x0E, 0x0E, 0x86, 0x86, 0x86, 0x86, 0xFE, 0xFE, 0x7C, /*0x00,*/ /*0x00, 0x00,*/ 0x30, 0x70, 0x70, 0x61, 0x61, 0x61, 0x61, 0x7F, 0x7F, 0x3E, /*0x00*/}, + {/*0x00, 0x00,*/ 0x80, 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0xFE, 0xFE, 0xFE, /*0x00,*/ /*0x00, 0x00,*/ 0x0F, 0x0F, 0x0F, 0x0C, 0x0C, 0x0C, 0x0C, 0x7F, 0x7F, 0x7F, /*0x00*/}, + {/*0x00, 0x00,*/ 0xFE, 0xFE, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x86, /*0x00,*/ /*0x00, 0x00,*/ 0x30, 0x70, 0x70, 0x60, 0x60, 0x60, 0x60, 0x7F, 0x7F, 0x3F, /*0x00*/}, + {/*0x00, 0x00,*/ 0xF8, 0xFC, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x80, /*0x00,*/ /*0x00, 0x00,*/ 0x3F, 0x7F, 0x7F, 0x60, 0x60, 0x60, 0x60, 0x7F, 0x7F, 0x3F, /*0x00*/}, + {/*0x00, 0x00,*/ 0x0E, 0x0E, 0x0E, 0x06, 0x06, 0x86, 0xE6, 0xFE, 0x7E, 0x1E, /*0x00,*/ /*0x00, 0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x7C, 0x7F, 0x7F, 0x03, 0x00, 0x00, /*0x00*/}, + {/*0x00, 0x00,*/ 0x7C, 0xFE, 0xFE, 0x86, 0x86, 0x86, 0x86, 0xFE, 0xFE, 0x7C, /*0x00,*/ /*0x00, 0x00,*/ 0x3F, 0x7F, 0x7F, 0x61, 0x61, 0x61, 0x61, 0x7F, 0x7F, 0x3F, /*0x00*/}, + {/*0x00, 0x00,*/ 0xFC, 0xFE, 0xFE, 0x06, 0x06, 0x06, 0x06, 0xFE, 0xFE, 0xFC, /*0x00,*/ /*0x00, 0x00,*/ 0x01, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x7F, 0x3F, 0x1F, /*0x00*/}, + {/*0x00, 0x00,*/ 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, /*0x00,*/ /*0x00, 0x00,*/ 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, /*0x00*/} + }; #endif /* const uint8_t gFontSmallDigits[11][7] = { - {0x00, 0x3E, 0x41, 0x41, 0x41, 0x41, 0x3E}, // '0' - {0x00, 0x00, 0x42, 0x7F, 0x40, 0x00, 0x00}, // '1' - {0x00, 0x62, 0x51, 0x51, 0x49, 0x49, 0x46}, // '2' - {0x00, 0x22, 0x41, 0x49, 0x49, 0x4D, 0x32}, // '3' - {0x00, 0x18, 0x14, 0x12, 0x11, 0x7F, 0x10}, // '4' - {0x00, 0x27, 0x45, 0x45, 0x45, 0x45, 0x39}, // '5' - {0x00, 0x3E, 0x49, 0x49, 0x49, 0x49, 0x30}, // '6' - {0x00, 0x01, 0x71, 0x09, 0x05, 0x03, 0x00}, // '7' - {0x00, 0x36, 0x49, 0x49, 0x49, 0x49, 0x36}, // '8' - {0x00, 0x46, 0x49, 0x49, 0x49, 0x29, 0x1E}, // '9' - {0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00} // '-' + {0x00, 0x3E, 0x41, 0x41, 0x41, 0x41, 0x3E}, // '0' + {0x00, 0x00, 0x42, 0x7F, 0x40, 0x00, 0x00}, // '1' + {0x00, 0x62, 0x51, 0x51, 0x49, 0x49, 0x46}, // '2' + {0x00, 0x22, 0x41, 0x49, 0x49, 0x4D, 0x32}, // '3' + {0x00, 0x18, 0x14, 0x12, 0x11, 0x7F, 0x10}, // '4' + {0x00, 0x27, 0x45, 0x45, 0x45, 0x45, 0x39}, // '5' + {0x00, 0x3E, 0x49, 0x49, 0x49, 0x49, 0x30}, // '6' + {0x00, 0x01, 0x71, 0x09, 0x05, 0x03, 0x00}, // '7' + {0x00, 0x36, 0x49, 0x49, 0x49, 0x49, 0x36}, // '8' + {0x00, 0x46, 0x49, 0x49, 0x49, 0x29, 0x1E}, // '9' + {0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00} // '-' }; */ const uint8_t gFontSmall[95-1][6] = { // {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // ' ' - {0x00, 0x00, 0x5E, 0x00, 0x00, 0x00}, // '!' - {0x00, 0x06, 0x00, 0x06, 0x00, 0x00}, // '"' - {0x14, 0x3E, 0x14, 0x3E, 0x14, 0x00}, // '#' - {0x26, 0x49, 0x7F, 0x49, 0x32, 0x00}, // '$' - {0x63, 0x13, 0x08, 0x04, 0x62, 0x61}, // '%' - {0x30, 0x4B, 0x4D, 0x55, 0x22, 0x50}, // '&' - {0x00, 0x00, 0x07, 0x07, 0x00, 0x00}, // ''' - {0x00, 0x1C, 0x22, 0x41, 0x00, 0x00}, // '(' - {0x00, 0x41, 0x22, 0x1C, 0x00, 0x00}, // ')' - {0x00, 0x2A, 0x1C, 0x1C, 0x2A, 0x00}, // '*' - {0x08, 0x08, 0x3E, 0x08, 0x08, 0x00}, // '+' - {0x00, 0x40, 0x60, 0x20, 0x00, 0x00}, // ',' - {0x00, 0x08, 0x08, 0x08, 0x08, 0x00}, // '-' - {0x00, 0x00, 0x60, 0x60, 0x00, 0x00}, // '.' - {0x40, 0x20, 0x10, 0x08, 0x04, 0x02}, // '/' - {0x3E, 0x41, 0x41, 0x41, 0x41, 0x3E}, // '0' - {0x00, 0x40, 0x42, 0x7F, 0x40, 0x40}, // '1' - {0x62, 0x51, 0x51, 0x49, 0x49, 0x46}, // '2' - {0x22, 0x41, 0x49, 0x49, 0x49, 0x36}, // '3' - {0x18, 0x14, 0x12, 0x11, 0x7F, 0x10}, // '4' - {0x27, 0x45, 0x45, 0x45, 0x45, 0x39}, // '5' - {0x3E, 0x49, 0x49, 0x49, 0x49, 0x32}, // '6' - {0x01, 0x01, 0x71, 0x09, 0x05, 0x03}, // '7' - {0x36, 0x49, 0x49, 0x49, 0x49, 0x36}, // '8' - {0x46, 0x49, 0x49, 0x49, 0x29, 0x1E}, // '9' - {0x00, 0x00, 0x6C, 0x6C, 0x00, 0x00}, // ':' - {0x00, 0x40, 0x6C, 0x2C, 0x00, 0x00}, // ';' - {0x08, 0x14, 0x22, 0x41, 0x00, 0x00}, // '<' - {0x14, 0x14, 0x14, 0x14, 0x14, 0x00}, // '=' - {0x00, 0x41, 0x22, 0x14, 0x08, 0x00}, // '>' - {0x02, 0x01, 0x51, 0x09, 0x06, 0x00}, // '?' - {0x30, 0x4A, 0x4A, 0x52, 0x3C, 0x00}, // '@' - {0x7E, 0x09, 0x09, 0x09, 0x09, 0x7E}, // 'A' - {0x7F, 0x49, 0x49, 0x49, 0x49, 0x36}, // 'B' - {0x3E, 0x41, 0x41, 0x41, 0x41, 0x22}, // 'C' - {0x7F, 0x41, 0x41, 0x41, 0x41, 0x3E}, // 'D' - {0x7F, 0x49, 0x49, 0x49, 0x49, 0x41}, // 'E' - {0x7F, 0x09, 0x09, 0x09, 0x09, 0x01}, // 'F' - {0x3E, 0x41, 0x49, 0x49, 0x49, 0x3A}, // 'G' - {0x7F, 0x08, 0x08, 0x08, 0x08, 0x7F}, // 'H' - {0x41, 0x41, 0x7F, 0x41, 0x41, 0x00}, // 'I' - {0x20, 0x41, 0x41, 0x3F, 0x01, 0x01}, // 'J' - {0x7F, 0x08, 0x0C, 0x12, 0x21, 0x40}, // 'K' - {0x7F, 0x40, 0x40, 0x40, 0x40, 0x40}, // 'L' - {0x7F, 0x02, 0x04, 0x04, 0x02, 0x7F}, // 'M' - {0x7F, 0x02, 0x04, 0x08, 0x10, 0x7F}, // 'N' - {0x3E, 0x41, 0x41, 0x41, 0x41, 0x3E}, // 'O' - {0x7F, 0x09, 0x09, 0x09, 0x09, 0x06}, // 'P' - {0x3E, 0x41, 0x51, 0x61, 0x41, 0x3E}, // 'Q' - {0x7F, 0x09, 0x09, 0x19, 0x29, 0x46}, // 'R' - {0x26, 0x49, 0x49, 0x49, 0x49, 0x32}, // 'S' - {0x01, 0x01, 0x7F, 0x01, 0x01, 0x00}, // 'T' - {0x3F, 0x40, 0x40, 0x40, 0x40, 0x3F}, // 'U' - {0x07, 0x38, 0x40, 0x40, 0x38, 0x07}, // 'V' - {0x3F, 0x40, 0x30, 0x30, 0x40, 0x3F}, // 'W' - {0x63, 0x14, 0x08, 0x08, 0x14, 0x63}, // 'X' - {0x07, 0x08, 0x70, 0x08, 0x07, 0x00}, // 'Y' - {0x61, 0x51, 0x49, 0x45, 0x43, 0x41}, // 'Z' - {0x00, 0x7F, 0x41, 0x41, 0x00, 0x00}, // '[' - {0x01, 0x02, 0x04, 0x08, 0x10, 0x60}, // '"\' - {0x00, 0x00, 0x41, 0x41, 0x7F, 0x00}, // ']' - {0x04, 0x02, 0x01, 0x02, 0x04, 0x00}, // '^' - {0x40, 0x40, 0x40, 0x40, 0x40, 0x40}, // '_' - {0x00, 0x03, 0x07, 0x06, 0x00, 0x00}, // '`' - {0x20, 0x54, 0x54, 0x54, 0x78, 0x00}, // 'a' - {0x7F, 0x44, 0x44, 0x44, 0x38, 0x00}, // 'b' - {0x38, 0x44, 0x44, 0x44, 0x28, 0x00}, // 'c' - {0x38, 0x44, 0x44, 0x44, 0x7F, 0x00}, // 'd' - {0x38, 0x54, 0x54, 0x54, 0x48, 0x00}, // 'e' - {0x7C, 0x0A, 0x0A, 0x0A, 0x02, 0x00}, // 'f' - {0x58, 0x54, 0x54, 0x54, 0x3C, 0x00}, // 'g' - {0x7F, 0x04, 0x04, 0x04, 0x78, 0x00}, // 'h' - {0x00, 0x00, 0x7A, 0x00, 0x00, 0x00}, // 'i' - {0x20, 0x40, 0x40, 0x3D, 0x00, 0x00}, // 'j' - {0x00, 0x7F, 0x10, 0x28, 0x44, 0x00}, // 'k' - {0x00, 0x00, 0x3F, 0x40, 0x00, 0x00}, // 'l' - {0x7C, 0x08, 0x10, 0x10, 0x08, 0x7C}, // 'm' - {0x7C, 0x04, 0x04, 0x04, 0x78, 0x00}, // 'n' - {0x38, 0x44, 0x44, 0x44, 0x38, 0x00}, // 'o' - {0x7C, 0x14, 0x14, 0x14, 0x08, 0x00}, // 'p' - {0x08, 0x14, 0x14, 0x14, 0x7C, 0x40}, // 'q' - {0x7C, 0x04, 0x04, 0x04, 0x08, 0x00}, // 'r' - {0x08, 0x54, 0x54, 0x54, 0x20, 0x00}, // 's' - {0x3F, 0x44, 0x44, 0x44, 0x40, 0x00}, // 't' - {0x3C, 0x40, 0x40, 0x40, 0x3C, 0x00}, // 'u' - {0x0C, 0x30, 0x40, 0x30, 0x0C, 0x00}, // 'v' - {0x3C, 0x40, 0x30, 0x40, 0x3C, 0x00}, // 'w' - {0x44, 0x28, 0x10, 0x28, 0x44, 0x00}, // 'x' - {0x0C, 0x50, 0x50, 0x50, 0x3C, 0x00}, // 'y' - {0x44, 0x64, 0x54, 0x4C, 0x44, 0x00}, // 'z' - {0x08, 0x36, 0x41, 0x00, 0x00, 0x00}, // '{' - {0x00, 0x00, 0x7F, 0x00, 0x00, 0x00}, // '|' - {0x00, 0x00, 0x41, 0x36, 0x08, 0x00}, // '}' - {0x04, 0x02, 0x04, 0x08, 0x04, 0x00} // '->' + {0x00, 0x00, 0x5E, 0x00, 0x00, 0x00}, // '!' + {0x00, 0x06, 0x00, 0x06, 0x00, 0x00}, // '"' + {0x14, 0x3E, 0x14, 0x3E, 0x14, 0x00}, // '#' + {0x26, 0x49, 0x7F, 0x49, 0x32, 0x00}, // '$' + {0x63, 0x13, 0x08, 0x04, 0x62, 0x61}, // '%' + {0x30, 0x4B, 0x4D, 0x55, 0x22, 0x50}, // '&' + {0x00, 0x00, 0x07, 0x07, 0x00, 0x00}, // ''' + {0x00, 0x1C, 0x22, 0x41, 0x00, 0x00}, // '(' + {0x00, 0x41, 0x22, 0x1C, 0x00, 0x00}, // ')' + {0x00, 0x2A, 0x1C, 0x1C, 0x2A, 0x00}, // '*' + {0x08, 0x08, 0x3E, 0x08, 0x08, 0x00}, // '+' + {0x00, 0x40, 0x60, 0x20, 0x00, 0x00}, // ',' + {0x00, 0x08, 0x08, 0x08, 0x08, 0x00}, // '-' + {0x00, 0x00, 0x60, 0x60, 0x00, 0x00}, // '.' + {0x40, 0x20, 0x10, 0x08, 0x04, 0x02}, // '/' + {0x3E, 0x41, 0x41, 0x41, 0x41, 0x3E}, // '0' + {0x00, 0x40, 0x42, 0x7F, 0x40, 0x40}, // '1' + {0x62, 0x51, 0x51, 0x49, 0x49, 0x46}, // '2' + {0x22, 0x41, 0x49, 0x49, 0x49, 0x36}, // '3' + {0x18, 0x14, 0x12, 0x11, 0x7F, 0x10}, // '4' + {0x27, 0x45, 0x45, 0x45, 0x45, 0x39}, // '5' + {0x3E, 0x49, 0x49, 0x49, 0x49, 0x32}, // '6' + {0x01, 0x01, 0x71, 0x09, 0x05, 0x03}, // '7' + {0x36, 0x49, 0x49, 0x49, 0x49, 0x36}, // '8' + {0x46, 0x49, 0x49, 0x49, 0x29, 0x1E}, // '9' + {0x00, 0x00, 0x6C, 0x6C, 0x00, 0x00}, // ':' + {0x00, 0x40, 0x6C, 0x2C, 0x00, 0x00}, // ';' + {0x08, 0x14, 0x22, 0x41, 0x00, 0x00}, // '<' + {0x14, 0x14, 0x14, 0x14, 0x14, 0x00}, // '=' + {0x00, 0x41, 0x22, 0x14, 0x08, 0x00}, // '>' + {0x02, 0x01, 0x51, 0x09, 0x06, 0x00}, // '?' + {0x30, 0x4A, 0x4A, 0x52, 0x3C, 0x00}, // '@' + {0x7E, 0x09, 0x09, 0x09, 0x09, 0x7E}, // 'A' + {0x7F, 0x49, 0x49, 0x49, 0x49, 0x36}, // 'B' + {0x3E, 0x41, 0x41, 0x41, 0x41, 0x22}, // 'C' + {0x7F, 0x41, 0x41, 0x41, 0x41, 0x3E}, // 'D' + {0x7F, 0x49, 0x49, 0x49, 0x49, 0x41}, // 'E' + {0x7F, 0x09, 0x09, 0x09, 0x09, 0x01}, // 'F' + {0x3E, 0x41, 0x49, 0x49, 0x49, 0x3A}, // 'G' + {0x7F, 0x08, 0x08, 0x08, 0x08, 0x7F}, // 'H' + {0x41, 0x41, 0x7F, 0x41, 0x41, 0x00}, // 'I' + {0x20, 0x41, 0x41, 0x3F, 0x01, 0x01}, // 'J' + {0x7F, 0x08, 0x0C, 0x12, 0x21, 0x40}, // 'K' + {0x7F, 0x40, 0x40, 0x40, 0x40, 0x40}, // 'L' + {0x7F, 0x02, 0x04, 0x04, 0x02, 0x7F}, // 'M' + {0x7F, 0x02, 0x04, 0x08, 0x10, 0x7F}, // 'N' + {0x3E, 0x41, 0x41, 0x41, 0x41, 0x3E}, // 'O' + {0x7F, 0x09, 0x09, 0x09, 0x09, 0x06}, // 'P' + {0x3E, 0x41, 0x51, 0x61, 0x41, 0x3E}, // 'Q' + {0x7F, 0x09, 0x09, 0x19, 0x29, 0x46}, // 'R' + {0x26, 0x49, 0x49, 0x49, 0x49, 0x32}, // 'S' + {0x01, 0x01, 0x7F, 0x01, 0x01, 0x00}, // 'T' + {0x3F, 0x40, 0x40, 0x40, 0x40, 0x3F}, // 'U' + {0x07, 0x38, 0x40, 0x40, 0x38, 0x07}, // 'V' + {0x3F, 0x40, 0x30, 0x30, 0x40, 0x3F}, // 'W' + {0x63, 0x14, 0x08, 0x08, 0x14, 0x63}, // 'X' + {0x07, 0x08, 0x70, 0x08, 0x07, 0x00}, // 'Y' + {0x61, 0x51, 0x49, 0x45, 0x43, 0x41}, // 'Z' + {0x00, 0x7F, 0x41, 0x41, 0x00, 0x00}, // '[' + {0x01, 0x02, 0x04, 0x08, 0x10, 0x60}, // '"\' + {0x00, 0x00, 0x41, 0x41, 0x7F, 0x00}, // ']' + {0x04, 0x02, 0x01, 0x02, 0x04, 0x00}, // '^' + {0x40, 0x40, 0x40, 0x40, 0x40, 0x40}, // '_' + {0x00, 0x03, 0x07, 0x06, 0x00, 0x00}, // '`' + {0x20, 0x54, 0x54, 0x54, 0x78, 0x00}, // 'a' + {0x7F, 0x44, 0x44, 0x44, 0x38, 0x00}, // 'b' + {0x38, 0x44, 0x44, 0x44, 0x28, 0x00}, // 'c' + {0x38, 0x44, 0x44, 0x44, 0x7F, 0x00}, // 'd' + {0x38, 0x54, 0x54, 0x54, 0x48, 0x00}, // 'e' + {0x7C, 0x0A, 0x0A, 0x0A, 0x02, 0x00}, // 'f' + {0x58, 0x54, 0x54, 0x54, 0x3C, 0x00}, // 'g' + {0x7F, 0x04, 0x04, 0x04, 0x78, 0x00}, // 'h' + {0x00, 0x00, 0x7A, 0x00, 0x00, 0x00}, // 'i' + {0x20, 0x40, 0x40, 0x3D, 0x00, 0x00}, // 'j' + {0x00, 0x7F, 0x10, 0x28, 0x44, 0x00}, // 'k' + {0x00, 0x00, 0x3F, 0x40, 0x00, 0x00}, // 'l' + {0x7C, 0x08, 0x10, 0x10, 0x08, 0x7C}, // 'm' + {0x7C, 0x04, 0x04, 0x04, 0x78, 0x00}, // 'n' + {0x38, 0x44, 0x44, 0x44, 0x38, 0x00}, // 'o' + {0x7C, 0x14, 0x14, 0x14, 0x08, 0x00}, // 'p' + {0x08, 0x14, 0x14, 0x14, 0x7C, 0x40}, // 'q' + {0x7C, 0x04, 0x04, 0x04, 0x08, 0x00}, // 'r' + {0x08, 0x54, 0x54, 0x54, 0x20, 0x00}, // 's' + {0x3F, 0x44, 0x44, 0x44, 0x40, 0x00}, // 't' + {0x3C, 0x40, 0x40, 0x40, 0x3C, 0x00}, // 'u' + {0x0C, 0x30, 0x40, 0x30, 0x0C, 0x00}, // 'v' + {0x3C, 0x40, 0x30, 0x40, 0x3C, 0x00}, // 'w' + {0x44, 0x28, 0x10, 0x28, 0x44, 0x00}, // 'x' + {0x0C, 0x50, 0x50, 0x50, 0x3C, 0x00}, // 'y' + {0x44, 0x64, 0x54, 0x4C, 0x44, 0x00}, // 'z' + {0x08, 0x36, 0x41, 0x00, 0x00, 0x00}, // '{' + {0x00, 0x00, 0x7F, 0x00, 0x00, 0x00}, // '|' + {0x00, 0x00, 0x41, 0x36, 0x08, 0x00}, // '}' + {0x04, 0x02, 0x04, 0x08, 0x04, 0x00} // '->' }; #ifdef ENABLE_SMALL_BOLD - const uint8_t gFontSmallBold[95 - 1][6] = - { -// {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x5E, 0x5E, 0x00, 0x00}, - {0x06, 0x06, 0x00, 0x06, 0x06, 0x00}, - {0x14, 0x3E, 0x14, 0x3E, 0x14, 0x00}, - {0x2E, 0x6B, 0x7F, 0x6B, 0x3A, 0x00}, - {0x63, 0x33, 0x18, 0x0C, 0x66, 0x63}, - {0x30, 0x4B, 0x4D, 0x55, 0x22, 0x50}, - {0x00, 0x00, 0x07, 0x07, 0x00, 0x00}, - {0x00, 0x1C, 0x3E, 0x63, 0x41, 0x00}, - {0x00, 0x41, 0x63, 0x3E, 0x1C, 0x00}, - {0x00, 0x2A, 0x1C, 0x1C, 0x2A, 0x00}, - {0x18, 0x18, 0x7E, 0x7E, 0x18, 0x18}, - {0x00, 0x40, 0x60, 0x20, 0x00, 0x00}, - {0x00, 0x18, 0x18, 0x18, 0x18, 0x00}, - {0x00, 0x00, 0x60, 0x60, 0x00, 0x00}, - {0x60, 0x30, 0x18, 0x0C, 0x06, 0x03}, - {0x3E, 0x7F, 0x63, 0x63, 0x7F, 0x3E}, - {0x64, 0x66, 0x7F, 0x7F, 0x60, 0x60}, - {0x62, 0x73, 0x7B, 0x7B, 0x6F, 0x66}, - {0x63, 0x63, 0x6B, 0x6B, 0x7F, 0x36}, - {0x38, 0x3C, 0x36, 0x7F, 0x7F, 0x30}, - {0x6F, 0x6F, 0x6B, 0x6B, 0x7B, 0x33}, - {0x3E, 0x7F, 0x6B, 0x6B, 0x7B, 0x32}, - {0x03, 0x03, 0x73, 0x7B, 0x0F, 0x07}, - {0x36, 0x7F, 0x6B, 0x6B, 0x7F, 0x36}, - {0x06, 0x6F, 0x6B, 0x6B, 0x7F, 0x3E}, - {0x00, 0x00, 0x6C, 0x6C, 0x00, 0x00}, - {0x00, 0x40, 0x6C, 0x2C, 0x00, 0x00}, - {0x08, 0x14, 0x22, 0x41, 0x00, 0x00}, - {0x36, 0x36, 0x36, 0x36, 0x36, 0x00}, - {0x00, 0x41, 0x22, 0x14, 0x08, 0x00}, - {0x06, 0x07, 0x53, 0x5B, 0x1F, 0x0E}, - {0x30, 0x7B, 0x6B, 0x7B, 0x7F, 0x3E}, - {0x7E, 0x7F, 0x1B, 0x1B, 0x7F, 0x7E}, - {0x7F, 0x7F, 0x6B, 0x6B, 0x7F, 0x36}, - {0x3E, 0x7F, 0x63, 0x63, 0x63, 0x36}, - {0x7F, 0x7F, 0x63, 0x63, 0x7F, 0x3E}, - {0x7F, 0x7F, 0x6B, 0x6B, 0x6B, 0x63}, - {0x7F, 0x7F, 0x1B, 0x1B, 0x1B, 0x03}, - {0x3E, 0x7F, 0x63, 0x6B, 0x7B, 0x3A}, - {0x7F, 0x7F, 0x0C, 0x0C, 0x7F, 0x7F}, - {0x63, 0x63, 0x7F, 0x7F, 0x63, 0x63}, - {0x30, 0x73, 0x63, 0x7F, 0x3F, 0x03}, - {0x7F, 0x7F, 0x1C, 0x36, 0x63, 0x41}, - {0x7F, 0x7F, 0x60, 0x60, 0x60, 0x60}, - {0x7F, 0x7F, 0x06, 0x06, 0x7F, 0x7F}, - {0x7F, 0x7F, 0x0C, 0x18, 0x7F, 0x7F}, - {0x3E, 0x7F, 0x63, 0x63, 0x7F, 0x3E}, - {0x7F, 0x7F, 0x1B, 0x1B, 0x1F, 0x0E}, - {0x3E, 0x7F, 0x63, 0x73, 0x7F, 0x7E}, - {0x7F, 0x7F, 0x1B, 0x3B, 0x7F, 0x66}, - {0x66, 0x6F, 0x6B, 0x6B, 0x7B, 0x33}, - {0x03, 0x03, 0x7F, 0x7F, 0x03, 0x03}, - {0x3F, 0x7F, 0x60, 0x60, 0x7F, 0x3F}, - {0x1F, 0x3F, 0x60, 0x60, 0x3F, 0x1F}, - {0x3F, 0x7F, 0x30, 0x30, 0x7F, 0x3F}, - {0x63, 0x77, 0x1C, 0x1C, 0x77, 0x63}, - {0x07, 0x0F, 0x78, 0x78, 0x0F, 0x07}, - {0x63, 0x73, 0x7B, 0x6F, 0x67, 0x63}, - {0x00, 0x7F, 0x7F, 0x63, 0x63, 0x00}, - {0x01, 0x02, 0x04, 0x08, 0x10, 0x60}, - {0x00, 0x63, 0x63, 0x7F, 0x7F, 0x00}, - {0x0C, 0x0E, 0x03, 0x03, 0x0E, 0x0C}, - {0x60, 0x60, 0x60, 0x60, 0x60, 0x60}, - {0x00, 0x03, 0x07, 0x06, 0x00, 0x00}, - {0x20, 0x76, 0x56, 0x56, 0x7E, 0x3C}, - {0x7F, 0x7F, 0x6C, 0x6C, 0x7C, 0x38}, - {0x38, 0x7C, 0x6C, 0x6C, 0x6C, 0x00}, - {0x38, 0x7C, 0x6C, 0x6C, 0x7F, 0x7F}, - {0x3C, 0x7E, 0x56, 0x56, 0x5E, 0x0C}, - {0x7E, 0x7F, 0x1B, 0x1B, 0x02, 0x00}, - {0x0C, 0x5E, 0x56, 0x56, 0x7E, 0x3C}, - {0x7F, 0x7F, 0x0C, 0x0C, 0x7C, 0x78}, - {0x00, 0x00, 0x7A, 0x7A, 0x00, 0x00}, - {0x30, 0x60, 0x60, 0x7D, 0x3D, 0x00}, - {0x7F, 0x7F, 0x18, 0x3C, 0x7E, 0x66}, - {0x00, 0x3F, 0x7F, 0x40, 0x00, 0x00}, - {0x7C, 0x7C, 0x18, 0x18, 0x7C, 0x7C}, - {0x7C, 0x7C, 0x0C, 0x0C, 0x7C, 0x78}, - {0x3C, 0x7E, 0x66, 0x66, 0x7E, 0x3C}, - {0x7E, 0x7E, 0x36, 0x36, 0x3E, 0x1C}, - {0x1C, 0x3E, 0x36, 0x7E, 0x7E, 0x60}, - {0x7C, 0x7C, 0x0C, 0x0C, 0x18, 0x00}, - {0x4C, 0x5E, 0x56, 0x56, 0x76, 0x20}, - {0x3F, 0x7F, 0x6C, 0x6C, 0x60, 0x00}, - {0x3C, 0x7C, 0x60, 0x60, 0x7C, 0x3C}, - {0x0C, 0x3C, 0x70, 0x70, 0x3C, 0x0C}, - {0x3C, 0x7C, 0x30, 0x30, 0x7C, 0x3C}, - {0x44, 0x6C, 0x38, 0x38, 0x6C, 0x44}, - {0x06, 0x6E, 0x68, 0x68, 0x7E, 0x3E}, - {0x66, 0x76, 0x7E, 0x6E, 0x66, 0x00}, - {0x08, 0x3E, 0x77, 0x41, 0x00, 0x00}, - {0x00, 0x00, 0x7F, 0x00, 0x00, 0x00}, - {0x00, 0x41, 0x77, 0x3E, 0x08, 0x00}, - {0x0C, 0x06, 0x0C, 0x18, 0x0C, 0x00} - }; + const uint8_t gFontSmallBold[95 - 1][6] = + { +// {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x5E, 0x5E, 0x00, 0x00}, + {0x06, 0x06, 0x00, 0x06, 0x06, 0x00}, + {0x14, 0x3E, 0x14, 0x3E, 0x14, 0x00}, + {0x2E, 0x6B, 0x7F, 0x6B, 0x3A, 0x00}, + {0x63, 0x33, 0x18, 0x0C, 0x66, 0x63}, + {0x30, 0x4B, 0x4D, 0x55, 0x22, 0x50}, + {0x00, 0x00, 0x07, 0x07, 0x00, 0x00}, + {0x00, 0x1C, 0x3E, 0x63, 0x41, 0x00}, + {0x00, 0x41, 0x63, 0x3E, 0x1C, 0x00}, + {0x00, 0x2A, 0x1C, 0x1C, 0x2A, 0x00}, + {0x18, 0x18, 0x7E, 0x7E, 0x18, 0x18}, + {0x00, 0x40, 0x60, 0x20, 0x00, 0x00}, + {0x00, 0x18, 0x18, 0x18, 0x18, 0x00}, + {0x00, 0x00, 0x60, 0x60, 0x00, 0x00}, + {0x60, 0x30, 0x18, 0x0C, 0x06, 0x03}, + {0x3E, 0x7F, 0x63, 0x63, 0x7F, 0x3E}, + {0x64, 0x66, 0x7F, 0x7F, 0x60, 0x60}, + {0x62, 0x73, 0x7B, 0x7B, 0x6F, 0x66}, + {0x63, 0x63, 0x6B, 0x6B, 0x7F, 0x36}, + {0x38, 0x3C, 0x36, 0x7F, 0x7F, 0x30}, + {0x6F, 0x6F, 0x6B, 0x6B, 0x7B, 0x33}, + {0x3E, 0x7F, 0x6B, 0x6B, 0x7B, 0x32}, + {0x03, 0x03, 0x73, 0x7B, 0x0F, 0x07}, + {0x36, 0x7F, 0x6B, 0x6B, 0x7F, 0x36}, + {0x06, 0x6F, 0x6B, 0x6B, 0x7F, 0x3E}, + {0x00, 0x00, 0x6C, 0x6C, 0x00, 0x00}, + {0x00, 0x40, 0x6C, 0x2C, 0x00, 0x00}, + {0x08, 0x14, 0x22, 0x41, 0x00, 0x00}, + {0x36, 0x36, 0x36, 0x36, 0x36, 0x00}, + {0x00, 0x41, 0x22, 0x14, 0x08, 0x00}, + {0x06, 0x07, 0x53, 0x5B, 0x1F, 0x0E}, + {0x30, 0x7B, 0x6B, 0x7B, 0x7F, 0x3E}, + {0x7E, 0x7F, 0x1B, 0x1B, 0x7F, 0x7E}, + {0x7F, 0x7F, 0x6B, 0x6B, 0x7F, 0x36}, + {0x3E, 0x7F, 0x63, 0x63, 0x63, 0x36}, + {0x7F, 0x7F, 0x63, 0x63, 0x7F, 0x3E}, + {0x7F, 0x7F, 0x6B, 0x6B, 0x6B, 0x63}, + {0x7F, 0x7F, 0x1B, 0x1B, 0x1B, 0x03}, + {0x3E, 0x7F, 0x63, 0x6B, 0x7B, 0x3A}, + {0x7F, 0x7F, 0x0C, 0x0C, 0x7F, 0x7F}, + {0x63, 0x63, 0x7F, 0x7F, 0x63, 0x63}, + {0x30, 0x73, 0x63, 0x7F, 0x3F, 0x03}, + {0x7F, 0x7F, 0x1C, 0x36, 0x63, 0x41}, + {0x7F, 0x7F, 0x60, 0x60, 0x60, 0x60}, + {0x7F, 0x7F, 0x06, 0x06, 0x7F, 0x7F}, + {0x7F, 0x7F, 0x0C, 0x18, 0x7F, 0x7F}, + {0x3E, 0x7F, 0x63, 0x63, 0x7F, 0x3E}, + {0x7F, 0x7F, 0x1B, 0x1B, 0x1F, 0x0E}, + {0x3E, 0x7F, 0x63, 0x73, 0x7F, 0x7E}, + {0x7F, 0x7F, 0x1B, 0x3B, 0x7F, 0x66}, + {0x66, 0x6F, 0x6B, 0x6B, 0x7B, 0x33}, + {0x03, 0x03, 0x7F, 0x7F, 0x03, 0x03}, + {0x3F, 0x7F, 0x60, 0x60, 0x7F, 0x3F}, + {0x1F, 0x3F, 0x60, 0x60, 0x3F, 0x1F}, + {0x3F, 0x7F, 0x30, 0x30, 0x7F, 0x3F}, + {0x63, 0x77, 0x1C, 0x1C, 0x77, 0x63}, + {0x07, 0x0F, 0x78, 0x78, 0x0F, 0x07}, + {0x63, 0x73, 0x7B, 0x6F, 0x67, 0x63}, + {0x00, 0x7F, 0x7F, 0x63, 0x63, 0x00}, + {0x01, 0x02, 0x04, 0x08, 0x10, 0x60}, + {0x00, 0x63, 0x63, 0x7F, 0x7F, 0x00}, + {0x0C, 0x0E, 0x03, 0x03, 0x0E, 0x0C}, + {0x60, 0x60, 0x60, 0x60, 0x60, 0x60}, + {0x00, 0x03, 0x07, 0x06, 0x00, 0x00}, + {0x20, 0x76, 0x56, 0x56, 0x7E, 0x3C}, + {0x7F, 0x7F, 0x6C, 0x6C, 0x7C, 0x38}, + {0x38, 0x7C, 0x6C, 0x6C, 0x6C, 0x00}, + {0x38, 0x7C, 0x6C, 0x6C, 0x7F, 0x7F}, + {0x3C, 0x7E, 0x56, 0x56, 0x5E, 0x0C}, + {0x7E, 0x7F, 0x1B, 0x1B, 0x02, 0x00}, + {0x0C, 0x5E, 0x56, 0x56, 0x7E, 0x3C}, + {0x7F, 0x7F, 0x0C, 0x0C, 0x7C, 0x78}, + {0x00, 0x00, 0x7A, 0x7A, 0x00, 0x00}, + {0x30, 0x60, 0x60, 0x7D, 0x3D, 0x00}, + {0x7F, 0x7F, 0x18, 0x3C, 0x7E, 0x66}, + {0x00, 0x3F, 0x7F, 0x40, 0x00, 0x00}, + {0x7C, 0x7C, 0x18, 0x18, 0x7C, 0x7C}, + {0x7C, 0x7C, 0x0C, 0x0C, 0x7C, 0x78}, + {0x3C, 0x7E, 0x66, 0x66, 0x7E, 0x3C}, + {0x7E, 0x7E, 0x36, 0x36, 0x3E, 0x1C}, + {0x1C, 0x3E, 0x36, 0x7E, 0x7E, 0x60}, + {0x7C, 0x7C, 0x0C, 0x0C, 0x18, 0x00}, + {0x4C, 0x5E, 0x56, 0x56, 0x76, 0x20}, + {0x3F, 0x7F, 0x6C, 0x6C, 0x60, 0x00}, + {0x3C, 0x7C, 0x60, 0x60, 0x7C, 0x3C}, + {0x0C, 0x3C, 0x70, 0x70, 0x3C, 0x0C}, + {0x3C, 0x7C, 0x30, 0x30, 0x7C, 0x3C}, + {0x44, 0x6C, 0x38, 0x38, 0x6C, 0x44}, + {0x06, 0x6E, 0x68, 0x68, 0x7E, 0x3E}, + {0x66, 0x76, 0x7E, 0x6E, 0x66, 0x00}, + {0x08, 0x3E, 0x77, 0x41, 0x00, 0x00}, + {0x00, 0x00, 0x7F, 0x00, 0x00, 0x00}, + {0x00, 0x41, 0x77, 0x3E, 0x08, 0x00}, + {0x0C, 0x06, 0x0C, 0x18, 0x0C, 0x00} + }; #endif //#ifdef ENABLE_SPECTRUM - const uint8_t gFont3x5[][3] = - { - {0x00, 0x00, 0x00}, // 32 - space - {0x00, 0x17, 0x00}, // 33 - exclam - {0x03, 0x00, 0x03}, // 34 - quotedbl - {0x1f, 0x0a, 0x1f}, // 35 - numbersign - {0x0a, 0x1f, 0x05}, // 36 - dollar - {0x09, 0x04, 0x12}, // 37 - percent - {0x0f, 0x17, 0x1c}, // 38 - ampersand - {0x00, 0x03, 0x00}, // 39 - quotesingle - {0x00, 0x0e, 0x11}, // 40 - parenleft - {0x11, 0x0e, 0x00}, // 41 - parenright - {0x05, 0x02, 0x05}, // 42 - asterisk - {0x04, 0x0e, 0x04}, // 43 - plus - {0x10, 0x08, 0x00}, // 44 - comma - {0x04, 0x04, 0x04}, // 45 - hyphen - {0x00, 0x10, 0x00}, // 46 - period - {0x18, 0x04, 0x03}, // 47 - slash - {0x1e, 0x11, 0x0f}, // 48 - zero - {0x02, 0x1f, 0x00}, // 49 - one - {0x19, 0x15, 0x12}, // 50 - two - {0x11, 0x15, 0x0a}, // 51 - three - {0x07, 0x04, 0x1f}, // 52 - four - {0x17, 0x15, 0x09}, // 53 - five - {0x1e, 0x15, 0x1d}, // 54 - six - {0x19, 0x05, 0x03}, // 55 - seven - {0x1f, 0x15, 0x1f}, // 56 - eight - {0x17, 0x15, 0x0f}, // 57 - nine - {0x00, 0x0a, 0x00}, // 58 - colon - {0x10, 0x0a, 0x00}, // 59 - semicolon - {0x04, 0x0a, 0x11}, // 60 - less - {0x0a, 0x0a, 0x0a}, // 61 - equal - {0x11, 0x0a, 0x04}, // 62 - greater - {0x01, 0x15, 0x03}, // 63 - question - {0x0e, 0x15, 0x16}, // 64 - at - {0x1e, 0x05, 0x1e}, // 65 - A - {0x1f, 0x15, 0x0a}, // 66 - B - {0x0e, 0x11, 0x11}, // 67 - C - {0x1f, 0x11, 0x0e}, // 68 - D - {0x1f, 0x15, 0x15}, // 69 - E - {0x1f, 0x05, 0x05}, // 70 - F - {0x0e, 0x15, 0x1d}, // 71 - G - {0x1f, 0x04, 0x1f}, // 72 - H - {0x11, 0x1f, 0x11}, // 73 - I - {0x08, 0x10, 0x0f}, // 74 - J - {0x1f, 0x04, 0x1b}, // 75 - K - {0x1f, 0x10, 0x10}, // 76 - L - {0x1f, 0x06, 0x1f}, // 77 - M - {0x1f, 0x0e, 0x1f}, // 78 - N - {0x0e, 0x11, 0x0e}, // 79 - O - {0x1f, 0x05, 0x02}, // 80 - P - {0x0e, 0x19, 0x1e}, // 81 - Q - {0x1f, 0x0d, 0x16}, // 82 - R - {0x12, 0x15, 0x09}, // 83 - S - {0x01, 0x1f, 0x01}, // 84 - T - {0x0f, 0x10, 0x1f}, // 85 - U - {0x07, 0x18, 0x07}, // 86 - V - {0x1f, 0x0c, 0x1f}, // 87 - W - {0x1b, 0x04, 0x1b}, // 88 - X - {0x03, 0x1c, 0x03}, // 89 - Y - {0x19, 0x15, 0x13}, // 90 - Z - {0x1f, 0x11, 0x11}, // 91 - bracketleft - {0x02, 0x04, 0x08}, // 92 - backslash - {0x11, 0x11, 0x1f}, // 93 - bracketright - {0x02, 0x01, 0x02}, // 94 - asciicircum - {0x10, 0x10, 0x10}, // 95 - underscore - {0x01, 0x02, 0x00}, // 96 - grave - {0x1a, 0x16, 0x1c}, // 97 - a - {0x1f, 0x12, 0x0c}, // 98 - b - {0x0c, 0x12, 0x12}, // 99 - c - {0x0c, 0x12, 0x1f}, // 100 - d - {0x0c, 0x1a, 0x16}, // 101 - e - {0x04, 0x1e, 0x05}, // 102 - f - {0x0c, 0x2a, 0x1e}, // 103 - g - {0x1f, 0x02, 0x1c}, // 104 - h - {0x00, 0x1d, 0x00}, // 105 - i - {0x10, 0x20, 0x1d}, // 106 - j - {0x1f, 0x0c, 0x12}, // 107 - k - {0x11, 0x1f, 0x10}, // 108 - l - {0x1e, 0x0e, 0x1e}, // 109 - m - {0x1e, 0x02, 0x1c}, // 110 - n - {0x0c, 0x12, 0x0c}, // 111 - o - {0x3e, 0x12, 0x0c}, // 112 - p - {0x0c, 0x12, 0x3e}, // 113 - q - {0x1c, 0x02, 0x02}, // 114 - r - {0x14, 0x1e, 0x0a}, // 115 - s - {0x02, 0x1f, 0x12}, // 116 - t - {0x0e, 0x10, 0x1e}, // 117 - u - {0x0e, 0x18, 0x0e}, // 118 - v - {0x1e, 0x1c, 0x1e}, // 119 - w - {0x12, 0x0c, 0x12}, // 120 - x - {0x06, 0x28, 0x1e}, // 121 - y - {0x1a, 0x1e, 0x16}, // 122 - z - {0x04, 0x1b, 0x11}, // 123 - braceleft - {0x00, 0x1b, 0x00}, // 124 - bar - {0x11, 0x1b, 0x04}, // 125 - braceright - {0x02, 0x03, 0x01}, // 126 - asciitilde + const uint8_t gFont3x5[][3] = + { + {0x00, 0x00, 0x00}, // 32 - space + {0x00, 0x17, 0x00}, // 33 - exclam + {0x03, 0x00, 0x03}, // 34 - quotedbl + {0x1f, 0x0a, 0x1f}, // 35 - numbersign + {0x0a, 0x1f, 0x05}, // 36 - dollar + {0x09, 0x04, 0x12}, // 37 - percent + {0x0f, 0x17, 0x1c}, // 38 - ampersand + {0x00, 0x03, 0x00}, // 39 - quotesingle + {0x00, 0x0e, 0x11}, // 40 - parenleft + {0x11, 0x0e, 0x00}, // 41 - parenright + {0x05, 0x02, 0x05}, // 42 - asterisk + {0x04, 0x0e, 0x04}, // 43 - plus + {0x10, 0x08, 0x00}, // 44 - comma + {0x04, 0x04, 0x04}, // 45 - hyphen + {0x00, 0x10, 0x00}, // 46 - period + {0x18, 0x04, 0x03}, // 47 - slash + {0x1e, 0x11, 0x0f}, // 48 - zero + {0x02, 0x1f, 0x00}, // 49 - one + {0x19, 0x15, 0x12}, // 50 - two + {0x11, 0x15, 0x0a}, // 51 - three + {0x07, 0x04, 0x1f}, // 52 - four + {0x17, 0x15, 0x09}, // 53 - five + {0x1e, 0x15, 0x1d}, // 54 - six + {0x19, 0x05, 0x03}, // 55 - seven + {0x1f, 0x15, 0x1f}, // 56 - eight + {0x17, 0x15, 0x0f}, // 57 - nine + {0x00, 0x0a, 0x00}, // 58 - colon + {0x10, 0x0a, 0x00}, // 59 - semicolon + {0x04, 0x0a, 0x11}, // 60 - less + {0x0a, 0x0a, 0x0a}, // 61 - equal + {0x11, 0x0a, 0x04}, // 62 - greater + {0x01, 0x15, 0x03}, // 63 - question + {0x0e, 0x15, 0x16}, // 64 - at + {0x1e, 0x05, 0x1e}, // 65 - A + {0x1f, 0x15, 0x0a}, // 66 - B + {0x0e, 0x11, 0x11}, // 67 - C + {0x1f, 0x11, 0x0e}, // 68 - D + {0x1f, 0x15, 0x15}, // 69 - E + {0x1f, 0x05, 0x05}, // 70 - F + {0x0e, 0x15, 0x1d}, // 71 - G + {0x1f, 0x04, 0x1f}, // 72 - H + {0x11, 0x1f, 0x11}, // 73 - I + {0x08, 0x10, 0x0f}, // 74 - J + {0x1f, 0x04, 0x1b}, // 75 - K + {0x1f, 0x10, 0x10}, // 76 - L + {0x1f, 0x06, 0x1f}, // 77 - M + {0x1f, 0x0e, 0x1f}, // 78 - N + {0x0e, 0x11, 0x0e}, // 79 - O + {0x1f, 0x05, 0x02}, // 80 - P + {0x0e, 0x19, 0x1e}, // 81 - Q + {0x1f, 0x0d, 0x16}, // 82 - R + {0x12, 0x15, 0x09}, // 83 - S + {0x01, 0x1f, 0x01}, // 84 - T + {0x0f, 0x10, 0x1f}, // 85 - U + {0x07, 0x18, 0x07}, // 86 - V + {0x1f, 0x0c, 0x1f}, // 87 - W + {0x1b, 0x04, 0x1b}, // 88 - X + {0x03, 0x1c, 0x03}, // 89 - Y + {0x19, 0x15, 0x13}, // 90 - Z + {0x1f, 0x11, 0x11}, // 91 - bracketleft + {0x02, 0x04, 0x08}, // 92 - backslash + {0x11, 0x11, 0x1f}, // 93 - bracketright + {0x02, 0x01, 0x02}, // 94 - asciicircum + {0x10, 0x10, 0x10}, // 95 - underscore + {0x01, 0x02, 0x00}, // 96 - grave + {0x1a, 0x16, 0x1c}, // 97 - a + {0x1f, 0x12, 0x0c}, // 98 - b + {0x0c, 0x12, 0x12}, // 99 - c + {0x0c, 0x12, 0x1f}, // 100 - d + {0x0c, 0x1a, 0x16}, // 101 - e + {0x04, 0x1e, 0x05}, // 102 - f + {0x0c, 0x2a, 0x1e}, // 103 - g + {0x1f, 0x02, 0x1c}, // 104 - h + {0x00, 0x1d, 0x00}, // 105 - i + {0x10, 0x20, 0x1d}, // 106 - j + {0x1f, 0x0c, 0x12}, // 107 - k + {0x11, 0x1f, 0x10}, // 108 - l + {0x1e, 0x0e, 0x1e}, // 109 - m + {0x1e, 0x02, 0x1c}, // 110 - n + {0x0c, 0x12, 0x0c}, // 111 - o + {0x3e, 0x12, 0x0c}, // 112 - p + {0x0c, 0x12, 0x3e}, // 113 - q + {0x1c, 0x02, 0x02}, // 114 - r + {0x14, 0x1e, 0x0a}, // 115 - s + {0x02, 0x1f, 0x12}, // 116 - t + {0x0e, 0x10, 0x1e}, // 117 - u + {0x0e, 0x18, 0x0e}, // 118 - v + {0x1e, 0x1c, 0x1e}, // 119 - w + {0x12, 0x0c, 0x12}, // 120 - x + {0x06, 0x28, 0x1e}, // 121 - y + {0x1a, 0x1e, 0x16}, // 122 - z + {0x04, 0x1b, 0x11}, // 123 - braceleft + {0x00, 0x1b, 0x00}, // 124 - bar + {0x11, 0x1b, 0x04}, // 125 - braceright + {0x02, 0x03, 0x01}, // 126 - asciitilde - {0x12, 0x17, 0x12}, // 127 - plusminus + {0x12, 0x17, 0x12}, // 127 - plusminus - // {0x00, 0x00, 0x00}, // 127 - empty - // {0x00, 0x00, 0x00}, // 128 - empty - // {0x00, 0x00, 0x00}, // 129 - empty - // {0x00, 0x00, 0x00}, // 130 - empty - // {0x00, 0x00, 0x00}, // 131 - empty - // {0x00, 0x00, 0x00}, // 132 - empty - // {0x00, 0x00, 0x00}, // 133 - empty - // {0x00, 0x00, 0x00}, // 134 - empty - // {0x00, 0x00, 0x00}, // 135 - empty - // {0x00, 0x00, 0x00}, // 136 - empty - // {0x00, 0x00, 0x00}, // 137 - empty - // {0x00, 0x00, 0x00}, // 138 - empty - // {0x00, 0x00, 0x00}, // 139 - empty - // {0x00, 0x00, 0x00}, // 140 - empty - // {0x00, 0x00, 0x00}, // 141 - empty - // {0x00, 0x00, 0x00}, // 142 - empty - // {0x00, 0x00, 0x00}, // 143 - empty - // {0x00, 0x00, 0x00}, // 144 - empty - // {0x00, 0x00, 0x00}, // 145 - empty - // {0x00, 0x00, 0x00}, // 146 - empty - // {0x00, 0x00, 0x00}, // 147 - empty - // {0x00, 0x00, 0x00}, // 148 - empty - // {0x00, 0x00, 0x00}, // 149 - empty - // {0x00, 0x00, 0x00}, // 150 - empty - // {0x00, 0x00, 0x00}, // 151 - empty - // {0x00, 0x00, 0x00}, // 152 - empty - // {0x00, 0x00, 0x00}, // 153 - empty - // {0x00, 0x00, 0x00}, // 154 - empty - // {0x00, 0x00, 0x00}, // 155 - empty - // {0x00, 0x00, 0x00}, // 156 - empty - // {0x00, 0x00, 0x00}, // 157 - empty - // {0x00, 0x00, 0x00}, // 158 - empty - // {0x00, 0x00, 0x00}, // 159 - empty - // {0x00, 0x00, 0x00}, // 160 - empty - // {0x00, 0x1d, 0x00}, // 161 - exclamdown - // {0x0e, 0x1b, 0x0a}, // 162 - cent - // {0x14, 0x1f, 0x15}, // 163 - sterling - // {0x15, 0x0e, 0x15}, // 164 - currency - // {0x0b, 0x1c, 0x0b}, // 165 - yen - // {0x00, 0x1b, 0x00}, // 166 - brokenbar - // {0x14, 0x1b, 0x05}, // 167 - section - // {0x01, 0x00, 0x01}, // 168 - dieresis - // {0x02, 0x05, 0x05}, // 169 - copyright - // {0x16, 0x15, 0x17}, // 170 - ordfeminine - // {0x02, 0x05, 0x00}, // 171 - guillemotleft - // {0x02, 0x02, 0x06}, // 172 - logicalnot - // {0x04, 0x04, 0x00}, // 173 - softhyphen - // {0x07, 0x03, 0x04}, // 174 - registered - // {0x01, 0x01, 0x01}, // 175 - macron - // {0x02, 0x05, 0x02}, // 176 - degree - // {0x12, 0x17, 0x12}, // 177 - plusminus - // {0x01, 0x07, 0x04}, // 178 - twosuperior - // {0x05, 0x07, 0x07}, // 179 - threesuperior - // {0x00, 0x02, 0x01}, // 180 - acute - // {0x1f, 0x08, 0x07}, // 181 - mu - // {0x02, 0x1d, 0x1f}, // 182 - paragraph - // {0x0e, 0x0e, 0x0e}, // 183 - periodcentered - // {0x10, 0x14, 0x08}, // 184 - cedilla - // {0x00, 0x07, 0x00}, // 185 - onesuperior - // {0x12, 0x15, 0x12}, // 186 - ordmasculine - // {0x00, 0x05, 0x02}, // 187 - guillemotright - // {0x03, 0x08, 0x18}, // 188 - onequarter - // {0x0b, 0x18, 0x10}, // 189 - onehalf - // {0x03, 0x0b, 0x18}, // 190 - threequarters - // {0x18, 0x15, 0x10}, // 191 - questiondown - }; + // {0x00, 0x00, 0x00}, // 127 - empty + // {0x00, 0x00, 0x00}, // 128 - empty + // {0x00, 0x00, 0x00}, // 129 - empty + // {0x00, 0x00, 0x00}, // 130 - empty + // {0x00, 0x00, 0x00}, // 131 - empty + // {0x00, 0x00, 0x00}, // 132 - empty + // {0x00, 0x00, 0x00}, // 133 - empty + // {0x00, 0x00, 0x00}, // 134 - empty + // {0x00, 0x00, 0x00}, // 135 - empty + // {0x00, 0x00, 0x00}, // 136 - empty + // {0x00, 0x00, 0x00}, // 137 - empty + // {0x00, 0x00, 0x00}, // 138 - empty + // {0x00, 0x00, 0x00}, // 139 - empty + // {0x00, 0x00, 0x00}, // 140 - empty + // {0x00, 0x00, 0x00}, // 141 - empty + // {0x00, 0x00, 0x00}, // 142 - empty + // {0x00, 0x00, 0x00}, // 143 - empty + // {0x00, 0x00, 0x00}, // 144 - empty + // {0x00, 0x00, 0x00}, // 145 - empty + // {0x00, 0x00, 0x00}, // 146 - empty + // {0x00, 0x00, 0x00}, // 147 - empty + // {0x00, 0x00, 0x00}, // 148 - empty + // {0x00, 0x00, 0x00}, // 149 - empty + // {0x00, 0x00, 0x00}, // 150 - empty + // {0x00, 0x00, 0x00}, // 151 - empty + // {0x00, 0x00, 0x00}, // 152 - empty + // {0x00, 0x00, 0x00}, // 153 - empty + // {0x00, 0x00, 0x00}, // 154 - empty + // {0x00, 0x00, 0x00}, // 155 - empty + // {0x00, 0x00, 0x00}, // 156 - empty + // {0x00, 0x00, 0x00}, // 157 - empty + // {0x00, 0x00, 0x00}, // 158 - empty + // {0x00, 0x00, 0x00}, // 159 - empty + // {0x00, 0x00, 0x00}, // 160 - empty + // {0x00, 0x1d, 0x00}, // 161 - exclamdown + // {0x0e, 0x1b, 0x0a}, // 162 - cent + // {0x14, 0x1f, 0x15}, // 163 - sterling + // {0x15, 0x0e, 0x15}, // 164 - currency + // {0x0b, 0x1c, 0x0b}, // 165 - yen + // {0x00, 0x1b, 0x00}, // 166 - brokenbar + // {0x14, 0x1b, 0x05}, // 167 - section + // {0x01, 0x00, 0x01}, // 168 - dieresis + // {0x02, 0x05, 0x05}, // 169 - copyright + // {0x16, 0x15, 0x17}, // 170 - ordfeminine + // {0x02, 0x05, 0x00}, // 171 - guillemotleft + // {0x02, 0x02, 0x06}, // 172 - logicalnot + // {0x04, 0x04, 0x00}, // 173 - softhyphen + // {0x07, 0x03, 0x04}, // 174 - registered + // {0x01, 0x01, 0x01}, // 175 - macron + // {0x02, 0x05, 0x02}, // 176 - degree + // {0x12, 0x17, 0x12}, // 177 - plusminus + // {0x01, 0x07, 0x04}, // 178 - twosuperior + // {0x05, 0x07, 0x07}, // 179 - threesuperior + // {0x00, 0x02, 0x01}, // 180 - acute + // {0x1f, 0x08, 0x07}, // 181 - mu + // {0x02, 0x1d, 0x1f}, // 182 - paragraph + // {0x0e, 0x0e, 0x0e}, // 183 - periodcentered + // {0x10, 0x14, 0x08}, // 184 - cedilla + // {0x00, 0x07, 0x00}, // 185 - onesuperior + // {0x12, 0x15, 0x12}, // 186 - ordmasculine + // {0x00, 0x05, 0x02}, // 187 - guillemotright + // {0x03, 0x08, 0x18}, // 188 - onequarter + // {0x0b, 0x18, 0x10}, // 189 - onehalf + // {0x03, 0x0b, 0x18}, // 190 - threequarters + // {0x18, 0x15, 0x10}, // 191 - questiondown + }; //#endif diff --git a/font.h b/font.h index f93ef5007..8972aabfc 100644 --- a/font.h +++ b/font.h @@ -25,7 +25,7 @@ extern const uint8_t gFontBigDigits[11][26 - 6]; extern const uint8_t gFont3x5[96][3]; extern const uint8_t gFontSmall[95 - 1][6]; #ifdef ENABLE_SMALL_BOLD - extern const uint8_t gFontSmallBold[95 - 1][6]; + extern const uint8_t gFontSmallBold[95 - 1][6]; #endif #endif diff --git a/frequencies.c b/frequencies.c index 000ff6da1..daad6ff48 100644 --- a/frequencies.c +++ b/frequencies.c @@ -29,87 +29,87 @@ const freq_band_table_t BX4819_band2 = {84000000, BX4819_band2_upper}; const freq_band_table_t frequencyBandTable[] = { - #ifndef ENABLE_WIDE_RX - // QS original - [BAND1_50MHz ]={.lower = 5000000, .upper = 7600000}, - [BAND7_470MHz]={.lower = 47000000, .upper = 60000000}, - #else - // extended range - [BAND1_50MHz ]={.lower = BX4819_band1_lower, .upper = 10800000}, - [BAND7_470MHz]={.lower = 47000000, .upper = BX4819_band2_upper}, - #endif - [BAND2_108MHz]={.lower = 10800000, .upper = 13700000}, - [BAND3_137MHz]={.lower = 13700000, .upper = 17400000}, - [BAND4_174MHz]={.lower = 17400000, .upper = 35000000}, - [BAND5_350MHz]={.lower = 35000000, .upper = 40000000}, - [BAND6_400MHz]={.lower = 40000000, .upper = 47000000} + #ifndef ENABLE_WIDE_RX + // QS original + [BAND1_50MHz ]={.lower = 5000000, .upper = 7600000}, + [BAND7_470MHz]={.lower = 47000000, .upper = 60000000}, + #else + // extended range + [BAND1_50MHz ]={.lower = BX4819_band1_lower, .upper = 10800000}, + [BAND7_470MHz]={.lower = 47000000, .upper = BX4819_band2_upper}, + #endif + [BAND2_108MHz]={.lower = 10800000, .upper = 13700000}, + [BAND3_137MHz]={.lower = 13700000, .upper = 17400000}, + [BAND4_174MHz]={.lower = 17400000, .upper = 35000000}, + [BAND5_350MHz]={.lower = 35000000, .upper = 40000000}, + [BAND6_400MHz]={.lower = 40000000, .upper = 47000000} }; #ifdef ENABLE_NOAA - const uint32_t NoaaFrequencyTable[10] = - { - 16255000, - 16240000, - 16247500, - 16242500, - 16245000, - 16250000, - 16252500, - 16152500, - 16177500, - 16327500 - }; + const uint32_t NoaaFrequencyTable[10] = + { + 16255000, + 16240000, + 16247500, + 16242500, + 16245000, + 16250000, + 16252500, + 16152500, + 16177500, + 16327500 + }; #endif // this order of steps has to be preserved for backwards compatibility with other/stock firmwares const uint16_t gStepFrequencyTable[] = { // standard steps - [STEP_2_5kHz] = 250, - [STEP_5kHz] = 500, - [STEP_6_25kHz] = 625, - [STEP_10kHz] = 1000, - [STEP_12_5kHz] = 1250, - [STEP_25kHz] = 2500, - [STEP_8_33kHz] = 833, + [STEP_2_5kHz] = 250, + [STEP_5kHz] = 500, + [STEP_6_25kHz] = 625, + [STEP_10kHz] = 1000, + [STEP_12_5kHz] = 1250, + [STEP_25kHz] = 2500, + [STEP_8_33kHz] = 833, // custom steps - [STEP_0_01kHz] = 1, - [STEP_0_05kHz] = 5, - [STEP_0_1kHz] = 10, - [STEP_0_25kHz] = 25, - [STEP_0_5kHz] = 50, - [STEP_1kHz] = 100, - [STEP_1_25kHz] = 125, - [STEP_9kHz] = 900, - [STEP_15kHz] = 1500, - [STEP_20kHz] = 2000, - [STEP_30kHz] = 3000, - [STEP_50kHz] = 5000, - [STEP_100kHz] = 10000, - [STEP_125kHz] = 12500, - [STEP_200kHz] = 20000, - [STEP_250kHz] = 25000, - [STEP_500kHz] = 50000 + [STEP_0_01kHz] = 1, + [STEP_0_05kHz] = 5, + [STEP_0_1kHz] = 10, + [STEP_0_25kHz] = 25, + [STEP_0_5kHz] = 50, + [STEP_1kHz] = 100, + [STEP_1_25kHz] = 125, + [STEP_9kHz] = 900, + [STEP_15kHz] = 1500, + [STEP_20kHz] = 2000, + [STEP_30kHz] = 3000, + [STEP_50kHz] = 5000, + [STEP_100kHz] = 10000, + [STEP_125kHz] = 12500, + [STEP_200kHz] = 20000, + [STEP_250kHz] = 25000, + [STEP_500kHz] = 50000 }; const STEP_Setting_t StepSortedIndexes[] = { - STEP_0_01kHz, STEP_0_05kHz, STEP_0_1kHz, STEP_0_25kHz, STEP_0_5kHz, STEP_1kHz, STEP_1_25kHz, STEP_2_5kHz, STEP_5kHz, STEP_6_25kHz, - STEP_8_33kHz, STEP_9kHz, STEP_10kHz, STEP_12_5kHz, STEP_15kHz, STEP_20kHz, STEP_25kHz, STEP_30kHz, STEP_50kHz, STEP_100kHz, - STEP_125kHz, STEP_200kHz, STEP_250kHz, STEP_500kHz + STEP_0_01kHz, STEP_0_05kHz, STEP_0_1kHz, STEP_0_25kHz, STEP_0_5kHz, STEP_1kHz, STEP_1_25kHz, STEP_2_5kHz, STEP_5kHz, STEP_6_25kHz, + STEP_8_33kHz, STEP_9kHz, STEP_10kHz, STEP_12_5kHz, STEP_15kHz, STEP_20kHz, STEP_25kHz, STEP_30kHz, STEP_50kHz, STEP_100kHz, + STEP_125kHz, STEP_200kHz, STEP_250kHz, STEP_500kHz }; STEP_Setting_t FREQUENCY_GetStepIdxFromSortedIdx(uint8_t sortedIdx) { - return StepSortedIndexes[sortedIdx]; + return StepSortedIndexes[sortedIdx]; } uint32_t FREQUENCY_GetSortedIdxFromStepIdx(uint8_t stepIdx) { - for(uint8_t i = 0; i < ARRAY_SIZE(gStepFrequencyTable); i++) - if(StepSortedIndexes[i] == stepIdx) - return i; - return 0; + for(uint8_t i = 0; i < ARRAY_SIZE(gStepFrequencyTable); i++) + if(StepSortedIndexes[i] == stepIdx) + return i; + return 0; } static_assert(ARRAY_SIZE(gStepFrequencyTable) == STEP_N_ELEM); @@ -117,165 +117,165 @@ static_assert(ARRAY_SIZE(gStepFrequencyTable) == STEP_N_ELEM); FREQUENCY_Band_t FREQUENCY_GetBand(uint32_t Frequency) { - for (int32_t band = BAND_N_ELEM - 1; band >= 0; band--) - if (Frequency >= frequencyBandTable[band].lower) - return (FREQUENCY_Band_t)band; + for (int32_t band = BAND_N_ELEM - 1; band >= 0; band--) + if (Frequency >= frequencyBandTable[band].lower) + return (FREQUENCY_Band_t)band; - return BAND1_50MHz; + return BAND1_50MHz; } uint8_t FREQUENCY_CalculateOutputPower(uint8_t TxpLow, uint8_t TxpMid, uint8_t TxpHigh, int32_t LowerLimit, int32_t Middle, int32_t UpperLimit, int32_t Frequency) { - if (Frequency <= LowerLimit) - return TxpLow; + if (Frequency <= LowerLimit) + return TxpLow; - if (UpperLimit <= Frequency) - return TxpHigh; + if (UpperLimit <= Frequency) + return TxpHigh; - if (Frequency <= Middle) - { - TxpMid += ((TxpMid - TxpLow) * (Frequency - LowerLimit)) / (Middle - LowerLimit); - return TxpMid; - } + if (Frequency <= Middle) + { + TxpMid += ((TxpMid - TxpLow) * (Frequency - LowerLimit)) / (Middle - LowerLimit); + return TxpMid; + } - TxpMid += ((TxpHigh - TxpMid) * (Frequency - Middle)) / (UpperLimit - Middle); + TxpMid += ((TxpHigh - TxpMid) * (Frequency - Middle)) / (UpperLimit - Middle); - return TxpMid; + return TxpMid; } uint32_t FREQUENCY_RoundToStep(uint32_t freq, uint16_t step) { - if(step == 833) { + if(step == 833) { uint32_t base = freq/2500*2500; int chno = (freq - base) / 700; // convert entered aviation 8.33Khz channel number scheme to actual frequency. return base + (chno * 833) + (chno == 3); - } + } - if(step == 1) - return freq; - if(step >= 1000) - step = step/2; - return (freq + (step + 1) / 2) / step * step; + if(step == 1) + return freq; + if(step >= 1000) + step = step/2; + return (freq + (step + 1) / 2) / step * step; } int32_t TX_freq_check(const uint32_t Frequency) -{ // return '0' if TX frequency is allowed - // otherwise return '-1' - - if (Frequency < frequencyBandTable[0].lower || Frequency > frequencyBandTable[BAND_N_ELEM - 1].upper) - return 1; // not allowed outside this range - - if (Frequency >= BX4819_band1.upper && Frequency < BX4819_band2.lower) - return -1; // BX chip does not work in this range - - switch (gSetting_F_LOCK) - { - case F_LOCK_DEF: - if (Frequency >= frequencyBandTable[BAND3_137MHz].lower && Frequency < frequencyBandTable[BAND3_137MHz].upper) - return 0; - if (Frequency >= frequencyBandTable[BAND4_174MHz].lower && Frequency < frequencyBandTable[BAND4_174MHz].upper) - if (gSetting_200TX) - return 0; - if (Frequency >= frequencyBandTable[BAND5_350MHz].lower && Frequency < frequencyBandTable[BAND5_350MHz].upper) - if (gSetting_350TX && gSetting_350EN) - return 0; - if (Frequency >= frequencyBandTable[BAND6_400MHz].lower && Frequency < frequencyBandTable[BAND6_400MHz].upper) - return 0; - if (Frequency >= frequencyBandTable[BAND7_470MHz].lower && Frequency <= 60000000) - if (gSetting_500TX) - return 0; - break; - - case F_LOCK_FCC: - if (Frequency >= 14400000 && Frequency < 14800000) - return 0; - if (Frequency >= 42000000 && Frequency < 45000000) - return 0; - break; - - case F_LOCK_CE: - if (Frequency >= 14400000 && Frequency < 14600000) - return 0; - if (Frequency >= 43000000 && Frequency < 44000000) - return 0; - break; - - case F_LOCK_GB: - if (Frequency >= 14400000 && Frequency < 14800000) - return 0; - if (Frequency >= 43000000 && Frequency < 44000000) - return 0; - break; - - case F_LOCK_430: - if (Frequency >= frequencyBandTable[BAND3_137MHz].lower && Frequency < 17400000) - return 0; - if (Frequency >= 40000000 && Frequency < 43000000) - return 0; - break; - - case F_LOCK_438: - if (Frequency >= frequencyBandTable[BAND3_137MHz].lower && Frequency < 17400000) - return 0; - if (Frequency >= 40000000 && Frequency < 43800000) - return 0; - break; +{ // return '0' if TX frequency is allowed + // otherwise return '-1' + + if (Frequency < frequencyBandTable[0].lower || Frequency > frequencyBandTable[BAND_N_ELEM - 1].upper) + return 1; // not allowed outside this range + + if (Frequency >= BX4819_band1.upper && Frequency < BX4819_band2.lower) + return -1; // BX chip does not work in this range + + switch (gSetting_F_LOCK) + { + case F_LOCK_DEF: + if (Frequency >= frequencyBandTable[BAND3_137MHz].lower && Frequency < frequencyBandTable[BAND3_137MHz].upper) + return 0; + if (Frequency >= frequencyBandTable[BAND4_174MHz].lower && Frequency < frequencyBandTable[BAND4_174MHz].upper) + if (gSetting_200TX) + return 0; + if (Frequency >= frequencyBandTable[BAND5_350MHz].lower && Frequency < frequencyBandTable[BAND5_350MHz].upper) + if (gSetting_350TX && gSetting_350EN) + return 0; + if (Frequency >= frequencyBandTable[BAND6_400MHz].lower && Frequency < frequencyBandTable[BAND6_400MHz].upper) + return 0; + if (Frequency >= frequencyBandTable[BAND7_470MHz].lower && Frequency <= 60000000) + if (gSetting_500TX) + return 0; + break; + + case F_LOCK_FCC: + if (Frequency >= 14400000 && Frequency < 14800000) + return 0; + if (Frequency >= 42000000 && Frequency < 45000000) + return 0; + break; + + case F_LOCK_CE: + if (Frequency >= 14400000 && Frequency < 14600000) + return 0; + if (Frequency >= 43000000 && Frequency < 44000000) + return 0; + break; + + case F_LOCK_GB: + if (Frequency >= 14400000 && Frequency < 14800000) + return 0; + if (Frequency >= 43000000 && Frequency < 44000000) + return 0; + break; + + case F_LOCK_430: + if (Frequency >= frequencyBandTable[BAND3_137MHz].lower && Frequency < 17400000) + return 0; + if (Frequency >= 40000000 && Frequency < 43000000) + return 0; + break; + + case F_LOCK_438: + if (Frequency >= frequencyBandTable[BAND3_137MHz].lower && Frequency < 17400000) + return 0; + if (Frequency >= 40000000 && Frequency < 43800000) + return 0; + break; #ifdef ENABLE_FEAT_F4HWN_PMR - case F_LOCK_PMR: - if (Frequency >= 44600625 && Frequency <= 44619375) - return 0; - break; + case F_LOCK_PMR: + if (Frequency >= 44600625 && Frequency <= 44619375) + return 0; + break; #endif #ifdef ENABLE_FEAT_F4HWN_GMRS_FRS_MURS - case F_LOCK_GMRS_FRS_MURS: - // https://forums.radioreference.com/threads/the-great-unofficial-radioreference-frs-gmrs-murs-fact-sheet.275370/ - if ((Frequency >= 46255000 && Frequency <= 46272500) || - (Frequency >= 46755000 && Frequency <= 46772500)) // FRS/GMRS - return 0; - if (Frequency == 15182000 || - Frequency == 15188000 || - Frequency == 15194000 || - Frequency == 15457000 || - Frequency == 15460000) // MURS - return 0; - break; + case F_LOCK_GMRS_FRS_MURS: + // https://forums.radioreference.com/threads/the-great-unofficial-radioreference-frs-gmrs-murs-fact-sheet.275370/ + if ((Frequency >= 46255000 && Frequency <= 46272500) || + (Frequency >= 46755000 && Frequency <= 46772500)) // FRS/GMRS + return 0; + if (Frequency == 15182000 || + Frequency == 15188000 || + Frequency == 15194000 || + Frequency == 15457000 || + Frequency == 15460000) // MURS + return 0; + break; #endif -#ifdef ENABLE_FEAT_F4HWN_CA - case F_LOCK_CA: - if (Frequency >= 14400000 && Frequency < 14800000) - return 0; - if (Frequency >= 43000000 && Frequency < 45000000) - return 0; - break; +#ifdef ENABLE_FEAT_F4HWN_CA + case F_LOCK_CA: + if (Frequency >= 14400000 && Frequency < 14800000) + return 0; + if (Frequency >= 43000000 && Frequency < 45000000) + return 0; + break; #endif - case F_LOCK_ALL: - break; + case F_LOCK_ALL: + break; - case F_LOCK_NONE: - for (uint32_t i = 0; i < ARRAY_SIZE(frequencyBandTable); i++) - if (Frequency >= frequencyBandTable[i].lower && Frequency < frequencyBandTable[i].upper) - return 0; - break; - } + case F_LOCK_NONE: + for (uint32_t i = 0; i < ARRAY_SIZE(frequencyBandTable); i++) + if (Frequency >= frequencyBandTable[i].lower && Frequency < frequencyBandTable[i].upper) + return 0; + break; + } - // dis-allowed TX frequency - return -1; + // dis-allowed TX frequency + return -1; } int32_t RX_freq_check(const uint32_t Frequency) -{ // return '0' if RX frequency is allowed - // otherwise return '-1' +{ // return '0' if RX frequency is allowed + // otherwise return '-1' - if (Frequency < frequencyBandTable[0].lower || Frequency > frequencyBandTable[BAND_N_ELEM - 1].upper) - return -1; + if (Frequency < frequencyBandTable[0].lower || Frequency > frequencyBandTable[BAND_N_ELEM - 1].upper) + return -1; - if (Frequency >= BX4819_band1.upper && Frequency < BX4819_band2.lower) - return -1; + if (Frequency >= BX4819_band1.upper && Frequency < BX4819_band2.lower) + return -1; - return 0; // OK frequency + return 0; // OK frequency } diff --git a/frequencies.h b/frequencies.h index b5d4c16fb..2e49ea1be 100644 --- a/frequencies.h +++ b/frequencies.h @@ -22,70 +22,70 @@ #define _1GHz_in_KHz 100000000 typedef struct { - const uint32_t lower; - const uint32_t upper; + const uint32_t lower; + const uint32_t upper; } freq_band_table_t; extern const freq_band_table_t BX4819_band1; extern const freq_band_table_t BX4819_band2; typedef enum { - BAND_NONE = -1, - BAND1_50MHz = 0, - BAND2_108MHz, - BAND3_137MHz, - BAND4_174MHz, - BAND5_350MHz, - BAND6_400MHz, - BAND7_470MHz, - BAND_N_ELEM + BAND_NONE = -1, + BAND1_50MHz = 0, + BAND2_108MHz, + BAND3_137MHz, + BAND4_174MHz, + BAND5_350MHz, + BAND6_400MHz, + BAND7_470MHz, + BAND_N_ELEM } FREQUENCY_Band_t; extern const freq_band_table_t frequencyBandTable[]; typedef enum { // standard steps - STEP_2_5kHz, - STEP_5kHz, - STEP_6_25kHz, - STEP_10kHz, - STEP_12_5kHz, - STEP_25kHz, - STEP_8_33kHz, + STEP_2_5kHz, + STEP_5kHz, + STEP_6_25kHz, + STEP_10kHz, + STEP_12_5kHz, + STEP_25kHz, + STEP_8_33kHz, // custom steps - STEP_0_01kHz, - STEP_0_05kHz, - STEP_0_1kHz, - STEP_0_25kHz, - STEP_0_5kHz, - STEP_1kHz, - STEP_1_25kHz, - STEP_9kHz, - STEP_15kHz, - STEP_20kHz, - STEP_30kHz, - STEP_50kHz, - STEP_100kHz, - STEP_125kHz, - STEP_200kHz, - STEP_250kHz, - STEP_500kHz, - STEP_N_ELEM + STEP_0_01kHz, + STEP_0_05kHz, + STEP_0_1kHz, + STEP_0_25kHz, + STEP_0_5kHz, + STEP_1kHz, + STEP_1_25kHz, + STEP_9kHz, + STEP_15kHz, + STEP_20kHz, + STEP_30kHz, + STEP_50kHz, + STEP_100kHz, + STEP_125kHz, + STEP_200kHz, + STEP_250kHz, + STEP_500kHz, + STEP_N_ELEM } STEP_Setting_t; extern const uint16_t gStepFrequencyTable[]; #ifdef ENABLE_NOAA - extern const uint32_t NoaaFrequencyTable[10]; + extern const uint32_t NoaaFrequencyTable[10]; #endif FREQUENCY_Band_t FREQUENCY_GetBand(uint32_t Frequency); uint8_t FREQUENCY_CalculateOutputPower(uint8_t TxpLow, uint8_t TxpMid, uint8_t TxpHigh, int32_t LowerLimit, int32_t Middle, int32_t UpperLimit, int32_t Frequency); -uint32_t FREQUENCY_RoundToStep(uint32_t freq, uint16_t step); +uint32_t FREQUENCY_RoundToStep(uint32_t freq, uint16_t step); STEP_Setting_t FREQUENCY_GetStepIdxFromSortedIdx(uint8_t sortedIdx); -uint32_t FREQUENCY_GetSortedIdxFromStepIdx(uint8_t step); +uint32_t FREQUENCY_GetSortedIdxFromStepIdx(uint8_t step); int32_t TX_freq_check(uint32_t Frequency); int32_t RX_freq_check(uint32_t Frequency); diff --git a/functions.c b/functions.c index 3a98566b6..7743005b0 100644 --- a/functions.c +++ b/functions.c @@ -18,14 +18,14 @@ #include "app/dtmf.h" #if defined(ENABLE_FMRADIO) - #include "app/fm.h" + #include "app/fm.h" #endif #include "audio.h" #include "bsp/dp32g030/gpio.h" #include "dcs.h" #include "driver/backlight.h" #if defined(ENABLE_FMRADIO) - #include "driver/bk1080.h" + #include "driver/bk1080.h" #endif #include "driver/bk4819.h" #include "driver/gpio.h" @@ -44,235 +44,235 @@ FUNCTION_Type_t gCurrentFunction; bool FUNCTION_IsRx() { - return gCurrentFunction == FUNCTION_MONITOR || - gCurrentFunction == FUNCTION_INCOMING || - gCurrentFunction == FUNCTION_RECEIVE; + return gCurrentFunction == FUNCTION_MONITOR || + gCurrentFunction == FUNCTION_INCOMING || + gCurrentFunction == FUNCTION_RECEIVE; } void FUNCTION_Init(void) { - g_CxCSS_TAIL_Found = false; - g_CDCSS_Lost = false; - g_CTCSS_Lost = false; + g_CxCSS_TAIL_Found = false; + g_CDCSS_Lost = false; + g_CTCSS_Lost = false; - g_SquelchLost = false; + g_SquelchLost = false; - gFlagTailNoteEliminationComplete = false; - gTailNoteEliminationCountdown_10ms = 0; - gFoundCTCSS = false; - gFoundCDCSS = false; - gFoundCTCSSCountdown_10ms = 0; - gFoundCDCSSCountdown_10ms = 0; - gEndOfRxDetectedMaybe = false; + gFlagTailNoteEliminationComplete = false; + gTailNoteEliminationCountdown_10ms = 0; + gFoundCTCSS = false; + gFoundCDCSS = false; + gFoundCTCSSCountdown_10ms = 0; + gFoundCDCSSCountdown_10ms = 0; + gEndOfRxDetectedMaybe = false; - gCurrentCodeType = (gRxVfo->Modulation != MODULATION_FM) ? CODE_TYPE_OFF : gRxVfo->pRX->CodeType; + gCurrentCodeType = (gRxVfo->Modulation != MODULATION_FM) ? CODE_TYPE_OFF : gRxVfo->pRX->CodeType; #ifdef ENABLE_VOX - g_VOX_Lost = false; + g_VOX_Lost = false; #endif #ifdef ENABLE_DTMF_CALLING - DTMF_clear_RX(); + DTMF_clear_RX(); #endif #ifdef ENABLE_NOAA - gNOAACountdown_10ms = 0; + gNOAACountdown_10ms = 0; - if (IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE)) { - gCurrentCodeType = CODE_TYPE_CONTINUOUS_TONE; - } + if (IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE)) { + gCurrentCodeType = CODE_TYPE_CONTINUOUS_TONE; + } #endif - gUpdateStatus = true; + gUpdateStatus = true; } void FUNCTION_Foreground(const FUNCTION_Type_t PreviousFunction) { #ifdef ENABLE_DTMF_CALLING - if (gDTMF_ReplyState != DTMF_REPLY_NONE) - RADIO_PrepareCssTX(); + if (gDTMF_ReplyState != DTMF_REPLY_NONE) + RADIO_PrepareCssTX(); #endif - if (PreviousFunction == FUNCTION_TRANSMIT) { - ST7565_FixInterfGlitch(); - gVFO_RSSI_bar_level[0] = 0; - gVFO_RSSI_bar_level[1] = 0; - } else if (PreviousFunction != FUNCTION_RECEIVE) { - return; - } + if (PreviousFunction == FUNCTION_TRANSMIT) { + ST7565_FixInterfGlitch(); + gVFO_RSSI_bar_level[0] = 0; + gVFO_RSSI_bar_level[1] = 0; + } else if (PreviousFunction != FUNCTION_RECEIVE) { + return; + } #if defined(ENABLE_FMRADIO) - if (gFmRadioMode) - gFM_RestoreCountdown_10ms = fm_restore_countdown_10ms; + if (gFmRadioMode) + gFM_RestoreCountdown_10ms = fm_restore_countdown_10ms; #endif #ifdef ENABLE_DTMF_CALLING - if (gDTMF_CallState == DTMF_CALL_STATE_CALL_OUT || - gDTMF_CallState == DTMF_CALL_STATE_RECEIVED || - gDTMF_CallState == DTMF_CALL_STATE_RECEIVED_STAY) - { - gDTMF_auto_reset_time_500ms = gEeprom.DTMF_auto_reset_time * 2; - } + if (gDTMF_CallState == DTMF_CALL_STATE_CALL_OUT || + gDTMF_CallState == DTMF_CALL_STATE_RECEIVED || + gDTMF_CallState == DTMF_CALL_STATE_RECEIVED_STAY) + { + gDTMF_auto_reset_time_500ms = gEeprom.DTMF_auto_reset_time * 2; + } #endif - gUpdateStatus = true; + gUpdateStatus = true; } void FUNCTION_PowerSave() { - gPowerSave_10ms = gEeprom.BATTERY_SAVE * 10; - gPowerSaveCountdownExpired = false; + gPowerSave_10ms = gEeprom.BATTERY_SAVE * 10; + gPowerSaveCountdownExpired = false; - gRxIdleMode = true; + gRxIdleMode = true; - gMonitor = false; + gMonitor = false; - BK4819_DisableVox(); - BK4819_Sleep(); + BK4819_DisableVox(); + BK4819_Sleep(); - BK4819_ToggleGpioOut(BK4819_GPIO0_PIN28_RX_ENABLE, false); + BK4819_ToggleGpioOut(BK4819_GPIO0_PIN28_RX_ENABLE, false); - gUpdateStatus = true; + gUpdateStatus = true; - if (gScreenToDisplay != DISPLAY_MENU) // 1of11 .. don't close the menu - GUI_SelectNextDisplay(DISPLAY_MAIN); + if (gScreenToDisplay != DISPLAY_MENU) // 1of11 .. don't close the menu + GUI_SelectNextDisplay(DISPLAY_MAIN); } void FUNCTION_Transmit() { - // if DTMF is enabled when TX'ing, it changes the TX audio filtering !! .. 1of11 - BK4819_DisableDTMF(); + // if DTMF is enabled when TX'ing, it changes the TX audio filtering !! .. 1of11 + BK4819_DisableDTMF(); #ifdef ENABLE_DTMF_CALLING - // clear the DTMF RX buffer - DTMF_clear_RX(); + // clear the DTMF RX buffer + DTMF_clear_RX(); #endif - // clear the DTMF RX live decoder buffer - gDTMF_RX_live_timeout = 0; - memset(gDTMF_RX_live, 0, sizeof(gDTMF_RX_live)); + // clear the DTMF RX live decoder buffer + gDTMF_RX_live_timeout = 0; + memset(gDTMF_RX_live, 0, sizeof(gDTMF_RX_live)); #if defined(ENABLE_FMRADIO) - if (gFmRadioMode) - BK1080_Init0(); + if (gFmRadioMode) + BK1080_Init0(); #endif #ifdef ENABLE_ALARM - if (gAlarmState == ALARM_STATE_SITE_ALARM) - { - GUI_DisplayScreen(); + if (gAlarmState == ALARM_STATE_SITE_ALARM) + { + GUI_DisplayScreen(); - AUDIO_AudioPathOff(); + AUDIO_AudioPathOff(); - SYSTEM_DelayMs(20); - BK4819_PlayTone(500, 0); - SYSTEM_DelayMs(2); + SYSTEM_DelayMs(20); + BK4819_PlayTone(500, 0); + SYSTEM_DelayMs(2); - AUDIO_AudioPathOn(); + AUDIO_AudioPathOn(); - gEnableSpeaker = true; + gEnableSpeaker = true; - SYSTEM_DelayMs(60); - BK4819_ExitTxMute(); + SYSTEM_DelayMs(60); + BK4819_ExitTxMute(); - gAlarmToneCounter = 0; - return; - } + gAlarmToneCounter = 0; + return; + } #endif - gUpdateStatus = true; + gUpdateStatus = true; - GUI_DisplayScreen(); + GUI_DisplayScreen(); - RADIO_SetTxParameters(); + RADIO_SetTxParameters(); - // turn the RED LED on - BK4819_ToggleGpioOut(BK4819_GPIO5_PIN1_RED, true); + // turn the RED LED on + BK4819_ToggleGpioOut(BK4819_GPIO5_PIN1_RED, true); - DTMF_Reply(); + DTMF_Reply(); - if (gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_APOLLO) - BK4819_PlaySingleTone(2525, 250, 0, gEeprom.DTMF_SIDE_TONE); + if (gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_APOLLO) + BK4819_PlaySingleTone(2525, 250, 0, gEeprom.DTMF_SIDE_TONE); #if defined(ENABLE_ALARM) || defined(ENABLE_TX1750) - if (gAlarmState != ALARM_STATE_OFF) { - #ifdef ENABLE_TX1750 - if (gAlarmState == ALARM_STATE_TX1750) - BK4819_TransmitTone(true, 1750); - #endif - - #ifdef ENABLE_ALARM - if (gAlarmState == ALARM_STATE_TXALARM) - BK4819_TransmitTone(true, 500); - - gAlarmToneCounter = 0; - #endif - - SYSTEM_DelayMs(2); - AUDIO_AudioPathOn(); - gEnableSpeaker = true; - - gVfoConfigureMode = VFO_CONFIGURE; - return; - } + if (gAlarmState != ALARM_STATE_OFF) { + #ifdef ENABLE_TX1750 + if (gAlarmState == ALARM_STATE_TX1750) + BK4819_TransmitTone(true, 1750); + #endif + + #ifdef ENABLE_ALARM + if (gAlarmState == ALARM_STATE_TXALARM) + BK4819_TransmitTone(true, 500); + + gAlarmToneCounter = 0; + #endif + + SYSTEM_DelayMs(2); + AUDIO_AudioPathOn(); + gEnableSpeaker = true; + + gVfoConfigureMode = VFO_CONFIGURE; + return; + } #endif #ifdef ENABLE_FEAT_F4HWN - BK4819_DisableScramble(); + BK4819_DisableScramble(); #else - if (gCurrentVfo->SCRAMBLING_TYPE > 0 && gSetting_ScrambleEnable) - BK4819_EnableScramble(gCurrentVfo->SCRAMBLING_TYPE - 1); - else - BK4819_DisableScramble(); + if (gCurrentVfo->SCRAMBLING_TYPE > 0 && gSetting_ScrambleEnable) + BK4819_EnableScramble(gCurrentVfo->SCRAMBLING_TYPE - 1); + else + BK4819_DisableScramble(); #endif - if (gSetting_backlight_on_tx_rx & BACKLIGHT_ON_TR_TX) { - BACKLIGHT_TurnOn(); - } + if (gSetting_backlight_on_tx_rx & BACKLIGHT_ON_TR_TX) { + BACKLIGHT_TurnOn(); + } } void FUNCTION_Select(FUNCTION_Type_t Function) { - const FUNCTION_Type_t PreviousFunction = gCurrentFunction; - const bool bWasPowerSave = PreviousFunction == FUNCTION_POWER_SAVE; + const FUNCTION_Type_t PreviousFunction = gCurrentFunction; + const bool bWasPowerSave = PreviousFunction == FUNCTION_POWER_SAVE; - gCurrentFunction = Function; + gCurrentFunction = Function; - if (bWasPowerSave && Function != FUNCTION_POWER_SAVE) { - BK4819_Conditional_RX_TurnOn_and_GPIO6_Enable(); - gRxIdleMode = false; - UI_DisplayStatus(); - } + if (bWasPowerSave && Function != FUNCTION_POWER_SAVE) { + BK4819_Conditional_RX_TurnOn_and_GPIO6_Enable(); + gRxIdleMode = false; + UI_DisplayStatus(); + } - switch (Function) { - case FUNCTION_FOREGROUND: - FUNCTION_Foreground(PreviousFunction); - return; + switch (Function) { + case FUNCTION_FOREGROUND: + FUNCTION_Foreground(PreviousFunction); + return; - case FUNCTION_POWER_SAVE: - FUNCTION_PowerSave(); - return; + case FUNCTION_POWER_SAVE: + FUNCTION_PowerSave(); + return; - case FUNCTION_TRANSMIT: - FUNCTION_Transmit(); - break; + case FUNCTION_TRANSMIT: + FUNCTION_Transmit(); + break; - case FUNCTION_MONITOR: - gMonitor = true; - break; + case FUNCTION_MONITOR: + gMonitor = true; + break; - case FUNCTION_INCOMING: - case FUNCTION_RECEIVE: - case FUNCTION_BAND_SCOPE: - default: - break; - } + case FUNCTION_INCOMING: + case FUNCTION_RECEIVE: + case FUNCTION_BAND_SCOPE: + default: + break; + } - gBatterySaveCountdown_10ms = battery_save_count_10ms; - gSchedulePowerSave = false; + gBatterySaveCountdown_10ms = battery_save_count_10ms; + gSchedulePowerSave = false; #if defined(ENABLE_FMRADIO) - if(Function != FUNCTION_INCOMING) - gFM_RestoreCountdown_10ms = 0; + if(Function != FUNCTION_INCOMING) + gFM_RestoreCountdown_10ms = 0; #endif } diff --git a/functions.h b/functions.h index bfec351b3..ec1d983c2 100644 --- a/functions.h +++ b/functions.h @@ -21,14 +21,14 @@ enum FUNCTION_Type_t { - FUNCTION_FOREGROUND = 0, // ??? - FUNCTION_TRANSMIT, // transmitting - FUNCTION_MONITOR, // receiving with squelch forced open - FUNCTION_INCOMING, // receiving a signal (squelch is open) - FUNCTION_RECEIVE, // RX mode, squelch closed - FUNCTION_POWER_SAVE, // sleeping - FUNCTION_BAND_SCOPE, // bandscope mode (panadpter/spectrum) .. not yet implemented - FUNCTION_N_ELEM + FUNCTION_FOREGROUND = 0, // ??? + FUNCTION_TRANSMIT, // transmitting + FUNCTION_MONITOR, // receiving with squelch forced open + FUNCTION_INCOMING, // receiving a signal (squelch is open) + FUNCTION_RECEIVE, // RX mode, squelch closed + FUNCTION_POWER_SAVE, // sleeping + FUNCTION_BAND_SCOPE, // bandscope mode (panadpter/spectrum) .. not yet implemented + FUNCTION_N_ELEM }; typedef enum FUNCTION_Type_t FUNCTION_Type_t; diff --git a/helper/battery.c b/helper/battery.c index ee8fe4685..f61974a6f 100644 --- a/helper/battery.c +++ b/helper/battery.c @@ -40,207 +40,207 @@ bool gLowBatteryConfirmed; uint16_t gBatteryCheckCounter; typedef enum { - BATTERY_LOW_INACTIVE, - BATTERY_LOW_ACTIVE, - BATTERY_LOW_CONFIRMED + BATTERY_LOW_INACTIVE, + BATTERY_LOW_ACTIVE, + BATTERY_LOW_CONFIRMED } BatteryLow_t; uint16_t lowBatteryCountdown; -const uint16_t lowBatteryPeriod = 30; +const uint16_t lowBatteryPeriod = 30; volatile uint16_t gPowerSave_10ms; const uint16_t Voltage2PercentageTable[][7][3] = { - [BATTERY_TYPE_1600_MAH] = { - {828, 100}, - {814, 97 }, - {760, 25 }, - {729, 6 }, - {630, 0 }, - {0, 0 }, - {0, 0 }, - }, - - [BATTERY_TYPE_2200_MAH] = { - {832, 100}, - {813, 95 }, - {740, 60 }, - {707, 21 }, - {682, 5 }, - {630, 0 }, - {0, 0 }, - }, - - [BATTERY_TYPE_3500_MAH] = { - {837, 100}, - {826, 95 }, - {750, 50 }, - {700, 25 }, - {620, 5 }, - {600, 0 }, - {0, 0 }, - }, + [BATTERY_TYPE_1600_MAH] = { + {828, 100}, + {814, 97 }, + {760, 25 }, + {729, 6 }, + {630, 0 }, + {0, 0 }, + {0, 0 }, + }, + + [BATTERY_TYPE_2200_MAH] = { + {832, 100}, + {813, 95 }, + {740, 60 }, + {707, 21 }, + {682, 5 }, + {630, 0 }, + {0, 0 }, + }, + + [BATTERY_TYPE_3500_MAH] = { + {837, 100}, + {826, 95 }, + {750, 50 }, + {700, 25 }, + {620, 5 }, + {600, 0 }, + {0, 0 }, + }, }; static_assert( - (ARRAY_SIZE(Voltage2PercentageTable[BATTERY_TYPE_1600_MAH]) == - ARRAY_SIZE(Voltage2PercentageTable[BATTERY_TYPE_2200_MAH])) && - (ARRAY_SIZE(Voltage2PercentageTable[BATTERY_TYPE_2200_MAH]) == - ARRAY_SIZE(Voltage2PercentageTable[BATTERY_TYPE_3500_MAH])) - ); + (ARRAY_SIZE(Voltage2PercentageTable[BATTERY_TYPE_1600_MAH]) == + ARRAY_SIZE(Voltage2PercentageTable[BATTERY_TYPE_2200_MAH])) && + (ARRAY_SIZE(Voltage2PercentageTable[BATTERY_TYPE_2200_MAH]) == + ARRAY_SIZE(Voltage2PercentageTable[BATTERY_TYPE_3500_MAH])) + ); unsigned int BATTERY_VoltsToPercent(const unsigned int voltage_10mV) { - const uint16_t (*crv)[3] = Voltage2PercentageTable[gEeprom.BATTERY_TYPE]; - const int mulipl = 1000; - for (unsigned int i = 1; i < ARRAY_SIZE(Voltage2PercentageTable[BATTERY_TYPE_2200_MAH]); i++) { - if (voltage_10mV > crv[i][0]) { - const int a = (crv[i - 1][1] - crv[i][1]) * mulipl / (crv[i - 1][0] - crv[i][0]); - const int b = crv[i][1] - a * crv[i][0] / mulipl; - const int p = a * voltage_10mV / mulipl + b; - return MIN(p, 100); - } - } - - return 0; + const uint16_t (*crv)[3] = Voltage2PercentageTable[gEeprom.BATTERY_TYPE]; + const int mulipl = 1000; + for (unsigned int i = 1; i < ARRAY_SIZE(Voltage2PercentageTable[BATTERY_TYPE_2200_MAH]); i++) { + if (voltage_10mV > crv[i][0]) { + const int a = (crv[i - 1][1] - crv[i][1]) * mulipl / (crv[i - 1][0] - crv[i][0]); + const int b = crv[i][1] - a * crv[i][0] / mulipl; + const int p = a * voltage_10mV / mulipl + b; + return MIN(p, 100); + } + } + + return 0; } void BATTERY_GetReadings(const bool bDisplayBatteryLevel) { - const uint8_t PreviousBatteryLevel = gBatteryDisplayLevel; - const uint16_t Voltage = (gBatteryVoltages[0] + gBatteryVoltages[1] + gBatteryVoltages[2] + gBatteryVoltages[3]) / 4; - - gBatteryVoltageAverage = (Voltage * 760) / gBatteryCalibration[3]; - - if(gBatteryVoltageAverage > 890) - gBatteryDisplayLevel = 7; // battery overvoltage - else if(gBatteryVoltageAverage < 630 && (gEeprom.BATTERY_TYPE == BATTERY_TYPE_1600_MAH || gEeprom.BATTERY_TYPE == BATTERY_TYPE_2200_MAH)) - gBatteryDisplayLevel = 0; // battery critical - else if(gBatteryVoltageAverage < 600 && (gEeprom.BATTERY_TYPE == BATTERY_TYPE_3500_MAH)) - gBatteryDisplayLevel = 0; // battery critical - else { - gBatteryDisplayLevel = 1; - const uint8_t levels[] = {5,17,41,65,88}; - uint8_t perc = BATTERY_VoltsToPercent(gBatteryVoltageAverage); - //char str[64]; - //LogUart("----------\n"); - //sprintf(str, "%d %d %d %d %d %d %d\n", gBatteryVoltages[0], gBatteryVoltages[1], gBatteryVoltages[2], gBatteryVoltages[3], Voltage, gBatteryVoltageAverage, perc); - //LogUart(str); - - for(uint8_t i = 6; i >= 2; i--){ - //sprintf(str, "%d %d %d\n", perc, levels[i-2], i); - //LogUart(str); - if (perc > levels[i-2]) { - gBatteryDisplayLevel = i; - break; - } - } - } - - - if ((gScreenToDisplay == DISPLAY_MENU) && UI_MENU_GetCurrentMenuId() == MENU_VOL) - gUpdateDisplay = true; - - if (gBatteryCurrent < 501) - { - if (gChargingWithTypeC) - { - gUpdateStatus = true; - gUpdateDisplay = true; - } - - gChargingWithTypeC = false; - } - else - { - if (!gChargingWithTypeC) - { - gUpdateStatus = true; - gUpdateDisplay = true; - BACKLIGHT_TurnOn(); - } - - gChargingWithTypeC = true; - } - - if (PreviousBatteryLevel != gBatteryDisplayLevel) - { - if(gBatteryDisplayLevel > 2) - gLowBatteryConfirmed = false; - else if (gBatteryDisplayLevel < 2) - { - gLowBattery = true; - } - else - { - gLowBattery = false; - - if (bDisplayBatteryLevel) - UI_DisplayBattery(gBatteryDisplayLevel, gLowBatteryBlink); - } - - if(!gLowBatteryConfirmed) - gUpdateDisplay = true; - - lowBatteryCountdown = 0; - } + const uint8_t PreviousBatteryLevel = gBatteryDisplayLevel; + const uint16_t Voltage = (gBatteryVoltages[0] + gBatteryVoltages[1] + gBatteryVoltages[2] + gBatteryVoltages[3]) / 4; + + gBatteryVoltageAverage = (Voltage * 760) / gBatteryCalibration[3]; + + if(gBatteryVoltageAverage > 890) + gBatteryDisplayLevel = 7; // battery overvoltage + else if(gBatteryVoltageAverage < 630 && (gEeprom.BATTERY_TYPE == BATTERY_TYPE_1600_MAH || gEeprom.BATTERY_TYPE == BATTERY_TYPE_2200_MAH)) + gBatteryDisplayLevel = 0; // battery critical + else if(gBatteryVoltageAverage < 600 && (gEeprom.BATTERY_TYPE == BATTERY_TYPE_3500_MAH)) + gBatteryDisplayLevel = 0; // battery critical + else { + gBatteryDisplayLevel = 1; + const uint8_t levels[] = {5,17,41,65,88}; + uint8_t perc = BATTERY_VoltsToPercent(gBatteryVoltageAverage); + //char str[64]; + //LogUart("----------\n"); + //sprintf(str, "%d %d %d %d %d %d %d\n", gBatteryVoltages[0], gBatteryVoltages[1], gBatteryVoltages[2], gBatteryVoltages[3], Voltage, gBatteryVoltageAverage, perc); + //LogUart(str); + + for(uint8_t i = 6; i >= 2; i--){ + //sprintf(str, "%d %d %d\n", perc, levels[i-2], i); + //LogUart(str); + if (perc > levels[i-2]) { + gBatteryDisplayLevel = i; + break; + } + } + } + + + if ((gScreenToDisplay == DISPLAY_MENU) && UI_MENU_GetCurrentMenuId() == MENU_VOL) + gUpdateDisplay = true; + + if (gBatteryCurrent < 501) + { + if (gChargingWithTypeC) + { + gUpdateStatus = true; + gUpdateDisplay = true; + } + + gChargingWithTypeC = false; + } + else + { + if (!gChargingWithTypeC) + { + gUpdateStatus = true; + gUpdateDisplay = true; + BACKLIGHT_TurnOn(); + } + + gChargingWithTypeC = true; + } + + if (PreviousBatteryLevel != gBatteryDisplayLevel) + { + if(gBatteryDisplayLevel > 2) + gLowBatteryConfirmed = false; + else if (gBatteryDisplayLevel < 2) + { + gLowBattery = true; + } + else + { + gLowBattery = false; + + if (bDisplayBatteryLevel) + UI_DisplayBattery(gBatteryDisplayLevel, gLowBatteryBlink); + } + + if(!gLowBatteryConfirmed) + gUpdateDisplay = true; + + lowBatteryCountdown = 0; + } } void BATTERY_TimeSlice500ms(void) { - if (!gLowBattery) { - return; - } + if (!gLowBattery) { + return; + } - gLowBatteryBlink = ++lowBatteryCountdown & 1; + gLowBatteryBlink = ++lowBatteryCountdown & 1; - UI_DisplayBattery(0, gLowBatteryBlink); + UI_DisplayBattery(0, gLowBatteryBlink); - if (gCurrentFunction == FUNCTION_TRANSMIT) { - return; - } + if (gCurrentFunction == FUNCTION_TRANSMIT) { + return; + } - // not transmitting + // not transmitting - if (lowBatteryCountdown < lowBatteryPeriod) { - if (lowBatteryCountdown == lowBatteryPeriod-1 && !gChargingWithTypeC && !gLowBatteryConfirmed) { - AUDIO_PlayBeep(BEEP_500HZ_60MS_DOUBLE_BEEP); - } - return; - } + if (lowBatteryCountdown < lowBatteryPeriod) { + if (lowBatteryCountdown == lowBatteryPeriod-1 && !gChargingWithTypeC && !gLowBatteryConfirmed) { + AUDIO_PlayBeep(BEEP_500HZ_60MS_DOUBLE_BEEP); + } + return; + } - lowBatteryCountdown = 0; + lowBatteryCountdown = 0; - if (gChargingWithTypeC) { - return; - } + if (gChargingWithTypeC) { + return; + } - // not on charge - if (!gLowBatteryConfirmed) { - AUDIO_PlayBeep(BEEP_500HZ_60MS_DOUBLE_BEEP); + // not on charge + if (!gLowBatteryConfirmed) { + AUDIO_PlayBeep(BEEP_500HZ_60MS_DOUBLE_BEEP); #ifdef ENABLE_VOICE - AUDIO_SetVoiceID(0, VOICE_ID_LOW_VOLTAGE); + AUDIO_SetVoiceID(0, VOICE_ID_LOW_VOLTAGE); #endif - } + } - if (gBatteryDisplayLevel != 0) { + if (gBatteryDisplayLevel != 0) { #ifdef ENABLE_VOICE - AUDIO_PlaySingleVoice(false); + AUDIO_PlaySingleVoice(false); #endif - return; - } + return; + } #ifdef ENABLE_VOICE - AUDIO_PlaySingleVoice(true); + AUDIO_PlaySingleVoice(true); #endif - gReducedService = true; + gReducedService = true; - FUNCTION_Select(FUNCTION_POWER_SAVE); + FUNCTION_Select(FUNCTION_POWER_SAVE); - ST7565_HardwareReset(); + ST7565_HardwareReset(); - if (gEeprom.BACKLIGHT_TIME < 61) { - BACKLIGHT_TurnOff(); - } + if (gEeprom.BACKLIGHT_TIME < 61) { + BACKLIGHT_TurnOff(); + } } diff --git a/helper/boot.c b/helper/boot.c index 4ac9d5ca9..2739ce00c 100644 --- a/helper/boot.c +++ b/helper/boot.c @@ -17,7 +17,7 @@ #include #ifdef ENABLE_AIRCOPY - #include "app/aircopy.h" + #include "app/aircopy.h" #endif #include "bsp/dp32g030/gpio.h" #include "driver/bk4819.h" @@ -33,81 +33,81 @@ BOOT_Mode_t BOOT_GetMode(void) { - unsigned int i; - KEY_Code_t Keys[2]; - - for (i = 0; i < 2; i++) - { - if (GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT)) - return BOOT_MODE_NORMAL; // PTT not pressed - Keys[i] = KEYBOARD_Poll(); - SYSTEM_DelayMs(20); - } - - if (Keys[0] == Keys[1]) - { - gKeyReading0 = Keys[0]; - gKeyReading1 = Keys[0]; - - gDebounceCounter = 2; - - if (Keys[0] == KEY_SIDE1) - return BOOT_MODE_F_LOCK; - - #ifdef ENABLE_AIRCOPY - if (Keys[0] == KEY_SIDE2) - return BOOT_MODE_AIRCOPY; - #endif - } - - return BOOT_MODE_NORMAL; + unsigned int i; + KEY_Code_t Keys[2]; + + for (i = 0; i < 2; i++) + { + if (GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT)) + return BOOT_MODE_NORMAL; // PTT not pressed + Keys[i] = KEYBOARD_Poll(); + SYSTEM_DelayMs(20); + } + + if (Keys[0] == Keys[1]) + { + gKeyReading0 = Keys[0]; + gKeyReading1 = Keys[0]; + + gDebounceCounter = 2; + + if (Keys[0] == KEY_SIDE1) + return BOOT_MODE_F_LOCK; + + #ifdef ENABLE_AIRCOPY + if (Keys[0] == KEY_SIDE2) + return BOOT_MODE_AIRCOPY; + #endif + } + + return BOOT_MODE_NORMAL; } void BOOT_ProcessMode(BOOT_Mode_t Mode) { - if (Mode == BOOT_MODE_F_LOCK) - { - GUI_SelectNextDisplay(DISPLAY_MENU); - } - #ifdef ENABLE_AIRCOPY - else - if (Mode == BOOT_MODE_AIRCOPY) - { - gEeprom.DUAL_WATCH = DUAL_WATCH_OFF; - gEeprom.BATTERY_SAVE = 0; - #ifdef ENABLE_VOX - gEeprom.VOX_SWITCH = false; - #endif - gEeprom.CROSS_BAND_RX_TX = CROSS_BAND_OFF; - gEeprom.AUTO_KEYPAD_LOCK = false; - gEeprom.KEY_1_SHORT_PRESS_ACTION = ACTION_OPT_NONE; - gEeprom.KEY_1_LONG_PRESS_ACTION = ACTION_OPT_NONE; - gEeprom.KEY_2_SHORT_PRESS_ACTION = ACTION_OPT_NONE; - gEeprom.KEY_2_LONG_PRESS_ACTION = ACTION_OPT_NONE; - gEeprom.KEY_M_LONG_PRESS_ACTION = ACTION_OPT_NONE; - - RADIO_InitInfo(gRxVfo, FREQ_CHANNEL_LAST - 1, 43400000); // LPD - - gRxVfo->CHANNEL_BANDWIDTH = BANDWIDTH_NARROW; - gRxVfo->OUTPUT_POWER = OUTPUT_POWER_LOW1; - - RADIO_ConfigureSquelchAndOutputPower(gRxVfo); - - gCurrentVfo = gRxVfo; - - RADIO_SetupRegisters(true); - BK4819_SetupAircopy(); - BK4819_ResetFSK(); - - gAircopyState = AIRCOPY_READY; - - gEeprom.BACKLIGHT_TIME = 61; - - GUI_SelectNextDisplay(DISPLAY_AIRCOPY); - } - #endif - else - { - GUI_SelectNextDisplay(DISPLAY_MAIN); - } + if (Mode == BOOT_MODE_F_LOCK) + { + GUI_SelectNextDisplay(DISPLAY_MENU); + } + #ifdef ENABLE_AIRCOPY + else + if (Mode == BOOT_MODE_AIRCOPY) + { + gEeprom.DUAL_WATCH = DUAL_WATCH_OFF; + gEeprom.BATTERY_SAVE = 0; + #ifdef ENABLE_VOX + gEeprom.VOX_SWITCH = false; + #endif + gEeprom.CROSS_BAND_RX_TX = CROSS_BAND_OFF; + gEeprom.AUTO_KEYPAD_LOCK = false; + gEeprom.KEY_1_SHORT_PRESS_ACTION = ACTION_OPT_NONE; + gEeprom.KEY_1_LONG_PRESS_ACTION = ACTION_OPT_NONE; + gEeprom.KEY_2_SHORT_PRESS_ACTION = ACTION_OPT_NONE; + gEeprom.KEY_2_LONG_PRESS_ACTION = ACTION_OPT_NONE; + gEeprom.KEY_M_LONG_PRESS_ACTION = ACTION_OPT_NONE; + + RADIO_InitInfo(gRxVfo, FREQ_CHANNEL_LAST - 1, 43400000); // LPD + + gRxVfo->CHANNEL_BANDWIDTH = BANDWIDTH_NARROW; + gRxVfo->OUTPUT_POWER = OUTPUT_POWER_LOW1; + + RADIO_ConfigureSquelchAndOutputPower(gRxVfo); + + gCurrentVfo = gRxVfo; + + RADIO_SetupRegisters(true); + BK4819_SetupAircopy(); + BK4819_ResetFSK(); + + gAircopyState = AIRCOPY_READY; + + gEeprom.BACKLIGHT_TIME = 61; + + GUI_SelectNextDisplay(DISPLAY_AIRCOPY); + } + #endif + else + { + GUI_SelectNextDisplay(DISPLAY_MAIN); + } } diff --git a/helper/boot.h b/helper/boot.h index fd6c96e94..e04c46293 100644 --- a/helper/boot.h +++ b/helper/boot.h @@ -22,11 +22,11 @@ enum BOOT_Mode_t { - BOOT_MODE_NORMAL = 0, - BOOT_MODE_F_LOCK, - #ifdef ENABLE_AIRCOPY - BOOT_MODE_AIRCOPY - #endif + BOOT_MODE_NORMAL = 0, + BOOT_MODE_F_LOCK, + #ifdef ENABLE_AIRCOPY + BOOT_MODE_AIRCOPY + #endif }; typedef enum BOOT_Mode_t BOOT_Mode_t; diff --git a/init.c b/init.c index 3e9266a27..2cda66382 100644 --- a/init.c +++ b/init.c @@ -30,18 +30,18 @@ void DATA_Init(void); void BSS_Init(void) { - for (uint32_t *pBss = __bss_start__; pBss < __bss_end__; pBss++) { - *pBss = 0; - } + for (uint32_t *pBss = __bss_start__; pBss < __bss_end__; pBss++) { + *pBss = 0; + } } void DATA_Init(void) { - volatile uint32_t *pDataRam = (volatile uint32_t *)sram_data_start; - volatile uint32_t *pDataFlash = (volatile uint32_t *)flash_data_start; - uint32_t Size = (uint32_t)sram_data_end - (uint32_t)sram_data_start; + volatile uint32_t *pDataRam = (volatile uint32_t *)sram_data_start; + volatile uint32_t *pDataFlash = (volatile uint32_t *)flash_data_start; + uint32_t Size = (uint32_t)sram_data_end - (uint32_t)sram_data_start; - for (unsigned int i = 0; i < (Size / 4); i++) { - *pDataRam++ = *pDataFlash++; - } + for (unsigned int i = 0; i < (Size / 4); i++) { + *pDataRam++ = *pDataFlash++; + } } diff --git a/main.c b/main.c index 7359658e4..ec83117b1 100644 --- a/main.c +++ b/main.c @@ -19,7 +19,7 @@ #include // NULL #ifdef ENABLE_AM_FIX - #include "am_fix.h" + #include "am_fix.h" #endif #include "audio.h" @@ -41,7 +41,7 @@ #include "driver/systick.h" #include "driver/eeprom.h" #ifdef ENABLE_UART - #include "driver/uart.h" + #include "driver/uart.h" #endif #include "helper/battery.h" @@ -54,200 +54,200 @@ void _putchar(__attribute__((unused)) char c) { #ifdef ENABLE_UART - UART_Send((uint8_t *)&c, 1); + UART_Send((uint8_t *)&c, 1); #endif } void Main(void) { - // Enable clock gating of blocks we need - SYSCON_DEV_CLK_GATE = 0 - | SYSCON_DEV_CLK_GATE_GPIOA_BITS_ENABLE - | SYSCON_DEV_CLK_GATE_GPIOB_BITS_ENABLE - | SYSCON_DEV_CLK_GATE_GPIOC_BITS_ENABLE - | SYSCON_DEV_CLK_GATE_UART1_BITS_ENABLE - | SYSCON_DEV_CLK_GATE_SPI0_BITS_ENABLE - | SYSCON_DEV_CLK_GATE_SARADC_BITS_ENABLE - | SYSCON_DEV_CLK_GATE_CRC_BITS_ENABLE - | SYSCON_DEV_CLK_GATE_AES_BITS_ENABLE - | SYSCON_DEV_CLK_GATE_PWM_PLUS0_BITS_ENABLE; + // Enable clock gating of blocks we need + SYSCON_DEV_CLK_GATE = 0 + | SYSCON_DEV_CLK_GATE_GPIOA_BITS_ENABLE + | SYSCON_DEV_CLK_GATE_GPIOB_BITS_ENABLE + | SYSCON_DEV_CLK_GATE_GPIOC_BITS_ENABLE + | SYSCON_DEV_CLK_GATE_UART1_BITS_ENABLE + | SYSCON_DEV_CLK_GATE_SPI0_BITS_ENABLE + | SYSCON_DEV_CLK_GATE_SARADC_BITS_ENABLE + | SYSCON_DEV_CLK_GATE_CRC_BITS_ENABLE + | SYSCON_DEV_CLK_GATE_AES_BITS_ENABLE + | SYSCON_DEV_CLK_GATE_PWM_PLUS0_BITS_ENABLE; - SYSTICK_Init(); - BOARD_Init(); + SYSTICK_Init(); + BOARD_Init(); - boot_counter_10ms = 250; // 2.5 sec + boot_counter_10ms = 250; // 2.5 sec #ifdef ENABLE_UART - UART_Init(); - UART_Send(UART_Version, strlen(UART_Version)); + UART_Init(); + UART_Send(UART_Version, strlen(UART_Version)); #endif - // Not implementing authentic device checks + // Not implementing authentic device checks - memset(gDTMF_String, '-', sizeof(gDTMF_String)); - gDTMF_String[sizeof(gDTMF_String) - 1] = 0; + memset(gDTMF_String, '-', sizeof(gDTMF_String)); + gDTMF_String[sizeof(gDTMF_String) - 1] = 0; - BK4819_Init(); + BK4819_Init(); - BOARD_ADC_GetBatteryInfo(&gBatteryCurrentVoltage, &gBatteryCurrent); + BOARD_ADC_GetBatteryInfo(&gBatteryCurrentVoltage, &gBatteryCurrent); - SETTINGS_InitEEPROM(); + SETTINGS_InitEEPROM(); - #ifdef ENABLE_FEAT_F4HWN - gDW = gEeprom.DUAL_WATCH; - gCB = gEeprom.CROSS_BAND_RX_TX; - #endif + #ifdef ENABLE_FEAT_F4HWN + gDW = gEeprom.DUAL_WATCH; + gCB = gEeprom.CROSS_BAND_RX_TX; + #endif - SETTINGS_WriteBuildOptions(); - SETTINGS_LoadCalibration(); + SETTINGS_WriteBuildOptions(); + SETTINGS_LoadCalibration(); - RADIO_ConfigureChannel(0, VFO_CONFIGURE_RELOAD); - RADIO_ConfigureChannel(1, VFO_CONFIGURE_RELOAD); + RADIO_ConfigureChannel(0, VFO_CONFIGURE_RELOAD); + RADIO_ConfigureChannel(1, VFO_CONFIGURE_RELOAD); - RADIO_SelectVfos(); + RADIO_SelectVfos(); - RADIO_SetupRegisters(true); + RADIO_SetupRegisters(true); - for (unsigned int i = 0; i < ARRAY_SIZE(gBatteryVoltages); i++) - BOARD_ADC_GetBatteryInfo(&gBatteryVoltages[i], &gBatteryCurrent); + for (unsigned int i = 0; i < ARRAY_SIZE(gBatteryVoltages); i++) + BOARD_ADC_GetBatteryInfo(&gBatteryVoltages[i], &gBatteryCurrent); - BATTERY_GetReadings(false); + BATTERY_GetReadings(false); #ifdef ENABLE_AM_FIX - AM_fix_init(); + AM_fix_init(); #endif - const BOOT_Mode_t BootMode = BOOT_GetMode(); - - if (BootMode == BOOT_MODE_F_LOCK) - { - - gF_LOCK = true; // flag to say include the hidden menu items - #ifdef ENABLE_FEAT_F4HWN - gEeprom.KEY_LOCK = 0; - SETTINGS_SaveSettings(); - #ifndef ENABLE_VOX - gMenuCursor = 64; // move to hidden section, fix me if change... !!! Remove VOX and Mic Bar - #else - gMenuCursor = 66; // move to hidden section, fix me if change... !!! - #endif - gSubMenuSelection = gSetting_F_LOCK; - #endif - } - - // count the number of menu items - gMenuListCount = 0; - while (MenuList[gMenuListCount].name[0] != '\0') { - if(!gF_LOCK && MenuList[gMenuListCount].menu_id == FIRST_HIDDEN_MENU_ITEM) - break; - - gMenuListCount++; - } - - // wait for user to release all butts before moving on - if (!GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT) || - KEYBOARD_Poll() != KEY_INVALID || - BootMode != BOOT_MODE_NORMAL) - { // keys are pressed - UI_DisplayReleaseKeys(); - BACKLIGHT_TurnOn(); - - // 500ms - for (int i = 0; i < 50;) - { - i = (GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT) && KEYBOARD_Poll() == KEY_INVALID) ? i + 1 : 0; - SYSTEM_DelayMs(10); - } - gKeyReading0 = KEY_INVALID; - gKeyReading1 = KEY_INVALID; - gDebounceCounter = 0; - } - - if (!gChargingWithTypeC && gBatteryDisplayLevel == 0) - { - FUNCTION_Select(FUNCTION_POWER_SAVE); - - if (gEeprom.BACKLIGHT_TIME < 61) // backlight is not set to be always on - BACKLIGHT_TurnOff(); // turn the backlight OFF - else - BACKLIGHT_TurnOn(); // turn the backlight ON - - gReducedService = true; - } - else - { - UI_DisplayWelcome(); - - BACKLIGHT_TurnOn(); + const BOOT_Mode_t BootMode = BOOT_GetMode(); + + if (BootMode == BOOT_MODE_F_LOCK) + { + + gF_LOCK = true; // flag to say include the hidden menu items + #ifdef ENABLE_FEAT_F4HWN + gEeprom.KEY_LOCK = 0; + SETTINGS_SaveSettings(); + #ifndef ENABLE_VOX + gMenuCursor = 64; // move to hidden section, fix me if change... !!! Remove VOX and Mic Bar + #else + gMenuCursor = 66; // move to hidden section, fix me if change... !!! + #endif + gSubMenuSelection = gSetting_F_LOCK; + #endif + } + + // count the number of menu items + gMenuListCount = 0; + while (MenuList[gMenuListCount].name[0] != '\0') { + if(!gF_LOCK && MenuList[gMenuListCount].menu_id == FIRST_HIDDEN_MENU_ITEM) + break; + + gMenuListCount++; + } + + // wait for user to release all butts before moving on + if (!GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT) || + KEYBOARD_Poll() != KEY_INVALID || + BootMode != BOOT_MODE_NORMAL) + { // keys are pressed + UI_DisplayReleaseKeys(); + BACKLIGHT_TurnOn(); + + // 500ms + for (int i = 0; i < 50;) + { + i = (GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT) && KEYBOARD_Poll() == KEY_INVALID) ? i + 1 : 0; + SYSTEM_DelayMs(10); + } + gKeyReading0 = KEY_INVALID; + gKeyReading1 = KEY_INVALID; + gDebounceCounter = 0; + } + + if (!gChargingWithTypeC && gBatteryDisplayLevel == 0) + { + FUNCTION_Select(FUNCTION_POWER_SAVE); + + if (gEeprom.BACKLIGHT_TIME < 61) // backlight is not set to be always on + BACKLIGHT_TurnOff(); // turn the backlight OFF + else + BACKLIGHT_TurnOn(); // turn the backlight ON + + gReducedService = true; + } + else + { + UI_DisplayWelcome(); + + BACKLIGHT_TurnOn(); #ifdef ENABLE_FEAT_F4HWN - if (gEeprom.POWER_ON_DISPLAY_MODE != POWER_ON_DISPLAY_MODE_NONE && gEeprom.POWER_ON_DISPLAY_MODE != POWER_ON_DISPLAY_MODE_SOUND) + if (gEeprom.POWER_ON_DISPLAY_MODE != POWER_ON_DISPLAY_MODE_NONE && gEeprom.POWER_ON_DISPLAY_MODE != POWER_ON_DISPLAY_MODE_SOUND) #else - if (gEeprom.POWER_ON_DISPLAY_MODE != POWER_ON_DISPLAY_MODE_NONE) + if (gEeprom.POWER_ON_DISPLAY_MODE != POWER_ON_DISPLAY_MODE_NONE) #endif - { // 2.55 second boot-up screen - while (boot_counter_10ms > 0) - { - if (KEYBOARD_Poll() != KEY_INVALID) - { // halt boot beeps - boot_counter_10ms = 0; - break; - } - } - RADIO_SetupRegisters(true); - } + { // 2.55 second boot-up screen + while (boot_counter_10ms > 0) + { + if (KEYBOARD_Poll() != KEY_INVALID) + { // halt boot beeps + boot_counter_10ms = 0; + break; + } + } + RADIO_SetupRegisters(true); + } #ifdef ENABLE_PWRON_PASSWORD - if (gEeprom.POWER_ON_PASSWORD < 1000000) - { - bIsInLockScreen = true; - UI_DisplayLock(); - bIsInLockScreen = false; - } + if (gEeprom.POWER_ON_PASSWORD < 1000000) + { + bIsInLockScreen = true; + UI_DisplayLock(); + bIsInLockScreen = false; + } #endif - BOOT_ProcessMode(BootMode); + BOOT_ProcessMode(BootMode); - GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_VOICE_0); + GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_VOICE_0); - gUpdateStatus = true; + gUpdateStatus = true; #ifdef ENABLE_VOICE - { - uint8_t Channel; - - AUDIO_SetVoiceID(0, VOICE_ID_WELCOME); - - Channel = gEeprom.ScreenChannel[gEeprom.TX_VFO]; - if (IS_MR_CHANNEL(Channel)) - { - AUDIO_SetVoiceID(1, VOICE_ID_CHANNEL_MODE); - AUDIO_SetDigitVoice(2, Channel + 1); - } - else if (IS_FREQ_CHANNEL(Channel)) - AUDIO_SetVoiceID(1, VOICE_ID_FREQUENCY_MODE); - - AUDIO_PlaySingleVoice(0); - } + { + uint8_t Channel; + + AUDIO_SetVoiceID(0, VOICE_ID_WELCOME); + + Channel = gEeprom.ScreenChannel[gEeprom.TX_VFO]; + if (IS_MR_CHANNEL(Channel)) + { + AUDIO_SetVoiceID(1, VOICE_ID_CHANNEL_MODE); + AUDIO_SetDigitVoice(2, Channel + 1); + } + else if (IS_FREQ_CHANNEL(Channel)) + AUDIO_SetVoiceID(1, VOICE_ID_FREQUENCY_MODE); + + AUDIO_PlaySingleVoice(0); + } #endif #ifdef ENABLE_NOAA - RADIO_ConfigureNOAA(); + RADIO_ConfigureNOAA(); #endif - } + } - while (true) { - APP_Update(); + while (true) { + APP_Update(); - if (gNextTimeslice) { + if (gNextTimeslice) { - APP_TimeSlice10ms(); + APP_TimeSlice10ms(); - if (gNextTimeslice_500ms) { - APP_TimeSlice500ms(); - } - } - } + if (gNextTimeslice_500ms) { + APP_TimeSlice500ms(); + } + } + } } diff --git a/misc.c b/misc.c index 811d1eb5d..6abf84304 100644 --- a/misc.c +++ b/misc.c @@ -45,21 +45,21 @@ const uint16_t key_debounce_10ms = 20 / 10; // 20ms const uint8_t scan_delay_10ms = 210 / 10; // 210ms #ifdef ENABLE_FEAT_F4HWN - const uint16_t dual_watch_count_after_tx_10ms = 420; // 4.2 sec after TX ends - const uint16_t dual_watch_count_after_rx_10ms = 1000 / 10; // 1 sec after RX ends ? - const uint16_t dual_watch_count_after_1_10ms = 5000 / 10; // 5 sec - const uint16_t dual_watch_count_after_2_10ms = 420; // 4.2 sec - const uint16_t dual_watch_count_noaa_10ms = 70 / 10; // 70ms + const uint16_t dual_watch_count_after_tx_10ms = 420; // 4.2 sec after TX ends + const uint16_t dual_watch_count_after_rx_10ms = 1000 / 10; // 1 sec after RX ends ? + const uint16_t dual_watch_count_after_1_10ms = 5000 / 10; // 5 sec + const uint16_t dual_watch_count_after_2_10ms = 420; // 4.2 sec + const uint16_t dual_watch_count_noaa_10ms = 70 / 10; // 70ms #else - const uint16_t dual_watch_count_after_tx_10ms = 3600 / 10; // 3.6 sec after TX ends - const uint16_t dual_watch_count_after_rx_10ms = 1000 / 10; // 1 sec after RX ends ? - const uint16_t dual_watch_count_after_1_10ms = 5000 / 10; // 5 sec - const uint16_t dual_watch_count_after_2_10ms = 3600 / 10; // 3.6 sec - const uint16_t dual_watch_count_noaa_10ms = 70 / 10; // 70ms + const uint16_t dual_watch_count_after_tx_10ms = 3600 / 10; // 3.6 sec after TX ends + const uint16_t dual_watch_count_after_rx_10ms = 1000 / 10; // 1 sec after RX ends ? + const uint16_t dual_watch_count_after_1_10ms = 5000 / 10; // 5 sec + const uint16_t dual_watch_count_after_2_10ms = 3600 / 10; // 3.6 sec + const uint16_t dual_watch_count_noaa_10ms = 70 / 10; // 70ms #endif #ifdef ENABLE_VOX - const uint16_t dual_watch_count_after_vox_10ms = 200 / 10; // 200ms + const uint16_t dual_watch_count_after_vox_10ms = 200 / 10; // 200ms #endif const uint16_t dual_watch_count_toggle_10ms = 100 / 10; // 100ms between VFO toggles @@ -77,7 +77,7 @@ const uint16_t power_save1_10ms = 100 / 10; // 100ms const uint16_t power_save2_10ms = 200 / 10; // 200ms #ifdef ENABLE_VOX - const uint16_t vox_stop_count_down_10ms = 1000 / 10; // 1 second + const uint16_t vox_stop_count_down_10ms = 1000 / 10; // 1 second #endif const uint16_t NOAA_countdown_10ms = 5000 / 10; // 5 seconds @@ -101,32 +101,32 @@ bool gSetting_ScrambleEnable; enum BacklightOnRxTx_t gSetting_backlight_on_tx_rx; #ifdef ENABLE_AM_FIX - bool gSetting_AM_fix = true; + bool gSetting_AM_fix = true; #endif #ifdef ENABLE_FEAT_F4HWN - uint8_t gSetting_set_pwr = 1; - bool gSetting_set_ptt = 0; - uint8_t gSetting_set_tot = 0; - uint8_t gSetting_set_ctr = 11; - bool gSetting_set_inv = false; - uint8_t gSetting_set_eot = 0; - bool gSetting_set_lck = false; - bool gSetting_set_met = 0; - bool gSetting_set_gui = 0; - bool gSetting_set_tmr = 0; - bool gSetting_set_ptt_session; - uint8_t gDebug; - uint8_t gDW = 0; - uint8_t gCB = 0; - bool gSaveRxMode = false; - uint8_t crc[15] = { 0 }; - uint8_t lErrorsDuringAirCopy = 0; - uint8_t gAircopyStep = 0; + uint8_t gSetting_set_pwr = 1; + bool gSetting_set_ptt = 0; + uint8_t gSetting_set_tot = 0; + uint8_t gSetting_set_ctr = 11; + bool gSetting_set_inv = false; + uint8_t gSetting_set_eot = 0; + bool gSetting_set_lck = false; + bool gSetting_set_met = 0; + bool gSetting_set_gui = 0; + bool gSetting_set_tmr = 0; + bool gSetting_set_ptt_session; + uint8_t gDebug; + uint8_t gDW = 0; + uint8_t gCB = 0; + bool gSaveRxMode = false; + uint8_t crc[15] = { 0 }; + uint8_t lErrorsDuringAirCopy = 0; + uint8_t gAircopyStep = 0; #endif #ifdef ENABLE_AUDIO_BAR - bool gSetting_mic_bar; + bool gSetting_mic_bar; #endif bool gSetting_live_DTMF_decoder; uint8_t gSetting_battery_text; @@ -164,12 +164,12 @@ volatile uint16_t gTxTimerCountdown_500ms; volatile bool gTxTimeoutReached; #ifdef ENABLE_FEAT_F4HWN - volatile uint16_t gTxTimerCountdownAlert_500ms; - volatile bool gTxTimeoutReachedAlert; - volatile uint16_t gTxTimeoutToneAlert = 800; - #ifdef ENABLE_FEAT_F4HWN_RX_TX_TIMER - volatile uint16_t gRxTimerCountdown_500ms; - #endif + volatile uint16_t gTxTimerCountdownAlert_500ms; + volatile bool gTxTimeoutReachedAlert; + volatile uint16_t gTxTimeoutToneAlert = 800; + #ifdef ENABLE_FEAT_F4HWN_RX_TX_TIMER + volatile uint16_t gRxTimerCountdown_500ms; + #endif #endif volatile uint16_t gTailNoteEliminationCountdown_10ms; @@ -177,7 +177,7 @@ volatile uint16_t gTailNoteEliminationCountdown_10ms; volatile uint8_t gVFOStateResumeCountdown_500ms; #ifdef ENABLE_NOAA - volatile uint16_t gNOAA_Countdown_10ms; + volatile uint16_t gNOAA_Countdown_10ms; #endif bool gEnableSpeaker; @@ -195,13 +195,13 @@ uint8_t gVFO_RSSI_bar_level[2]; uint8_t gReducedService; uint8_t gBatteryVoltageIndex; -bool gCssBackgroundScan; +bool gCssBackgroundScan; volatile bool gScheduleScanListen = true; volatile uint16_t gScanPauseDelayIn_10ms; #if defined(ENABLE_ALARM) || defined(ENABLE_TX1750) - AlarmState_t gAlarmState; + AlarmState_t gAlarmState; #endif uint16_t gMenuCountdown; bool gPttWasReleased; @@ -214,7 +214,7 @@ bool gRequestSaveVFO; uint8_t gRequestSaveChannel; bool gRequestSaveSettings; #ifdef ENABLE_FMRADIO - bool gRequestSaveFM; + bool gRequestSaveFM; #endif bool gFlagPrepareTX; @@ -222,17 +222,17 @@ bool gFlagAcceptSetting; bool gFlagRefreshSetting; #ifdef ENABLE_FMRADIO - bool gFlagSaveFM; + bool gFlagSaveFM; #endif bool g_CDCSS_Lost; uint8_t gCDCSSCodeType; bool g_CTCSS_Lost; bool g_CxCSS_TAIL_Found; #ifdef ENABLE_VOX - bool g_VOX_Lost; - bool gVOX_NoiseDetected; - uint16_t gVoxResumeCountdown; - uint16_t gVoxPauseCountdown; + bool g_VOX_Lost; + bool gVOX_NoiseDetected; + uint16_t gVoxResumeCountdown; + uint16_t gVoxPauseCountdown; #endif bool g_SquelchLost; @@ -244,8 +244,8 @@ ReceptionMode_t gRxReceptionMode; bool gRxVfoIsActive; #ifdef ENABLE_ALARM - uint8_t gAlarmToneCounter; - uint16_t gAlarmRunningCounter; + uint8_t gAlarmToneCounter; + uint16_t gAlarmRunningCounter; #endif bool gKeyBeingHeld; bool gPttIsPressed; @@ -256,8 +256,8 @@ uint8_t gScanDelay_10ms; uint8_t gFSKWriteIndex; #ifdef ENABLE_NOAA - bool gIsNoaaMode; - uint8_t gNoaaChannel; + bool gIsNoaaMode; + uint8_t gNoaaChannel; #endif bool gUpdateDisplay; @@ -270,16 +270,16 @@ volatile bool gNextTimeslice; volatile uint8_t gFoundCDCSSCountdown_10ms; volatile uint8_t gFoundCTCSSCountdown_10ms; #ifdef ENABLE_VOX - volatile uint16_t gVoxStopCountdown_10ms; + volatile uint16_t gVoxStopCountdown_10ms; #endif volatile bool gNextTimeslice40ms; #ifdef ENABLE_NOAA - volatile uint16_t gNOAACountdown_10ms = 0; - volatile bool gScheduleNOAA = true; + volatile uint16_t gNOAACountdown_10ms = 0; + volatile bool gScheduleNOAA = true; #endif volatile bool gFlagTailNoteEliminationComplete; #ifdef ENABLE_FMRADIO - volatile bool gScheduleFM; + volatile bool gScheduleFM; #endif volatile uint8_t boot_counter_10ms; @@ -288,12 +288,12 @@ uint8_t gIsLocked = 0xFF; #ifdef ENABLE_FEAT_F4HWN - bool gK5startup = true; - bool gBackLight = false; - uint8_t gBacklightTimeOriginal; - uint8_t gBacklightBrightnessOld; - uint8_t gPttOnePushCounter = 0; - uint32_t gBlinkCounter = 0; + bool gK5startup = true; + bool gBackLight = false; + uint8_t gBacklightTimeOriginal; + uint8_t gBacklightBrightnessOld; + uint8_t gPttOnePushCounter = 0; + uint32_t gBlinkCounter = 0; #endif inline void FUNCTION_NOP() { ; } @@ -301,25 +301,25 @@ inline void FUNCTION_NOP() { ; } int32_t NUMBER_AddWithWraparound(int32_t Base, int32_t Add, int32_t LowerLimit, int32_t UpperLimit) { - Base += Add; + Base += Add; - if (Base == 0x7fffffff || Base < LowerLimit) - return UpperLimit; + if (Base == 0x7fffffff || Base < LowerLimit) + return UpperLimit; - if (Base > UpperLimit) - return LowerLimit; + if (Base > UpperLimit) + return LowerLimit; - return Base; + return Base; } unsigned long StrToUL(const char * str) { - unsigned long ul = 0; - for(uint8_t i = 0; i < strlen(str); i++){ - char c = str[i]; - if(c < '0' || c > '9') - break; - ul = ul * 10 + (uint8_t)(c-'0'); - } - return ul; + unsigned long ul = 0; + for(uint8_t i = 0; i < strlen(str); i++){ + char c = str[i]; + if(c < '0' || c > '9') + break; + ul = ul * 10 + (uint8_t)(c-'0'); + } + return ul; } diff --git a/misc.h b/misc.h index 4fb8cb08d..854e6e46a 100644 --- a/misc.h +++ b/misc.h @@ -21,19 +21,19 @@ #include #ifndef ARRAY_SIZE - #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) + #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) #endif #ifndef MAX - #define MAX(a, b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a > _b ? _a : _b; }) + #define MAX(a, b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a > _b ? _a : _b; }) #endif #ifndef MIN - #define MIN(a, b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a < _b ? _a : _b; }) + #define MIN(a, b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a < _b ? _a : _b; }) #endif #ifndef SWAP - #define SWAP(a, b) ({ __typeof__ (a) _c = (a); a = b; b = _c; }) + #define SWAP(a, b) ({ __typeof__ (a) _c = (a); a = b; b = _c; }) #endif #define IS_MR_CHANNEL(x) ((x) <= MR_CHANNEL_LAST) @@ -42,41 +42,41 @@ #define IS_NOAA_CHANNEL(x) ((x) >= NOAA_CHANNEL_FIRST && (x) <= NOAA_CHANNEL_LAST) enum { - MR_CHANNEL_FIRST = 0, - MR_CHANNEL_LAST = 199u, - FREQ_CHANNEL_FIRST = 200u, - FREQ_CHANNEL_LAST = 206u, - NOAA_CHANNEL_FIRST = 207u, - NOAA_CHANNEL_LAST = 216u, - LAST_CHANNEL + MR_CHANNEL_FIRST = 0, + MR_CHANNEL_LAST = 199u, + FREQ_CHANNEL_FIRST = 200u, + FREQ_CHANNEL_LAST = 206u, + NOAA_CHANNEL_FIRST = 207u, + NOAA_CHANNEL_LAST = 216u, + LAST_CHANNEL }; enum { - VFO_CONFIGURE_NONE = 0, - VFO_CONFIGURE, - VFO_CONFIGURE_RELOAD + VFO_CONFIGURE_NONE = 0, + VFO_CONFIGURE, + VFO_CONFIGURE_RELOAD }; enum AlarmState_t { - ALARM_STATE_OFF = 0, - ALARM_STATE_TXALARM, - ALARM_STATE_SITE_ALARM, - ALARM_STATE_TX1750 + ALARM_STATE_OFF = 0, + ALARM_STATE_TXALARM, + ALARM_STATE_SITE_ALARM, + ALARM_STATE_TX1750 }; typedef enum AlarmState_t AlarmState_t; enum ReceptionMode_t { - RX_MODE_NONE = 0, // squelch close ? - RX_MODE_DETECTED, // signal detected - RX_MODE_LISTENING // + RX_MODE_NONE = 0, // squelch close ? + RX_MODE_DETECTED, // signal detected + RX_MODE_LISTENING // }; typedef enum ReceptionMode_t ReceptionMode_t; enum BacklightOnRxTx_t { - BACKLIGHT_ON_TR_OFF, - BACKLIGHT_ON_TR_TX, - BACKLIGHT_ON_TR_RX, - BACKLIGHT_ON_TR_TXRX + BACKLIGHT_ON_TR_OFF, + BACKLIGHT_ON_TR_TX, + BACKLIGHT_ON_TR_RX, + BACKLIGHT_ON_TR_TXRX }; extern const uint8_t fm_radio_countdown_500ms; @@ -110,7 +110,7 @@ extern const uint16_t power_save1_10ms; extern const uint16_t power_save2_10ms; #ifdef ENABLE_VOX - extern const uint16_t vox_stop_count_down_10ms; + extern const uint16_t vox_stop_count_down_10ms; #endif extern const uint16_t NOAA_countdown_10ms; @@ -124,7 +124,7 @@ extern const uint16_t dual_watch_count_after_2_10ms; extern const uint16_t dual_watch_count_toggle_10ms; extern const uint16_t dual_watch_count_noaa_10ms; #ifdef ENABLE_VOX - extern const uint16_t dual_watch_count_after_vox_10ms; + extern const uint16_t dual_watch_count_after_vox_10ms; #endif extern const uint16_t scan_pause_delay_in_1_10ms; @@ -153,32 +153,32 @@ extern bool gSetting_ScrambleEnable; extern enum BacklightOnRxTx_t gSetting_backlight_on_tx_rx; #ifdef ENABLE_AM_FIX - extern bool gSetting_AM_fix; + extern bool gSetting_AM_fix; #endif #ifdef ENABLE_FEAT_F4HWN - extern uint8_t gSetting_set_pwr; - extern bool gSetting_set_ptt; - extern uint8_t gSetting_set_tot; - extern uint8_t gSetting_set_ctr; - extern bool gSetting_set_inv; - extern uint8_t gSetting_set_eot; - extern bool gSetting_set_lck; - extern bool gSetting_set_met; - extern bool gSetting_set_gui; - extern bool gSetting_set_tmr; - extern bool gSetting_set_ptt_session; - extern uint8_t gDebug; - extern uint8_t gDW; - extern uint8_t gCB; - extern bool gSaveRxMode; - extern uint8_t crc[15]; - extern uint8_t lErrorsDuringAirCopy; - extern uint8_t gAircopyStep; + extern uint8_t gSetting_set_pwr; + extern bool gSetting_set_ptt; + extern uint8_t gSetting_set_tot; + extern uint8_t gSetting_set_ctr; + extern bool gSetting_set_inv; + extern uint8_t gSetting_set_eot; + extern bool gSetting_set_lck; + extern bool gSetting_set_met; + extern bool gSetting_set_gui; + extern bool gSetting_set_tmr; + extern bool gSetting_set_ptt_session; + extern uint8_t gDebug; + extern uint8_t gDW; + extern uint8_t gCB; + extern bool gSaveRxMode; + extern uint8_t crc[15]; + extern uint8_t lErrorsDuringAirCopy; + extern uint8_t gAircopyStep; #endif #ifdef ENABLE_AUDIO_BAR - extern bool gSetting_mic_bar; + extern bool gSetting_mic_bar; #endif extern bool gSetting_live_DTMF_decoder; extern uint8_t gSetting_battery_text; @@ -229,18 +229,18 @@ extern volatile uint16_t gTxTimerCountdown_500ms; extern volatile bool gTxTimeoutReached; #ifdef ENABLE_FEAT_F4HWN - extern volatile uint16_t gTxTimerCountdownAlert_500ms; - extern volatile bool gTxTimeoutReachedAlert; - extern volatile uint16_t gTxTimeoutToneAlert; - #ifdef ENABLE_FEAT_F4HWN_RX_TX_TIMER - extern volatile uint16_t gRxTimerCountdown_500ms; - #endif + extern volatile uint16_t gTxTimerCountdownAlert_500ms; + extern volatile bool gTxTimeoutReachedAlert; + extern volatile uint16_t gTxTimeoutToneAlert; + #ifdef ENABLE_FEAT_F4HWN_RX_TX_TIMER + extern volatile uint16_t gRxTimerCountdown_500ms; + #endif #endif extern volatile uint16_t gTailNoteEliminationCountdown_10ms; #ifdef ENABLE_NOAA - extern volatile uint16_t gNOAA_Countdown_10ms; + extern volatile uint16_t gNOAA_Countdown_10ms; #endif extern bool gEnableSpeaker; extern uint8_t gKeyInputCountdown; @@ -265,9 +265,9 @@ extern bool gCssBackgroundScan; enum { - SCAN_REV = -1, - SCAN_OFF = 0, - SCAN_FWD = +1 + SCAN_REV = -1, + SCAN_OFF = 0, + SCAN_FWD = +1 }; extern volatile bool gScheduleScanListen; @@ -284,7 +284,7 @@ extern bool gRequestSaveVFO; extern uint8_t gRequestSaveChannel; extern bool gRequestSaveSettings; #ifdef ENABLE_FMRADIO - extern bool gRequestSaveFM; + extern bool gRequestSaveFM; #endif extern uint8_t gKeypadLocked; extern bool gFlagPrepareTX; @@ -293,17 +293,17 @@ extern bool gFlagAcceptSetting; // accept menu setting extern bool gFlagRefreshSetting; // refresh menu display #ifdef ENABLE_FMRADIO - extern bool gFlagSaveFM; + extern bool gFlagSaveFM; #endif extern bool g_CDCSS_Lost; extern uint8_t gCDCSSCodeType; extern bool g_CTCSS_Lost; extern bool g_CxCSS_TAIL_Found; #ifdef ENABLE_VOX - extern bool g_VOX_Lost; - extern bool gVOX_NoiseDetected; - extern uint16_t gVoxResumeCountdown; - extern uint16_t gVoxPauseCountdown; + extern bool g_VOX_Lost; + extern bool gVOX_NoiseDetected; + extern uint16_t gVoxResumeCountdown; + extern uint16_t gVoxPauseCountdown; #endif // true means we are receiving signal @@ -327,41 +327,41 @@ extern uint8_t gBackup_CROSS_BAND_RX_TX; extern uint8_t gScanDelay_10ms; extern uint8_t gFSKWriteIndex; #ifdef ENABLE_NOAA - extern bool gIsNoaaMode; - extern uint8_t gNoaaChannel; + extern bool gIsNoaaMode; + extern uint8_t gNoaaChannel; #endif extern volatile bool gNextTimeslice; extern bool gUpdateDisplay; extern bool gF_LOCK; #ifdef ENABLE_FMRADIO - extern uint8_t gFM_ChannelPosition; + extern uint8_t gFM_ChannelPosition; #endif extern uint8_t gShowChPrefix; extern volatile uint8_t gFoundCDCSSCountdown_10ms; extern volatile uint8_t gFoundCTCSSCountdown_10ms; #ifdef ENABLE_VOX - extern volatile uint16_t gVoxStopCountdown_10ms; + extern volatile uint16_t gVoxStopCountdown_10ms; #endif extern volatile bool gNextTimeslice40ms; #ifdef ENABLE_NOAA - extern volatile uint16_t gNOAACountdown_10ms; - extern volatile bool gScheduleNOAA; + extern volatile uint16_t gNOAACountdown_10ms; + extern volatile bool gScheduleNOAA; #endif extern volatile bool gFlagTailNoteEliminationComplete; extern volatile uint8_t gVFOStateResumeCountdown_500ms; #ifdef ENABLE_FMRADIO - extern volatile bool gScheduleFM; + extern volatile bool gScheduleFM; #endif extern uint8_t gIsLocked; extern volatile uint8_t boot_counter_10ms; #ifdef ENABLE_FEAT_F4HWN - extern bool gK5startup; - extern bool gBackLight; - extern uint8_t gBacklightTimeOriginal; - extern uint8_t gBacklightBrightnessOld; - extern uint8_t gPttOnePushCounter; - extern uint32_t gBlinkCounter; + extern bool gK5startup; + extern bool gBackLight; + extern uint8_t gBacklightTimeOriginal; + extern uint8_t gBacklightBrightnessOld; + extern uint8_t gPttOnePushCounter; + extern uint32_t gBlinkCounter; #endif int32_t NUMBER_AddWithWraparound(int32_t Base, int32_t Add, int32_t LowerLimit, int32_t UpperLimit); diff --git a/radio.c b/radio.c index 634b8935c..517054516 100644 --- a/radio.c +++ b/radio.c @@ -20,7 +20,7 @@ #include "am_fix.h" #include "app/dtmf.h" #ifdef ENABLE_FMRADIO - #include "app/fm.h" + #include "app/fm.h" #endif #include "audio.h" #include "bsp/dp32g030/gpio.h" @@ -44,1156 +44,1156 @@ DCS_CodeType_t gCurrentCodeType; VfoState_t VfoState[2]; const char gModulationStr[MODULATION_UKNOWN][4] = { - [MODULATION_FM]="FM", - [MODULATION_AM]="AM", - [MODULATION_USB]="USB", + [MODULATION_FM]="FM", + [MODULATION_AM]="AM", + [MODULATION_USB]="USB", #ifdef ENABLE_BYP_RAW_DEMODULATORS - [MODULATION_BYP]="BYP", - [MODULATION_RAW]="RAW" + [MODULATION_BYP]="BYP", + [MODULATION_RAW]="RAW" #endif }; bool RADIO_CheckValidChannel(uint16_t channel, bool checkScanList, uint8_t scanList) { - // return true if the channel appears valid - if (!IS_MR_CHANNEL(channel)) - return false; - - const ChannelAttributes_t att = gMR_ChannelAttributes[channel]; - - if (checkScanList && gMR_ChannelExclude[channel] == true) - return false; - - if (att.band > BAND7_470MHz) - return false; - - if (!checkScanList || scanList > 4) - return true; - - /* - if(scanList == 0 && (att.scanlist1 == 1 || att.scanlist2 == 1 || att.scanlist3 == 1)) - { - return false; - } - else if(scanList == 1 && att.scanlist1 != 1) - { - return false; - } - else if(scanList == 2 && att.scanlist2 != 1) - { - return false; - } - else if(scanList == 3 && att.scanlist3 != 1) - { - return false; - } - else if(scanList == 4 && (att.scanlist1 == 0 && att.scanlist2 == 0 && att.scanlist3 == 0)) - { - return false; - } - */ - - if ((scanList == 0 && (att.scanlist1 == 1 || att.scanlist2 == 1 || att.scanlist3 == 1)) || - (scanList == 1 && att.scanlist1 != 1) || - (scanList == 2 && att.scanlist2 != 1) || - (scanList == 3 && att.scanlist3 != 1) || - (scanList == 4 && (att.scanlist1 == 0 && att.scanlist2 == 0 && att.scanlist3 == 0))) { - return false; - } - - //return true; - - // I don't understand what this code is for... - - const uint8_t PriorityCh1 = gEeprom.SCANLIST_PRIORITY_CH1[scanList - 1]; - const uint8_t PriorityCh2 = gEeprom.SCANLIST_PRIORITY_CH2[scanList - 1]; - - return PriorityCh1 != channel && PriorityCh2 != channel; + // return true if the channel appears valid + if (!IS_MR_CHANNEL(channel)) + return false; + + const ChannelAttributes_t att = gMR_ChannelAttributes[channel]; + + if (checkScanList && gMR_ChannelExclude[channel] == true) + return false; + + if (att.band > BAND7_470MHz) + return false; + + if (!checkScanList || scanList > 4) + return true; + + /* + if(scanList == 0 && (att.scanlist1 == 1 || att.scanlist2 == 1 || att.scanlist3 == 1)) + { + return false; + } + else if(scanList == 1 && att.scanlist1 != 1) + { + return false; + } + else if(scanList == 2 && att.scanlist2 != 1) + { + return false; + } + else if(scanList == 3 && att.scanlist3 != 1) + { + return false; + } + else if(scanList == 4 && (att.scanlist1 == 0 && att.scanlist2 == 0 && att.scanlist3 == 0)) + { + return false; + } + */ + + if ((scanList == 0 && (att.scanlist1 == 1 || att.scanlist2 == 1 || att.scanlist3 == 1)) || + (scanList == 1 && att.scanlist1 != 1) || + (scanList == 2 && att.scanlist2 != 1) || + (scanList == 3 && att.scanlist3 != 1) || + (scanList == 4 && (att.scanlist1 == 0 && att.scanlist2 == 0 && att.scanlist3 == 0))) { + return false; + } + + //return true; + + // I don't understand what this code is for... + + const uint8_t PriorityCh1 = gEeprom.SCANLIST_PRIORITY_CH1[scanList - 1]; + const uint8_t PriorityCh2 = gEeprom.SCANLIST_PRIORITY_CH2[scanList - 1]; + + return PriorityCh1 != channel && PriorityCh2 != channel; } uint8_t RADIO_FindNextChannel(uint8_t Channel, int8_t Direction, bool bCheckScanList, uint8_t VFO) { - for (unsigned int i = 0; IS_MR_CHANNEL(i); i++, Channel += Direction) { - if (Channel == 0xFF) { - Channel = MR_CHANNEL_LAST; - } else if (!IS_MR_CHANNEL(Channel)) { - Channel = MR_CHANNEL_FIRST; - } - - if (RADIO_CheckValidChannel(Channel, bCheckScanList, VFO)) { - return Channel; - } - } - - return 0xFF; + for (unsigned int i = 0; IS_MR_CHANNEL(i); i++, Channel += Direction) { + if (Channel == 0xFF) { + Channel = MR_CHANNEL_LAST; + } else if (!IS_MR_CHANNEL(Channel)) { + Channel = MR_CHANNEL_FIRST; + } + + if (RADIO_CheckValidChannel(Channel, bCheckScanList, VFO)) { + return Channel; + } + } + + return 0xFF; } void RADIO_InitInfo(VFO_Info_t *pInfo, const uint8_t ChannelSave, const uint32_t Frequency) { - memset(pInfo, 0, sizeof(*pInfo)); - - pInfo->Band = FREQUENCY_GetBand(Frequency); - pInfo->SCANLIST1_PARTICIPATION = false; - pInfo->SCANLIST2_PARTICIPATION = false; - pInfo->SCANLIST3_PARTICIPATION = false; - pInfo->STEP_SETTING = STEP_12_5kHz; - pInfo->StepFrequency = gStepFrequencyTable[pInfo->STEP_SETTING]; - pInfo->CHANNEL_SAVE = ChannelSave; - pInfo->FrequencyReverse = false; - pInfo->TX_LOCK = true; - pInfo->OUTPUT_POWER = OUTPUT_POWER_LOW1; - pInfo->freq_config_RX.Frequency = Frequency; - pInfo->freq_config_TX.Frequency = Frequency; - pInfo->pRX = &pInfo->freq_config_RX; - pInfo->pTX = &pInfo->freq_config_TX; - pInfo->Compander = 0; // off - - if (ChannelSave == (FREQ_CHANNEL_FIRST + BAND2_108MHz)) - pInfo->Modulation = MODULATION_AM; - else - pInfo->Modulation = MODULATION_FM; - - RADIO_ConfigureSquelchAndOutputPower(pInfo); + memset(pInfo, 0, sizeof(*pInfo)); + + pInfo->Band = FREQUENCY_GetBand(Frequency); + pInfo->SCANLIST1_PARTICIPATION = false; + pInfo->SCANLIST2_PARTICIPATION = false; + pInfo->SCANLIST3_PARTICIPATION = false; + pInfo->STEP_SETTING = STEP_12_5kHz; + pInfo->StepFrequency = gStepFrequencyTable[pInfo->STEP_SETTING]; + pInfo->CHANNEL_SAVE = ChannelSave; + pInfo->FrequencyReverse = false; + pInfo->TX_LOCK = true; + pInfo->OUTPUT_POWER = OUTPUT_POWER_LOW1; + pInfo->freq_config_RX.Frequency = Frequency; + pInfo->freq_config_TX.Frequency = Frequency; + pInfo->pRX = &pInfo->freq_config_RX; + pInfo->pTX = &pInfo->freq_config_TX; + pInfo->Compander = 0; // off + + if (ChannelSave == (FREQ_CHANNEL_FIRST + BAND2_108MHz)) + pInfo->Modulation = MODULATION_AM; + else + pInfo->Modulation = MODULATION_FM; + + RADIO_ConfigureSquelchAndOutputPower(pInfo); } void RADIO_ConfigureChannel(const unsigned int VFO, const unsigned int configure) { - VFO_Info_t *pVfo = &gEeprom.VfoInfo[VFO]; + VFO_Info_t *pVfo = &gEeprom.VfoInfo[VFO]; - if (!gSetting_350EN) { - if (gEeprom.FreqChannel[VFO] == FREQ_CHANNEL_FIRST + BAND5_350MHz) - gEeprom.FreqChannel[VFO] = FREQ_CHANNEL_FIRST + BAND6_400MHz; + if (!gSetting_350EN) { + if (gEeprom.FreqChannel[VFO] == FREQ_CHANNEL_FIRST + BAND5_350MHz) + gEeprom.FreqChannel[VFO] = FREQ_CHANNEL_FIRST + BAND6_400MHz; - if (gEeprom.ScreenChannel[VFO] == FREQ_CHANNEL_FIRST + BAND5_350MHz) - gEeprom.ScreenChannel[VFO] = FREQ_CHANNEL_FIRST + BAND6_400MHz; - } + if (gEeprom.ScreenChannel[VFO] == FREQ_CHANNEL_FIRST + BAND5_350MHz) + gEeprom.ScreenChannel[VFO] = FREQ_CHANNEL_FIRST + BAND6_400MHz; + } - uint8_t channel = gEeprom.ScreenChannel[VFO]; + uint8_t channel = gEeprom.ScreenChannel[VFO]; - if (IS_VALID_CHANNEL(channel)) { + if (IS_VALID_CHANNEL(channel)) { #ifdef ENABLE_NOAA - if (IS_NOAA_CHANNEL(channel)) - { - RADIO_InitInfo(pVfo, gEeprom.ScreenChannel[VFO], NoaaFrequencyTable[channel - NOAA_CHANNEL_FIRST]); + if (IS_NOAA_CHANNEL(channel)) + { + RADIO_InitInfo(pVfo, gEeprom.ScreenChannel[VFO], NoaaFrequencyTable[channel - NOAA_CHANNEL_FIRST]); - if (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF) - return; + if (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF) + return; - gEeprom.CROSS_BAND_RX_TX = CROSS_BAND_OFF; + gEeprom.CROSS_BAND_RX_TX = CROSS_BAND_OFF; - gUpdateStatus = true; - return; - } + gUpdateStatus = true; + return; + } #endif - if (IS_MR_CHANNEL(channel)) { - channel = RADIO_FindNextChannel(channel, RADIO_CHANNEL_UP, false, VFO); - if (channel == 0xFF) { - channel = gEeprom.FreqChannel[VFO]; - gEeprom.ScreenChannel[VFO] = gEeprom.FreqChannel[VFO]; - } - else { - gEeprom.ScreenChannel[VFO] = channel; - gEeprom.MrChannel[VFO] = channel; - } - } - } - else - channel = FREQ_CHANNEL_LAST - 1; - - ChannelAttributes_t att = gMR_ChannelAttributes[channel]; - if (att.__val == 0xFF) { // invalid/unused channel - if (IS_MR_CHANNEL(channel)) { - channel = gEeprom.FreqChannel[VFO]; - gEeprom.ScreenChannel[VFO] = channel; - } - - uint8_t bandIdx = channel - FREQ_CHANNEL_FIRST; - RADIO_InitInfo(pVfo, channel, frequencyBandTable[bandIdx].lower); - return; - } - - uint8_t band = att.band; - if (band > BAND7_470MHz) { - band = BAND6_400MHz; - } - - bool bParticipation1; - bool bParticipation2; - bool bParticipation3; - - if (IS_MR_CHANNEL(channel)) { - bParticipation1 = att.scanlist1; - bParticipation2 = att.scanlist2; - bParticipation3 = att.scanlist3; - } - else { - band = channel - FREQ_CHANNEL_FIRST; - bParticipation1 = true; - bParticipation2 = true; - bParticipation3 = true; - } - - pVfo->Band = band; - pVfo->SCANLIST1_PARTICIPATION = bParticipation1; - pVfo->SCANLIST2_PARTICIPATION = bParticipation2; - pVfo->SCANLIST3_PARTICIPATION = bParticipation3; - pVfo->CHANNEL_SAVE = channel; - - uint16_t base; - if (IS_MR_CHANNEL(channel)) - base = channel * 16; - else - base = 0x0C80 + ((channel - FREQ_CHANNEL_FIRST) * 32) + (VFO * 16); - - if (configure == VFO_CONFIGURE_RELOAD || IS_FREQ_CHANNEL(channel)) - { - uint8_t tmp; - uint8_t data[8]; - - // *************** - - EEPROM_ReadBuffer(base + 8, data, sizeof(data)); - - tmp = data[3] & 0x0F; - if (tmp > TX_OFFSET_FREQUENCY_DIRECTION_SUB) - tmp = 0; - pVfo->TX_OFFSET_FREQUENCY_DIRECTION = tmp; - tmp = data[3] >> 4; - if (tmp >= MODULATION_UKNOWN) - tmp = MODULATION_FM; - pVfo->Modulation = tmp; - - tmp = data[6]; - if (tmp >= STEP_N_ELEM) - tmp = STEP_12_5kHz; - pVfo->STEP_SETTING = tmp; - pVfo->StepFrequency = gStepFrequencyTable[tmp]; - - tmp = data[7]; + if (IS_MR_CHANNEL(channel)) { + channel = RADIO_FindNextChannel(channel, RADIO_CHANNEL_UP, false, VFO); + if (channel == 0xFF) { + channel = gEeprom.FreqChannel[VFO]; + gEeprom.ScreenChannel[VFO] = gEeprom.FreqChannel[VFO]; + } + else { + gEeprom.ScreenChannel[VFO] = channel; + gEeprom.MrChannel[VFO] = channel; + } + } + } + else + channel = FREQ_CHANNEL_LAST - 1; + + ChannelAttributes_t att = gMR_ChannelAttributes[channel]; + if (att.__val == 0xFF) { // invalid/unused channel + if (IS_MR_CHANNEL(channel)) { + channel = gEeprom.FreqChannel[VFO]; + gEeprom.ScreenChannel[VFO] = channel; + } + + uint8_t bandIdx = channel - FREQ_CHANNEL_FIRST; + RADIO_InitInfo(pVfo, channel, frequencyBandTable[bandIdx].lower); + return; + } + + uint8_t band = att.band; + if (band > BAND7_470MHz) { + band = BAND6_400MHz; + } + + bool bParticipation1; + bool bParticipation2; + bool bParticipation3; + + if (IS_MR_CHANNEL(channel)) { + bParticipation1 = att.scanlist1; + bParticipation2 = att.scanlist2; + bParticipation3 = att.scanlist3; + } + else { + band = channel - FREQ_CHANNEL_FIRST; + bParticipation1 = true; + bParticipation2 = true; + bParticipation3 = true; + } + + pVfo->Band = band; + pVfo->SCANLIST1_PARTICIPATION = bParticipation1; + pVfo->SCANLIST2_PARTICIPATION = bParticipation2; + pVfo->SCANLIST3_PARTICIPATION = bParticipation3; + pVfo->CHANNEL_SAVE = channel; + + uint16_t base; + if (IS_MR_CHANNEL(channel)) + base = channel * 16; + else + base = 0x0C80 + ((channel - FREQ_CHANNEL_FIRST) * 32) + (VFO * 16); + + if (configure == VFO_CONFIGURE_RELOAD || IS_FREQ_CHANNEL(channel)) + { + uint8_t tmp; + uint8_t data[8]; + + // *************** + + EEPROM_ReadBuffer(base + 8, data, sizeof(data)); + + tmp = data[3] & 0x0F; + if (tmp > TX_OFFSET_FREQUENCY_DIRECTION_SUB) + tmp = 0; + pVfo->TX_OFFSET_FREQUENCY_DIRECTION = tmp; + tmp = data[3] >> 4; + if (tmp >= MODULATION_UKNOWN) + tmp = MODULATION_FM; + pVfo->Modulation = tmp; + + tmp = data[6]; + if (tmp >= STEP_N_ELEM) + tmp = STEP_12_5kHz; + pVfo->STEP_SETTING = tmp; + pVfo->StepFrequency = gStepFrequencyTable[tmp]; + + tmp = data[7]; #ifndef ENABLE_FEAT_F4HWN - if (tmp > (ARRAY_SIZE(gSubMenu_SCRAMBLER) - 1)) - tmp = 0; - pVfo->SCRAMBLING_TYPE = tmp; + if (tmp > (ARRAY_SIZE(gSubMenu_SCRAMBLER) - 1)) + tmp = 0; + pVfo->SCRAMBLING_TYPE = tmp; #else - pVfo->SCRAMBLING_TYPE = 0; + pVfo->SCRAMBLING_TYPE = 0; #endif - pVfo->freq_config_RX.CodeType = (data[2] >> 0) & 0x0F; - pVfo->freq_config_TX.CodeType = (data[2] >> 4) & 0x0F; - - tmp = data[0]; - switch (pVfo->freq_config_RX.CodeType) - { - default: - case CODE_TYPE_OFF: - pVfo->freq_config_RX.CodeType = CODE_TYPE_OFF; - tmp = 0; - break; - - case CODE_TYPE_CONTINUOUS_TONE: - if (tmp > (ARRAY_SIZE(CTCSS_Options) - 1)) - tmp = 0; - break; - - case CODE_TYPE_DIGITAL: - case CODE_TYPE_REVERSE_DIGITAL: - if (tmp > (ARRAY_SIZE(DCS_Options) - 1)) - tmp = 0; - break; - } - pVfo->freq_config_RX.Code = tmp; - - tmp = data[1]; - switch (pVfo->freq_config_TX.CodeType) - { - default: - case CODE_TYPE_OFF: - pVfo->freq_config_TX.CodeType = CODE_TYPE_OFF; - tmp = 0; - break; - - case CODE_TYPE_CONTINUOUS_TONE: - if (tmp > (ARRAY_SIZE(CTCSS_Options) - 1)) - tmp = 0; - break; - - case CODE_TYPE_DIGITAL: - case CODE_TYPE_REVERSE_DIGITAL: - if (tmp > (ARRAY_SIZE(DCS_Options) - 1)) - tmp = 0; - break; - } - pVfo->freq_config_TX.Code = tmp; - - if (data[4] == 0xFF) - { - pVfo->FrequencyReverse = false; - pVfo->CHANNEL_BANDWIDTH = BK4819_FILTER_BW_WIDE; - pVfo->OUTPUT_POWER = OUTPUT_POWER_LOW1; - pVfo->BUSY_CHANNEL_LOCK = false; - pVfo->TX_LOCK = true; - } - else - { - const uint8_t d4 = data[4]; - pVfo->FrequencyReverse = !!((d4 >> 0) & 1u); - pVfo->CHANNEL_BANDWIDTH = !!((d4 >> 1) & 1u); - pVfo->OUTPUT_POWER = ((d4 >> 2) & 7u); - pVfo->BUSY_CHANNEL_LOCK = !!((d4 >> 5) & 1u); - pVfo->TX_LOCK = !!((d4 >> 6) & 1u); - } - - if (data[5] == 0xFF) - { + pVfo->freq_config_RX.CodeType = (data[2] >> 0) & 0x0F; + pVfo->freq_config_TX.CodeType = (data[2] >> 4) & 0x0F; + + tmp = data[0]; + switch (pVfo->freq_config_RX.CodeType) + { + default: + case CODE_TYPE_OFF: + pVfo->freq_config_RX.CodeType = CODE_TYPE_OFF; + tmp = 0; + break; + + case CODE_TYPE_CONTINUOUS_TONE: + if (tmp > (ARRAY_SIZE(CTCSS_Options) - 1)) + tmp = 0; + break; + + case CODE_TYPE_DIGITAL: + case CODE_TYPE_REVERSE_DIGITAL: + if (tmp > (ARRAY_SIZE(DCS_Options) - 1)) + tmp = 0; + break; + } + pVfo->freq_config_RX.Code = tmp; + + tmp = data[1]; + switch (pVfo->freq_config_TX.CodeType) + { + default: + case CODE_TYPE_OFF: + pVfo->freq_config_TX.CodeType = CODE_TYPE_OFF; + tmp = 0; + break; + + case CODE_TYPE_CONTINUOUS_TONE: + if (tmp > (ARRAY_SIZE(CTCSS_Options) - 1)) + tmp = 0; + break; + + case CODE_TYPE_DIGITAL: + case CODE_TYPE_REVERSE_DIGITAL: + if (tmp > (ARRAY_SIZE(DCS_Options) - 1)) + tmp = 0; + break; + } + pVfo->freq_config_TX.Code = tmp; + + if (data[4] == 0xFF) + { + pVfo->FrequencyReverse = false; + pVfo->CHANNEL_BANDWIDTH = BK4819_FILTER_BW_WIDE; + pVfo->OUTPUT_POWER = OUTPUT_POWER_LOW1; + pVfo->BUSY_CHANNEL_LOCK = false; + pVfo->TX_LOCK = true; + } + else + { + const uint8_t d4 = data[4]; + pVfo->FrequencyReverse = !!((d4 >> 0) & 1u); + pVfo->CHANNEL_BANDWIDTH = !!((d4 >> 1) & 1u); + pVfo->OUTPUT_POWER = ((d4 >> 2) & 7u); + pVfo->BUSY_CHANNEL_LOCK = !!((d4 >> 5) & 1u); + pVfo->TX_LOCK = !!((d4 >> 6) & 1u); + } + + if (data[5] == 0xFF) + { #ifdef ENABLE_DTMF_CALLING - pVfo->DTMF_DECODING_ENABLE = false; + pVfo->DTMF_DECODING_ENABLE = false; #endif - pVfo->DTMF_PTT_ID_TX_MODE = PTT_ID_OFF; - } - else - { + pVfo->DTMF_PTT_ID_TX_MODE = PTT_ID_OFF; + } + else + { #ifdef ENABLE_DTMF_CALLING - pVfo->DTMF_DECODING_ENABLE = ((data[5] >> 0) & 1u) ? true : false; + pVfo->DTMF_DECODING_ENABLE = ((data[5] >> 0) & 1u) ? true : false; #endif - uint8_t pttId = ((data[5] >> 1) & 7u); - pVfo->DTMF_PTT_ID_TX_MODE = pttId < ARRAY_SIZE(gSubMenu_PTT_ID) ? pttId : PTT_ID_OFF; - } - - // *************** - - struct { - uint32_t Frequency; - uint32_t Offset; - } __attribute__((packed)) info; - EEPROM_ReadBuffer(base, &info, sizeof(info)); - if(info.Frequency==0xFFFFFFFF) - pVfo->freq_config_RX.Frequency = frequencyBandTable[band].lower; - else - pVfo->freq_config_RX.Frequency = info.Frequency; - - if (info.Offset >= _1GHz_in_KHz) - info.Offset = _1GHz_in_KHz / 100; - - pVfo->TX_OFFSET_FREQUENCY = info.Offset; - - // *************** - } - - uint32_t frequency = pVfo->freq_config_RX.Frequency; - - // fix previously set incorrect band - band = FREQUENCY_GetBand(frequency); - - if (frequency < frequencyBandTable[band].lower) - frequency = frequencyBandTable[band].lower; - else if (frequency > frequencyBandTable[band].upper) - frequency = frequencyBandTable[band].upper; - else if (channel >= FREQ_CHANNEL_FIRST) - frequency = FREQUENCY_RoundToStep(frequency, pVfo->StepFrequency); - - pVfo->freq_config_RX.Frequency = frequency; - - if (frequency >= frequencyBandTable[BAND2_108MHz].upper && frequency < frequencyBandTable[BAND2_108MHz].upper) - pVfo->TX_OFFSET_FREQUENCY_DIRECTION = TX_OFFSET_FREQUENCY_DIRECTION_OFF; - else if (!IS_MR_CHANNEL(channel)) - pVfo->TX_OFFSET_FREQUENCY = FREQUENCY_RoundToStep(pVfo->TX_OFFSET_FREQUENCY, pVfo->StepFrequency); - - RADIO_ApplyOffset(pVfo); - - if (IS_MR_CHANNEL(channel)) - { // 16 bytes allocated to the channel name but only 10 used, the rest are 0's - SETTINGS_FetchChannelName(pVfo->Name, channel); - } - - if (!pVfo->FrequencyReverse) - { - pVfo->pRX = &pVfo->freq_config_RX; - pVfo->pTX = &pVfo->freq_config_TX; - } - else - { - pVfo->pRX = &pVfo->freq_config_TX; - pVfo->pTX = &pVfo->freq_config_RX; - } - - if (!gSetting_350EN) - { - FREQ_Config_t *pConfig = pVfo->pRX; - if (pConfig->Frequency >= 35000000 && pConfig->Frequency < 40000000) - pConfig->Frequency = 43300000; - } - - pVfo->Compander = att.compander; - - RADIO_ConfigureSquelchAndOutputPower(pVfo); + uint8_t pttId = ((data[5] >> 1) & 7u); + pVfo->DTMF_PTT_ID_TX_MODE = pttId < ARRAY_SIZE(gSubMenu_PTT_ID) ? pttId : PTT_ID_OFF; + } + + // *************** + + struct { + uint32_t Frequency; + uint32_t Offset; + } __attribute__((packed)) info; + EEPROM_ReadBuffer(base, &info, sizeof(info)); + if(info.Frequency==0xFFFFFFFF) + pVfo->freq_config_RX.Frequency = frequencyBandTable[band].lower; + else + pVfo->freq_config_RX.Frequency = info.Frequency; + + if (info.Offset >= _1GHz_in_KHz) + info.Offset = _1GHz_in_KHz / 100; + + pVfo->TX_OFFSET_FREQUENCY = info.Offset; + + // *************** + } + + uint32_t frequency = pVfo->freq_config_RX.Frequency; + + // fix previously set incorrect band + band = FREQUENCY_GetBand(frequency); + + if (frequency < frequencyBandTable[band].lower) + frequency = frequencyBandTable[band].lower; + else if (frequency > frequencyBandTable[band].upper) + frequency = frequencyBandTable[band].upper; + else if (channel >= FREQ_CHANNEL_FIRST) + frequency = FREQUENCY_RoundToStep(frequency, pVfo->StepFrequency); + + pVfo->freq_config_RX.Frequency = frequency; + + if (frequency >= frequencyBandTable[BAND2_108MHz].upper && frequency < frequencyBandTable[BAND2_108MHz].upper) + pVfo->TX_OFFSET_FREQUENCY_DIRECTION = TX_OFFSET_FREQUENCY_DIRECTION_OFF; + else if (!IS_MR_CHANNEL(channel)) + pVfo->TX_OFFSET_FREQUENCY = FREQUENCY_RoundToStep(pVfo->TX_OFFSET_FREQUENCY, pVfo->StepFrequency); + + RADIO_ApplyOffset(pVfo); + + if (IS_MR_CHANNEL(channel)) + { // 16 bytes allocated to the channel name but only 10 used, the rest are 0's + SETTINGS_FetchChannelName(pVfo->Name, channel); + } + + if (!pVfo->FrequencyReverse) + { + pVfo->pRX = &pVfo->freq_config_RX; + pVfo->pTX = &pVfo->freq_config_TX; + } + else + { + pVfo->pRX = &pVfo->freq_config_TX; + pVfo->pTX = &pVfo->freq_config_RX; + } + + if (!gSetting_350EN) + { + FREQ_Config_t *pConfig = pVfo->pRX; + if (pConfig->Frequency >= 35000000 && pConfig->Frequency < 40000000) + pConfig->Frequency = 43300000; + } + + pVfo->Compander = att.compander; + + RADIO_ConfigureSquelchAndOutputPower(pVfo); } void RADIO_ConfigureSquelchAndOutputPower(VFO_Info_t *pInfo) { - // ******************************* - // squelch + // ******************************* + // squelch - FREQUENCY_Band_t Band = FREQUENCY_GetBand(pInfo->pRX->Frequency); - uint16_t Base = (Band < BAND4_174MHz) ? 0x1E60 : 0x1E00; + FREQUENCY_Band_t Band = FREQUENCY_GetBand(pInfo->pRX->Frequency); + uint16_t Base = (Band < BAND4_174MHz) ? 0x1E60 : 0x1E00; - if (gEeprom.SQUELCH_LEVEL == 0) - { // squelch == 0 (off) - pInfo->SquelchOpenRSSIThresh = 0; // 0 ~ 255 - pInfo->SquelchOpenNoiseThresh = 127; // 127 ~ 0 - pInfo->SquelchCloseGlitchThresh = 255; // 255 ~ 0 + if (gEeprom.SQUELCH_LEVEL == 0) + { // squelch == 0 (off) + pInfo->SquelchOpenRSSIThresh = 0; // 0 ~ 255 + pInfo->SquelchOpenNoiseThresh = 127; // 127 ~ 0 + pInfo->SquelchCloseGlitchThresh = 255; // 255 ~ 0 - pInfo->SquelchCloseRSSIThresh = 0; // 0 ~ 255 - pInfo->SquelchCloseNoiseThresh = 127; // 127 ~ 0 - pInfo->SquelchOpenGlitchThresh = 255; // 255 ~ 0 - } - else - { // squelch >= 1 - Base += gEeprom.SQUELCH_LEVEL; // my eeprom squelch-1 - // VHF UHF - EEPROM_ReadBuffer(Base + 0x00, &pInfo->SquelchOpenRSSIThresh, 1); // 50 10 - EEPROM_ReadBuffer(Base + 0x10, &pInfo->SquelchCloseRSSIThresh, 1); // 40 5 + pInfo->SquelchCloseRSSIThresh = 0; // 0 ~ 255 + pInfo->SquelchCloseNoiseThresh = 127; // 127 ~ 0 + pInfo->SquelchOpenGlitchThresh = 255; // 255 ~ 0 + } + else + { // squelch >= 1 + Base += gEeprom.SQUELCH_LEVEL; // my eeprom squelch-1 + // VHF UHF + EEPROM_ReadBuffer(Base + 0x00, &pInfo->SquelchOpenRSSIThresh, 1); // 50 10 + EEPROM_ReadBuffer(Base + 0x10, &pInfo->SquelchCloseRSSIThresh, 1); // 40 5 - EEPROM_ReadBuffer(Base + 0x20, &pInfo->SquelchOpenNoiseThresh, 1); // 65 90 - EEPROM_ReadBuffer(Base + 0x30, &pInfo->SquelchCloseNoiseThresh, 1); // 70 100 + EEPROM_ReadBuffer(Base + 0x20, &pInfo->SquelchOpenNoiseThresh, 1); // 65 90 + EEPROM_ReadBuffer(Base + 0x30, &pInfo->SquelchCloseNoiseThresh, 1); // 70 100 - EEPROM_ReadBuffer(Base + 0x40, &pInfo->SquelchCloseGlitchThresh, 1); // 90 90 - EEPROM_ReadBuffer(Base + 0x50, &pInfo->SquelchOpenGlitchThresh, 1); // 100 100 + EEPROM_ReadBuffer(Base + 0x40, &pInfo->SquelchCloseGlitchThresh, 1); // 90 90 + EEPROM_ReadBuffer(Base + 0x50, &pInfo->SquelchOpenGlitchThresh, 1); // 100 100 - uint16_t noise_open = pInfo->SquelchOpenNoiseThresh; - uint16_t noise_close = pInfo->SquelchCloseNoiseThresh; + uint16_t noise_open = pInfo->SquelchOpenNoiseThresh; + uint16_t noise_close = pInfo->SquelchCloseNoiseThresh; #if ENABLE_SQUELCH_MORE_SENSITIVE - uint16_t rssi_open = pInfo->SquelchOpenRSSIThresh; - uint16_t rssi_close = pInfo->SquelchCloseRSSIThresh; - uint16_t glitch_open = pInfo->SquelchOpenGlitchThresh; - uint16_t glitch_close = pInfo->SquelchCloseGlitchThresh; - // make squelch more sensitive - // note that 'noise' and 'glitch' values are inverted compared to 'rssi' values - rssi_open = (rssi_open * 1) / 2; - noise_open = (noise_open * 2) / 1; - glitch_open = (glitch_open * 2) / 1; - - // ensure the 'close' threshold is lower than the 'open' threshold - if (rssi_close == rssi_open && rssi_close >= 2) - rssi_close -= 2; - if (noise_close == noise_open && noise_close <= 125) - noise_close += 2; - if (glitch_close == glitch_open && glitch_close <= 253) - glitch_close += 2; - - pInfo->SquelchOpenRSSIThresh = (rssi_open > 255) ? 255 : rssi_open; - pInfo->SquelchCloseRSSIThresh = (rssi_close > 255) ? 255 : rssi_close; - pInfo->SquelchOpenGlitchThresh = (glitch_open > 255) ? 255 : glitch_open; - pInfo->SquelchCloseGlitchThresh = (glitch_close > 255) ? 255 : glitch_close; + uint16_t rssi_open = pInfo->SquelchOpenRSSIThresh; + uint16_t rssi_close = pInfo->SquelchCloseRSSIThresh; + uint16_t glitch_open = pInfo->SquelchOpenGlitchThresh; + uint16_t glitch_close = pInfo->SquelchCloseGlitchThresh; + // make squelch more sensitive + // note that 'noise' and 'glitch' values are inverted compared to 'rssi' values + rssi_open = (rssi_open * 1) / 2; + noise_open = (noise_open * 2) / 1; + glitch_open = (glitch_open * 2) / 1; + + // ensure the 'close' threshold is lower than the 'open' threshold + if (rssi_close == rssi_open && rssi_close >= 2) + rssi_close -= 2; + if (noise_close == noise_open && noise_close <= 125) + noise_close += 2; + if (glitch_close == glitch_open && glitch_close <= 253) + glitch_close += 2; + + pInfo->SquelchOpenRSSIThresh = (rssi_open > 255) ? 255 : rssi_open; + pInfo->SquelchCloseRSSIThresh = (rssi_close > 255) ? 255 : rssi_close; + pInfo->SquelchOpenGlitchThresh = (glitch_open > 255) ? 255 : glitch_open; + pInfo->SquelchCloseGlitchThresh = (glitch_close > 255) ? 255 : glitch_close; #endif - pInfo->SquelchOpenNoiseThresh = (noise_open > 127) ? 127 : noise_open; - pInfo->SquelchCloseNoiseThresh = (noise_close > 127) ? 127 : noise_close; - } - - // ******************************* - // output power - - Band = FREQUENCY_GetBand(pInfo->pTX->Frequency); - - // my eeprom calibration data - // - // 1ED0 32 32 32 64 64 64 8c 8c 8c ff ff ff ff ff ff ff 50 MHz - // 1EE0 32 32 32 64 64 64 8c 8c 8c ff ff ff ff ff ff ff 108 MHz - // 1EF0 5f 5f 5f 69 69 69 87 87 87 ff ff ff ff ff ff ff 137 MHz - // 1F00 32 32 32 64 64 64 8c 8c 8c ff ff ff ff ff ff ff 174 MHz - // 1F10 5f 5f 5f 69 69 69 87 87 87 ff ff ff ff ff ff ff 350 MHz - // 1F20 5f 5f 5f 69 69 69 87 87 87 ff ff ff ff ff ff ff 400 MHz - // 1F30 32 32 32 64 64 64 8c 8c 8c ff ff ff ff ff ff ff 470 MHz - - uint8_t Txp[3]; - uint8_t Op = 0; // Low eeprom calibration data - uint8_t currentPower = pInfo->OUTPUT_POWER; - - if(currentPower == OUTPUT_POWER_USER) - { - if(gSetting_set_pwr == 5) - { - Op = 1; // Mid eeprom calibration data - } - else if(gSetting_set_pwr == 6) - { - Op = 2; // High eeprom calibration data - } - currentPower = gSetting_set_pwr; - } - else - { - if (currentPower == OUTPUT_POWER_MID) - { - Op = 1; // Mid eeprom calibration data - } - else if(currentPower == OUTPUT_POWER_HIGH) - { - Op = 2; // High eeprom calibration data - } - currentPower--; - } - - EEPROM_ReadBuffer(0x1ED0 + (Band * 16) + (Op * 3), Txp, 3); + pInfo->SquelchOpenNoiseThresh = (noise_open > 127) ? 127 : noise_open; + pInfo->SquelchCloseNoiseThresh = (noise_close > 127) ? 127 : noise_close; + } + + // ******************************* + // output power + + Band = FREQUENCY_GetBand(pInfo->pTX->Frequency); + + // my eeprom calibration data + // + // 1ED0 32 32 32 64 64 64 8c 8c 8c ff ff ff ff ff ff ff 50 MHz + // 1EE0 32 32 32 64 64 64 8c 8c 8c ff ff ff ff ff ff ff 108 MHz + // 1EF0 5f 5f 5f 69 69 69 87 87 87 ff ff ff ff ff ff ff 137 MHz + // 1F00 32 32 32 64 64 64 8c 8c 8c ff ff ff ff ff ff ff 174 MHz + // 1F10 5f 5f 5f 69 69 69 87 87 87 ff ff ff ff ff ff ff 350 MHz + // 1F20 5f 5f 5f 69 69 69 87 87 87 ff ff ff ff ff ff ff 400 MHz + // 1F30 32 32 32 64 64 64 8c 8c 8c ff ff ff ff ff ff ff 470 MHz + + uint8_t Txp[3]; + uint8_t Op = 0; // Low eeprom calibration data + uint8_t currentPower = pInfo->OUTPUT_POWER; + + if(currentPower == OUTPUT_POWER_USER) + { + if(gSetting_set_pwr == 5) + { + Op = 1; // Mid eeprom calibration data + } + else if(gSetting_set_pwr == 6) + { + Op = 2; // High eeprom calibration data + } + currentPower = gSetting_set_pwr; + } + else + { + if (currentPower == OUTPUT_POWER_MID) + { + Op = 1; // Mid eeprom calibration data + } + else if(currentPower == OUTPUT_POWER_HIGH) + { + Op = 2; // High eeprom calibration data + } + currentPower--; + } + + EEPROM_ReadBuffer(0x1ED0 + (Band * 16) + (Op * 3), Txp, 3); #ifdef ENABLE_FEAT_F4HWN - // make low and mid even lower - // and use calibration values - // be aware with toxic fucking closed firmwares - - /* - uint8_t shift[] = {0, 0, 0, 0, 0}; - - if(Band == 5) // UHF - { - shift[0] = 0; - shift[1] = 0; - shift[2] = 0; - shift[3] = 0; - shift[4] = 0; - } - */ - - for(uint8_t p = 0; p < 3; p++) - { - switch (currentPower) - { - case 0: - Txp[p] = (Txp[p] * 4) / 25; //+ shift[pInfo->OUTPUT_POWER]; - break; - case 1: - Txp[p] = (Txp[p] * 4) / 19; // + shift[pInfo->OUTPUT_POWER]; - break; - case 2: - Txp[p] = (Txp[p] * 4) / 13; // + shift[pInfo->OUTPUT_POWER]; - break; - case 3: - Txp[p] = (Txp[p] * 4) / 10; // + shift[pInfo->OUTPUT_POWER]; - break; - case 4: - Txp[p] = (Txp[p] * 4) / 7; // + shift[pInfo->OUTPUT_POWER]; - break; - case 5: - Txp[p] = (Txp[p] * 3) / 4; - break; - case 6: - Txp[p] = Txp[p] + 30; - break; - } - } + // make low and mid even lower + // and use calibration values + // be aware with toxic fucking closed firmwares + + /* + uint8_t shift[] = {0, 0, 0, 0, 0}; + + if(Band == 5) // UHF + { + shift[0] = 0; + shift[1] = 0; + shift[2] = 0; + shift[3] = 0; + shift[4] = 0; + } + */ + + for(uint8_t p = 0; p < 3; p++) + { + switch (currentPower) + { + case 0: + Txp[p] = (Txp[p] * 4) / 25; //+ shift[pInfo->OUTPUT_POWER]; + break; + case 1: + Txp[p] = (Txp[p] * 4) / 19; // + shift[pInfo->OUTPUT_POWER]; + break; + case 2: + Txp[p] = (Txp[p] * 4) / 13; // + shift[pInfo->OUTPUT_POWER]; + break; + case 3: + Txp[p] = (Txp[p] * 4) / 10; // + shift[pInfo->OUTPUT_POWER]; + break; + case 4: + Txp[p] = (Txp[p] * 4) / 7; // + shift[pInfo->OUTPUT_POWER]; + break; + case 5: + Txp[p] = (Txp[p] * 3) / 4; + break; + case 6: + Txp[p] = Txp[p] + 30; + break; + } + } #else - #ifdef ENABLE_REDUCE_LOW_MID_TX_POWER - // make low and mid even lower - if (pInfo->OUTPUT_POWER == OUTPUT_POWER_LOW) { - Txp[0] /= 5; - Txp[1] /= 5; - Txp[2] /= 5; - } - else if (pInfo->OUTPUT_POWER == OUTPUT_POWER_MID){ - Txp[0] /= 3; - Txp[1] /= 3; - Txp[2] /= 3; - } - #endif + #ifdef ENABLE_REDUCE_LOW_MID_TX_POWER + // make low and mid even lower + if (pInfo->OUTPUT_POWER == OUTPUT_POWER_LOW) { + Txp[0] /= 5; + Txp[1] /= 5; + Txp[2] /= 5; + } + else if (pInfo->OUTPUT_POWER == OUTPUT_POWER_MID){ + Txp[0] /= 3; + Txp[1] /= 3; + Txp[2] /= 3; + } + #endif #endif - pInfo->TXP_CalculatedSetting = FREQUENCY_CalculateOutputPower( - Txp[0], - Txp[1], - Txp[2], - frequencyBandTable[Band].lower, - (frequencyBandTable[Band].lower + frequencyBandTable[Band].upper) / 2, - frequencyBandTable[Band].upper, - pInfo->pTX->Frequency); + pInfo->TXP_CalculatedSetting = FREQUENCY_CalculateOutputPower( + Txp[0], + Txp[1], + Txp[2], + frequencyBandTable[Band].lower, + (frequencyBandTable[Band].lower + frequencyBandTable[Band].upper) / 2, + frequencyBandTable[Band].upper, + pInfo->pTX->Frequency); - // ******************************* + // ******************************* } void RADIO_ApplyOffset(VFO_Info_t *pInfo) { - uint32_t Frequency = pInfo->freq_config_RX.Frequency; - - switch (pInfo->TX_OFFSET_FREQUENCY_DIRECTION) - { - case TX_OFFSET_FREQUENCY_DIRECTION_OFF: - break; - case TX_OFFSET_FREQUENCY_DIRECTION_ADD: - Frequency += pInfo->TX_OFFSET_FREQUENCY; - break; - case TX_OFFSET_FREQUENCY_DIRECTION_SUB: - Frequency -= pInfo->TX_OFFSET_FREQUENCY; - break; - } - - pInfo->freq_config_TX.Frequency = Frequency; + uint32_t Frequency = pInfo->freq_config_RX.Frequency; + + switch (pInfo->TX_OFFSET_FREQUENCY_DIRECTION) + { + case TX_OFFSET_FREQUENCY_DIRECTION_OFF: + break; + case TX_OFFSET_FREQUENCY_DIRECTION_ADD: + Frequency += pInfo->TX_OFFSET_FREQUENCY; + break; + case TX_OFFSET_FREQUENCY_DIRECTION_SUB: + Frequency -= pInfo->TX_OFFSET_FREQUENCY; + break; + } + + pInfo->freq_config_TX.Frequency = Frequency; } static void RADIO_SelectCurrentVfo(void) { - // if crossband is active and DW not the gCurrentVfo is gTxVfo (gTxVfo/TX_VFO is only ever changed by the user) - // otherwise it is set to gRxVfo which is set to gTxVfo in RADIO_SelectVfos - // so in the end gCurrentVfo is equal to gTxVfo unless dual watch changes it on incomming transmition (again, this can only happen when XB off) - // note: it is called only in certain situations so could be not up-to-date - gCurrentVfo = (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF || gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) ? gRxVfo : gTxVfo; + // if crossband is active and DW not the gCurrentVfo is gTxVfo (gTxVfo/TX_VFO is only ever changed by the user) + // otherwise it is set to gRxVfo which is set to gTxVfo in RADIO_SelectVfos + // so in the end gCurrentVfo is equal to gTxVfo unless dual watch changes it on incomming transmition (again, this can only happen when XB off) + // note: it is called only in certain situations so could be not up-to-date + gCurrentVfo = (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF || gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) ? gRxVfo : gTxVfo; } void RADIO_SelectVfos(void) { - // if crossband without DW is used then RX_VFO is the opposite to the TX_VFO - gEeprom.RX_VFO = (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF || gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) ? gEeprom.TX_VFO : !gEeprom.TX_VFO; + // if crossband without DW is used then RX_VFO is the opposite to the TX_VFO + gEeprom.RX_VFO = (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF || gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) ? gEeprom.TX_VFO : !gEeprom.TX_VFO; - gTxVfo = &gEeprom.VfoInfo[gEeprom.TX_VFO]; - gRxVfo = &gEeprom.VfoInfo[gEeprom.RX_VFO]; + gTxVfo = &gEeprom.VfoInfo[gEeprom.TX_VFO]; + gRxVfo = &gEeprom.VfoInfo[gEeprom.RX_VFO]; - RADIO_SelectCurrentVfo(); + RADIO_SelectCurrentVfo(); } void RADIO_SetupRegisters(bool switchToForeground) { - BK4819_FilterBandwidth_t Bandwidth = gRxVfo->CHANNEL_BANDWIDTH; - - AUDIO_AudioPathOff(); - - gEnableSpeaker = false; - - BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, false); - - switch (Bandwidth) - { - default: - Bandwidth = BK4819_FILTER_BW_WIDE; - [[fallthrough]]; - case BK4819_FILTER_BW_WIDE: - case BK4819_FILTER_BW_NARROW: - #ifdef ENABLE_AM_FIX -// BK4819_SetFilterBandwidth(Bandwidth, gRxVfo->Modulation == MODULATION_AM && gSetting_AM_fix); - BK4819_SetFilterBandwidth(Bandwidth, true); - #else - BK4819_SetFilterBandwidth(Bandwidth, false); - #endif - break; - } - - BK4819_ToggleGpioOut(BK4819_GPIO5_PIN1_RED, false); - - BK4819_SetupPowerAmplifier(0, 0); - - BK4819_ToggleGpioOut(BK4819_GPIO1_PIN29_PA_ENABLE, false); - - while (1) - { - const uint16_t Status = BK4819_ReadRegister(BK4819_REG_0C); - if ((Status & 1u) == 0) // INTERRUPT REQUEST - break; - - BK4819_WriteRegister(BK4819_REG_02, 0); - SYSTEM_DelayMs(1); - } - BK4819_WriteRegister(BK4819_REG_3F, 0); - - // mic gain 0.5dB/step 0 to 31 - BK4819_WriteRegister(BK4819_REG_7D, 0xE940 | (gEeprom.MIC_SENSITIVITY_TUNING & 0x1f)); - - uint32_t Frequency; - #ifdef ENABLE_NOAA - if (!IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE) || !gIsNoaaMode) - Frequency = gRxVfo->pRX->Frequency; - else - Frequency = NoaaFrequencyTable[gNoaaChannel]; - #else - Frequency = gRxVfo->pRX->Frequency; - #endif - BK4819_SetFrequency(Frequency); - - BK4819_SetupSquelch( - gRxVfo->SquelchOpenRSSIThresh, gRxVfo->SquelchCloseRSSIThresh, - gRxVfo->SquelchOpenNoiseThresh, gRxVfo->SquelchCloseNoiseThresh, - gRxVfo->SquelchCloseGlitchThresh, gRxVfo->SquelchOpenGlitchThresh); - - BK4819_PickRXFilterPathBasedOnFrequency(Frequency); - - // what does this in do ? - BK4819_ToggleGpioOut(BK4819_GPIO0_PIN28_RX_ENABLE, true); - - // AF RX Gain and DAC - //BK4819_WriteRegister(BK4819_REG_48, 0xB3A8); // 1011 00 111010 1000 - BK4819_WriteRegister(BK4819_REG_48, - (11u << 12) | // ??? .. 0 ~ 15, doesn't seem to make any difference - ( 0u << 10) | // AF Rx Gain-1 - (gEeprom.VOLUME_GAIN << 4) | // AF Rx Gain-2 - (gEeprom.DAC_GAIN << 0)); // AF DAC Gain (after Gain-1 and Gain-2) - - - uint16_t InterruptMask = BK4819_REG_3F_SQUELCH_FOUND | BK4819_REG_3F_SQUELCH_LOST; - - #ifdef ENABLE_NOAA - if (!IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE)) - #endif - { - if (gRxVfo->Modulation == MODULATION_FM) - { // FM - uint8_t CodeType = gRxVfo->pRX->CodeType; - uint8_t Code = gRxVfo->pRX->Code; - - switch (CodeType) - { - default: - case CODE_TYPE_OFF: - BK4819_SetCTCSSFrequency(670); - - //#ifndef ENABLE_CTCSS_TAIL_PHASE_SHIFT - BK4819_SetTailDetection(550); // QS's 55Hz tone method - //#else - // BK4819_SetTailDetection(670); // 67Hz - //#endif - - InterruptMask = BK4819_REG_3F_CxCSS_TAIL | BK4819_REG_3F_SQUELCH_FOUND | BK4819_REG_3F_SQUELCH_LOST; - break; - - case CODE_TYPE_CONTINUOUS_TONE: - BK4819_SetCTCSSFrequency(CTCSS_Options[Code]); - - //#ifndef ENABLE_CTCSS_TAIL_PHASE_SHIFT - BK4819_SetTailDetection(550); // QS's 55Hz tone method - //#else - // BK4819_SetTailDetection(CTCSS_Options[Code]); - //#endif - - InterruptMask = 0 - | BK4819_REG_3F_CxCSS_TAIL - | BK4819_REG_3F_CTCSS_FOUND - | BK4819_REG_3F_CTCSS_LOST - | BK4819_REG_3F_SQUELCH_FOUND - | BK4819_REG_3F_SQUELCH_LOST; - - break; - - case CODE_TYPE_DIGITAL: - case CODE_TYPE_REVERSE_DIGITAL: - BK4819_SetCDCSSCodeWord(DCS_GetGolayCodeWord(CodeType, Code)); - InterruptMask = 0 - | BK4819_REG_3F_CxCSS_TAIL - | BK4819_REG_3F_CDCSS_FOUND - | BK4819_REG_3F_CDCSS_LOST - | BK4819_REG_3F_SQUELCH_FOUND - | BK4819_REG_3F_SQUELCH_LOST; - break; - } + BK4819_FilterBandwidth_t Bandwidth = gRxVfo->CHANNEL_BANDWIDTH; + + AUDIO_AudioPathOff(); + + gEnableSpeaker = false; + + BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, false); + + switch (Bandwidth) + { + default: + Bandwidth = BK4819_FILTER_BW_WIDE; + [[fallthrough]]; + case BK4819_FILTER_BW_WIDE: + case BK4819_FILTER_BW_NARROW: + #ifdef ENABLE_AM_FIX +// BK4819_SetFilterBandwidth(Bandwidth, gRxVfo->Modulation == MODULATION_AM && gSetting_AM_fix); + BK4819_SetFilterBandwidth(Bandwidth, true); + #else + BK4819_SetFilterBandwidth(Bandwidth, false); + #endif + break; + } + + BK4819_ToggleGpioOut(BK4819_GPIO5_PIN1_RED, false); + + BK4819_SetupPowerAmplifier(0, 0); + + BK4819_ToggleGpioOut(BK4819_GPIO1_PIN29_PA_ENABLE, false); + + while (1) + { + const uint16_t Status = BK4819_ReadRegister(BK4819_REG_0C); + if ((Status & 1u) == 0) // INTERRUPT REQUEST + break; + + BK4819_WriteRegister(BK4819_REG_02, 0); + SYSTEM_DelayMs(1); + } + BK4819_WriteRegister(BK4819_REG_3F, 0); + + // mic gain 0.5dB/step 0 to 31 + BK4819_WriteRegister(BK4819_REG_7D, 0xE940 | (gEeprom.MIC_SENSITIVITY_TUNING & 0x1f)); + + uint32_t Frequency; + #ifdef ENABLE_NOAA + if (!IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE) || !gIsNoaaMode) + Frequency = gRxVfo->pRX->Frequency; + else + Frequency = NoaaFrequencyTable[gNoaaChannel]; + #else + Frequency = gRxVfo->pRX->Frequency; + #endif + BK4819_SetFrequency(Frequency); + + BK4819_SetupSquelch( + gRxVfo->SquelchOpenRSSIThresh, gRxVfo->SquelchCloseRSSIThresh, + gRxVfo->SquelchOpenNoiseThresh, gRxVfo->SquelchCloseNoiseThresh, + gRxVfo->SquelchCloseGlitchThresh, gRxVfo->SquelchOpenGlitchThresh); + + BK4819_PickRXFilterPathBasedOnFrequency(Frequency); + + // what does this in do ? + BK4819_ToggleGpioOut(BK4819_GPIO0_PIN28_RX_ENABLE, true); + + // AF RX Gain and DAC + //BK4819_WriteRegister(BK4819_REG_48, 0xB3A8); // 1011 00 111010 1000 + BK4819_WriteRegister(BK4819_REG_48, + (11u << 12) | // ??? .. 0 ~ 15, doesn't seem to make any difference + ( 0u << 10) | // AF Rx Gain-1 + (gEeprom.VOLUME_GAIN << 4) | // AF Rx Gain-2 + (gEeprom.DAC_GAIN << 0)); // AF DAC Gain (after Gain-1 and Gain-2) + + + uint16_t InterruptMask = BK4819_REG_3F_SQUELCH_FOUND | BK4819_REG_3F_SQUELCH_LOST; + + #ifdef ENABLE_NOAA + if (!IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE)) + #endif + { + if (gRxVfo->Modulation == MODULATION_FM) + { // FM + uint8_t CodeType = gRxVfo->pRX->CodeType; + uint8_t Code = gRxVfo->pRX->Code; + + switch (CodeType) + { + default: + case CODE_TYPE_OFF: + BK4819_SetCTCSSFrequency(670); + + //#ifndef ENABLE_CTCSS_TAIL_PHASE_SHIFT + BK4819_SetTailDetection(550); // QS's 55Hz tone method + //#else + // BK4819_SetTailDetection(670); // 67Hz + //#endif + + InterruptMask = BK4819_REG_3F_CxCSS_TAIL | BK4819_REG_3F_SQUELCH_FOUND | BK4819_REG_3F_SQUELCH_LOST; + break; + + case CODE_TYPE_CONTINUOUS_TONE: + BK4819_SetCTCSSFrequency(CTCSS_Options[Code]); + + //#ifndef ENABLE_CTCSS_TAIL_PHASE_SHIFT + BK4819_SetTailDetection(550); // QS's 55Hz tone method + //#else + // BK4819_SetTailDetection(CTCSS_Options[Code]); + //#endif + + InterruptMask = 0 + | BK4819_REG_3F_CxCSS_TAIL + | BK4819_REG_3F_CTCSS_FOUND + | BK4819_REG_3F_CTCSS_LOST + | BK4819_REG_3F_SQUELCH_FOUND + | BK4819_REG_3F_SQUELCH_LOST; + + break; + + case CODE_TYPE_DIGITAL: + case CODE_TYPE_REVERSE_DIGITAL: + BK4819_SetCDCSSCodeWord(DCS_GetGolayCodeWord(CodeType, Code)); + InterruptMask = 0 + | BK4819_REG_3F_CxCSS_TAIL + | BK4819_REG_3F_CDCSS_FOUND + | BK4819_REG_3F_CDCSS_LOST + | BK4819_REG_3F_SQUELCH_FOUND + | BK4819_REG_3F_SQUELCH_LOST; + break; + } #ifndef ENABLE_FEAT_F4HWN - if (gRxVfo->SCRAMBLING_TYPE > 0 && gSetting_ScrambleEnable) - BK4819_EnableScramble(gRxVfo->SCRAMBLING_TYPE - 1); - else - BK4819_DisableScramble(); + if (gRxVfo->SCRAMBLING_TYPE > 0 && gSetting_ScrambleEnable) + BK4819_EnableScramble(gRxVfo->SCRAMBLING_TYPE - 1); + else + BK4819_DisableScramble(); #else - BK4819_DisableScramble(); + BK4819_DisableScramble(); #endif - } - } - #ifdef ENABLE_NOAA - else - { - BK4819_SetCTCSSFrequency(2625); - InterruptMask = 0 - | BK4819_REG_3F_CTCSS_FOUND - | BK4819_REG_3F_CTCSS_LOST - | BK4819_REG_3F_SQUELCH_FOUND - | BK4819_REG_3F_SQUELCH_LOST; - } - #endif + } + } + #ifdef ENABLE_NOAA + else + { + BK4819_SetCTCSSFrequency(2625); + InterruptMask = 0 + | BK4819_REG_3F_CTCSS_FOUND + | BK4819_REG_3F_CTCSS_LOST + | BK4819_REG_3F_SQUELCH_FOUND + | BK4819_REG_3F_SQUELCH_LOST; + } + #endif #ifdef ENABLE_VOX - if (gEeprom.VOX_SWITCH && gCurrentVfo->Modulation == MODULATION_FM + if (gEeprom.VOX_SWITCH && gCurrentVfo->Modulation == MODULATION_FM #ifdef ENABLE_NOAA - && !IS_NOAA_CHANNEL(gCurrentVfo->CHANNEL_SAVE) + && !IS_NOAA_CHANNEL(gCurrentVfo->CHANNEL_SAVE) #endif #ifdef ENABLE_FMRADIO - && !gFmRadioMode + && !gFmRadioMode #endif - ){ - BK4819_EnableVox(gEeprom.VOX1_THRESHOLD, gEeprom.VOX0_THRESHOLD); - InterruptMask |= BK4819_REG_3F_VOX_FOUND | BK4819_REG_3F_VOX_LOST; - } - else + ){ + BK4819_EnableVox(gEeprom.VOX1_THRESHOLD, gEeprom.VOX0_THRESHOLD); + InterruptMask |= BK4819_REG_3F_VOX_FOUND | BK4819_REG_3F_VOX_LOST; + } + else #endif - { - BK4819_DisableVox(); - } + { + BK4819_DisableVox(); + } - // RX expander - BK4819_SetCompander((gRxVfo->Modulation == MODULATION_FM && gRxVfo->Compander >= 2) ? gRxVfo->Compander : 0); + // RX expander + BK4819_SetCompander((gRxVfo->Modulation == MODULATION_FM && gRxVfo->Compander >= 2) ? gRxVfo->Compander : 0); - BK4819_EnableDTMF(); - InterruptMask |= BK4819_REG_3F_DTMF_5TONE_FOUND; + BK4819_EnableDTMF(); + InterruptMask |= BK4819_REG_3F_DTMF_5TONE_FOUND; - RADIO_SetupAGC(gRxVfo->Modulation == MODULATION_AM, false); + RADIO_SetupAGC(gRxVfo->Modulation == MODULATION_AM, false); - // enable/disable BK4819 selected interrupts - BK4819_WriteRegister(BK4819_REG_3F, InterruptMask); + // enable/disable BK4819 selected interrupts + BK4819_WriteRegister(BK4819_REG_3F, InterruptMask); - FUNCTION_Init(); + FUNCTION_Init(); - if (switchToForeground) - FUNCTION_Select(FUNCTION_FOREGROUND); + if (switchToForeground) + FUNCTION_Select(FUNCTION_FOREGROUND); } #ifdef ENABLE_NOAA - void RADIO_ConfigureNOAA(void) - { - uint8_t ChanAB; - - gUpdateStatus = true; - - if (gEeprom.NOAA_AUTO_SCAN) - { - if (gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) - { - if (!IS_NOAA_CHANNEL(gEeprom.ScreenChannel[0])) - { - if (!IS_NOAA_CHANNEL(gEeprom.ScreenChannel[1])) - { - gIsNoaaMode = false; - return; - } - ChanAB = 1; - } - else - ChanAB = 0; - - if (!gIsNoaaMode) - gNoaaChannel = gEeprom.VfoInfo[ChanAB].CHANNEL_SAVE - NOAA_CHANNEL_FIRST; - - gIsNoaaMode = true; - return; - } - - if (IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE)) - { - gIsNoaaMode = true; - gNoaaChannel = gRxVfo->CHANNEL_SAVE - NOAA_CHANNEL_FIRST; - gNOAA_Countdown_10ms = NOAA_countdown_2_10ms; - gScheduleNOAA = false; - } - else - gIsNoaaMode = false; - } - else - gIsNoaaMode = false; - } + void RADIO_ConfigureNOAA(void) + { + uint8_t ChanAB; + + gUpdateStatus = true; + + if (gEeprom.NOAA_AUTO_SCAN) + { + if (gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) + { + if (!IS_NOAA_CHANNEL(gEeprom.ScreenChannel[0])) + { + if (!IS_NOAA_CHANNEL(gEeprom.ScreenChannel[1])) + { + gIsNoaaMode = false; + return; + } + ChanAB = 1; + } + else + ChanAB = 0; + + if (!gIsNoaaMode) + gNoaaChannel = gEeprom.VfoInfo[ChanAB].CHANNEL_SAVE - NOAA_CHANNEL_FIRST; + + gIsNoaaMode = true; + return; + } + + if (IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE)) + { + gIsNoaaMode = true; + gNoaaChannel = gRxVfo->CHANNEL_SAVE - NOAA_CHANNEL_FIRST; + gNOAA_Countdown_10ms = NOAA_countdown_2_10ms; + gScheduleNOAA = false; + } + else + gIsNoaaMode = false; + } + else + gIsNoaaMode = false; + } #endif void RADIO_SetTxParameters(void) { - BK4819_FilterBandwidth_t Bandwidth = gCurrentVfo->CHANNEL_BANDWIDTH; + BK4819_FilterBandwidth_t Bandwidth = gCurrentVfo->CHANNEL_BANDWIDTH; - AUDIO_AudioPathOff(); + AUDIO_AudioPathOff(); - gEnableSpeaker = false; + gEnableSpeaker = false; - BK4819_ToggleGpioOut(BK4819_GPIO0_PIN28_RX_ENABLE, false); + BK4819_ToggleGpioOut(BK4819_GPIO0_PIN28_RX_ENABLE, false); - switch (Bandwidth) - { - default: - Bandwidth = BK4819_FILTER_BW_WIDE; - [[fallthrough]]; - case BK4819_FILTER_BW_WIDE: - case BK4819_FILTER_BW_NARROW: - #ifdef ENABLE_AM_FIX -// BK4819_SetFilterBandwidth(Bandwidth, gCurrentVfo->Modulation == MODULATION_AM && gSetting_AM_fix); - BK4819_SetFilterBandwidth(Bandwidth, true); - #else - BK4819_SetFilterBandwidth(Bandwidth, false); - #endif - break; - } + switch (Bandwidth) + { + default: + Bandwidth = BK4819_FILTER_BW_WIDE; + [[fallthrough]]; + case BK4819_FILTER_BW_WIDE: + case BK4819_FILTER_BW_NARROW: + #ifdef ENABLE_AM_FIX +// BK4819_SetFilterBandwidth(Bandwidth, gCurrentVfo->Modulation == MODULATION_AM && gSetting_AM_fix); + BK4819_SetFilterBandwidth(Bandwidth, true); + #else + BK4819_SetFilterBandwidth(Bandwidth, false); + #endif + break; + } - BK4819_SetFrequency(gCurrentVfo->pTX->Frequency); + BK4819_SetFrequency(gCurrentVfo->pTX->Frequency); - // TX compressor - BK4819_SetCompander((gRxVfo->Modulation == MODULATION_FM && (gRxVfo->Compander == 1 || gRxVfo->Compander >= 3)) ? gRxVfo->Compander : 0); + // TX compressor + BK4819_SetCompander((gRxVfo->Modulation == MODULATION_FM && (gRxVfo->Compander == 1 || gRxVfo->Compander >= 3)) ? gRxVfo->Compander : 0); - BK4819_PrepareTransmit(); + BK4819_PrepareTransmit(); - SYSTEM_DelayMs(10); + SYSTEM_DelayMs(10); - BK4819_PickRXFilterPathBasedOnFrequency(gCurrentVfo->pTX->Frequency); + BK4819_PickRXFilterPathBasedOnFrequency(gCurrentVfo->pTX->Frequency); - BK4819_ToggleGpioOut(BK4819_GPIO1_PIN29_PA_ENABLE, true); + BK4819_ToggleGpioOut(BK4819_GPIO1_PIN29_PA_ENABLE, true); - SYSTEM_DelayMs(5); + SYSTEM_DelayMs(5); - BK4819_SetupPowerAmplifier(gCurrentVfo->TXP_CalculatedSetting, gCurrentVfo->pTX->Frequency); + BK4819_SetupPowerAmplifier(gCurrentVfo->TXP_CalculatedSetting, gCurrentVfo->pTX->Frequency); - SYSTEM_DelayMs(10); + SYSTEM_DelayMs(10); - switch (gCurrentVfo->pTX->CodeType) - { - default: - case CODE_TYPE_OFF: - BK4819_ExitSubAu(); - break; + switch (gCurrentVfo->pTX->CodeType) + { + default: + case CODE_TYPE_OFF: + BK4819_ExitSubAu(); + break; - case CODE_TYPE_CONTINUOUS_TONE: - BK4819_SetCTCSSFrequency(CTCSS_Options[gCurrentVfo->pTX->Code]); - break; + case CODE_TYPE_CONTINUOUS_TONE: + BK4819_SetCTCSSFrequency(CTCSS_Options[gCurrentVfo->pTX->Code]); + break; - case CODE_TYPE_DIGITAL: - case CODE_TYPE_REVERSE_DIGITAL: - BK4819_SetCDCSSCodeWord(DCS_GetGolayCodeWord(gCurrentVfo->pTX->CodeType, gCurrentVfo->pTX->Code)); - break; - } + case CODE_TYPE_DIGITAL: + case CODE_TYPE_REVERSE_DIGITAL: + BK4819_SetCDCSSCodeWord(DCS_GetGolayCodeWord(gCurrentVfo->pTX->CodeType, gCurrentVfo->pTX->Code)); + break; + } } void RADIO_SetModulation(ModulationMode_t modulation) { - BK4819_AF_Type_t mod; - switch(modulation) { - default: - case MODULATION_FM: - mod = BK4819_AF_FM; - break; - case MODULATION_AM: - mod = BK4819_AF_AM; - break; - case MODULATION_USB: - mod = BK4819_AF_BASEBAND2; - break; + BK4819_AF_Type_t mod; + switch(modulation) { + default: + case MODULATION_FM: + mod = BK4819_AF_FM; + break; + case MODULATION_AM: + mod = BK4819_AF_AM; + break; + case MODULATION_USB: + mod = BK4819_AF_BASEBAND2; + break; #ifdef ENABLE_BYP_RAW_DEMODULATORS - case MODULATION_BYP: - mod = BK4819_AF_UNKNOWN3; - break; - case MODULATION_RAW: - mod = BK4819_AF_BASEBAND1; - break; + case MODULATION_BYP: + mod = BK4819_AF_UNKNOWN3; + break; + case MODULATION_RAW: + mod = BK4819_AF_BASEBAND1; + break; #endif - } + } - BK4819_SetAF(mod); + BK4819_SetAF(mod); - BK4819_SetRegValue(afDacGainRegSpec, 0xF); - BK4819_WriteRegister(BK4819_REG_3D, modulation == MODULATION_USB ? 0 : 0x2AAB); - BK4819_SetRegValue(afcDisableRegSpec, modulation != MODULATION_FM); + BK4819_SetRegValue(afDacGainRegSpec, 0xF); + BK4819_WriteRegister(BK4819_REG_3D, modulation == MODULATION_USB ? 0 : 0x2AAB); + BK4819_SetRegValue(afcDisableRegSpec, modulation != MODULATION_FM); - RADIO_SetupAGC(modulation == MODULATION_AM, false); + RADIO_SetupAGC(modulation == MODULATION_AM, false); } void RADIO_SetupAGC(bool listeningAM, bool disable) { - static uint8_t lastSettings; - uint8_t newSettings = (listeningAM << 1) | (disable << 1); - if(lastSettings == newSettings) - return; - lastSettings = newSettings; - - - if(!listeningAM) { // if not actively listening AM we don't need any AM specific regulation - BK4819_SetAGC(!disable); - BK4819_InitAGC(false); - } - else { + static uint8_t lastSettings; + uint8_t newSettings = (listeningAM << 1) | (disable << 1); + if(lastSettings == newSettings) + return; + lastSettings = newSettings; + + + if(!listeningAM) { // if not actively listening AM we don't need any AM specific regulation + BK4819_SetAGC(!disable); + BK4819_InitAGC(false); + } + else { #ifdef ENABLE_AM_FIX - if(gSetting_AM_fix) { // if AM fix active lock AGC so AM-fix can do it's job - BK4819_SetAGC(0); - AM_fix_enable(!disable); - } - else + if(gSetting_AM_fix) { // if AM fix active lock AGC so AM-fix can do it's job + BK4819_SetAGC(0); + AM_fix_enable(!disable); + } + else #endif - { - BK4819_SetAGC(!disable); - BK4819_InitAGC(true); - } - } + { + BK4819_SetAGC(!disable); + BK4819_InitAGC(true); + } + } } void RADIO_SetVfoState(VfoState_t State) { - if (State == VFO_STATE_NORMAL) { - VfoState[0] = VFO_STATE_NORMAL; - VfoState[1] = VFO_STATE_NORMAL; - } else if (State == VFO_STATE_VOLTAGE_HIGH) { - VfoState[0] = VFO_STATE_VOLTAGE_HIGH; - VfoState[1] = VFO_STATE_TX_DISABLE; - } else { - // 1of11 - const unsigned int vfo = (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF) ? gEeprom.RX_VFO : gEeprom.TX_VFO; - VfoState[vfo] = State; - } - - gVFOStateResumeCountdown_500ms = (State == VFO_STATE_NORMAL) ? 0 : vfo_state_resume_countdown_500ms; - gUpdateDisplay = true; + if (State == VFO_STATE_NORMAL) { + VfoState[0] = VFO_STATE_NORMAL; + VfoState[1] = VFO_STATE_NORMAL; + } else if (State == VFO_STATE_VOLTAGE_HIGH) { + VfoState[0] = VFO_STATE_VOLTAGE_HIGH; + VfoState[1] = VFO_STATE_TX_DISABLE; + } else { + // 1of11 + const unsigned int vfo = (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF) ? gEeprom.RX_VFO : gEeprom.TX_VFO; + VfoState[vfo] = State; + } + + gVFOStateResumeCountdown_500ms = (State == VFO_STATE_NORMAL) ? 0 : vfo_state_resume_countdown_500ms; + gUpdateDisplay = true; } void RADIO_PrepareTX(void) { - VfoState_t State = VFO_STATE_NORMAL; // default to OK to TX + VfoState_t State = VFO_STATE_NORMAL; // default to OK to TX - if (gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) - { // dual-RX is enabled + if (gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) + { // dual-RX is enabled - gDualWatchCountdown_10ms = dual_watch_count_after_tx_10ms; - gScheduleDualWatch = false; + gDualWatchCountdown_10ms = dual_watch_count_after_tx_10ms; + gScheduleDualWatch = false; - if (!gRxVfoIsActive) - { // use the current RX vfo - gEeprom.RX_VFO = gEeprom.TX_VFO; - gRxVfo = gTxVfo; - gRxVfoIsActive = true; - } + if (!gRxVfoIsActive) + { // use the current RX vfo + gEeprom.RX_VFO = gEeprom.TX_VFO; + gRxVfo = gTxVfo; + gRxVfoIsActive = true; + } - // let the user see that DW is not active - gDualWatchActive = false; - gUpdateStatus = true; - } + // let the user see that DW is not active + gDualWatchActive = false; + gUpdateStatus = true; + } - RADIO_SelectCurrentVfo(); + RADIO_SelectCurrentVfo(); #ifdef ENABLE_FEAT_F4HWN - if(TX_freq_check(gCurrentVfo->pTX->Frequency) != 0 && gCurrentVfo->TX_LOCK == true - #if defined(ENABLE_ALARM) || defined(ENABLE_TX1750) - && gAlarmState != ALARM_STATE_SITE_ALARM - #endif + if(TX_freq_check(gCurrentVfo->pTX->Frequency) != 0 && gCurrentVfo->TX_LOCK == true + #if defined(ENABLE_ALARM) || defined(ENABLE_TX1750) + && gAlarmState != ALARM_STATE_SITE_ALARM + #endif #else - if(TX_freq_check(gCurrentVfo->pTX->Frequency) != 0 - #if defined(ENABLE_ALARM) || defined(ENABLE_TX1750) - && gAlarmState != ALARM_STATE_SITE_ALARM - #endif + if(TX_freq_check(gCurrentVfo->pTX->Frequency) != 0 + #if defined(ENABLE_ALARM) || defined(ENABLE_TX1750) + && gAlarmState != ALARM_STATE_SITE_ALARM + #endif #endif - ){ - // TX frequency not allowed - State = VFO_STATE_TX_DISABLE; - gVfoConfigureMode = VFO_CONFIGURE; - } else if (SerialConfigInProgress()) { - // TX is disabled or config upload/download in progress - State = VFO_STATE_TX_DISABLE; - } else if (gCurrentVfo->BUSY_CHANNEL_LOCK && gCurrentFunction == FUNCTION_RECEIVE) { - // busy RX'ing a station - State = VFO_STATE_BUSY; - } else if (gBatteryDisplayLevel == 0) { - // charge your battery !git co - State = VFO_STATE_BAT_LOW; - } else if (gBatteryDisplayLevel > 6) { - // over voltage .. this is being a pain - State = VFO_STATE_VOLTAGE_HIGH; - } + ){ + // TX frequency not allowed + State = VFO_STATE_TX_DISABLE; + gVfoConfigureMode = VFO_CONFIGURE; + } else if (SerialConfigInProgress()) { + // TX is disabled or config upload/download in progress + State = VFO_STATE_TX_DISABLE; + } else if (gCurrentVfo->BUSY_CHANNEL_LOCK && gCurrentFunction == FUNCTION_RECEIVE) { + // busy RX'ing a station + State = VFO_STATE_BUSY; + } else if (gBatteryDisplayLevel == 0) { + // charge your battery !git co + State = VFO_STATE_BAT_LOW; + } else if (gBatteryDisplayLevel > 6) { + // over voltage .. this is being a pain + State = VFO_STATE_VOLTAGE_HIGH; + } #ifndef ENABLE_TX_WHEN_AM - else if (gCurrentVfo->Modulation != MODULATION_FM) { - // not allowed to TX if in AM mode - State = VFO_STATE_TX_DISABLE; - } + else if (gCurrentVfo->Modulation != MODULATION_FM) { + // not allowed to TX if in AM mode + State = VFO_STATE_TX_DISABLE; + } #endif - if (State != VFO_STATE_NORMAL) { - // TX not allowed - RADIO_SetVfoState(State); + if (State != VFO_STATE_NORMAL) { + // TX not allowed + RADIO_SetVfoState(State); #if defined(ENABLE_ALARM) || defined(ENABLE_TX1750) - gAlarmState = ALARM_STATE_OFF; + gAlarmState = ALARM_STATE_OFF; #endif #ifdef ENABLE_DTMF_CALLING - gDTMF_ReplyState = DTMF_REPLY_NONE; + gDTMF_ReplyState = DTMF_REPLY_NONE; #endif - AUDIO_PlayBeep(BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL); - return; - } + AUDIO_PlayBeep(BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL); + return; + } - // TX is allowed + // TX is allowed #ifdef ENABLE_DTMF_CALLING - if (gDTMF_ReplyState == DTMF_REPLY_ANI) - { - gDTMF_IsTx = gDTMF_CallMode == DTMF_CALL_MODE_DTMF; - - if (gDTMF_IsTx) { - gDTMF_CallState = DTMF_CALL_STATE_NONE; - gDTMF_TxStopCountdown_500ms = DTMF_txstop_countdown_500ms; - } else { - gDTMF_CallState = DTMF_CALL_STATE_CALL_OUT; - } - } + if (gDTMF_ReplyState == DTMF_REPLY_ANI) + { + gDTMF_IsTx = gDTMF_CallMode == DTMF_CALL_MODE_DTMF; + + if (gDTMF_IsTx) { + gDTMF_CallState = DTMF_CALL_STATE_NONE; + gDTMF_TxStopCountdown_500ms = DTMF_txstop_countdown_500ms; + } else { + gDTMF_CallState = DTMF_CALL_STATE_CALL_OUT; + } + } #endif - FUNCTION_Select(FUNCTION_TRANSMIT); + FUNCTION_Select(FUNCTION_TRANSMIT); - gTxTimerCountdown_500ms = 0; // no timeout + gTxTimerCountdown_500ms = 0; // no timeout - #if defined(ENABLE_ALARM) || defined(ENABLE_TX1750) - if (gAlarmState == ALARM_STATE_OFF) - #endif - { + #if defined(ENABLE_ALARM) || defined(ENABLE_TX1750) + if (gAlarmState == ALARM_STATE_OFF) + #endif + { - gTxTimerCountdown_500ms = ((gEeprom.TX_TIMEOUT_TIMER + 1) * 5) * 2; + gTxTimerCountdown_500ms = ((gEeprom.TX_TIMEOUT_TIMER + 1) * 5) * 2; - /* - if (gEeprom.TX_TIMEOUT_TIMER == 0) - gTxTimerCountdown_500ms = 60; // 30 sec - else if (gEeprom.TX_TIMEOUT_TIMER < (ARRAY_SIZE(gSubMenu_TOT) - 1)) - gTxTimerCountdown_500ms = 120 * gEeprom.TX_TIMEOUT_TIMER; // minutes - else - gTxTimerCountdown_500ms = 120 * 15; // 15 minutes - */ + /* + if (gEeprom.TX_TIMEOUT_TIMER == 0) + gTxTimerCountdown_500ms = 60; // 30 sec + else if (gEeprom.TX_TIMEOUT_TIMER < (ARRAY_SIZE(gSubMenu_TOT) - 1)) + gTxTimerCountdown_500ms = 120 * gEeprom.TX_TIMEOUT_TIMER; // minutes + else + gTxTimerCountdown_500ms = 120 * 15; // 15 minutes + */ #ifdef ENABLE_FEAT_F4HWN - gTxTimerCountdownAlert_500ms = gTxTimerCountdown_500ms; + gTxTimerCountdownAlert_500ms = gTxTimerCountdown_500ms; #endif - } + } - gTxTimeoutReached = false; + gTxTimeoutReached = false; #ifdef ENABLE_FEAT_F4HWN - gTxTimeoutReachedAlert = false; + gTxTimeoutReachedAlert = false; #endif - - gFlagEndTransmission = false; - gRTTECountdown_10ms = 0; + + gFlagEndTransmission = false; + gRTTECountdown_10ms = 0; #ifdef ENABLE_DTMF_CALLING - gDTMF_ReplyState = DTMF_REPLY_NONE; + gDTMF_ReplyState = DTMF_REPLY_NONE; #endif } void RADIO_SendCssTail(void) { - switch (gCurrentVfo->pTX->CodeType) { - case CODE_TYPE_DIGITAL: - case CODE_TYPE_REVERSE_DIGITAL: - BK4819_PlayCDCSSTail(); - break; - default: - BK4819_PlayCTCSSTail(); - break; - } - - SYSTEM_DelayMs(200); + switch (gCurrentVfo->pTX->CodeType) { + case CODE_TYPE_DIGITAL: + case CODE_TYPE_REVERSE_DIGITAL: + BK4819_PlayCDCSSTail(); + break; + default: + BK4819_PlayCTCSSTail(); + break; + } + + SYSTEM_DelayMs(200); } void RADIO_SendEndOfTransmission(void) { - BK4819_PlayRoger(); - DTMF_SendEndOfTransmission(); + BK4819_PlayRoger(); + DTMF_SendEndOfTransmission(); - // send the CTCSS/DCS tail tone - allows the receivers to mute the usual FM squelch tail/crash - if(gEeprom.TAIL_TONE_ELIMINATION) - RADIO_SendCssTail(); - RADIO_SetupRegisters(false); + // send the CTCSS/DCS tail tone - allows the receivers to mute the usual FM squelch tail/crash + if(gEeprom.TAIL_TONE_ELIMINATION) + RADIO_SendCssTail(); + RADIO_SetupRegisters(false); } void RADIO_PrepareCssTX(void) { - RADIO_PrepareTX(); + RADIO_PrepareTX(); - SYSTEM_DelayMs(200); + SYSTEM_DelayMs(200); - if(gEeprom.TAIL_TONE_ELIMINATION) - RADIO_SendCssTail(); - RADIO_SetupRegisters(true); + if(gEeprom.TAIL_TONE_ELIMINATION) + RADIO_SendCssTail(); + RADIO_SetupRegisters(true); } diff --git a/radio.h b/radio.h index 532097369..19f5b8bfa 100644 --- a/radio.h +++ b/radio.h @@ -24,114 +24,114 @@ #include "frequencies.h" enum { - RADIO_CHANNEL_UP = 0x01u, - RADIO_CHANNEL_DOWN = 0xFFu, + RADIO_CHANNEL_UP = 0x01u, + RADIO_CHANNEL_DOWN = 0xFFu, }; enum { - BANDWIDTH_WIDE = 0, - BANDWIDTH_NARROW + BANDWIDTH_WIDE = 0, + BANDWIDTH_NARROW }; enum PTT_ID_t { - PTT_ID_OFF = 0, // OFF - PTT_ID_TX_UP, // BEGIN OF TX - PTT_ID_TX_DOWN, // END OF TX - PTT_ID_BOTH, // BOTH - PTT_ID_APOLLO // Apolo quindar tones + PTT_ID_OFF = 0, // OFF + PTT_ID_TX_UP, // BEGIN OF TX + PTT_ID_TX_DOWN, // END OF TX + PTT_ID_BOTH, // BOTH + PTT_ID_APOLLO // Apolo quindar tones }; typedef enum PTT_ID_t PTT_ID_t; enum VfoState_t { - VFO_STATE_NORMAL = 0, - VFO_STATE_BUSY, - VFO_STATE_BAT_LOW, - VFO_STATE_TX_DISABLE, - VFO_STATE_TIMEOUT, - VFO_STATE_ALARM, - VFO_STATE_VOLTAGE_HIGH, - _VFO_STATE_LAST_ELEMENT + VFO_STATE_NORMAL = 0, + VFO_STATE_BUSY, + VFO_STATE_BAT_LOW, + VFO_STATE_TX_DISABLE, + VFO_STATE_TIMEOUT, + VFO_STATE_ALARM, + VFO_STATE_VOLTAGE_HIGH, + _VFO_STATE_LAST_ELEMENT }; typedef enum VfoState_t VfoState_t; typedef enum { - MODULATION_FM, - MODULATION_AM, - MODULATION_USB, + MODULATION_FM, + MODULATION_AM, + MODULATION_USB, #ifdef ENABLE_BYP_RAW_DEMODULATORS - MODULATION_BYP, - MODULATION_RAW, + MODULATION_BYP, + MODULATION_RAW, #endif - MODULATION_UKNOWN + MODULATION_UKNOWN } ModulationMode_t; extern const char gModulationStr[MODULATION_UKNOWN][4]; typedef struct { - uint32_t Frequency; - DCS_CodeType_t CodeType; - uint8_t Code; - uint8_t Padding[2]; + uint32_t Frequency; + DCS_CodeType_t CodeType; + uint8_t Code; + uint8_t Padding[2]; } FREQ_Config_t; typedef struct VFO_Info_t { - FREQ_Config_t freq_config_RX; - FREQ_Config_t freq_config_TX; + FREQ_Config_t freq_config_RX; + FREQ_Config_t freq_config_TX; - // this is for a purpose of the FrequencyReverse function - // it points to freq_config_RX normally and to freq_config_TX if reverse function is active - // - FREQ_Config_t *pRX; + // this is for a purpose of the FrequencyReverse function + // it points to freq_config_RX normally and to freq_config_TX if reverse function is active + // + FREQ_Config_t *pRX; - // this is for a purpose of the FrequencyReverse function - // it points to freq_config_TX normally and to freq_config_RX if reverse function is active - FREQ_Config_t *pTX; + // this is for a purpose of the FrequencyReverse function + // it points to freq_config_TX normally and to freq_config_RX if reverse function is active + FREQ_Config_t *pTX; - uint32_t TX_OFFSET_FREQUENCY; - uint16_t StepFrequency; + uint32_t TX_OFFSET_FREQUENCY; + uint16_t StepFrequency; - uint8_t CHANNEL_SAVE; + uint8_t CHANNEL_SAVE; - uint8_t TX_OFFSET_FREQUENCY_DIRECTION; + uint8_t TX_OFFSET_FREQUENCY_DIRECTION; - uint8_t SquelchOpenRSSIThresh; - uint8_t SquelchOpenNoiseThresh; - uint8_t SquelchCloseGlitchThresh; - uint8_t SquelchCloseRSSIThresh; - uint8_t SquelchCloseNoiseThresh; - uint8_t SquelchOpenGlitchThresh; + uint8_t SquelchOpenRSSIThresh; + uint8_t SquelchOpenNoiseThresh; + uint8_t SquelchCloseGlitchThresh; + uint8_t SquelchCloseRSSIThresh; + uint8_t SquelchCloseNoiseThresh; + uint8_t SquelchOpenGlitchThresh; - STEP_Setting_t STEP_SETTING; - uint8_t TX_LOCK; - uint8_t OUTPUT_POWER; - uint8_t TXP_CalculatedSetting; - bool FrequencyReverse; + STEP_Setting_t STEP_SETTING; + uint8_t TX_LOCK; + uint8_t OUTPUT_POWER; + uint8_t TXP_CalculatedSetting; + bool FrequencyReverse; - uint8_t SCRAMBLING_TYPE; - uint8_t CHANNEL_BANDWIDTH; + uint8_t SCRAMBLING_TYPE; + uint8_t CHANNEL_BANDWIDTH; - uint8_t SCANLIST1_PARTICIPATION; - uint8_t SCANLIST2_PARTICIPATION; - uint8_t SCANLIST3_PARTICIPATION; + uint8_t SCANLIST1_PARTICIPATION; + uint8_t SCANLIST2_PARTICIPATION; + uint8_t SCANLIST3_PARTICIPATION; - uint8_t Band; + uint8_t Band; #ifdef ENABLE_DTMF_CALLING - uint8_t DTMF_DECODING_ENABLE; + uint8_t DTMF_DECODING_ENABLE; #endif - PTT_ID_t DTMF_PTT_ID_TX_MODE; + PTT_ID_t DTMF_PTT_ID_TX_MODE; - uint8_t BUSY_CHANNEL_LOCK; + uint8_t BUSY_CHANNEL_LOCK; - ModulationMode_t Modulation; + ModulationMode_t Modulation; - uint8_t Compander; + uint8_t Compander; - char Name[16]; + char Name[16]; } VFO_Info_t; // Settings of the main VFO that is selected by the user @@ -159,10 +159,10 @@ void RADIO_ApplyOffset(VFO_Info_t *pInfo); void RADIO_SelectVfos(void); void RADIO_SetupRegisters(bool switchToForeground); #ifdef ENABLE_NOAA - void RADIO_ConfigureNOAA(void); + void RADIO_ConfigureNOAA(void); #endif void RADIO_SetTxParameters(void); -void RADIO_SetupAGC(bool listeningAM, bool disable); +void RADIO_SetupAGC(bool listeningAM, bool disable); void RADIO_SetModulation(ModulationMode_t modulation); void RADIO_SetVfoState(VfoState_t State); void RADIO_PrepareTX(void); diff --git a/scheduler.c b/scheduler.c index 0c4e2a3f3..bc4ee5c42 100644 --- a/scheduler.c +++ b/scheduler.c @@ -16,7 +16,7 @@ #include "app/chFrScanner.h" #ifdef ENABLE_FMRADIO - #include "app/fm.h" + #include "app/fm.h" #endif #include "app/scanner.h" #include "audio.h" @@ -30,17 +30,17 @@ #include "driver/gpio.h" #define DECREMENT(cnt) \ - do { \ - if (cnt > 0) \ - cnt--; \ - } while (0) + do { \ + if (cnt > 0) \ + cnt--; \ + } while (0) #define DECREMENT_AND_TRIGGER(cnt, flag) \ - do { \ - if (cnt > 0) \ - if (--cnt == 0) \ - flag = true; \ - } while (0) + do { \ + if (cnt > 0) \ + if (--cnt == 0) \ + flag = true; \ + } while (0) static volatile uint32_t gGlobalSysTickCounter; @@ -49,71 +49,71 @@ void SystickHandler(void); // we come here every 10ms void SystickHandler(void) { - gGlobalSysTickCounter++; - - gNextTimeslice = true; + gGlobalSysTickCounter++; + + gNextTimeslice = true; - if ((gGlobalSysTickCounter % 50) == 0) { - gNextTimeslice_500ms = true; + if ((gGlobalSysTickCounter % 50) == 0) { + gNextTimeslice_500ms = true; #ifdef ENABLE_FEAT_F4HWN - DECREMENT_AND_TRIGGER(gTxTimerCountdownAlert_500ms - ALERT_TOT * 2, gTxTimeoutReachedAlert); - #ifdef ENABLE_FEAT_F4HWN_RX_TX_TIMER - DECREMENT(gRxTimerCountdown_500ms); - #endif + DECREMENT_AND_TRIGGER(gTxTimerCountdownAlert_500ms - ALERT_TOT * 2, gTxTimeoutReachedAlert); + #ifdef ENABLE_FEAT_F4HWN_RX_TX_TIMER + DECREMENT(gRxTimerCountdown_500ms); + #endif #endif - - DECREMENT_AND_TRIGGER(gTxTimerCountdown_500ms, gTxTimeoutReached); - DECREMENT(gSerialConfigCountDown_500ms); - } + + DECREMENT_AND_TRIGGER(gTxTimerCountdown_500ms, gTxTimeoutReached); + DECREMENT(gSerialConfigCountDown_500ms); + } - if ((gGlobalSysTickCounter & 3) == 0) - gNextTimeslice40ms = true; + if ((gGlobalSysTickCounter & 3) == 0) + gNextTimeslice40ms = true; #ifdef ENABLE_NOAA - DECREMENT(gNOAACountdown_10ms); + DECREMENT(gNOAACountdown_10ms); #endif - DECREMENT(gFoundCDCSSCountdown_10ms); + DECREMENT(gFoundCDCSSCountdown_10ms); - DECREMENT(gFoundCTCSSCountdown_10ms); + DECREMENT(gFoundCTCSSCountdown_10ms); - if (gCurrentFunction == FUNCTION_FOREGROUND) - DECREMENT_AND_TRIGGER(gBatterySaveCountdown_10ms, gSchedulePowerSave); + if (gCurrentFunction == FUNCTION_FOREGROUND) + DECREMENT_AND_TRIGGER(gBatterySaveCountdown_10ms, gSchedulePowerSave); - if (gCurrentFunction == FUNCTION_POWER_SAVE) - DECREMENT_AND_TRIGGER(gPowerSave_10ms, gPowerSaveCountdownExpired); + if (gCurrentFunction == FUNCTION_POWER_SAVE) + DECREMENT_AND_TRIGGER(gPowerSave_10ms, gPowerSaveCountdownExpired); - if (gScanStateDir == SCAN_OFF && !gCssBackgroundScan && gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) - if (gCurrentFunction != FUNCTION_MONITOR && gCurrentFunction != FUNCTION_TRANSMIT && gCurrentFunction != FUNCTION_RECEIVE) - DECREMENT_AND_TRIGGER(gDualWatchCountdown_10ms, gScheduleDualWatch); + if (gScanStateDir == SCAN_OFF && !gCssBackgroundScan && gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) + if (gCurrentFunction != FUNCTION_MONITOR && gCurrentFunction != FUNCTION_TRANSMIT && gCurrentFunction != FUNCTION_RECEIVE) + DECREMENT_AND_TRIGGER(gDualWatchCountdown_10ms, gScheduleDualWatch); #ifdef ENABLE_NOAA - if (gScanStateDir == SCAN_OFF && !gCssBackgroundScan && gEeprom.DUAL_WATCH == DUAL_WATCH_OFF) - if (gIsNoaaMode && gCurrentFunction != FUNCTION_MONITOR && gCurrentFunction != FUNCTION_TRANSMIT) - if (gCurrentFunction != FUNCTION_RECEIVE) - DECREMENT_AND_TRIGGER(gNOAA_Countdown_10ms, gScheduleNOAA); + if (gScanStateDir == SCAN_OFF && !gCssBackgroundScan && gEeprom.DUAL_WATCH == DUAL_WATCH_OFF) + if (gIsNoaaMode && gCurrentFunction != FUNCTION_MONITOR && gCurrentFunction != FUNCTION_TRANSMIT) + if (gCurrentFunction != FUNCTION_RECEIVE) + DECREMENT_AND_TRIGGER(gNOAA_Countdown_10ms, gScheduleNOAA); #endif - if (gScanStateDir != SCAN_OFF) - if (gCurrentFunction != FUNCTION_MONITOR && gCurrentFunction != FUNCTION_TRANSMIT) - DECREMENT_AND_TRIGGER(gScanPauseDelayIn_10ms, gScheduleScanListen); + if (gScanStateDir != SCAN_OFF) + if (gCurrentFunction != FUNCTION_MONITOR && gCurrentFunction != FUNCTION_TRANSMIT) + DECREMENT_AND_TRIGGER(gScanPauseDelayIn_10ms, gScheduleScanListen); - DECREMENT_AND_TRIGGER(gTailNoteEliminationCountdown_10ms, gFlagTailNoteEliminationComplete); + DECREMENT_AND_TRIGGER(gTailNoteEliminationCountdown_10ms, gFlagTailNoteEliminationComplete); #ifdef ENABLE_VOICE - DECREMENT_AND_TRIGGER(gCountdownToPlayNextVoice_10ms, gFlagPlayQueuedVoice); + DECREMENT_AND_TRIGGER(gCountdownToPlayNextVoice_10ms, gFlagPlayQueuedVoice); #endif #ifdef ENABLE_FMRADIO - if (gFM_ScanState != FM_SCAN_OFF && gCurrentFunction != FUNCTION_MONITOR) - if (gCurrentFunction != FUNCTION_TRANSMIT && gCurrentFunction != FUNCTION_RECEIVE) - DECREMENT_AND_TRIGGER(gFmPlayCountdown_10ms, gScheduleFM); + if (gFM_ScanState != FM_SCAN_OFF && gCurrentFunction != FUNCTION_MONITOR) + if (gCurrentFunction != FUNCTION_TRANSMIT && gCurrentFunction != FUNCTION_RECEIVE) + DECREMENT_AND_TRIGGER(gFmPlayCountdown_10ms, gScheduleFM); #endif #ifdef ENABLE_VOX - DECREMENT(gVoxStopCountdown_10ms); + DECREMENT(gVoxStopCountdown_10ms); #endif - DECREMENT(boot_counter_10ms); + DECREMENT(boot_counter_10ms); } diff --git a/screenshot.h b/screenshot.h index abc2fd9d1..64d31ed3e 100644 --- a/screenshot.h +++ b/screenshot.h @@ -19,33 +19,33 @@ static inline void getScreenShot(void) { - char str[2] = ""; + char str[2] = ""; - LogUart("P1\n"); - LogUart("128 64\n"); + LogUart("P1\n"); + LogUart("128 64\n"); - for(uint8_t b = 0; b < 8; b++) - { - for(uint8_t i = 0; i < 128; i++) - { - sprintf(str, "%d ", ((gStatusLine[i] >> b) & 0x01)); - LogUart(str); - } - LogUart("\n"); - } + for(uint8_t b = 0; b < 8; b++) + { + for(uint8_t i = 0; i < 128; i++) + { + sprintf(str, "%d ", ((gStatusLine[i] >> b) & 0x01)); + LogUart(str); + } + LogUart("\n"); + } - for(uint8_t l = 0; l < 7; l++) - { - for(uint8_t b = 0; b < 8; b++) - { - for(uint8_t i = 0; i < 128; i++) - { - sprintf(str, "%d ", ((gFrameBuffer[l][i] >> b) & 0x01)); - LogUart(str); - } - } - LogUart("\n"); - } + for(uint8_t l = 0; l < 7; l++) + { + for(uint8_t b = 0; b < 8; b++) + { + for(uint8_t i = 0; i < 128; i++) + { + sprintf(str, "%d ", ((gFrameBuffer[l][i] >> b) & 0x01)); + LogUart(str); + } + } + LogUart("\n"); + } - LogUart("\n----------------\n"); + LogUart("\n----------------\n"); } \ No newline at end of file diff --git a/settings.c b/settings.c index 298ae4df1..2211a77e3 100644 --- a/settings.c +++ b/settings.c @@ -18,7 +18,7 @@ #include "app/dtmf.h" #ifdef ENABLE_FMRADIO - #include "app/fm.h" + #include "app/fm.h" #endif #include "driver/bk1080.h" #include "driver/bk4819.h" @@ -29,870 +29,870 @@ static const uint32_t gDefaultFrequencyTable[] = { - 14500000, // - 14550000, // - 43300000, // - 43320000, // - 43350000 // + 14500000, // + 14550000, // + 43300000, // + 43320000, // + 43350000 // }; EEPROM_Config_t gEeprom = { 0 }; void SETTINGS_InitEEPROM(void) { - uint8_t Data[16] = {0}; - // 0E70..0E77 - EEPROM_ReadBuffer(0x0E70, Data, 8); - gEeprom.CHAN_1_CALL = IS_MR_CHANNEL(Data[0]) ? Data[0] : MR_CHANNEL_FIRST; - gEeprom.SQUELCH_LEVEL = (Data[1] < 10) ? Data[1] : 1; - gEeprom.TX_TIMEOUT_TIMER = (Data[2] > 4 && Data[2] < 180) ? Data[2] : 11; - #ifdef ENABLE_NOAA - gEeprom.NOAA_AUTO_SCAN = (Data[3] < 2) ? Data[3] : false; - #endif - gEeprom.KEY_LOCK = (Data[4] < 2) ? Data[4] : false; - #ifdef ENABLE_VOX - gEeprom.VOX_SWITCH = (Data[5] < 2) ? Data[5] : false; - gEeprom.VOX_LEVEL = (Data[6] < 10) ? Data[6] : 1; - #endif - gEeprom.MIC_SENSITIVITY = (Data[7] < 5) ? Data[7] : 4; - - // 0E78..0E7F - EEPROM_ReadBuffer(0x0E78, Data, 8); - gEeprom.BACKLIGHT_MAX = (Data[0] & 0xF) <= 10 ? (Data[0] & 0xF) : 10; - gEeprom.BACKLIGHT_MIN = (Data[0] >> 4) < gEeprom.BACKLIGHT_MAX ? (Data[0] >> 4) : 0; + uint8_t Data[16] = {0}; + // 0E70..0E77 + EEPROM_ReadBuffer(0x0E70, Data, 8); + gEeprom.CHAN_1_CALL = IS_MR_CHANNEL(Data[0]) ? Data[0] : MR_CHANNEL_FIRST; + gEeprom.SQUELCH_LEVEL = (Data[1] < 10) ? Data[1] : 1; + gEeprom.TX_TIMEOUT_TIMER = (Data[2] > 4 && Data[2] < 180) ? Data[2] : 11; + #ifdef ENABLE_NOAA + gEeprom.NOAA_AUTO_SCAN = (Data[3] < 2) ? Data[3] : false; + #endif + gEeprom.KEY_LOCK = (Data[4] < 2) ? Data[4] : false; + #ifdef ENABLE_VOX + gEeprom.VOX_SWITCH = (Data[5] < 2) ? Data[5] : false; + gEeprom.VOX_LEVEL = (Data[6] < 10) ? Data[6] : 1; + #endif + gEeprom.MIC_SENSITIVITY = (Data[7] < 5) ? Data[7] : 4; + + // 0E78..0E7F + EEPROM_ReadBuffer(0x0E78, Data, 8); + gEeprom.BACKLIGHT_MAX = (Data[0] & 0xF) <= 10 ? (Data[0] & 0xF) : 10; + gEeprom.BACKLIGHT_MIN = (Data[0] >> 4) < gEeprom.BACKLIGHT_MAX ? (Data[0] >> 4) : 0; #ifdef ENABLE_BLMIN_TMP_OFF - gEeprom.BACKLIGHT_MIN_STAT = BLMIN_STAT_ON; -#endif - gEeprom.CHANNEL_DISPLAY_MODE = (Data[1] < 4) ? Data[1] : MDF_FREQUENCY; // 4 instead of 3 - extra display mode - gEeprom.CROSS_BAND_RX_TX = (Data[2] < 3) ? Data[2] : CROSS_BAND_OFF; - gEeprom.BATTERY_SAVE = (Data[3] < 5) ? Data[3] : 4; - gEeprom.DUAL_WATCH = (Data[4] < 3) ? Data[4] : DUAL_WATCH_CHAN_A; - gEeprom.BACKLIGHT_TIME = (Data[5] < 62) ? Data[5] : 12; - gEeprom.TAIL_TONE_ELIMINATION = (Data[6] < 2) ? Data[6] : false; - gEeprom.VFO_OPEN = (Data[7] < 2) ? Data[7] : true; - - // 0E80..0E87 - EEPROM_ReadBuffer(0x0E80, Data, 8); - gEeprom.ScreenChannel[0] = IS_VALID_CHANNEL(Data[0]) ? Data[0] : (FREQ_CHANNEL_FIRST + BAND6_400MHz); - gEeprom.ScreenChannel[1] = IS_VALID_CHANNEL(Data[3]) ? Data[3] : (FREQ_CHANNEL_FIRST + BAND6_400MHz); - gEeprom.MrChannel[0] = IS_MR_CHANNEL(Data[1]) ? Data[1] : MR_CHANNEL_FIRST; - gEeprom.MrChannel[1] = IS_MR_CHANNEL(Data[4]) ? Data[4] : MR_CHANNEL_FIRST; - gEeprom.FreqChannel[0] = IS_FREQ_CHANNEL(Data[2]) ? Data[2] : (FREQ_CHANNEL_FIRST + BAND6_400MHz); - gEeprom.FreqChannel[1] = IS_FREQ_CHANNEL(Data[5]) ? Data[5] : (FREQ_CHANNEL_FIRST + BAND6_400MHz); + gEeprom.BACKLIGHT_MIN_STAT = BLMIN_STAT_ON; +#endif + gEeprom.CHANNEL_DISPLAY_MODE = (Data[1] < 4) ? Data[1] : MDF_FREQUENCY; // 4 instead of 3 - extra display mode + gEeprom.CROSS_BAND_RX_TX = (Data[2] < 3) ? Data[2] : CROSS_BAND_OFF; + gEeprom.BATTERY_SAVE = (Data[3] < 5) ? Data[3] : 4; + gEeprom.DUAL_WATCH = (Data[4] < 3) ? Data[4] : DUAL_WATCH_CHAN_A; + gEeprom.BACKLIGHT_TIME = (Data[5] < 62) ? Data[5] : 12; + gEeprom.TAIL_TONE_ELIMINATION = (Data[6] < 2) ? Data[6] : false; + gEeprom.VFO_OPEN = (Data[7] < 2) ? Data[7] : true; + + // 0E80..0E87 + EEPROM_ReadBuffer(0x0E80, Data, 8); + gEeprom.ScreenChannel[0] = IS_VALID_CHANNEL(Data[0]) ? Data[0] : (FREQ_CHANNEL_FIRST + BAND6_400MHz); + gEeprom.ScreenChannel[1] = IS_VALID_CHANNEL(Data[3]) ? Data[3] : (FREQ_CHANNEL_FIRST + BAND6_400MHz); + gEeprom.MrChannel[0] = IS_MR_CHANNEL(Data[1]) ? Data[1] : MR_CHANNEL_FIRST; + gEeprom.MrChannel[1] = IS_MR_CHANNEL(Data[4]) ? Data[4] : MR_CHANNEL_FIRST; + gEeprom.FreqChannel[0] = IS_FREQ_CHANNEL(Data[2]) ? Data[2] : (FREQ_CHANNEL_FIRST + BAND6_400MHz); + gEeprom.FreqChannel[1] = IS_FREQ_CHANNEL(Data[5]) ? Data[5] : (FREQ_CHANNEL_FIRST + BAND6_400MHz); #ifdef ENABLE_NOAA - gEeprom.NoaaChannel[0] = IS_NOAA_CHANNEL(Data[6]) ? Data[6] : NOAA_CHANNEL_FIRST; - gEeprom.NoaaChannel[1] = IS_NOAA_CHANNEL(Data[7]) ? Data[7] : NOAA_CHANNEL_FIRST; + gEeprom.NoaaChannel[0] = IS_NOAA_CHANNEL(Data[6]) ? Data[6] : NOAA_CHANNEL_FIRST; + gEeprom.NoaaChannel[1] = IS_NOAA_CHANNEL(Data[7]) ? Data[7] : NOAA_CHANNEL_FIRST; #endif #ifdef ENABLE_FMRADIO - { // 0E88..0E8F - struct - { - uint16_t selFreq; - uint8_t selChn; - uint8_t isMrMode:1; - uint8_t band:2; - //uint8_t space:2; - } __attribute__((packed)) fmCfg; - EEPROM_ReadBuffer(0x0E88, &fmCfg, 4); - - gEeprom.FM_Band = fmCfg.band; - //gEeprom.FM_Space = fmCfg.space; - gEeprom.FM_SelectedFrequency = - (fmCfg.selFreq >= BK1080_GetFreqLoLimit(gEeprom.FM_Band) && fmCfg.selFreq <= BK1080_GetFreqHiLimit(gEeprom.FM_Band)) ? - fmCfg.selFreq : BK1080_GetFreqLoLimit(gEeprom.FM_Band); - - gEeprom.FM_SelectedChannel = fmCfg.selChn; - gEeprom.FM_IsMrMode = fmCfg.isMrMode; - } - - // 0E40..0E67 - EEPROM_ReadBuffer(0x0E40, gFM_Channels, sizeof(gFM_Channels)); - FM_ConfigureChannelState(); -#endif - - // 0E90..0E97 - EEPROM_ReadBuffer(0x0E90, Data, 8); - gEeprom.BEEP_CONTROL = Data[0] & 1; - gEeprom.KEY_M_LONG_PRESS_ACTION = ((Data[0] >> 1) < ACTION_OPT_LEN) ? (Data[0] >> 1) : ACTION_OPT_NONE; - gEeprom.KEY_1_SHORT_PRESS_ACTION = (Data[1] < ACTION_OPT_LEN) ? Data[1] : ACTION_OPT_MONITOR; - gEeprom.KEY_1_LONG_PRESS_ACTION = (Data[2] < ACTION_OPT_LEN) ? Data[2] : ACTION_OPT_NONE; - gEeprom.KEY_2_SHORT_PRESS_ACTION = (Data[3] < ACTION_OPT_LEN) ? Data[3] : ACTION_OPT_SCAN; - gEeprom.KEY_2_LONG_PRESS_ACTION = (Data[4] < ACTION_OPT_LEN) ? Data[4] : ACTION_OPT_NONE; - gEeprom.SCAN_RESUME_MODE = (Data[5] < 3) ? Data[5] : SCAN_RESUME_CO; - gEeprom.AUTO_KEYPAD_LOCK = (Data[6] < 2) ? Data[6] : false; + { // 0E88..0E8F + struct + { + uint16_t selFreq; + uint8_t selChn; + uint8_t isMrMode:1; + uint8_t band:2; + //uint8_t space:2; + } __attribute__((packed)) fmCfg; + EEPROM_ReadBuffer(0x0E88, &fmCfg, 4); + + gEeprom.FM_Band = fmCfg.band; + //gEeprom.FM_Space = fmCfg.space; + gEeprom.FM_SelectedFrequency = + (fmCfg.selFreq >= BK1080_GetFreqLoLimit(gEeprom.FM_Band) && fmCfg.selFreq <= BK1080_GetFreqHiLimit(gEeprom.FM_Band)) ? + fmCfg.selFreq : BK1080_GetFreqLoLimit(gEeprom.FM_Band); + + gEeprom.FM_SelectedChannel = fmCfg.selChn; + gEeprom.FM_IsMrMode = fmCfg.isMrMode; + } + + // 0E40..0E67 + EEPROM_ReadBuffer(0x0E40, gFM_Channels, sizeof(gFM_Channels)); + FM_ConfigureChannelState(); +#endif + + // 0E90..0E97 + EEPROM_ReadBuffer(0x0E90, Data, 8); + gEeprom.BEEP_CONTROL = Data[0] & 1; + gEeprom.KEY_M_LONG_PRESS_ACTION = ((Data[0] >> 1) < ACTION_OPT_LEN) ? (Data[0] >> 1) : ACTION_OPT_NONE; + gEeprom.KEY_1_SHORT_PRESS_ACTION = (Data[1] < ACTION_OPT_LEN) ? Data[1] : ACTION_OPT_MONITOR; + gEeprom.KEY_1_LONG_PRESS_ACTION = (Data[2] < ACTION_OPT_LEN) ? Data[2] : ACTION_OPT_NONE; + gEeprom.KEY_2_SHORT_PRESS_ACTION = (Data[3] < ACTION_OPT_LEN) ? Data[3] : ACTION_OPT_SCAN; + gEeprom.KEY_2_LONG_PRESS_ACTION = (Data[4] < ACTION_OPT_LEN) ? Data[4] : ACTION_OPT_NONE; + gEeprom.SCAN_RESUME_MODE = (Data[5] < 3) ? Data[5] : SCAN_RESUME_CO; + gEeprom.AUTO_KEYPAD_LOCK = (Data[6] < 2) ? Data[6] : false; #ifdef ENABLE_FEAT_F4HWN - gEeprom.POWER_ON_DISPLAY_MODE = (Data[7] < 6) ? Data[7] : POWER_ON_DISPLAY_MODE_VOLTAGE; + gEeprom.POWER_ON_DISPLAY_MODE = (Data[7] < 6) ? Data[7] : POWER_ON_DISPLAY_MODE_VOLTAGE; #else - gEeprom.POWER_ON_DISPLAY_MODE = (Data[7] < 4) ? Data[7] : POWER_ON_DISPLAY_MODE_VOLTAGE; -#endif - - // 0E98..0E9F - #ifdef ENABLE_PWRON_PASSWORD - EEPROM_ReadBuffer(0x0E98, Data, 8); - memcpy(&gEeprom.POWER_ON_PASSWORD, Data, 4); - #endif - - // 0EA0..0EA7 - EEPROM_ReadBuffer(0x0EA0, Data, 8); - #ifdef ENABLE_VOICE - gEeprom.VOICE_PROMPT = (Data[0] < 3) ? Data[0] : VOICE_PROMPT_ENGLISH; - #endif - #ifdef ENABLE_RSSI_BAR - if((Data[1] < 200 && Data[1] > 90) && (Data[2] < Data[1]-9 && Data[1] < 160 && Data[2] > 50)) { - gEeprom.S0_LEVEL = Data[1]; - gEeprom.S9_LEVEL = Data[2]; - } - else { - gEeprom.S0_LEVEL = 130; - gEeprom.S9_LEVEL = 76; - } - #endif - - // 0EA8..0EAF - EEPROM_ReadBuffer(0x0EA8, Data, 8); - #ifdef ENABLE_ALARM - gEeprom.ALARM_MODE = (Data[0] < 2) ? Data[0] : true; - #endif - gEeprom.ROGER = (Data[1] < 3) ? Data[1] : ROGER_MODE_OFF; - gEeprom.REPEATER_TAIL_TONE_ELIMINATION = (Data[2] < 11) ? Data[2] : 0; - gEeprom.TX_VFO = (Data[3] < 2) ? Data[3] : 0; - gEeprom.BATTERY_TYPE = (Data[4] < BATTERY_TYPE_UNKNOWN) ? Data[4] : BATTERY_TYPE_1600_MAH; - - // 0ED0..0ED7 - EEPROM_ReadBuffer(0x0ED0, Data, 8); - gEeprom.DTMF_SIDE_TONE = (Data[0] < 2) ? Data[0] : true; + gEeprom.POWER_ON_DISPLAY_MODE = (Data[7] < 4) ? Data[7] : POWER_ON_DISPLAY_MODE_VOLTAGE; +#endif + + // 0E98..0E9F + #ifdef ENABLE_PWRON_PASSWORD + EEPROM_ReadBuffer(0x0E98, Data, 8); + memcpy(&gEeprom.POWER_ON_PASSWORD, Data, 4); + #endif + + // 0EA0..0EA7 + EEPROM_ReadBuffer(0x0EA0, Data, 8); + #ifdef ENABLE_VOICE + gEeprom.VOICE_PROMPT = (Data[0] < 3) ? Data[0] : VOICE_PROMPT_ENGLISH; + #endif + #ifdef ENABLE_RSSI_BAR + if((Data[1] < 200 && Data[1] > 90) && (Data[2] < Data[1]-9 && Data[1] < 160 && Data[2] > 50)) { + gEeprom.S0_LEVEL = Data[1]; + gEeprom.S9_LEVEL = Data[2]; + } + else { + gEeprom.S0_LEVEL = 130; + gEeprom.S9_LEVEL = 76; + } + #endif + + // 0EA8..0EAF + EEPROM_ReadBuffer(0x0EA8, Data, 8); + #ifdef ENABLE_ALARM + gEeprom.ALARM_MODE = (Data[0] < 2) ? Data[0] : true; + #endif + gEeprom.ROGER = (Data[1] < 3) ? Data[1] : ROGER_MODE_OFF; + gEeprom.REPEATER_TAIL_TONE_ELIMINATION = (Data[2] < 11) ? Data[2] : 0; + gEeprom.TX_VFO = (Data[3] < 2) ? Data[3] : 0; + gEeprom.BATTERY_TYPE = (Data[4] < BATTERY_TYPE_UNKNOWN) ? Data[4] : BATTERY_TYPE_1600_MAH; + + // 0ED0..0ED7 + EEPROM_ReadBuffer(0x0ED0, Data, 8); + gEeprom.DTMF_SIDE_TONE = (Data[0] < 2) ? Data[0] : true; #ifdef ENABLE_DTMF_CALLING - gEeprom.DTMF_SEPARATE_CODE = DTMF_ValidateCodes((char *)(Data + 1), 1) ? Data[1] : '*'; - gEeprom.DTMF_GROUP_CALL_CODE = DTMF_ValidateCodes((char *)(Data + 2), 1) ? Data[2] : '#'; - gEeprom.DTMF_DECODE_RESPONSE = (Data[3] < 4) ? Data[3] : 0; - gEeprom.DTMF_auto_reset_time = (Data[4] < 61) ? Data[4] : (Data[4] >= 5) ? Data[4] : 10; -#endif - gEeprom.DTMF_PRELOAD_TIME = (Data[5] < 101) ? Data[5] * 10 : 300; - gEeprom.DTMF_FIRST_CODE_PERSIST_TIME = (Data[6] < 101) ? Data[6] * 10 : 100; - gEeprom.DTMF_HASH_CODE_PERSIST_TIME = (Data[7] < 101) ? Data[7] * 10 : 100; - - // 0ED8..0EDF - EEPROM_ReadBuffer(0x0ED8, Data, 8); - gEeprom.DTMF_CODE_PERSIST_TIME = (Data[0] < 101) ? Data[0] * 10 : 100; - gEeprom.DTMF_CODE_INTERVAL_TIME = (Data[1] < 101) ? Data[1] * 10 : 100; + gEeprom.DTMF_SEPARATE_CODE = DTMF_ValidateCodes((char *)(Data + 1), 1) ? Data[1] : '*'; + gEeprom.DTMF_GROUP_CALL_CODE = DTMF_ValidateCodes((char *)(Data + 2), 1) ? Data[2] : '#'; + gEeprom.DTMF_DECODE_RESPONSE = (Data[3] < 4) ? Data[3] : 0; + gEeprom.DTMF_auto_reset_time = (Data[4] < 61) ? Data[4] : (Data[4] >= 5) ? Data[4] : 10; +#endif + gEeprom.DTMF_PRELOAD_TIME = (Data[5] < 101) ? Data[5] * 10 : 300; + gEeprom.DTMF_FIRST_CODE_PERSIST_TIME = (Data[6] < 101) ? Data[6] * 10 : 100; + gEeprom.DTMF_HASH_CODE_PERSIST_TIME = (Data[7] < 101) ? Data[7] * 10 : 100; + + // 0ED8..0EDF + EEPROM_ReadBuffer(0x0ED8, Data, 8); + gEeprom.DTMF_CODE_PERSIST_TIME = (Data[0] < 101) ? Data[0] * 10 : 100; + gEeprom.DTMF_CODE_INTERVAL_TIME = (Data[1] < 101) ? Data[1] * 10 : 100; #ifdef ENABLE_DTMF_CALLING - gEeprom.PERMIT_REMOTE_KILL = (Data[2] < 2) ? Data[2] : true; - - // 0EE0..0EE7 - - EEPROM_ReadBuffer(0x0EE0, Data, sizeof(gEeprom.ANI_DTMF_ID)); - if (DTMF_ValidateCodes((char *)Data, sizeof(gEeprom.ANI_DTMF_ID))) { - memcpy(gEeprom.ANI_DTMF_ID, Data, sizeof(gEeprom.ANI_DTMF_ID)); - } else { - strcpy(gEeprom.ANI_DTMF_ID, "123"); - } - - - // 0EE8..0EEF - EEPROM_ReadBuffer(0x0EE8, Data, sizeof(gEeprom.KILL_CODE)); - if (DTMF_ValidateCodes((char *)Data, sizeof(gEeprom.KILL_CODE))) { - memcpy(gEeprom.KILL_CODE, Data, sizeof(gEeprom.KILL_CODE)); - } else { - strcpy(gEeprom.KILL_CODE, "ABCD9"); - } - - // 0EF0..0EF7 - EEPROM_ReadBuffer(0x0EF0, Data, sizeof(gEeprom.REVIVE_CODE)); - if (DTMF_ValidateCodes((char *)Data, sizeof(gEeprom.REVIVE_CODE))) { - memcpy(gEeprom.REVIVE_CODE, Data, sizeof(gEeprom.REVIVE_CODE)); - } else { - strcpy(gEeprom.REVIVE_CODE, "9DCBA"); - } -#endif - - // 0EF8..0F07 - EEPROM_ReadBuffer(0x0EF8, Data, sizeof(gEeprom.DTMF_UP_CODE)); - if (DTMF_ValidateCodes((char *)Data, sizeof(gEeprom.DTMF_UP_CODE))) { - memcpy(gEeprom.DTMF_UP_CODE, Data, sizeof(gEeprom.DTMF_UP_CODE)); - } else { - strcpy(gEeprom.DTMF_UP_CODE, "12345"); - } - - // 0F08..0F17 - EEPROM_ReadBuffer(0x0F08, Data, sizeof(gEeprom.DTMF_DOWN_CODE)); - if (DTMF_ValidateCodes((char *)Data, sizeof(gEeprom.DTMF_DOWN_CODE))) { - memcpy(gEeprom.DTMF_DOWN_CODE, Data, sizeof(gEeprom.DTMF_DOWN_CODE)); - } else { - strcpy(gEeprom.DTMF_DOWN_CODE, "54321"); - } - - // 0F18..0F1F - EEPROM_ReadBuffer(0x0F18, Data, 8); - gEeprom.SCAN_LIST_DEFAULT = (Data[0] < 6) ? Data[0] : 0; // we now have 'all' channel scan option - - // Fake data - /* - gEeprom.SCAN_LIST_ENABLED[0] = 0; - gEeprom.SCAN_LIST_ENABLED[1] = 0; - gEeprom.SCAN_LIST_ENABLED[2] = 0; - - gEeprom.SCANLIST_PRIORITY_CH1[0] = 0; - gEeprom.SCANLIST_PRIORITY_CH2[0] = 2; - - gEeprom.SCANLIST_PRIORITY_CH1[1] = 14; - gEeprom.SCANLIST_PRIORITY_CH2[1] = 15; - - gEeprom.SCANLIST_PRIORITY_CH1[2] = 40; - gEeprom.SCANLIST_PRIORITY_CH2[2] = 41; - */ - - // Fix me probably after Chirp update... - for (unsigned int i = 0; i < 3; i++) - { - gEeprom.SCAN_LIST_ENABLED[i] = (Data[1] >> i) & 1; - } - - for (unsigned int i = 0; i < 3; i++) - { - const unsigned int j = 1 + (i * 2); - gEeprom.SCANLIST_PRIORITY_CH1[i] = Data[j + 1]; - gEeprom.SCANLIST_PRIORITY_CH2[i] = Data[j + 2]; - } - - // 0F40..0F47 - EEPROM_ReadBuffer(0x0F40, Data, 8); - gSetting_F_LOCK = (Data[0] < F_LOCK_LEN) ? Data[0] : F_LOCK_DEF; - gSetting_350TX = (Data[1] < 2) ? Data[1] : false; // was true + gEeprom.PERMIT_REMOTE_KILL = (Data[2] < 2) ? Data[2] : true; + + // 0EE0..0EE7 + + EEPROM_ReadBuffer(0x0EE0, Data, sizeof(gEeprom.ANI_DTMF_ID)); + if (DTMF_ValidateCodes((char *)Data, sizeof(gEeprom.ANI_DTMF_ID))) { + memcpy(gEeprom.ANI_DTMF_ID, Data, sizeof(gEeprom.ANI_DTMF_ID)); + } else { + strcpy(gEeprom.ANI_DTMF_ID, "123"); + } + + + // 0EE8..0EEF + EEPROM_ReadBuffer(0x0EE8, Data, sizeof(gEeprom.KILL_CODE)); + if (DTMF_ValidateCodes((char *)Data, sizeof(gEeprom.KILL_CODE))) { + memcpy(gEeprom.KILL_CODE, Data, sizeof(gEeprom.KILL_CODE)); + } else { + strcpy(gEeprom.KILL_CODE, "ABCD9"); + } + + // 0EF0..0EF7 + EEPROM_ReadBuffer(0x0EF0, Data, sizeof(gEeprom.REVIVE_CODE)); + if (DTMF_ValidateCodes((char *)Data, sizeof(gEeprom.REVIVE_CODE))) { + memcpy(gEeprom.REVIVE_CODE, Data, sizeof(gEeprom.REVIVE_CODE)); + } else { + strcpy(gEeprom.REVIVE_CODE, "9DCBA"); + } +#endif + + // 0EF8..0F07 + EEPROM_ReadBuffer(0x0EF8, Data, sizeof(gEeprom.DTMF_UP_CODE)); + if (DTMF_ValidateCodes((char *)Data, sizeof(gEeprom.DTMF_UP_CODE))) { + memcpy(gEeprom.DTMF_UP_CODE, Data, sizeof(gEeprom.DTMF_UP_CODE)); + } else { + strcpy(gEeprom.DTMF_UP_CODE, "12345"); + } + + // 0F08..0F17 + EEPROM_ReadBuffer(0x0F08, Data, sizeof(gEeprom.DTMF_DOWN_CODE)); + if (DTMF_ValidateCodes((char *)Data, sizeof(gEeprom.DTMF_DOWN_CODE))) { + memcpy(gEeprom.DTMF_DOWN_CODE, Data, sizeof(gEeprom.DTMF_DOWN_CODE)); + } else { + strcpy(gEeprom.DTMF_DOWN_CODE, "54321"); + } + + // 0F18..0F1F + EEPROM_ReadBuffer(0x0F18, Data, 8); + gEeprom.SCAN_LIST_DEFAULT = (Data[0] < 6) ? Data[0] : 0; // we now have 'all' channel scan option + + // Fake data + /* + gEeprom.SCAN_LIST_ENABLED[0] = 0; + gEeprom.SCAN_LIST_ENABLED[1] = 0; + gEeprom.SCAN_LIST_ENABLED[2] = 0; + + gEeprom.SCANLIST_PRIORITY_CH1[0] = 0; + gEeprom.SCANLIST_PRIORITY_CH2[0] = 2; + + gEeprom.SCANLIST_PRIORITY_CH1[1] = 14; + gEeprom.SCANLIST_PRIORITY_CH2[1] = 15; + + gEeprom.SCANLIST_PRIORITY_CH1[2] = 40; + gEeprom.SCANLIST_PRIORITY_CH2[2] = 41; + */ + + // Fix me probably after Chirp update... + for (unsigned int i = 0; i < 3; i++) + { + gEeprom.SCAN_LIST_ENABLED[i] = (Data[1] >> i) & 1; + } + + for (unsigned int i = 0; i < 3; i++) + { + const unsigned int j = 1 + (i * 2); + gEeprom.SCANLIST_PRIORITY_CH1[i] = Data[j + 1]; + gEeprom.SCANLIST_PRIORITY_CH2[i] = Data[j + 2]; + } + + // 0F40..0F47 + EEPROM_ReadBuffer(0x0F40, Data, 8); + gSetting_F_LOCK = (Data[0] < F_LOCK_LEN) ? Data[0] : F_LOCK_DEF; + gSetting_350TX = (Data[1] < 2) ? Data[1] : false; // was true #ifdef ENABLE_DTMF_CALLING - gSetting_KILLED = (Data[2] < 2) ? Data[2] : false; + gSetting_KILLED = (Data[2] < 2) ? Data[2] : false; #endif - gSetting_200TX = (Data[3] < 2) ? Data[3] : false; - gSetting_500TX = (Data[4] < 2) ? Data[4] : false; - gSetting_350EN = (Data[5] < 2) ? Data[5] : true; + gSetting_200TX = (Data[3] < 2) ? Data[3] : false; + gSetting_500TX = (Data[4] < 2) ? Data[4] : false; + gSetting_350EN = (Data[5] < 2) ? Data[5] : true; #ifdef ENABLE_FEAT_F4HWN - gSetting_ScrambleEnable = false; + gSetting_ScrambleEnable = false; #else - gSetting_ScrambleEnable = (Data[6] < 2) ? Data[6] : true; -#endif - - //gSetting_TX_EN = (Data[7] & (1u << 0)) ? true : false; - gSetting_live_DTMF_decoder = !!(Data[7] & (1u << 1)); - gSetting_battery_text = (((Data[7] >> 2) & 3u) <= 2) ? (Data[7] >> 2) & 3 : 2; - #ifdef ENABLE_AUDIO_BAR - gSetting_mic_bar = !!(Data[7] & (1u << 4)); - #endif - #ifndef ENABLE_FEAT_F4HWN - #ifdef ENABLE_AM_FIX - gSetting_AM_fix = !!(Data[7] & (1u << 5)); - #endif - #endif - gSetting_backlight_on_tx_rx = (Data[7] >> 6) & 3u; - - if (!gEeprom.VFO_OPEN) - { - gEeprom.ScreenChannel[0] = gEeprom.MrChannel[0]; - gEeprom.ScreenChannel[1] = gEeprom.MrChannel[1]; - } - - // 0D60..0E27 - EEPROM_ReadBuffer(0x0D60, gMR_ChannelAttributes, sizeof(gMR_ChannelAttributes)); - for(uint16_t i = 0; i < sizeof(gMR_ChannelAttributes); i++) { - ChannelAttributes_t *att = &gMR_ChannelAttributes[i]; - if(att->__val == 0xff){ - att->__val = 0; - att->band = 0x7; - } - gMR_ChannelExclude[i] = false; - } - - // 0F30..0F3F - EEPROM_ReadBuffer(0x0F30, gCustomAesKey, sizeof(gCustomAesKey)); - bHasCustomAesKey = false; - for (unsigned int i = 0; i < ARRAY_SIZE(gCustomAesKey); i++) - { - if (gCustomAesKey[i] != 0xFFFFFFFFu) - { - bHasCustomAesKey = true; - return; - } - } - - #ifdef ENABLE_FEAT_F4HWN - // 1FF0..0x1FF7 - EEPROM_ReadBuffer(0x1FF0, Data, 8); - gSetting_set_pwr = (((Data[7] & 0xF0) >> 4) < 7) ? ((Data[7] & 0xF0) >> 4) : 0; - gSetting_set_ptt = (((Data[7] & 0x0F)) < 2) ? ((Data[7] & 0x0F)) : 0; - - gSetting_set_tot = (((Data[6] & 0xF0) >> 4) < 4) ? ((Data[6] & 0xF0) >> 4) : 0; - gSetting_set_eot = (((Data[6] & 0x0F)) < 4) ? ((Data[6] & 0x0F)) : 0; - - /* - int tmp = ((Data[5] & 0xF0) >> 4); - - gSetting_set_inv = (((tmp >> 0) & 0x01) < 2) ? ((tmp >> 0) & 0x01): 0; - gSetting_set_lck = (((tmp >> 1) & 0x01) < 2) ? ((tmp >> 1) & 0x01): 0; - gSetting_set_met = (((tmp >> 2) & 0x01) < 2) ? ((tmp >> 2) & 0x01): 0; - gSetting_set_gui = (((tmp >> 3) & 0x01) < 2) ? ((tmp >> 3) & 0x01): 0; - gSetting_set_ctr = (((Data[5] & 0x0F)) > 00 && ((Data[5] & 0x0F)) < 16) ? ((Data[5] & 0x0F)) : 10; - - gSetting_set_tmr = ((Data[4] & 1) < 2) ? (Data[4] & 1): 0; - */ - - int tmp = (Data[5] & 0xF0) >> 4; - - gSetting_set_inv = (tmp >> 0) & 0x01; - gSetting_set_lck = (tmp >> 1) & 0x01; - gSetting_set_met = (tmp >> 2) & 0x01; - gSetting_set_gui = (tmp >> 3) & 0x01; - - int ctr_value = Data[5] & 0x0F; - gSetting_set_ctr = (ctr_value > 0 && ctr_value < 16) ? ctr_value : 10; - - gSetting_set_tmr = Data[4] & 1; - - // And set special session settings for actions - gSetting_set_ptt_session = gSetting_set_ptt; - gEeprom.KEY_LOCK_PTT = gSetting_set_lck; - #endif + gSetting_ScrambleEnable = (Data[6] < 2) ? Data[6] : true; +#endif + + //gSetting_TX_EN = (Data[7] & (1u << 0)) ? true : false; + gSetting_live_DTMF_decoder = !!(Data[7] & (1u << 1)); + gSetting_battery_text = (((Data[7] >> 2) & 3u) <= 2) ? (Data[7] >> 2) & 3 : 2; + #ifdef ENABLE_AUDIO_BAR + gSetting_mic_bar = !!(Data[7] & (1u << 4)); + #endif + #ifndef ENABLE_FEAT_F4HWN + #ifdef ENABLE_AM_FIX + gSetting_AM_fix = !!(Data[7] & (1u << 5)); + #endif + #endif + gSetting_backlight_on_tx_rx = (Data[7] >> 6) & 3u; + + if (!gEeprom.VFO_OPEN) + { + gEeprom.ScreenChannel[0] = gEeprom.MrChannel[0]; + gEeprom.ScreenChannel[1] = gEeprom.MrChannel[1]; + } + + // 0D60..0E27 + EEPROM_ReadBuffer(0x0D60, gMR_ChannelAttributes, sizeof(gMR_ChannelAttributes)); + for(uint16_t i = 0; i < sizeof(gMR_ChannelAttributes); i++) { + ChannelAttributes_t *att = &gMR_ChannelAttributes[i]; + if(att->__val == 0xff){ + att->__val = 0; + att->band = 0x7; + } + gMR_ChannelExclude[i] = false; + } + + // 0F30..0F3F + EEPROM_ReadBuffer(0x0F30, gCustomAesKey, sizeof(gCustomAesKey)); + bHasCustomAesKey = false; + for (unsigned int i = 0; i < ARRAY_SIZE(gCustomAesKey); i++) + { + if (gCustomAesKey[i] != 0xFFFFFFFFu) + { + bHasCustomAesKey = true; + return; + } + } + + #ifdef ENABLE_FEAT_F4HWN + // 1FF0..0x1FF7 + EEPROM_ReadBuffer(0x1FF0, Data, 8); + gSetting_set_pwr = (((Data[7] & 0xF0) >> 4) < 7) ? ((Data[7] & 0xF0) >> 4) : 0; + gSetting_set_ptt = (((Data[7] & 0x0F)) < 2) ? ((Data[7] & 0x0F)) : 0; + + gSetting_set_tot = (((Data[6] & 0xF0) >> 4) < 4) ? ((Data[6] & 0xF0) >> 4) : 0; + gSetting_set_eot = (((Data[6] & 0x0F)) < 4) ? ((Data[6] & 0x0F)) : 0; + + /* + int tmp = ((Data[5] & 0xF0) >> 4); + + gSetting_set_inv = (((tmp >> 0) & 0x01) < 2) ? ((tmp >> 0) & 0x01): 0; + gSetting_set_lck = (((tmp >> 1) & 0x01) < 2) ? ((tmp >> 1) & 0x01): 0; + gSetting_set_met = (((tmp >> 2) & 0x01) < 2) ? ((tmp >> 2) & 0x01): 0; + gSetting_set_gui = (((tmp >> 3) & 0x01) < 2) ? ((tmp >> 3) & 0x01): 0; + gSetting_set_ctr = (((Data[5] & 0x0F)) > 00 && ((Data[5] & 0x0F)) < 16) ? ((Data[5] & 0x0F)) : 10; + + gSetting_set_tmr = ((Data[4] & 1) < 2) ? (Data[4] & 1): 0; + */ + + int tmp = (Data[5] & 0xF0) >> 4; + + gSetting_set_inv = (tmp >> 0) & 0x01; + gSetting_set_lck = (tmp >> 1) & 0x01; + gSetting_set_met = (tmp >> 2) & 0x01; + gSetting_set_gui = (tmp >> 3) & 0x01; + + int ctr_value = Data[5] & 0x0F; + gSetting_set_ctr = (ctr_value > 0 && ctr_value < 16) ? ctr_value : 10; + + gSetting_set_tmr = Data[4] & 1; + + // And set special session settings for actions + gSetting_set_ptt_session = gSetting_set_ptt; + gEeprom.KEY_LOCK_PTT = gSetting_set_lck; + #endif } void SETTINGS_LoadCalibration(void) { -// uint8_t Mic; - - EEPROM_ReadBuffer(0x1EC0, gEEPROM_RSSI_CALIB[3], 8); - memcpy(gEEPROM_RSSI_CALIB[4], gEEPROM_RSSI_CALIB[3], 8); - memcpy(gEEPROM_RSSI_CALIB[5], gEEPROM_RSSI_CALIB[3], 8); - memcpy(gEEPROM_RSSI_CALIB[6], gEEPROM_RSSI_CALIB[3], 8); - - EEPROM_ReadBuffer(0x1EC8, gEEPROM_RSSI_CALIB[0], 8); - memcpy(gEEPROM_RSSI_CALIB[1], gEEPROM_RSSI_CALIB[0], 8); - memcpy(gEEPROM_RSSI_CALIB[2], gEEPROM_RSSI_CALIB[0], 8); - - EEPROM_ReadBuffer(0x1F40, gBatteryCalibration, 12); - if (gBatteryCalibration[0] >= 5000) - { - gBatteryCalibration[0] = 1900; - gBatteryCalibration[1] = 2000; - } - gBatteryCalibration[5] = 2300; - - #ifdef ENABLE_VOX - EEPROM_ReadBuffer(0x1F50 + (gEeprom.VOX_LEVEL * 2), &gEeprom.VOX1_THRESHOLD, 2); - EEPROM_ReadBuffer(0x1F68 + (gEeprom.VOX_LEVEL * 2), &gEeprom.VOX0_THRESHOLD, 2); - #endif - - //EEPROM_ReadBuffer(0x1F80 + gEeprom.MIC_SENSITIVITY, &Mic, 1); - //gEeprom.MIC_SENSITIVITY_TUNING = (Mic < 32) ? Mic : 15; - gEeprom.MIC_SENSITIVITY_TUNING = gMicGain_dB2[gEeprom.MIC_SENSITIVITY]; - - { - struct - { - int16_t BK4819_XtalFreqLow; - uint16_t EEPROM_1F8A; - uint16_t EEPROM_1F8C; - uint8_t VOLUME_GAIN; - uint8_t DAC_GAIN; - } __attribute__((packed)) Misc; - - // radio 1 .. 04 00 46 00 50 00 2C 0E - // radio 2 .. 05 00 46 00 50 00 2C 0E - EEPROM_ReadBuffer(0x1F88, &Misc, 8); - - gEeprom.BK4819_XTAL_FREQ_LOW = (Misc.BK4819_XtalFreqLow >= -1000 && Misc.BK4819_XtalFreqLow <= 1000) ? Misc.BK4819_XtalFreqLow : 0; - gEEPROM_1F8A = Misc.EEPROM_1F8A & 0x01FF; - gEEPROM_1F8C = Misc.EEPROM_1F8C & 0x01FF; - gEeprom.VOLUME_GAIN = (Misc.VOLUME_GAIN < 64) ? Misc.VOLUME_GAIN : 58; - gEeprom.DAC_GAIN = (Misc.DAC_GAIN < 16) ? Misc.DAC_GAIN : 8; - - BK4819_WriteRegister(BK4819_REG_3B, 22656 + gEeprom.BK4819_XTAL_FREQ_LOW); -// BK4819_WriteRegister(BK4819_REG_3C, gEeprom.BK4819_XTAL_FREQ_HIGH); - } +// uint8_t Mic; + + EEPROM_ReadBuffer(0x1EC0, gEEPROM_RSSI_CALIB[3], 8); + memcpy(gEEPROM_RSSI_CALIB[4], gEEPROM_RSSI_CALIB[3], 8); + memcpy(gEEPROM_RSSI_CALIB[5], gEEPROM_RSSI_CALIB[3], 8); + memcpy(gEEPROM_RSSI_CALIB[6], gEEPROM_RSSI_CALIB[3], 8); + + EEPROM_ReadBuffer(0x1EC8, gEEPROM_RSSI_CALIB[0], 8); + memcpy(gEEPROM_RSSI_CALIB[1], gEEPROM_RSSI_CALIB[0], 8); + memcpy(gEEPROM_RSSI_CALIB[2], gEEPROM_RSSI_CALIB[0], 8); + + EEPROM_ReadBuffer(0x1F40, gBatteryCalibration, 12); + if (gBatteryCalibration[0] >= 5000) + { + gBatteryCalibration[0] = 1900; + gBatteryCalibration[1] = 2000; + } + gBatteryCalibration[5] = 2300; + + #ifdef ENABLE_VOX + EEPROM_ReadBuffer(0x1F50 + (gEeprom.VOX_LEVEL * 2), &gEeprom.VOX1_THRESHOLD, 2); + EEPROM_ReadBuffer(0x1F68 + (gEeprom.VOX_LEVEL * 2), &gEeprom.VOX0_THRESHOLD, 2); + #endif + + //EEPROM_ReadBuffer(0x1F80 + gEeprom.MIC_SENSITIVITY, &Mic, 1); + //gEeprom.MIC_SENSITIVITY_TUNING = (Mic < 32) ? Mic : 15; + gEeprom.MIC_SENSITIVITY_TUNING = gMicGain_dB2[gEeprom.MIC_SENSITIVITY]; + + { + struct + { + int16_t BK4819_XtalFreqLow; + uint16_t EEPROM_1F8A; + uint16_t EEPROM_1F8C; + uint8_t VOLUME_GAIN; + uint8_t DAC_GAIN; + } __attribute__((packed)) Misc; + + // radio 1 .. 04 00 46 00 50 00 2C 0E + // radio 2 .. 05 00 46 00 50 00 2C 0E + EEPROM_ReadBuffer(0x1F88, &Misc, 8); + + gEeprom.BK4819_XTAL_FREQ_LOW = (Misc.BK4819_XtalFreqLow >= -1000 && Misc.BK4819_XtalFreqLow <= 1000) ? Misc.BK4819_XtalFreqLow : 0; + gEEPROM_1F8A = Misc.EEPROM_1F8A & 0x01FF; + gEEPROM_1F8C = Misc.EEPROM_1F8C & 0x01FF; + gEeprom.VOLUME_GAIN = (Misc.VOLUME_GAIN < 64) ? Misc.VOLUME_GAIN : 58; + gEeprom.DAC_GAIN = (Misc.DAC_GAIN < 16) ? Misc.DAC_GAIN : 8; + + BK4819_WriteRegister(BK4819_REG_3B, 22656 + gEeprom.BK4819_XTAL_FREQ_LOW); +// BK4819_WriteRegister(BK4819_REG_3C, gEeprom.BK4819_XTAL_FREQ_HIGH); + } } uint32_t SETTINGS_FetchChannelFrequency(const int channel) { - struct - { - uint32_t frequency; - uint32_t offset; - } __attribute__((packed)) info; + struct + { + uint32_t frequency; + uint32_t offset; + } __attribute__((packed)) info; - EEPROM_ReadBuffer(channel * 16, &info, sizeof(info)); + EEPROM_ReadBuffer(channel * 16, &info, sizeof(info)); - return info.frequency; + return info.frequency; } void SETTINGS_FetchChannelName(char *s, const int channel) { - if (s == NULL) - return; + if (s == NULL) + return; - s[0] = 0; + s[0] = 0; - if (channel < 0) - return; + if (channel < 0) + return; - if (!RADIO_CheckValidChannel(channel, false, 0)) - return; + if (!RADIO_CheckValidChannel(channel, false, 0)) + return; - EEPROM_ReadBuffer(0x0F50 + (channel * 16), s, 10); + EEPROM_ReadBuffer(0x0F50 + (channel * 16), s, 10); - int i; - for (i = 0; i < 10; i++) - if (s[i] < 32 || s[i] > 127) - break; // invalid char + int i; + for (i = 0; i < 10; i++) + if (s[i] < 32 || s[i] > 127) + break; // invalid char - s[i--] = 0; // null term + s[i--] = 0; // null term - while (i >= 0 && s[i] == 32) // trim trailing spaces - s[i--] = 0; // null term + while (i >= 0 && s[i] == 32) // trim trailing spaces + s[i--] = 0; // null term } void SETTINGS_FactoryReset(bool bIsAll) { - uint16_t i; - uint8_t Template[8]; - - memset(Template, 0xFF, sizeof(Template)); - - //for (i = 0x0C80; i < 0x1E00; i += 8) - for (i = 0x0000; i < 0x1E00; i += 8) - { - if ( - !(i >= 0x0EE0 && i < 0x0F18) && // ANI ID + DTMF codes - !(i >= 0x0F30 && i < 0x0F50) && // AES KEY + F LOCK + Scramble Enable - !(i >= 0x1C00 && i < 0x1E00) && // DTMF contacts - !(i >= 0x0EB0 && i < 0x0ED0) && // Welcome strings - !(i >= 0x0EA0 && i < 0x0EA8) && // Voice Prompt - (bIsAll || - ( - !(i >= 0x0D60 && i < 0x0E28) && // MR Channel Attributes - !(i >= 0x0F18 && i < 0x0F30) && // Scan List - !(i >= 0x0F50 && i < 0x1C00) && // MR Channel Names - !(i >= 0x0E40 && i < 0x0E70) && // FM Channels - !(i >= 0x0E88 && i < 0x0E90) // FM settings - )) - ) - { - EEPROM_WriteBuffer(i, Template); - } - } - - if (bIsAll) - { - RADIO_InitInfo(gRxVfo, FREQ_CHANNEL_FIRST + BAND6_400MHz, 43350000); - - // set the first few memory channels - for (i = 0; i < ARRAY_SIZE(gDefaultFrequencyTable); i++) - { - const uint32_t Frequency = gDefaultFrequencyTable[i]; - gRxVfo->freq_config_RX.Frequency = Frequency; - gRxVfo->freq_config_TX.Frequency = Frequency; - gRxVfo->Band = FREQUENCY_GetBand(Frequency); - SETTINGS_SaveChannel(MR_CHANNEL_FIRST + i, 0, gRxVfo, 2); - } - - #ifdef ENABLE_FEAT_F4HWN - EEPROM_WriteBuffer(0x1FF0, Template); - #endif - } + uint16_t i; + uint8_t Template[8]; + + memset(Template, 0xFF, sizeof(Template)); + + //for (i = 0x0C80; i < 0x1E00; i += 8) + for (i = 0x0000; i < 0x1E00; i += 8) + { + if ( + !(i >= 0x0EE0 && i < 0x0F18) && // ANI ID + DTMF codes + !(i >= 0x0F30 && i < 0x0F50) && // AES KEY + F LOCK + Scramble Enable + !(i >= 0x1C00 && i < 0x1E00) && // DTMF contacts + !(i >= 0x0EB0 && i < 0x0ED0) && // Welcome strings + !(i >= 0x0EA0 && i < 0x0EA8) && // Voice Prompt + (bIsAll || + ( + !(i >= 0x0D60 && i < 0x0E28) && // MR Channel Attributes + !(i >= 0x0F18 && i < 0x0F30) && // Scan List + !(i >= 0x0F50 && i < 0x1C00) && // MR Channel Names + !(i >= 0x0E40 && i < 0x0E70) && // FM Channels + !(i >= 0x0E88 && i < 0x0E90) // FM settings + )) + ) + { + EEPROM_WriteBuffer(i, Template); + } + } + + if (bIsAll) + { + RADIO_InitInfo(gRxVfo, FREQ_CHANNEL_FIRST + BAND6_400MHz, 43350000); + + // set the first few memory channels + for (i = 0; i < ARRAY_SIZE(gDefaultFrequencyTable); i++) + { + const uint32_t Frequency = gDefaultFrequencyTable[i]; + gRxVfo->freq_config_RX.Frequency = Frequency; + gRxVfo->freq_config_TX.Frequency = Frequency; + gRxVfo->Band = FREQUENCY_GetBand(Frequency); + SETTINGS_SaveChannel(MR_CHANNEL_FIRST + i, 0, gRxVfo, 2); + } + + #ifdef ENABLE_FEAT_F4HWN + EEPROM_WriteBuffer(0x1FF0, Template); + #endif + } } #ifdef ENABLE_FMRADIO void SETTINGS_SaveFM(void) - { - union { - struct { - uint16_t selFreq; - uint8_t selChn; - uint8_t isMrMode:1; - uint8_t band:2; - //uint8_t space:2; - }; - uint8_t __raw[8]; - } __attribute__((packed)) fmCfg; - - memset(fmCfg.__raw, 0xFF, sizeof(fmCfg.__raw)); - fmCfg.selChn = gEeprom.FM_SelectedChannel; - fmCfg.selFreq = gEeprom.FM_SelectedFrequency; - fmCfg.isMrMode = gEeprom.FM_IsMrMode; - fmCfg.band = gEeprom.FM_Band; - //fmCfg.space = gEeprom.FM_Space; - EEPROM_WriteBuffer(0x0E88, fmCfg.__raw); - - for (unsigned i = 0; i < 5; i++) - EEPROM_WriteBuffer(0x0E40 + (i * 8), &gFM_Channels[i * 4]); - } + { + union { + struct { + uint16_t selFreq; + uint8_t selChn; + uint8_t isMrMode:1; + uint8_t band:2; + //uint8_t space:2; + }; + uint8_t __raw[8]; + } __attribute__((packed)) fmCfg; + + memset(fmCfg.__raw, 0xFF, sizeof(fmCfg.__raw)); + fmCfg.selChn = gEeprom.FM_SelectedChannel; + fmCfg.selFreq = gEeprom.FM_SelectedFrequency; + fmCfg.isMrMode = gEeprom.FM_IsMrMode; + fmCfg.band = gEeprom.FM_Band; + //fmCfg.space = gEeprom.FM_Space; + EEPROM_WriteBuffer(0x0E88, fmCfg.__raw); + + for (unsigned i = 0; i < 5; i++) + EEPROM_WriteBuffer(0x0E40 + (i * 8), &gFM_Channels[i * 4]); + } #endif void SETTINGS_SaveVfoIndices(void) { - uint8_t State[8]; - - #ifndef ENABLE_NOAA - EEPROM_ReadBuffer(0x0E80, State, sizeof(State)); - #endif - - State[0] = gEeprom.ScreenChannel[0]; - State[1] = gEeprom.MrChannel[0]; - State[2] = gEeprom.FreqChannel[0]; - State[3] = gEeprom.ScreenChannel[1]; - State[4] = gEeprom.MrChannel[1]; - State[5] = gEeprom.FreqChannel[1]; - #ifdef ENABLE_NOAA - State[6] = gEeprom.NoaaChannel[0]; - State[7] = gEeprom.NoaaChannel[1]; - #endif - - EEPROM_WriteBuffer(0x0E80, State); + uint8_t State[8]; + + #ifndef ENABLE_NOAA + EEPROM_ReadBuffer(0x0E80, State, sizeof(State)); + #endif + + State[0] = gEeprom.ScreenChannel[0]; + State[1] = gEeprom.MrChannel[0]; + State[2] = gEeprom.FreqChannel[0]; + State[3] = gEeprom.ScreenChannel[1]; + State[4] = gEeprom.MrChannel[1]; + State[5] = gEeprom.FreqChannel[1]; + #ifdef ENABLE_NOAA + State[6] = gEeprom.NoaaChannel[0]; + State[7] = gEeprom.NoaaChannel[1]; + #endif + + EEPROM_WriteBuffer(0x0E80, State); } void SETTINGS_SaveSettings(void) { - uint8_t State[8]; - uint8_t tmp = 0; - - #ifdef ENABLE_PWRON_PASSWORD - uint32_t Password[2]; - #endif - - State[0] = gEeprom.CHAN_1_CALL; - State[1] = gEeprom.SQUELCH_LEVEL; - State[2] = gEeprom.TX_TIMEOUT_TIMER; - #ifdef ENABLE_NOAA - State[3] = gEeprom.NOAA_AUTO_SCAN; - #else - State[3] = false; - #endif - State[4] = gEeprom.KEY_LOCK; - #ifdef ENABLE_VOX - State[5] = gEeprom.VOX_SWITCH; - State[6] = gEeprom.VOX_LEVEL; - #else - State[5] = false; - State[6] = 0; - #endif - State[7] = gEeprom.MIC_SENSITIVITY; - EEPROM_WriteBuffer(0x0E70, State); - - State[0] = (gEeprom.BACKLIGHT_MIN << 4) + gEeprom.BACKLIGHT_MAX; - State[1] = gEeprom.CHANNEL_DISPLAY_MODE; - State[2] = gEeprom.CROSS_BAND_RX_TX; - State[3] = gEeprom.BATTERY_SAVE; - State[4] = gEeprom.DUAL_WATCH; - - #ifdef ENABLE_FEAT_F4HWN - if(!gSaveRxMode) - { - State[2] = gCB; - State[4] = gDW; - } - if(gBackLight) - { - State[5] = gBacklightTimeOriginal; - } - else - { - State[5] = gEeprom.BACKLIGHT_TIME; - } - #else - State[5] = gEeprom.BACKLIGHT_TIME; - #endif - - State[6] = gEeprom.TAIL_TONE_ELIMINATION; - State[7] = gEeprom.VFO_OPEN; - EEPROM_WriteBuffer(0x0E78, State); - - State[0] = gEeprom.BEEP_CONTROL; - State[0] |= gEeprom.KEY_M_LONG_PRESS_ACTION << 1; - State[1] = gEeprom.KEY_1_SHORT_PRESS_ACTION; - State[2] = gEeprom.KEY_1_LONG_PRESS_ACTION; - State[3] = gEeprom.KEY_2_SHORT_PRESS_ACTION; - State[4] = gEeprom.KEY_2_LONG_PRESS_ACTION; - State[5] = gEeprom.SCAN_RESUME_MODE; - State[6] = gEeprom.AUTO_KEYPAD_LOCK; - State[7] = gEeprom.POWER_ON_DISPLAY_MODE; - EEPROM_WriteBuffer(0x0E90, State); - - #ifdef ENABLE_PWRON_PASSWORD - memset(Password, 0xFF, sizeof(Password)); - Password[0] = gEeprom.POWER_ON_PASSWORD; - EEPROM_WriteBuffer(0x0E98, Password); - #endif - - memset(State, 0xFF, sizeof(State)); + uint8_t State[8]; + uint8_t tmp = 0; + + #ifdef ENABLE_PWRON_PASSWORD + uint32_t Password[2]; + #endif + + State[0] = gEeprom.CHAN_1_CALL; + State[1] = gEeprom.SQUELCH_LEVEL; + State[2] = gEeprom.TX_TIMEOUT_TIMER; + #ifdef ENABLE_NOAA + State[3] = gEeprom.NOAA_AUTO_SCAN; + #else + State[3] = false; + #endif + State[4] = gEeprom.KEY_LOCK; + #ifdef ENABLE_VOX + State[5] = gEeprom.VOX_SWITCH; + State[6] = gEeprom.VOX_LEVEL; + #else + State[5] = false; + State[6] = 0; + #endif + State[7] = gEeprom.MIC_SENSITIVITY; + EEPROM_WriteBuffer(0x0E70, State); + + State[0] = (gEeprom.BACKLIGHT_MIN << 4) + gEeprom.BACKLIGHT_MAX; + State[1] = gEeprom.CHANNEL_DISPLAY_MODE; + State[2] = gEeprom.CROSS_BAND_RX_TX; + State[3] = gEeprom.BATTERY_SAVE; + State[4] = gEeprom.DUAL_WATCH; + + #ifdef ENABLE_FEAT_F4HWN + if(!gSaveRxMode) + { + State[2] = gCB; + State[4] = gDW; + } + if(gBackLight) + { + State[5] = gBacklightTimeOriginal; + } + else + { + State[5] = gEeprom.BACKLIGHT_TIME; + } + #else + State[5] = gEeprom.BACKLIGHT_TIME; + #endif + + State[6] = gEeprom.TAIL_TONE_ELIMINATION; + State[7] = gEeprom.VFO_OPEN; + EEPROM_WriteBuffer(0x0E78, State); + + State[0] = gEeprom.BEEP_CONTROL; + State[0] |= gEeprom.KEY_M_LONG_PRESS_ACTION << 1; + State[1] = gEeprom.KEY_1_SHORT_PRESS_ACTION; + State[2] = gEeprom.KEY_1_LONG_PRESS_ACTION; + State[3] = gEeprom.KEY_2_SHORT_PRESS_ACTION; + State[4] = gEeprom.KEY_2_LONG_PRESS_ACTION; + State[5] = gEeprom.SCAN_RESUME_MODE; + State[6] = gEeprom.AUTO_KEYPAD_LOCK; + State[7] = gEeprom.POWER_ON_DISPLAY_MODE; + EEPROM_WriteBuffer(0x0E90, State); + + #ifdef ENABLE_PWRON_PASSWORD + memset(Password, 0xFF, sizeof(Password)); + Password[0] = gEeprom.POWER_ON_PASSWORD; + EEPROM_WriteBuffer(0x0E98, Password); + #endif + + memset(State, 0xFF, sizeof(State)); #ifdef ENABLE_VOICE - State[0] = gEeprom.VOICE_PROMPT; + State[0] = gEeprom.VOICE_PROMPT; #endif #ifdef ENABLE_RSSI_BAR - State[1] = gEeprom.S0_LEVEL; - State[2] = gEeprom.S9_LEVEL; + State[1] = gEeprom.S0_LEVEL; + State[2] = gEeprom.S9_LEVEL; #endif - EEPROM_WriteBuffer(0x0EA0, State); + EEPROM_WriteBuffer(0x0EA0, State); - #if defined(ENABLE_ALARM) || defined(ENABLE_TX1750) - State[0] = gEeprom.ALARM_MODE; - #else - State[0] = false; - #endif - State[1] = gEeprom.ROGER; - State[2] = gEeprom.REPEATER_TAIL_TONE_ELIMINATION; - State[3] = gEeprom.TX_VFO; - State[4] = gEeprom.BATTERY_TYPE; - EEPROM_WriteBuffer(0x0EA8, State); + #if defined(ENABLE_ALARM) || defined(ENABLE_TX1750) + State[0] = gEeprom.ALARM_MODE; + #else + State[0] = false; + #endif + State[1] = gEeprom.ROGER; + State[2] = gEeprom.REPEATER_TAIL_TONE_ELIMINATION; + State[3] = gEeprom.TX_VFO; + State[4] = gEeprom.BATTERY_TYPE; + EEPROM_WriteBuffer(0x0EA8, State); - State[0] = gEeprom.DTMF_SIDE_TONE; + State[0] = gEeprom.DTMF_SIDE_TONE; #ifdef ENABLE_DTMF_CALLING - State[1] = gEeprom.DTMF_SEPARATE_CODE; - State[2] = gEeprom.DTMF_GROUP_CALL_CODE; - State[3] = gEeprom.DTMF_DECODE_RESPONSE; - State[4] = gEeprom.DTMF_auto_reset_time; -#endif - State[5] = gEeprom.DTMF_PRELOAD_TIME / 10U; - State[6] = gEeprom.DTMF_FIRST_CODE_PERSIST_TIME / 10U; - State[7] = gEeprom.DTMF_HASH_CODE_PERSIST_TIME / 10U; - EEPROM_WriteBuffer(0x0ED0, State); - - memset(State, 0xFF, sizeof(State)); - State[0] = gEeprom.DTMF_CODE_PERSIST_TIME / 10U; - State[1] = gEeprom.DTMF_CODE_INTERVAL_TIME / 10U; + State[1] = gEeprom.DTMF_SEPARATE_CODE; + State[2] = gEeprom.DTMF_GROUP_CALL_CODE; + State[3] = gEeprom.DTMF_DECODE_RESPONSE; + State[4] = gEeprom.DTMF_auto_reset_time; +#endif + State[5] = gEeprom.DTMF_PRELOAD_TIME / 10U; + State[6] = gEeprom.DTMF_FIRST_CODE_PERSIST_TIME / 10U; + State[7] = gEeprom.DTMF_HASH_CODE_PERSIST_TIME / 10U; + EEPROM_WriteBuffer(0x0ED0, State); + + memset(State, 0xFF, sizeof(State)); + State[0] = gEeprom.DTMF_CODE_PERSIST_TIME / 10U; + State[1] = gEeprom.DTMF_CODE_INTERVAL_TIME / 10U; #ifdef ENABLE_DTMF_CALLING - State[2] = gEeprom.PERMIT_REMOTE_KILL; + State[2] = gEeprom.PERMIT_REMOTE_KILL; #endif - EEPROM_WriteBuffer(0x0ED8, State); + EEPROM_WriteBuffer(0x0ED8, State); - State[0] = gEeprom.SCAN_LIST_DEFAULT; + State[0] = gEeprom.SCAN_LIST_DEFAULT; - tmp = 0; + tmp = 0; - if (gEeprom.SCAN_LIST_ENABLED[0] == 1) - tmp = tmp | (1 << 0); - if (gEeprom.SCAN_LIST_ENABLED[1] == 1) - tmp = tmp | (1 << 1); - if (gEeprom.SCAN_LIST_ENABLED[2] == 1) - tmp = tmp | (1 << 2); + if (gEeprom.SCAN_LIST_ENABLED[0] == 1) + tmp = tmp | (1 << 0); + if (gEeprom.SCAN_LIST_ENABLED[1] == 1) + tmp = tmp | (1 << 1); + if (gEeprom.SCAN_LIST_ENABLED[2] == 1) + tmp = tmp | (1 << 2); - State[1] = tmp; - State[2] = gEeprom.SCANLIST_PRIORITY_CH1[0]; - State[3] = gEeprom.SCANLIST_PRIORITY_CH2[0]; - State[4] = gEeprom.SCANLIST_PRIORITY_CH1[1]; - State[5] = gEeprom.SCANLIST_PRIORITY_CH2[1]; - State[6] = gEeprom.SCANLIST_PRIORITY_CH1[2]; - State[7] = gEeprom.SCANLIST_PRIORITY_CH2[2]; - EEPROM_WriteBuffer(0x0F18, State); + State[1] = tmp; + State[2] = gEeprom.SCANLIST_PRIORITY_CH1[0]; + State[3] = gEeprom.SCANLIST_PRIORITY_CH2[0]; + State[4] = gEeprom.SCANLIST_PRIORITY_CH1[1]; + State[5] = gEeprom.SCANLIST_PRIORITY_CH2[1]; + State[6] = gEeprom.SCANLIST_PRIORITY_CH1[2]; + State[7] = gEeprom.SCANLIST_PRIORITY_CH2[2]; + EEPROM_WriteBuffer(0x0F18, State); - memset(State, 0xFF, sizeof(State)); - State[0] = gSetting_F_LOCK; - State[1] = gSetting_350TX; + memset(State, 0xFF, sizeof(State)); + State[0] = gSetting_F_LOCK; + State[1] = gSetting_350TX; #ifdef ENABLE_DTMF_CALLING - State[2] = gSetting_KILLED; + State[2] = gSetting_KILLED; #endif - State[3] = gSetting_200TX; - State[4] = gSetting_500TX; - State[5] = gSetting_350EN; + State[3] = gSetting_200TX; + State[4] = gSetting_500TX; + State[5] = gSetting_350EN; #ifdef ENABLE_FEAT_F4HWN - State[6] = false; + State[6] = false; #else - State[6] = gSetting_ScrambleEnable; + State[6] = gSetting_ScrambleEnable; #endif - //if (!gSetting_TX_EN) State[7] &= ~(1u << 0); - if (!gSetting_live_DTMF_decoder) State[7] &= ~(1u << 1); - State[7] = (State[7] & ~(3u << 2)) | ((gSetting_battery_text & 3u) << 2); - #ifdef ENABLE_AUDIO_BAR - if (!gSetting_mic_bar) State[7] &= ~(1u << 4); - #endif - #ifndef ENABLE_FEAT_F4HWN - #ifdef ENABLE_AM_FIX - if (!gSetting_AM_fix) State[7] &= ~(1u << 5); - #endif - #endif - State[7] = (State[7] & ~(3u << 6)) | ((gSetting_backlight_on_tx_rx & 3u) << 6); + //if (!gSetting_TX_EN) State[7] &= ~(1u << 0); + if (!gSetting_live_DTMF_decoder) State[7] &= ~(1u << 1); + State[7] = (State[7] & ~(3u << 2)) | ((gSetting_battery_text & 3u) << 2); + #ifdef ENABLE_AUDIO_BAR + if (!gSetting_mic_bar) State[7] &= ~(1u << 4); + #endif + #ifndef ENABLE_FEAT_F4HWN + #ifdef ENABLE_AM_FIX + if (!gSetting_AM_fix) State[7] &= ~(1u << 5); + #endif + #endif + State[7] = (State[7] & ~(3u << 6)) | ((gSetting_backlight_on_tx_rx & 3u) << 6); - EEPROM_WriteBuffer(0x0F40, State); + EEPROM_WriteBuffer(0x0F40, State); #ifdef ENABLE_FEAT_F4HWN - memset(State, 0xFF, sizeof(State)); + memset(State, 0xFF, sizeof(State)); - /* - tmp = 0; + /* + tmp = 0; - if(gSetting_set_tmr == 1) - tmp = tmp | (1 << 0); + if(gSetting_set_tmr == 1) + tmp = tmp | (1 << 0); - State[4] = tmp; + State[4] = tmp; - tmp = 0; + tmp = 0; - if(gSetting_set_inv == 1) - tmp = tmp | (1 << 0); - if (gSetting_set_lck == 1) - tmp = tmp | (1 << 1); - if (gSetting_set_met == 1) - tmp = tmp | (1 << 2); - if (gSetting_set_gui == 1) - tmp = tmp | (1 << 3); - */ + if(gSetting_set_inv == 1) + tmp = tmp | (1 << 0); + if (gSetting_set_lck == 1) + tmp = tmp | (1 << 1); + if (gSetting_set_met == 1) + tmp = tmp | (1 << 2); + if (gSetting_set_gui == 1) + tmp = tmp | (1 << 3); + */ - State[4] = gSetting_set_tmr ? (1 << 0) : 0; + State[4] = gSetting_set_tmr ? (1 << 0) : 0; - tmp = (gSetting_set_inv << 0) | - (gSetting_set_lck << 1) | - (gSetting_set_met << 2) | - (gSetting_set_gui << 3); + tmp = (gSetting_set_inv << 0) | + (gSetting_set_lck << 1) | + (gSetting_set_met << 2) | + (gSetting_set_gui << 3); - State[5] = ((tmp << 4) | (gSetting_set_ctr & 0x0F)); - State[6] = ((gSetting_set_tot << 4) | (gSetting_set_eot & 0x0F)); - State[7] = ((gSetting_set_pwr << 4) | (gSetting_set_ptt & 0x0F)); + State[5] = ((tmp << 4) | (gSetting_set_ctr & 0x0F)); + State[6] = ((gSetting_set_tot << 4) | (gSetting_set_eot & 0x0F)); + State[7] = ((gSetting_set_pwr << 4) | (gSetting_set_ptt & 0x0F)); - gEeprom.KEY_LOCK_PTT = gSetting_set_lck; + gEeprom.KEY_LOCK_PTT = gSetting_set_lck; - EEPROM_WriteBuffer(0x1FF0, State); + EEPROM_WriteBuffer(0x1FF0, State); #endif } void SETTINGS_SaveChannel(uint8_t Channel, uint8_t VFO, const VFO_Info_t *pVFO, uint8_t Mode) { #ifdef ENABLE_NOAA - if (IS_NOAA_CHANNEL(Channel)) - return; -#endif - - uint16_t OffsetVFO = Channel * 16; - - if (IS_FREQ_CHANNEL(Channel)) { // it's a VFO, not a channel - OffsetVFO = (VFO == 0) ? 0x0C80 : 0x0C90; - OffsetVFO += (Channel - FREQ_CHANNEL_FIRST) * 32; - } - - if (Mode >= 2 || IS_FREQ_CHANNEL(Channel)) { // copy VFO to a channel - union { - uint8_t _8[8]; - uint32_t _32[2]; - } State; - - State._32[0] = pVFO->freq_config_RX.Frequency; - State._32[1] = pVFO->TX_OFFSET_FREQUENCY; - EEPROM_WriteBuffer(OffsetVFO + 0, State._32); - - State._8[0] = pVFO->freq_config_RX.Code; - State._8[1] = pVFO->freq_config_TX.Code; - State._8[2] = (pVFO->freq_config_TX.CodeType << 4) | pVFO->freq_config_RX.CodeType; - State._8[3] = (pVFO->Modulation << 4) | pVFO->TX_OFFSET_FREQUENCY_DIRECTION; - State._8[4] = 0 - | (pVFO->TX_LOCK << 6) - | (pVFO->BUSY_CHANNEL_LOCK << 5) - | (pVFO->OUTPUT_POWER << 2) - | (pVFO->CHANNEL_BANDWIDTH << 1) - | (pVFO->FrequencyReverse << 0); - State._8[5] = ((pVFO->DTMF_PTT_ID_TX_MODE & 7u) << 1) + if (IS_NOAA_CHANNEL(Channel)) + return; +#endif + + uint16_t OffsetVFO = Channel * 16; + + if (IS_FREQ_CHANNEL(Channel)) { // it's a VFO, not a channel + OffsetVFO = (VFO == 0) ? 0x0C80 : 0x0C90; + OffsetVFO += (Channel - FREQ_CHANNEL_FIRST) * 32; + } + + if (Mode >= 2 || IS_FREQ_CHANNEL(Channel)) { // copy VFO to a channel + union { + uint8_t _8[8]; + uint32_t _32[2]; + } State; + + State._32[0] = pVFO->freq_config_RX.Frequency; + State._32[1] = pVFO->TX_OFFSET_FREQUENCY; + EEPROM_WriteBuffer(OffsetVFO + 0, State._32); + + State._8[0] = pVFO->freq_config_RX.Code; + State._8[1] = pVFO->freq_config_TX.Code; + State._8[2] = (pVFO->freq_config_TX.CodeType << 4) | pVFO->freq_config_RX.CodeType; + State._8[3] = (pVFO->Modulation << 4) | pVFO->TX_OFFSET_FREQUENCY_DIRECTION; + State._8[4] = 0 + | (pVFO->TX_LOCK << 6) + | (pVFO->BUSY_CHANNEL_LOCK << 5) + | (pVFO->OUTPUT_POWER << 2) + | (pVFO->CHANNEL_BANDWIDTH << 1) + | (pVFO->FrequencyReverse << 0); + State._8[5] = ((pVFO->DTMF_PTT_ID_TX_MODE & 7u) << 1) #ifdef ENABLE_DTMF_CALLING - | ((pVFO->DTMF_DECODING_ENABLE & 1u) << 0) + | ((pVFO->DTMF_DECODING_ENABLE & 1u) << 0) #endif - ; - State._8[6] = pVFO->STEP_SETTING; + ; + State._8[6] = pVFO->STEP_SETTING; #ifdef ENABLE_FEAT_F4HWN - State._8[7] = 0; + State._8[7] = 0; #else - State._8[7] = pVFO->SCRAMBLING_TYPE; + State._8[7] = pVFO->SCRAMBLING_TYPE; #endif - EEPROM_WriteBuffer(OffsetVFO + 8, State._8); + EEPROM_WriteBuffer(OffsetVFO + 8, State._8); - SETTINGS_UpdateChannel(Channel, pVFO, true, true, true); + SETTINGS_UpdateChannel(Channel, pVFO, true, true, true); - if (IS_MR_CHANNEL(Channel)) { + if (IS_MR_CHANNEL(Channel)) { #ifndef ENABLE_KEEP_MEM_NAME - // clear/reset the channel name - SETTINGS_SaveChannelName(Channel, ""); + // clear/reset the channel name + SETTINGS_SaveChannelName(Channel, ""); #else - if (Mode >= 3) { - SETTINGS_SaveChannelName(Channel, pVFO->Name); - } + if (Mode >= 3) { + SETTINGS_SaveChannelName(Channel, pVFO->Name); + } #endif - } - } + } + } } void SETTINGS_SaveBatteryCalibration(const uint16_t * batteryCalibration) { - uint16_t buf[4]; - EEPROM_WriteBuffer(0x1F40, batteryCalibration); - EEPROM_ReadBuffer( 0x1F48, buf, sizeof(buf)); - buf[0] = batteryCalibration[4]; - buf[1] = batteryCalibration[5]; - EEPROM_WriteBuffer(0x1F48, buf); + uint16_t buf[4]; + EEPROM_WriteBuffer(0x1F40, batteryCalibration); + EEPROM_ReadBuffer( 0x1F48, buf, sizeof(buf)); + buf[0] = batteryCalibration[4]; + buf[1] = batteryCalibration[5]; + EEPROM_WriteBuffer(0x1F48, buf); } void SETTINGS_SaveChannelName(uint8_t channel, const char * name) { - uint16_t offset = channel * 16; - uint8_t buf[16] = {0}; - memcpy(buf, name, MIN(strlen(name), 10u)); - EEPROM_WriteBuffer(0x0F50 + offset, buf); - EEPROM_WriteBuffer(0x0F58 + offset, buf + 8); + uint16_t offset = channel * 16; + uint8_t buf[16] = {0}; + memcpy(buf, name, MIN(strlen(name), 10u)); + EEPROM_WriteBuffer(0x0F50 + offset, buf); + EEPROM_WriteBuffer(0x0F58 + offset, buf + 8); } void SETTINGS_UpdateChannel(uint8_t channel, const VFO_Info_t *pVFO, bool keep, bool check, bool save) { #ifdef ENABLE_NOAA - if (!IS_NOAA_CHANNEL(channel)) -#endif - { - uint8_t state[8]; - ChannelAttributes_t att = { - .band = 0x7, - .compander = 0, - .scanlist1 = 0, - .scanlist2 = 0, - .scanlist3 = 0, - }; // default attributes - - uint16_t offset = 0x0D60 + (channel & ~7u); - EEPROM_ReadBuffer(offset, state, sizeof(state)); - - if (keep) { - att.band = pVFO->Band; - att.scanlist1 = pVFO->SCANLIST1_PARTICIPATION; - att.scanlist2 = pVFO->SCANLIST2_PARTICIPATION; - att.scanlist3 = pVFO->SCANLIST3_PARTICIPATION; - att.compander = pVFO->Compander; - if (check && state[channel & 7u] == att.__val) - return; // no change in the attributes - } - - state[channel & 7u] = att.__val; + if (!IS_NOAA_CHANNEL(channel)) +#endif + { + uint8_t state[8]; + ChannelAttributes_t att = { + .band = 0x7, + .compander = 0, + .scanlist1 = 0, + .scanlist2 = 0, + .scanlist3 = 0, + }; // default attributes + + uint16_t offset = 0x0D60 + (channel & ~7u); + EEPROM_ReadBuffer(offset, state, sizeof(state)); + + if (keep) { + att.band = pVFO->Band; + att.scanlist1 = pVFO->SCANLIST1_PARTICIPATION; + att.scanlist2 = pVFO->SCANLIST2_PARTICIPATION; + att.scanlist3 = pVFO->SCANLIST3_PARTICIPATION; + att.compander = pVFO->Compander; + if (check && state[channel & 7u] == att.__val) + return; // no change in the attributes + } + + state[channel & 7u] = att.__val; #ifdef ENABLE_FEAT_F4HWN - if(save) - { - EEPROM_WriteBuffer(offset, state); - } + if(save) + { + EEPROM_WriteBuffer(offset, state); + } #else - EEPROM_WriteBuffer(offset, state); + EEPROM_WriteBuffer(offset, state); #endif - gMR_ChannelAttributes[channel] = att; + gMR_ChannelAttributes[channel] = att; - if (IS_MR_CHANNEL(channel)) { // it's a memory channel - if (!keep) { - // clear/reset the channel name - SETTINGS_SaveChannelName(channel, ""); - } - } - } + if (IS_MR_CHANNEL(channel)) { // it's a memory channel + if (!keep) { + // clear/reset the channel name + SETTINGS_SaveChannelName(channel, ""); + } + } + } } void SETTINGS_WriteBuildOptions(void) { - uint8_t buf[8] = {0}; + uint8_t buf[8] = {0}; #ifdef ENABLE_FEAT_F4HWN - EEPROM_ReadBuffer(0x1FF0, buf, 8); + EEPROM_ReadBuffer(0x1FF0, buf, 8); #endif - + buf[0] = 0 #ifdef ENABLE_FMRADIO | (1 << 0) @@ -940,5 +940,5 @@ buf[1] = 0 | (1 << 5) #endif ; - EEPROM_WriteBuffer(0x1FF0, buf); + EEPROM_WriteBuffer(0x1FF0, buf); } \ No newline at end of file diff --git a/settings.h b/settings.h index 900421ffe..410a857a0 100644 --- a/settings.h +++ b/settings.h @@ -27,258 +27,258 @@ enum POWER_OnDisplayMode_t { #ifdef ENABLE_FEAT_F4HWN - POWER_ON_DISPLAY_MODE_ALL, - POWER_ON_DISPLAY_MODE_SOUND, + POWER_ON_DISPLAY_MODE_ALL, + POWER_ON_DISPLAY_MODE_SOUND, #else - POWER_ON_DISPLAY_MODE_FULL_SCREEN = 0, + POWER_ON_DISPLAY_MODE_FULL_SCREEN = 0, #endif - POWER_ON_DISPLAY_MODE_MESSAGE, - POWER_ON_DISPLAY_MODE_VOLTAGE, - POWER_ON_DISPLAY_MODE_NONE + POWER_ON_DISPLAY_MODE_MESSAGE, + POWER_ON_DISPLAY_MODE_VOLTAGE, + POWER_ON_DISPLAY_MODE_NONE }; typedef enum POWER_OnDisplayMode_t POWER_OnDisplayMode_t; enum TxLockModes_t { - F_LOCK_DEF, //all default frequencies + configurable - F_LOCK_FCC, + F_LOCK_DEF, //all default frequencies + configurable + F_LOCK_FCC, #ifdef ENABLE_FEAT_F4HWN_CA - F_LOCK_CA, + F_LOCK_CA, #endif - F_LOCK_CE, - F_LOCK_GB, - F_LOCK_430, - F_LOCK_438, + F_LOCK_CE, + F_LOCK_GB, + F_LOCK_430, + F_LOCK_438, #ifdef ENABLE_FEAT_F4HWN_PMR - F_LOCK_PMR, + F_LOCK_PMR, #endif #ifdef ENABLE_FEAT_F4HWN_GMRS_FRS_MURS - F_LOCK_GMRS_FRS_MURS, + F_LOCK_GMRS_FRS_MURS, #endif - F_LOCK_ALL, // disable TX on all frequencies - F_LOCK_NONE, // enable TX on all frequencies - F_LOCK_LEN + F_LOCK_ALL, // disable TX on all frequencies + F_LOCK_NONE, // enable TX on all frequencies + F_LOCK_LEN }; enum { - SCAN_RESUME_TO = 0, - SCAN_RESUME_CO, - SCAN_RESUME_SE + SCAN_RESUME_TO = 0, + SCAN_RESUME_CO, + SCAN_RESUME_SE }; enum { - CROSS_BAND_OFF = 0, - CROSS_BAND_CHAN_A, - CROSS_BAND_CHAN_B + CROSS_BAND_OFF = 0, + CROSS_BAND_CHAN_A, + CROSS_BAND_CHAN_B }; enum { - DUAL_WATCH_OFF = 0, - DUAL_WATCH_CHAN_A, - DUAL_WATCH_CHAN_B + DUAL_WATCH_OFF = 0, + DUAL_WATCH_CHAN_A, + DUAL_WATCH_CHAN_B }; enum { - TX_OFFSET_FREQUENCY_DIRECTION_OFF = 0, - TX_OFFSET_FREQUENCY_DIRECTION_ADD, - TX_OFFSET_FREQUENCY_DIRECTION_SUB + TX_OFFSET_FREQUENCY_DIRECTION_OFF = 0, + TX_OFFSET_FREQUENCY_DIRECTION_ADD, + TX_OFFSET_FREQUENCY_DIRECTION_SUB }; enum { - OUTPUT_POWER_USER = 0, - OUTPUT_POWER_LOW1, - OUTPUT_POWER_LOW2, - OUTPUT_POWER_LOW3, - OUTPUT_POWER_LOW4, - OUTPUT_POWER_LOW5, - OUTPUT_POWER_MID, - OUTPUT_POWER_HIGH + OUTPUT_POWER_USER = 0, + OUTPUT_POWER_LOW1, + OUTPUT_POWER_LOW2, + OUTPUT_POWER_LOW3, + OUTPUT_POWER_LOW4, + OUTPUT_POWER_LOW5, + OUTPUT_POWER_MID, + OUTPUT_POWER_HIGH }; enum ACTION_OPT_t { - ACTION_OPT_NONE = 0, - ACTION_OPT_FLASHLIGHT, - ACTION_OPT_POWER, - ACTION_OPT_MONITOR, - ACTION_OPT_SCAN, - ACTION_OPT_VOX, - ACTION_OPT_ALARM, - ACTION_OPT_FM, - ACTION_OPT_1750, - ACTION_OPT_KEYLOCK, - ACTION_OPT_A_B, - ACTION_OPT_VFO_MR, - ACTION_OPT_SWITCH_DEMODUL, - ACTION_OPT_BLMIN_TMP_OFF, //BackLight Minimum Temporay OFF + ACTION_OPT_NONE = 0, + ACTION_OPT_FLASHLIGHT, + ACTION_OPT_POWER, + ACTION_OPT_MONITOR, + ACTION_OPT_SCAN, + ACTION_OPT_VOX, + ACTION_OPT_ALARM, + ACTION_OPT_FM, + ACTION_OPT_1750, + ACTION_OPT_KEYLOCK, + ACTION_OPT_A_B, + ACTION_OPT_VFO_MR, + ACTION_OPT_SWITCH_DEMODUL, + ACTION_OPT_BLMIN_TMP_OFF, //BackLight Minimum Temporay OFF #ifdef ENABLE_FEAT_F4HWN - ACTION_OPT_RXMODE, - ACTION_OPT_MAINONLY, - ACTION_OPT_PTT, - ACTION_OPT_WN, - ACTION_OPT_BACKLIGHT, + ACTION_OPT_RXMODE, + ACTION_OPT_MAINONLY, + ACTION_OPT_PTT, + ACTION_OPT_WN, + ACTION_OPT_BACKLIGHT, #endif - ACTION_OPT_LEN + ACTION_OPT_LEN }; #ifdef ENABLE_VOICE - enum VOICE_Prompt_t - { - VOICE_PROMPT_OFF = 0, - VOICE_PROMPT_CHINESE, - VOICE_PROMPT_ENGLISH - }; - typedef enum VOICE_Prompt_t VOICE_Prompt_t; + enum VOICE_Prompt_t + { + VOICE_PROMPT_OFF = 0, + VOICE_PROMPT_CHINESE, + VOICE_PROMPT_ENGLISH + }; + typedef enum VOICE_Prompt_t VOICE_Prompt_t; #endif enum ALARM_Mode_t { - ALARM_MODE_SITE = 0, - ALARM_MODE_TONE + ALARM_MODE_SITE = 0, + ALARM_MODE_TONE }; typedef enum ALARM_Mode_t ALARM_Mode_t; enum ROGER_Mode_t { - ROGER_MODE_OFF = 0, - ROGER_MODE_ROGER, - ROGER_MODE_MDC + ROGER_MODE_OFF = 0, + ROGER_MODE_ROGER, + ROGER_MODE_MDC }; typedef enum ROGER_Mode_t ROGER_Mode_t; enum CHANNEL_DisplayMode_t { - MDF_FREQUENCY = 0, - MDF_CHANNEL, - MDF_NAME, - MDF_NAME_FREQ + MDF_FREQUENCY = 0, + MDF_CHANNEL, + MDF_NAME, + MDF_NAME_FREQ }; typedef enum CHANNEL_DisplayMode_t CHANNEL_DisplayMode_t; typedef struct { - uint8_t ScreenChannel[2]; // current channels set in the radio (memory or frequency channels) - uint8_t FreqChannel[2]; // last frequency channels used - uint8_t MrChannel[2]; // last memory channels used + uint8_t ScreenChannel[2]; // current channels set in the radio (memory or frequency channels) + uint8_t FreqChannel[2]; // last frequency channels used + uint8_t MrChannel[2]; // last memory channels used #ifdef ENABLE_NOAA - uint8_t NoaaChannel[2]; + uint8_t NoaaChannel[2]; #endif - // The actual VFO index (0-upper/1-lower) that is now used for RX, - // It is being alternated by dual watch, and flipped by crossband - uint8_t RX_VFO; + // The actual VFO index (0-upper/1-lower) that is now used for RX, + // It is being alternated by dual watch, and flipped by crossband + uint8_t RX_VFO; - // The main VFO index (0-upper/1-lower) selected by the user - // - uint8_t TX_VFO; + // The main VFO index (0-upper/1-lower) selected by the user + // + uint8_t TX_VFO; - uint8_t field7_0xa; - uint8_t field8_0xb; + uint8_t field7_0xa; + uint8_t field8_0xb; #ifdef ENABLE_FMRADIO - uint16_t FM_SelectedFrequency; - uint8_t FM_SelectedChannel; - bool FM_IsMrMode; - uint16_t FM_FrequencyPlaying; - uint8_t FM_Band : 2; - //uint8_t FM_Space : 2; + uint16_t FM_SelectedFrequency; + uint8_t FM_SelectedChannel; + bool FM_IsMrMode; + uint16_t FM_FrequencyPlaying; + uint8_t FM_Band : 2; + //uint8_t FM_Space : 2; #endif - uint8_t SQUELCH_LEVEL; - uint8_t TX_TIMEOUT_TIMER; - bool KEY_LOCK; + uint8_t SQUELCH_LEVEL; + uint8_t TX_TIMEOUT_TIMER; + bool KEY_LOCK; #ifdef ENABLE_FEAT_F4HWN - bool KEY_LOCK_PTT; + bool KEY_LOCK_PTT; #endif - bool VOX_SWITCH; - uint8_t VOX_LEVEL; + bool VOX_SWITCH; + uint8_t VOX_LEVEL; #ifdef ENABLE_VOICE - VOICE_Prompt_t VOICE_PROMPT; + VOICE_Prompt_t VOICE_PROMPT; #endif - bool BEEP_CONTROL; - uint8_t CHANNEL_DISPLAY_MODE; - bool TAIL_TONE_ELIMINATION; - bool VFO_OPEN; - uint8_t DUAL_WATCH; - uint8_t CROSS_BAND_RX_TX; - uint8_t BATTERY_SAVE; - uint8_t BACKLIGHT_TIME; - uint8_t SCAN_RESUME_MODE; - uint8_t SCAN_LIST_DEFAULT; - bool SCAN_LIST_ENABLED[3]; - uint8_t SCANLIST_PRIORITY_CH1[3]; - uint8_t SCANLIST_PRIORITY_CH2[3]; - - uint8_t field29_0x26; - uint8_t field30_0x27; - - uint8_t field37_0x32; - uint8_t field38_0x33; - - bool AUTO_KEYPAD_LOCK; + bool BEEP_CONTROL; + uint8_t CHANNEL_DISPLAY_MODE; + bool TAIL_TONE_ELIMINATION; + bool VFO_OPEN; + uint8_t DUAL_WATCH; + uint8_t CROSS_BAND_RX_TX; + uint8_t BATTERY_SAVE; + uint8_t BACKLIGHT_TIME; + uint8_t SCAN_RESUME_MODE; + uint8_t SCAN_LIST_DEFAULT; + bool SCAN_LIST_ENABLED[3]; + uint8_t SCANLIST_PRIORITY_CH1[3]; + uint8_t SCANLIST_PRIORITY_CH2[3]; + + uint8_t field29_0x26; + uint8_t field30_0x27; + + uint8_t field37_0x32; + uint8_t field38_0x33; + + bool AUTO_KEYPAD_LOCK; #if defined(ENABLE_ALARM) || defined(ENABLE_TX1750) - ALARM_Mode_t ALARM_MODE; + ALARM_Mode_t ALARM_MODE; #endif - POWER_OnDisplayMode_t POWER_ON_DISPLAY_MODE; - ROGER_Mode_t ROGER; - uint8_t REPEATER_TAIL_TONE_ELIMINATION; - uint8_t KEY_1_SHORT_PRESS_ACTION; - uint8_t KEY_1_LONG_PRESS_ACTION; - uint8_t KEY_2_SHORT_PRESS_ACTION; - uint8_t KEY_2_LONG_PRESS_ACTION; - uint8_t MIC_SENSITIVITY; - uint8_t MIC_SENSITIVITY_TUNING; - uint8_t CHAN_1_CALL; + POWER_OnDisplayMode_t POWER_ON_DISPLAY_MODE; + ROGER_Mode_t ROGER; + uint8_t REPEATER_TAIL_TONE_ELIMINATION; + uint8_t KEY_1_SHORT_PRESS_ACTION; + uint8_t KEY_1_LONG_PRESS_ACTION; + uint8_t KEY_2_SHORT_PRESS_ACTION; + uint8_t KEY_2_LONG_PRESS_ACTION; + uint8_t MIC_SENSITIVITY; + uint8_t MIC_SENSITIVITY_TUNING; + uint8_t CHAN_1_CALL; #ifdef ENABLE_DTMF_CALLING - char ANI_DTMF_ID[8]; - char KILL_CODE[8]; - char REVIVE_CODE[8]; + char ANI_DTMF_ID[8]; + char KILL_CODE[8]; + char REVIVE_CODE[8]; #endif - char DTMF_UP_CODE[16]; + char DTMF_UP_CODE[16]; - uint8_t field57_0x6c; - uint8_t field58_0x6d; + uint8_t field57_0x6c; + uint8_t field58_0x6d; - char DTMF_DOWN_CODE[16]; + char DTMF_DOWN_CODE[16]; - uint8_t field60_0x7e; - uint8_t field61_0x7f; + uint8_t field60_0x7e; + uint8_t field61_0x7f; #ifdef ENABLE_DTMF_CALLING - char DTMF_SEPARATE_CODE; - char DTMF_GROUP_CALL_CODE; - uint8_t DTMF_DECODE_RESPONSE; - uint8_t DTMF_auto_reset_time; -#endif - uint16_t DTMF_PRELOAD_TIME; - uint16_t DTMF_FIRST_CODE_PERSIST_TIME; - uint16_t DTMF_HASH_CODE_PERSIST_TIME; - uint16_t DTMF_CODE_PERSIST_TIME; - uint16_t DTMF_CODE_INTERVAL_TIME; - bool DTMF_SIDE_TONE; + char DTMF_SEPARATE_CODE; + char DTMF_GROUP_CALL_CODE; + uint8_t DTMF_DECODE_RESPONSE; + uint8_t DTMF_auto_reset_time; +#endif + uint16_t DTMF_PRELOAD_TIME; + uint16_t DTMF_FIRST_CODE_PERSIST_TIME; + uint16_t DTMF_HASH_CODE_PERSIST_TIME; + uint16_t DTMF_CODE_PERSIST_TIME; + uint16_t DTMF_CODE_INTERVAL_TIME; + bool DTMF_SIDE_TONE; #ifdef ENABLE_DTMF_CALLING - bool PERMIT_REMOTE_KILL; + bool PERMIT_REMOTE_KILL; #endif - int16_t BK4819_XTAL_FREQ_LOW; + int16_t BK4819_XTAL_FREQ_LOW; #ifdef ENABLE_NOAA - bool NOAA_AUTO_SCAN; + bool NOAA_AUTO_SCAN; #endif - uint8_t VOLUME_GAIN; - uint8_t DAC_GAIN; + uint8_t VOLUME_GAIN; + uint8_t DAC_GAIN; - VFO_Info_t VfoInfo[2]; - uint32_t POWER_ON_PASSWORD; - uint16_t VOX1_THRESHOLD; - uint16_t VOX0_THRESHOLD; + VFO_Info_t VfoInfo[2]; + uint32_t POWER_ON_PASSWORD; + uint16_t VOX1_THRESHOLD; + uint16_t VOX0_THRESHOLD; - uint8_t field77_0x95; - uint8_t field78_0x96; - uint8_t field79_0x97; + uint8_t field77_0x95; + uint8_t field78_0x96; + uint8_t field79_0x97; - uint8_t KEY_M_LONG_PRESS_ACTION; - uint8_t BACKLIGHT_MIN; + uint8_t KEY_M_LONG_PRESS_ACTION; + uint8_t BACKLIGHT_MIN; #ifdef ENABLE_BLMIN_TMP_OFF - BLMIN_STAT_t BACKLIGHT_MIN_STAT; + BLMIN_STAT_t BACKLIGHT_MIN_STAT; #endif - uint8_t BACKLIGHT_MAX; - BATTERY_Type_t BATTERY_TYPE; + uint8_t BACKLIGHT_MAX; + BATTERY_Type_t BATTERY_TYPE; #ifdef ENABLE_RSSI_BAR - uint8_t S0_LEVEL; - uint8_t S9_LEVEL; + uint8_t S0_LEVEL; + uint8_t S9_LEVEL; #endif } EEPROM_Config_t; @@ -290,7 +290,7 @@ uint32_t SETTINGS_FetchChannelFrequency(const int channel); void SETTINGS_FetchChannelName(char *s, const int channel); void SETTINGS_FactoryReset(bool bIsAll); #ifdef ENABLE_FMRADIO - void SETTINGS_SaveFM(void); + void SETTINGS_SaveFM(void); #endif void SETTINGS_SaveVfoIndices(void); void SETTINGS_SaveSettings(void); diff --git a/sram-overlay.c b/sram-overlay.c index 844351e25..96bb0a98d 100644 --- a/sram-overlay.c +++ b/sram-overlay.c @@ -27,172 +27,172 @@ uint32_t overlay_0x20000478; // Nothing is using this?? void overlay_FLASH_RebootToBootloader(void) { - overlay_FLASH_MaskUnlock(); - overlay_FLASH_SetMaskSel(FLASH_MASK_SELECTION_NONE); - overlay_FLASH_MaskLock(); - overlay_SystemReset(); + overlay_FLASH_MaskUnlock(); + overlay_FLASH_SetMaskSel(FLASH_MASK_SELECTION_NONE); + overlay_FLASH_MaskLock(); + overlay_SystemReset(); } bool overlay_FLASH_IsBusy(void) { - return (FLASH_ST & FLASH_ST_BUSY_MASK) != FLASH_ST_BUSY_BITS_READY; + return (FLASH_ST & FLASH_ST_BUSY_MASK) != FLASH_ST_BUSY_BITS_READY; } bool overlay_FLASH_IsInitComplete(void) { - return (FLASH_ST & FLASH_ST_INIT_BUSY_MASK) == FLASH_ST_INIT_BUSY_BITS_COMPLETE; + return (FLASH_ST & FLASH_ST_INIT_BUSY_MASK) == FLASH_ST_INIT_BUSY_BITS_COMPLETE; } void overlay_FLASH_Start(void) { - overlay_FLASH_Unlock(); - FLASH_START |= FLASH_START_START_BITS_START; + overlay_FLASH_Unlock(); + FLASH_START |= FLASH_START_START_BITS_START; } void overlay_FLASH_Init(FLASH_READ_MODE ReadMode) { - overlay_FLASH_WakeFromDeepSleep(); - overlay_FLASH_SetMode(FLASH_MODE_READ_AHB); - overlay_FLASH_SetReadMode(ReadMode); - overlay_FLASH_SetEraseTime(); - overlay_FLASH_SetProgramTime(); - overlay_FLASH_Lock(); + overlay_FLASH_WakeFromDeepSleep(); + overlay_FLASH_SetMode(FLASH_MODE_READ_AHB); + overlay_FLASH_SetReadMode(ReadMode); + overlay_FLASH_SetEraseTime(); + overlay_FLASH_SetProgramTime(); + overlay_FLASH_Lock(); } void overlay_FLASH_MaskLock(void) { - FLASH_MASK = (FLASH_MASK & ~FLASH_MASK_LOCK_MASK) | FLASH_MASK_LOCK_BITS_SET; + FLASH_MASK = (FLASH_MASK & ~FLASH_MASK_LOCK_MASK) | FLASH_MASK_LOCK_BITS_SET; } void overlay_FLASH_SetMaskSel(FLASH_MASK_SELECTION Mask) { - FLASH_MASK = (FLASH_MASK & ~FLASH_MASK_SEL_MASK) | ((Mask << FLASH_MASK_SEL_SHIFT) & FLASH_MASK_SEL_MASK); + FLASH_MASK = (FLASH_MASK & ~FLASH_MASK_SEL_MASK) | ((Mask << FLASH_MASK_SEL_SHIFT) & FLASH_MASK_SEL_MASK); } void overlay_FLASH_MaskUnlock(void) { - FLASH_MASK = (FLASH_MASK & ~FLASH_MASK_LOCK_MASK) | FLASH_MASK_LOCK_BITS_NOT_SET; + FLASH_MASK = (FLASH_MASK & ~FLASH_MASK_LOCK_MASK) | FLASH_MASK_LOCK_BITS_NOT_SET; } void overlay_FLASH_Lock(void) { - FLASH_LOCK = FLASH_LOCK_LOCK_BITS_LOCK; + FLASH_LOCK = FLASH_LOCK_LOCK_BITS_LOCK; } void overlay_FLASH_Unlock(void) { - FLASH_UNLOCK = FLASH_UNLOCK_UNLOCK_BITS_UNLOCK; + FLASH_UNLOCK = FLASH_UNLOCK_UNLOCK_BITS_UNLOCK; } uint32_t overlay_FLASH_ReadByAHB(uint32_t Offset) { - return pFlash[(Offset & ~3U) / 4]; + return pFlash[(Offset & ~3U) / 4]; } uint32_t overlay_FLASH_ReadByAPB(uint32_t Offset) { - uint32_t Data; + uint32_t Data; - while (overlay_FLASH_IsBusy()) {} + while (overlay_FLASH_IsBusy()) {} - overlay_FLASH_SetMode(FLASH_MODE_READ_APB); - FLASH_ADDR = Offset >> 2; + overlay_FLASH_SetMode(FLASH_MODE_READ_APB); + FLASH_ADDR = Offset >> 2; - overlay_FLASH_Start(); + overlay_FLASH_Start(); - while (overlay_FLASH_IsBusy()) {} + while (overlay_FLASH_IsBusy()) {} - Data = FLASH_RDATA; + Data = FLASH_RDATA; - overlay_FLASH_SetMode(FLASH_MODE_READ_AHB); - overlay_FLASH_Lock(); + overlay_FLASH_SetMode(FLASH_MODE_READ_AHB); + overlay_FLASH_Lock(); - return Data; + return Data; } void overlay_FLASH_SetArea(FLASH_AREA Area) { - FLASH_CFG = (FLASH_CFG & ~FLASH_CFG_NVR_SEL_MASK) | ((Area << FLASH_CFG_NVR_SEL_SHIFT) & FLASH_CFG_NVR_SEL_MASK); + FLASH_CFG = (FLASH_CFG & ~FLASH_CFG_NVR_SEL_MASK) | ((Area << FLASH_CFG_NVR_SEL_SHIFT) & FLASH_CFG_NVR_SEL_MASK); } void overlay_FLASH_SetReadMode(FLASH_READ_MODE Mode) { - if (Mode == FLASH_READ_MODE_1_CYCLE) - FLASH_CFG = (FLASH_CFG & ~FLASH_CFG_READ_MD_MASK) | FLASH_CFG_READ_MD_BITS_1_CYCLE; - else - if (Mode == FLASH_READ_MODE_2_CYCLE) - FLASH_CFG = (FLASH_CFG & ~FLASH_CFG_READ_MD_MASK) | FLASH_CFG_READ_MD_BITS_2_CYCLE; + if (Mode == FLASH_READ_MODE_1_CYCLE) + FLASH_CFG = (FLASH_CFG & ~FLASH_CFG_READ_MD_MASK) | FLASH_CFG_READ_MD_BITS_1_CYCLE; + else + if (Mode == FLASH_READ_MODE_2_CYCLE) + FLASH_CFG = (FLASH_CFG & ~FLASH_CFG_READ_MD_MASK) | FLASH_CFG_READ_MD_BITS_2_CYCLE; } void overlay_FLASH_SetEraseTime(void) { - FLASH_ERASETIME = ((overlay_FLASH_ClockMultiplier & 0xFFFFU) * 0x1A00000U) + (overlay_FLASH_ClockMultiplier * 3600U); + FLASH_ERASETIME = ((overlay_FLASH_ClockMultiplier & 0xFFFFU) * 0x1A00000U) + (overlay_FLASH_ClockMultiplier * 3600U); } void overlay_FLASH_WakeFromDeepSleep(void) { - FLASH_CFG = (FLASH_CFG & ~FLASH_CFG_DEEP_PD_MASK) | FLASH_CFG_DEEP_PD_BITS_NORMAL; - while (!overlay_FLASH_IsInitComplete()) {} + FLASH_CFG = (FLASH_CFG & ~FLASH_CFG_DEEP_PD_MASK) | FLASH_CFG_DEEP_PD_BITS_NORMAL; + while (!overlay_FLASH_IsInitComplete()) {} } void overlay_FLASH_SetMode(FLASH_MODE Mode) { - FLASH_CFG = (FLASH_CFG & ~FLASH_CFG_MODE_MASK) | ((Mode << FLASH_CFG_MODE_SHIFT) & FLASH_CFG_MODE_MASK); + FLASH_CFG = (FLASH_CFG & ~FLASH_CFG_MODE_MASK) | ((Mode << FLASH_CFG_MODE_SHIFT) & FLASH_CFG_MODE_MASK); } void overlay_FLASH_SetProgramTime(void) { - FLASH_PROGTIME = overlay_FLASH_ClockMultiplier * 45074; + FLASH_PROGTIME = overlay_FLASH_ClockMultiplier * 45074; } void overlay_SystemReset(void) { - // Lifted from core_cm0.h to preserve function order in the object file. + // Lifted from core_cm0.h to preserve function order in the object file. - __DSB(); // Ensure all outstanding memory accesses included buffered write are completed before reset - SCB->AIRCR = (0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | SCB_AIRCR_SYSRESETREQ_Msk; - __DSB(); // Ensure completion of memory access + __DSB(); // Ensure all outstanding memory accesses included buffered write are completed before reset + SCB->AIRCR = (0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | SCB_AIRCR_SYSRESETREQ_Msk; + __DSB(); // Ensure completion of memory access - for (;;) // wait until reset - __NOP(); + for (;;) // wait until reset + __NOP(); } uint32_t overlay_FLASH_ReadNvrWord(uint32_t Offset) { - uint32_t Data; - overlay_FLASH_SetArea(FLASH_AREA_NVR); - Data = overlay_FLASH_ReadByAHB(Offset); - overlay_FLASH_SetArea(FLASH_AREA_MAIN); - return Data; + uint32_t Data; + overlay_FLASH_SetArea(FLASH_AREA_NVR); + Data = overlay_FLASH_ReadByAHB(Offset); + overlay_FLASH_SetArea(FLASH_AREA_MAIN); + return Data; } void overlay_FLASH_ConfigureTrimValues(void) { - uint32_t Data; + uint32_t Data; - overlay_FLASH_SetArea(FLASH_AREA_NVR); + overlay_FLASH_SetArea(FLASH_AREA_NVR); - SYSCON_CHIP_ID0 = overlay_FLASH_ReadByAPB(0xF018); - SYSCON_CHIP_ID1 = overlay_FLASH_ReadByAPB(0xF01C); - SYSCON_CHIP_ID2 = overlay_FLASH_ReadByAPB(0xF020); - SYSCON_CHIP_ID3 = overlay_FLASH_ReadByAPB(0xF024); + SYSCON_CHIP_ID0 = overlay_FLASH_ReadByAPB(0xF018); + SYSCON_CHIP_ID1 = overlay_FLASH_ReadByAPB(0xF01C); + SYSCON_CHIP_ID2 = overlay_FLASH_ReadByAPB(0xF020); + SYSCON_CHIP_ID3 = overlay_FLASH_ReadByAPB(0xF024); - SYSCON_RC_FREQ_DELTA = overlay_FLASH_ReadByAHB(0x07C8); - SYSCON_VREF_VOLT_DELTA = overlay_FLASH_ReadByAHB(0x07C4); + SYSCON_RC_FREQ_DELTA = overlay_FLASH_ReadByAHB(0x07C8); + SYSCON_VREF_VOLT_DELTA = overlay_FLASH_ReadByAHB(0x07C4); - PMU_TRIM_POW0 = overlay_FLASH_ReadByAHB(0x07E4); - PMU_TRIM_POW1 = overlay_FLASH_ReadByAHB(0x07E0); - PMU_TRIM_RCHF = overlay_FLASH_ReadByAHB(0x07D8); - PMU_TRIM_RCLF = overlay_FLASH_ReadByAHB(0x07D4); - PMU_TRIM_OPA = overlay_FLASH_ReadByAHB(0x07D0); - PMU_TRIM_PLL = overlay_FLASH_ReadByAHB(0x07CC); + PMU_TRIM_POW0 = overlay_FLASH_ReadByAHB(0x07E4); + PMU_TRIM_POW1 = overlay_FLASH_ReadByAHB(0x07E0); + PMU_TRIM_RCHF = overlay_FLASH_ReadByAHB(0x07D8); + PMU_TRIM_RCLF = overlay_FLASH_ReadByAHB(0x07D4); + PMU_TRIM_OPA = overlay_FLASH_ReadByAHB(0x07D0); + PMU_TRIM_PLL = overlay_FLASH_ReadByAHB(0x07CC); - overlay_0x20000478 = overlay_FLASH_ReadByAHB(0x07B8); + overlay_0x20000478 = overlay_FLASH_ReadByAHB(0x07B8); - Data = overlay_FLASH_ReadByAHB(0x07BC); - SYSCON_DEV_CLK_GATE = (SYSCON_DEV_CLK_GATE & ~SYSCON_DEV_CLK_GATE_SARADC_MASK) | SYSCON_DEV_CLK_GATE_SARADC_BITS_ENABLE; - SARADC_CALIB_OFFSET = ((Data & 0xFFFF) << SARADC_CALIB_OFFSET_OFFSET_SHIFT) & SARADC_CALIB_OFFSET_OFFSET_MASK; - SARADC_CALIB_KD = (((Data >> 16) & 0xFFFF) << SARADC_CALIB_KD_KD_SHIFT) & SARADC_CALIB_KD_KD_MASK; - overlay_FLASH_SetArea(FLASH_AREA_MAIN); + Data = overlay_FLASH_ReadByAHB(0x07BC); + SYSCON_DEV_CLK_GATE = (SYSCON_DEV_CLK_GATE & ~SYSCON_DEV_CLK_GATE_SARADC_MASK) | SYSCON_DEV_CLK_GATE_SARADC_BITS_ENABLE; + SARADC_CALIB_OFFSET = ((Data & 0xFFFF) << SARADC_CALIB_OFFSET_OFFSET_SHIFT) & SARADC_CALIB_OFFSET_OFFSET_MASK; + SARADC_CALIB_KD = (((Data >> 16) & 0xFFFF) << SARADC_CALIB_KD_KD_SHIFT) & SARADC_CALIB_KD_KD_MASK; + overlay_FLASH_SetArea(FLASH_AREA_MAIN); } diff --git a/ui/aircopy.c b/ui/aircopy.c index 0c3da4c76..8dd166613 100644 --- a/ui/aircopy.c +++ b/ui/aircopy.c @@ -37,83 +37,83 @@ static int get_bit(uint8_t* array, int bit_index) { void UI_DisplayAircopy(void) { - char String[16] = { 0 }; - char *pPrintStr = { 0 }; - uint16_t percent; - - UI_DisplayClear(); - - if (gAircopyState == AIRCOPY_READY) { - pPrintStr = "AIR COPY(RDY)"; - } else if (gAircopyState == AIRCOPY_TRANSFER) { - pPrintStr = "AIR COPY"; - } else { - pPrintStr = "AIR COPY(CMP)"; - gAircopyState = AIRCOPY_READY; - } - - UI_PrintString(pPrintStr, 2, 127, 0, 8); - - if (gInputBoxIndex == 0) { - uint32_t frequency = gRxVfo->freq_config_RX.Frequency; - sprintf(String, "%3u.%05u", frequency / 100000, frequency % 100000); - // show the remaining 2 small frequency digits - UI_PrintStringSmallNormal(String + 7, 97, 0, 3); - String[7] = 0; - // show the main large frequency digits - UI_DisplayFrequency(String, 16, 2, false); - } else { - const char *ascii = INPUTBOX_GetAscii(); - sprintf(String, "%.3s.%.3s", ascii, ascii + 3); - UI_DisplayFrequency(String, 16, 2, false); - } - - memset(String, 0, sizeof(String)); - - percent = (gAirCopyBlockNumber * 10000) / 120; - - if (gAirCopyIsSendMode == 0) { - sprintf(String, "RCV:%02u.%02u%% E:%d", percent / 100, percent % 100, gErrorsDuringAirCopy); - } else if (gAirCopyIsSendMode == 1) { - sprintf(String, "SND:%02u.%02u%%", percent / 100, percent % 100); - } - - // Draw gauge - if(gAircopyStep != 0) - { - UI_PrintString(String, 2, 127, 5, 8); - - gFrameBuffer[4][1] = 0x3c; - gFrameBuffer[4][2] = 0x42; - - for(uint8_t i = 1; i <= 122; i++) - { - gFrameBuffer[4][2 + i] = 0x81; - } - - gFrameBuffer[4][125] = 0x42; - gFrameBuffer[4][126] = 0x3c; - } - - if(gAirCopyBlockNumber + gErrorsDuringAirCopy != 0) - { - // Check CRC - if(gErrorsDuringAirCopy != lErrorsDuringAirCopy) - { - set_bit(crc, gAirCopyBlockNumber + gErrorsDuringAirCopy); - lErrorsDuringAirCopy = gErrorsDuringAirCopy; - } - - for(uint8_t i = 0; i < (gAirCopyBlockNumber + gErrorsDuringAirCopy); i++) - { - if(get_bit(crc, i) == 0) - { - gFrameBuffer[4][i + 4] = 0xbd; - } - } - } - - ST7565_BlitFullScreen(); + char String[16] = { 0 }; + char *pPrintStr = { 0 }; + uint16_t percent; + + UI_DisplayClear(); + + if (gAircopyState == AIRCOPY_READY) { + pPrintStr = "AIR COPY(RDY)"; + } else if (gAircopyState == AIRCOPY_TRANSFER) { + pPrintStr = "AIR COPY"; + } else { + pPrintStr = "AIR COPY(CMP)"; + gAircopyState = AIRCOPY_READY; + } + + UI_PrintString(pPrintStr, 2, 127, 0, 8); + + if (gInputBoxIndex == 0) { + uint32_t frequency = gRxVfo->freq_config_RX.Frequency; + sprintf(String, "%3u.%05u", frequency / 100000, frequency % 100000); + // show the remaining 2 small frequency digits + UI_PrintStringSmallNormal(String + 7, 97, 0, 3); + String[7] = 0; + // show the main large frequency digits + UI_DisplayFrequency(String, 16, 2, false); + } else { + const char *ascii = INPUTBOX_GetAscii(); + sprintf(String, "%.3s.%.3s", ascii, ascii + 3); + UI_DisplayFrequency(String, 16, 2, false); + } + + memset(String, 0, sizeof(String)); + + percent = (gAirCopyBlockNumber * 10000) / 120; + + if (gAirCopyIsSendMode == 0) { + sprintf(String, "RCV:%02u.%02u%% E:%d", percent / 100, percent % 100, gErrorsDuringAirCopy); + } else if (gAirCopyIsSendMode == 1) { + sprintf(String, "SND:%02u.%02u%%", percent / 100, percent % 100); + } + + // Draw gauge + if(gAircopyStep != 0) + { + UI_PrintString(String, 2, 127, 5, 8); + + gFrameBuffer[4][1] = 0x3c; + gFrameBuffer[4][2] = 0x42; + + for(uint8_t i = 1; i <= 122; i++) + { + gFrameBuffer[4][2 + i] = 0x81; + } + + gFrameBuffer[4][125] = 0x42; + gFrameBuffer[4][126] = 0x3c; + } + + if(gAirCopyBlockNumber + gErrorsDuringAirCopy != 0) + { + // Check CRC + if(gErrorsDuringAirCopy != lErrorsDuringAirCopy) + { + set_bit(crc, gAirCopyBlockNumber + gErrorsDuringAirCopy); + lErrorsDuringAirCopy = gErrorsDuringAirCopy; + } + + for(uint8_t i = 0; i < (gAirCopyBlockNumber + gErrorsDuringAirCopy); i++) + { + if(get_bit(crc, i) == 0) + { + gFrameBuffer[4][i + 4] = 0xbd; + } + } + } + + ST7565_BlitFullScreen(); } #endif diff --git a/ui/aircopy.h b/ui/aircopy.h index 2c78aeca4..186e86b04 100644 --- a/ui/aircopy.h +++ b/ui/aircopy.h @@ -18,7 +18,7 @@ #define UI_AIRCOPY_H #ifdef ENABLE_AIRCOPY - void UI_DisplayAircopy(void); + void UI_DisplayAircopy(void); #endif #endif diff --git a/ui/battery.c b/ui/battery.c index 1dd8e7576..ec0f77715 100644 --- a/ui/battery.c +++ b/ui/battery.c @@ -25,31 +25,31 @@ void UI_DrawBattery(uint8_t* bitmap, uint8_t level, uint8_t blink) { - if (level < 2 && blink == 1) { - memset(bitmap, 0, sizeof(BITMAP_BatteryLevel1)); - return; - } + if (level < 2 && blink == 1) { + memset(bitmap, 0, sizeof(BITMAP_BatteryLevel1)); + return; + } - memcpy(bitmap, BITMAP_BatteryLevel1, sizeof(BITMAP_BatteryLevel1)); + memcpy(bitmap, BITMAP_BatteryLevel1, sizeof(BITMAP_BatteryLevel1)); - if (level <= 2) { - return; - } + if (level <= 2) { + return; + } - const uint8_t bars = MIN(4, level - 2); + const uint8_t bars = MIN(4, level - 2); - for (int i = 0; i < bars; i++) { + for (int i = 0; i < bars; i++) { #ifndef ENABLE_REVERSE_BAT_SYMBOL - memcpy(bitmap + sizeof(BITMAP_BatteryLevel1) - 4 - (i * 3), BITMAP_BatteryLevel, 2); + memcpy(bitmap + sizeof(BITMAP_BatteryLevel1) - 4 - (i * 3), BITMAP_BatteryLevel, 2); #else - memcpy(bitmap + 3 + (i * 3) + 0, BITMAP_BatteryLevel, 2); + memcpy(bitmap + 3 + (i * 3) + 0, BITMAP_BatteryLevel, 2); #endif - } + } } void UI_DisplayBattery(uint8_t level, uint8_t blink) { - uint8_t bitmap[sizeof(BITMAP_BatteryLevel1)]; - UI_DrawBattery(bitmap, level, blink); - ST7565_DrawLine(LCD_WIDTH - sizeof(bitmap), 0, bitmap, sizeof(bitmap)); + uint8_t bitmap[sizeof(BITMAP_BatteryLevel1)]; + UI_DrawBattery(bitmap, level, blink); + ST7565_DrawLine(LCD_WIDTH - sizeof(bitmap), 0, bitmap, sizeof(bitmap)); } diff --git a/ui/fmradio.c b/ui/fmradio.c index 022464bac..f6f20c14d 100644 --- a/ui/fmradio.c +++ b/ui/fmradio.c @@ -31,72 +31,72 @@ void UI_DisplayFM(void) { - char String[16] = {0}; - char *pPrintStr = String; - UI_DisplayClear(); + char String[16] = {0}; + char *pPrintStr = String; + UI_DisplayClear(); - UI_PrintString("FM", 2, 0, 0, 8); + UI_PrintString("FM", 2, 0, 0, 8); - sprintf(String, "%d%s-%dM", - BK1080_GetFreqLoLimit(gEeprom.FM_Band)/10, - gEeprom.FM_Band == 0 ? ".5" : "", - BK1080_GetFreqHiLimit(gEeprom.FM_Band)/10 - ); - - UI_PrintStringSmallNormal(String, 1, 0, 6); + sprintf(String, "%d%s-%dM", + BK1080_GetFreqLoLimit(gEeprom.FM_Band)/10, + gEeprom.FM_Band == 0 ? ".5" : "", + BK1080_GetFreqHiLimit(gEeprom.FM_Band)/10 + ); + + UI_PrintStringSmallNormal(String, 1, 0, 6); - //uint8_t spacings[] = {20,10,5}; - //sprintf(String, "%d0k", spacings[gEeprom.FM_Space % 3]); - //UI_PrintStringSmallNormal(String, 127 - 4*7, 0, 6); + //uint8_t spacings[] = {20,10,5}; + //sprintf(String, "%d0k", spacings[gEeprom.FM_Space % 3]); + //UI_PrintStringSmallNormal(String, 127 - 4*7, 0, 6); - if (gAskToSave) { - pPrintStr = "SAVE?"; - } else if (gAskToDelete) { - pPrintStr = "DEL?"; - } else if (gFM_ScanState == FM_SCAN_OFF) { - if (gEeprom.FM_IsMrMode) { - sprintf(String, "MR(CH%02u)", gEeprom.FM_SelectedChannel + 1); - pPrintStr = String; - } else { - pPrintStr = "VFO"; - for (unsigned int i = 0; i < 20; i++) { - if (gEeprom.FM_FrequencyPlaying == gFM_Channels[i]) { - sprintf(String, "VFO(CH%02u)", i + 1); - pPrintStr = String; - break; - } - } - } - } else if (gFM_AutoScan) { - sprintf(String, "A-SCAN(%u)", gFM_ChannelPosition + 1); - pPrintStr = String; - } else { - pPrintStr = "M-SCAN"; - } + if (gAskToSave) { + pPrintStr = "SAVE?"; + } else if (gAskToDelete) { + pPrintStr = "DEL?"; + } else if (gFM_ScanState == FM_SCAN_OFF) { + if (gEeprom.FM_IsMrMode) { + sprintf(String, "MR(CH%02u)", gEeprom.FM_SelectedChannel + 1); + pPrintStr = String; + } else { + pPrintStr = "VFO"; + for (unsigned int i = 0; i < 20; i++) { + if (gEeprom.FM_FrequencyPlaying == gFM_Channels[i]) { + sprintf(String, "VFO(CH%02u)", i + 1); + pPrintStr = String; + break; + } + } + } + } else if (gFM_AutoScan) { + sprintf(String, "A-SCAN(%u)", gFM_ChannelPosition + 1); + pPrintStr = String; + } else { + pPrintStr = "M-SCAN"; + } - UI_PrintString(pPrintStr, 0, 127, 3, 10); // memory, vfo, scan + UI_PrintString(pPrintStr, 0, 127, 3, 10); // memory, vfo, scan - memset(String, 0, sizeof(String)); - if (gAskToSave || (gEeprom.FM_IsMrMode && gInputBoxIndex > 0)) { - UI_GenerateChannelString(String, gFM_ChannelPosition); - } else if (gAskToDelete) { - sprintf(String, "CH-%02u", gEeprom.FM_SelectedChannel + 1); - } else { - if (gInputBoxIndex == 0) { - sprintf(String, "%3d.%d", gEeprom.FM_FrequencyPlaying / 10, gEeprom.FM_FrequencyPlaying % 10); - } else { - const char * ascii = INPUTBOX_GetAscii(); - sprintf(String, "%.3s.%.1s",ascii, ascii + 3); - } + memset(String, 0, sizeof(String)); + if (gAskToSave || (gEeprom.FM_IsMrMode && gInputBoxIndex > 0)) { + UI_GenerateChannelString(String, gFM_ChannelPosition); + } else if (gAskToDelete) { + sprintf(String, "CH-%02u", gEeprom.FM_SelectedChannel + 1); + } else { + if (gInputBoxIndex == 0) { + sprintf(String, "%3d.%d", gEeprom.FM_FrequencyPlaying / 10, gEeprom.FM_FrequencyPlaying % 10); + } else { + const char * ascii = INPUTBOX_GetAscii(); + sprintf(String, "%.3s.%.1s",ascii, ascii + 3); + } - UI_DisplayFrequency(String, 36, 1, gInputBoxIndex == 0); // frequency - ST7565_BlitFullScreen(); - return; - } + UI_DisplayFrequency(String, 36, 1, gInputBoxIndex == 0); // frequency + ST7565_BlitFullScreen(); + return; + } - UI_PrintString(String, 0, 127, 1, 10); + UI_PrintString(String, 0, 127, 1, 10); - ST7565_BlitFullScreen(); + ST7565_BlitFullScreen(); } #endif diff --git a/ui/fmradio.h b/ui/fmradio.h index 9aee109ab..b1f7e3149 100644 --- a/ui/fmradio.h +++ b/ui/fmradio.h @@ -18,7 +18,7 @@ #define UI_FM_H #ifdef ENABLE_FMRADIO - void UI_DisplayFM(void); + void UI_DisplayFM(void); #endif #endif diff --git a/ui/helper.c b/ui/helper.c index e4629706f..c42c4453f 100644 --- a/ui/helper.c +++ b/ui/helper.c @@ -24,288 +24,288 @@ #include "misc.h" #ifndef ARRAY_SIZE - #define ARRAY_SIZE(arr) (sizeof(arr)/sizeof((arr)[0])) + #define ARRAY_SIZE(arr) (sizeof(arr)/sizeof((arr)[0])) #endif void UI_GenerateChannelString(char *pString, const uint8_t Channel) { - unsigned int i; - - if (gInputBoxIndex == 0) - { - sprintf(pString, "CH-%02u", Channel + 1); - return; - } - - pString[0] = 'C'; - pString[1] = 'H'; - pString[2] = '-'; - for (i = 0; i < 2; i++) - pString[i + 3] = (gInputBox[i] == 10) ? '-' : gInputBox[i] + '0'; + unsigned int i; + + if (gInputBoxIndex == 0) + { + sprintf(pString, "CH-%02u", Channel + 1); + return; + } + + pString[0] = 'C'; + pString[1] = 'H'; + pString[2] = '-'; + for (i = 0; i < 2; i++) + pString[i + 3] = (gInputBox[i] == 10) ? '-' : gInputBox[i] + '0'; } void UI_GenerateChannelStringEx(char *pString, const bool bShowPrefix, const uint8_t ChannelNumber) { - if (gInputBoxIndex > 0) { - for (unsigned int i = 0; i < 3; i++) { - pString[i] = (gInputBox[i] == 10) ? '-' : gInputBox[i] + '0'; - } - - pString[3] = 0; - return; - } - - if (bShowPrefix) { - // BUG here? Prefixed NULLs are allowed - sprintf(pString, "CH-%03u", ChannelNumber + 1); - } else if (ChannelNumber == 0xFF) { - strcpy(pString, "NULL"); - } else { - sprintf(pString, "%03u", ChannelNumber + 1); - } + if (gInputBoxIndex > 0) { + for (unsigned int i = 0; i < 3; i++) { + pString[i] = (gInputBox[i] == 10) ? '-' : gInputBox[i] + '0'; + } + + pString[3] = 0; + return; + } + + if (bShowPrefix) { + // BUG here? Prefixed NULLs are allowed + sprintf(pString, "CH-%03u", ChannelNumber + 1); + } else if (ChannelNumber == 0xFF) { + strcpy(pString, "NULL"); + } else { + sprintf(pString, "%03u", ChannelNumber + 1); + } } void UI_PrintStringBuffer(const char *pString, uint8_t * buffer, uint32_t char_width, const uint8_t *font) { - const size_t Length = strlen(pString); - const unsigned int char_spacing = char_width + 1; - for (size_t i = 0; i < Length; i++) { - const unsigned int index = pString[i] - ' ' - 1; - if (pString[i] > ' ' && pString[i] < 127) { - const uint32_t offset = i * char_spacing + 1; - memcpy(buffer + offset, font + index * char_width, char_width); - } - } + const size_t Length = strlen(pString); + const unsigned int char_spacing = char_width + 1; + for (size_t i = 0; i < Length; i++) { + const unsigned int index = pString[i] - ' ' - 1; + if (pString[i] > ' ' && pString[i] < 127) { + const uint32_t offset = i * char_spacing + 1; + memcpy(buffer + offset, font + index * char_width, char_width); + } + } } void UI_PrintString(const char *pString, uint8_t Start, uint8_t End, uint8_t Line, uint8_t Width) { - size_t i; - size_t Length = strlen(pString); - - if (End > Start) - Start += (((End - Start) - (Length * Width)) + 1) / 2; - - for (i = 0; i < Length; i++) - { - const unsigned int ofs = (unsigned int)Start + (i * Width); - if (pString[i] > ' ' && pString[i] < 127) - { - const unsigned int index = pString[i] - ' ' - 1; - memcpy(gFrameBuffer[Line + 0] + ofs, &gFontBig[index][0], 7); - memcpy(gFrameBuffer[Line + 1] + ofs, &gFontBig[index][7], 7); - } - } + size_t i; + size_t Length = strlen(pString); + + if (End > Start) + Start += (((End - Start) - (Length * Width)) + 1) / 2; + + for (i = 0; i < Length; i++) + { + const unsigned int ofs = (unsigned int)Start + (i * Width); + if (pString[i] > ' ' && pString[i] < 127) + { + const unsigned int index = pString[i] - ' ' - 1; + memcpy(gFrameBuffer[Line + 0] + ofs, &gFontBig[index][0], 7); + memcpy(gFrameBuffer[Line + 1] + ofs, &gFontBig[index][7], 7); + } + } } void UI_PrintStringSmall(const char *pString, uint8_t Start, uint8_t End, uint8_t Line, uint8_t char_width, const uint8_t *font) { - const size_t Length = strlen(pString); - const unsigned int char_spacing = char_width + 1; + const size_t Length = strlen(pString); + const unsigned int char_spacing = char_width + 1; - if (End > Start) { - Start += (((End - Start) - Length * char_spacing) + 1) / 2; - } + if (End > Start) { + Start += (((End - Start) - Length * char_spacing) + 1) / 2; + } - UI_PrintStringBuffer(pString, gFrameBuffer[Line] + Start, char_width, font); + UI_PrintStringBuffer(pString, gFrameBuffer[Line] + Start, char_width, font); } void UI_PrintStringSmallNormal(const char *pString, uint8_t Start, uint8_t End, uint8_t Line) { - UI_PrintStringSmall(pString, Start, End, Line, ARRAY_SIZE(gFontSmall[0]), (const uint8_t *)gFontSmall); + UI_PrintStringSmall(pString, Start, End, Line, ARRAY_SIZE(gFontSmall[0]), (const uint8_t *)gFontSmall); } void UI_PrintStringSmallBold(const char *pString, uint8_t Start, uint8_t End, uint8_t Line) { #ifdef ENABLE_SMALL_BOLD - const uint8_t *font = (uint8_t *)gFontSmallBold; - const uint8_t char_width = ARRAY_SIZE(gFontSmallBold[0]); + const uint8_t *font = (uint8_t *)gFontSmallBold; + const uint8_t char_width = ARRAY_SIZE(gFontSmallBold[0]); #else - const uint8_t *font = (uint8_t *)gFontSmall; - const uint8_t char_width = ARRAY_SIZE(gFontSmall[0]); + const uint8_t *font = (uint8_t *)gFontSmall; + const uint8_t char_width = ARRAY_SIZE(gFontSmall[0]); #endif - UI_PrintStringSmall(pString, Start, End, Line, char_width, font); + UI_PrintStringSmall(pString, Start, End, Line, char_width, font); } void UI_PrintStringSmallBufferNormal(const char *pString, uint8_t * buffer) { - UI_PrintStringBuffer(pString, buffer, ARRAY_SIZE(gFontSmall[0]), (uint8_t *)gFontSmall); + UI_PrintStringBuffer(pString, buffer, ARRAY_SIZE(gFontSmall[0]), (uint8_t *)gFontSmall); } void UI_PrintStringSmallBufferBold(const char *pString, uint8_t * buffer) { #ifdef ENABLE_SMALL_BOLD - const uint8_t *font = (uint8_t *)gFontSmallBold; - const uint8_t char_width = ARRAY_SIZE(gFontSmallBold[0]); + const uint8_t *font = (uint8_t *)gFontSmallBold; + const uint8_t char_width = ARRAY_SIZE(gFontSmallBold[0]); #else - const uint8_t *font = (uint8_t *)gFontSmall; - const uint8_t char_width = ARRAY_SIZE(gFontSmall[0]); + const uint8_t *font = (uint8_t *)gFontSmall; + const uint8_t char_width = ARRAY_SIZE(gFontSmall[0]); #endif - UI_PrintStringBuffer(pString, buffer, char_width, font); + UI_PrintStringBuffer(pString, buffer, char_width, font); } void UI_DisplayFrequency(const char *string, uint8_t X, uint8_t Y, bool center) { - const unsigned int char_width = 13; - uint8_t *pFb0 = gFrameBuffer[Y] + X; - uint8_t *pFb1 = pFb0 + 128; - bool bCanDisplay = false; - - uint8_t len = strlen(string); - for(int i = 0; i < len; i++) { - char c = string[i]; - if(c=='-') c = '9' + 1; - if (bCanDisplay || c != ' ') - { - bCanDisplay = true; - if(c>='0' && c<='9' + 1) { - memcpy(pFb0 + 2, gFontBigDigits[c-'0'], char_width - 3); - memcpy(pFb1 + 2, gFontBigDigits[c-'0'] + char_width - 3, char_width - 3); - } - else if(c=='.') { - *pFb1 = 0x60; pFb0++; pFb1++; - *pFb1 = 0x60; pFb0++; pFb1++; - *pFb1 = 0x60; pFb0++; pFb1++; - continue; - } - - } - else if (center) { - pFb0 -= 6; - pFb1 -= 6; - } - pFb0 += char_width; - pFb1 += char_width; - } + const unsigned int char_width = 13; + uint8_t *pFb0 = gFrameBuffer[Y] + X; + uint8_t *pFb1 = pFb0 + 128; + bool bCanDisplay = false; + + uint8_t len = strlen(string); + for(int i = 0; i < len; i++) { + char c = string[i]; + if(c=='-') c = '9' + 1; + if (bCanDisplay || c != ' ') + { + bCanDisplay = true; + if(c>='0' && c<='9' + 1) { + memcpy(pFb0 + 2, gFontBigDigits[c-'0'], char_width - 3); + memcpy(pFb1 + 2, gFontBigDigits[c-'0'] + char_width - 3, char_width - 3); + } + else if(c=='.') { + *pFb1 = 0x60; pFb0++; pFb1++; + *pFb1 = 0x60; pFb0++; pFb1++; + *pFb1 = 0x60; pFb0++; pFb1++; + continue; + } + + } + else if (center) { + pFb0 -= 6; + pFb1 -= 6; + } + pFb0 += char_width; + pFb1 += char_width; + } } void UI_DrawPixelBuffer(uint8_t (*buffer)[128], uint8_t x, uint8_t y, bool black) { - const uint8_t pattern = 1 << (y % 8); - if(black) - buffer[y/8][x] |= pattern; - else - buffer[y/8][x] &= ~pattern; + const uint8_t pattern = 1 << (y % 8); + if(black) + buffer[y/8][x] |= pattern; + else + buffer[y/8][x] &= ~pattern; } static void sort(int16_t *a, int16_t *b) { - if(*a > *b) { - int16_t t = *a; - *a = *b; - *b = t; - } + if(*a > *b) { + int16_t t = *a; + *a = *b; + *b = t; + } } #ifdef ENABLE_FEAT_F4HWN - /* - void UI_DrawLineDottedBuffer(uint8_t (*buffer)[128], int16_t x1, int16_t y1, int16_t x2, int16_t y2, bool black) - { - if(x2==x1) { - sort(&y1, &y2); - for(int16_t i = y1; i <= y2; i+=2) { - UI_DrawPixelBuffer(buffer, x1, i, black); - } - } else { - const int multipl = 1000; - int a = (y2-y1)*multipl / (x2-x1); - int b = y1 - a * x1 / multipl; - - sort(&x1, &x2); - for(int i = x1; i<= x2; i+=2) - { - UI_DrawPixelBuffer(buffer, i, i*a/multipl +b, black); - } - } - } - */ - - void PutPixel(uint8_t x, uint8_t y, bool fill) { - UI_DrawPixelBuffer(gFrameBuffer, x, y, fill); - } - - void PutPixelStatus(uint8_t x, uint8_t y, bool fill) { - UI_DrawPixelBuffer(&gStatusLine, x, y, fill); - } - - void GUI_DisplaySmallest(const char *pString, uint8_t x, uint8_t y, - bool statusbar, bool fill) { - uint8_t c; - uint8_t pixels; - const uint8_t *p = (const uint8_t *)pString; - - while ((c = *p++) && c != '\0') { - c -= 0x20; - for (int i = 0; i < 3; ++i) { - pixels = gFont3x5[c][i]; - for (int j = 0; j < 6; ++j) { - if (pixels & 1) { - if (statusbar) - PutPixelStatus(x + i, y + j, fill); - else - PutPixel(x + i, y + j, fill); - } - pixels >>= 1; - } - } - x += 4; - } - } + /* + void UI_DrawLineDottedBuffer(uint8_t (*buffer)[128], int16_t x1, int16_t y1, int16_t x2, int16_t y2, bool black) + { + if(x2==x1) { + sort(&y1, &y2); + for(int16_t i = y1; i <= y2; i+=2) { + UI_DrawPixelBuffer(buffer, x1, i, black); + } + } else { + const int multipl = 1000; + int a = (y2-y1)*multipl / (x2-x1); + int b = y1 - a * x1 / multipl; + + sort(&x1, &x2); + for(int i = x1; i<= x2; i+=2) + { + UI_DrawPixelBuffer(buffer, i, i*a/multipl +b, black); + } + } + } + */ + + void PutPixel(uint8_t x, uint8_t y, bool fill) { + UI_DrawPixelBuffer(gFrameBuffer, x, y, fill); + } + + void PutPixelStatus(uint8_t x, uint8_t y, bool fill) { + UI_DrawPixelBuffer(&gStatusLine, x, y, fill); + } + + void GUI_DisplaySmallest(const char *pString, uint8_t x, uint8_t y, + bool statusbar, bool fill) { + uint8_t c; + uint8_t pixels; + const uint8_t *p = (const uint8_t *)pString; + + while ((c = *p++) && c != '\0') { + c -= 0x20; + for (int i = 0; i < 3; ++i) { + pixels = gFont3x5[c][i]; + for (int j = 0; j < 6; ++j) { + if (pixels & 1) { + if (statusbar) + PutPixelStatus(x + i, y + j, fill); + else + PutPixel(x + i, y + j, fill); + } + pixels >>= 1; + } + } + x += 4; + } + } #endif - + void UI_DrawLineBuffer(uint8_t (*buffer)[128], int16_t x1, int16_t y1, int16_t x2, int16_t y2, bool black) { - if(x2==x1) { - sort(&y1, &y2); - for(int16_t i = y1; i <= y2; i++) { - UI_DrawPixelBuffer(buffer, x1, i, black); - } - } else { - const int multipl = 1000; - int a = (y2-y1)*multipl / (x2-x1); - int b = y1 - a * x1 / multipl; - - sort(&x1, &x2); - for(int i = x1; i<= x2; i++) - { - UI_DrawPixelBuffer(buffer, i, i*a/multipl +b, black); - } - } + if(x2==x1) { + sort(&y1, &y2); + for(int16_t i = y1; i <= y2; i++) { + UI_DrawPixelBuffer(buffer, x1, i, black); + } + } else { + const int multipl = 1000; + int a = (y2-y1)*multipl / (x2-x1); + int b = y1 - a * x1 / multipl; + + sort(&x1, &x2); + for(int i = x1; i<= x2; i++) + { + UI_DrawPixelBuffer(buffer, i, i*a/multipl +b, black); + } + } } void UI_DrawRectangleBuffer(uint8_t (*buffer)[128], int16_t x1, int16_t y1, int16_t x2, int16_t y2, bool black) { - UI_DrawLineBuffer(buffer, x1,y1, x1,y2, black); - UI_DrawLineBuffer(buffer, x1,y1, x2,y1, black); - UI_DrawLineBuffer(buffer, x2,y1, x2,y2, black); - UI_DrawLineBuffer(buffer, x1,y2, x2,y2, black); + UI_DrawLineBuffer(buffer, x1,y1, x1,y2, black); + UI_DrawLineBuffer(buffer, x1,y1, x2,y1, black); + UI_DrawLineBuffer(buffer, x2,y1, x2,y2, black); + UI_DrawLineBuffer(buffer, x1,y2, x2,y2, black); } void UI_DisplayPopup(const char *string) { - UI_DisplayClear(); - - // for(uint8_t i = 1; i < 5; i++) { - // memset(gFrameBuffer[i]+8, 0x00, 111); - // } - - // for(uint8_t x = 10; x < 118; x++) { - // UI_DrawPixelBuffer(x, 10, true); - // UI_DrawPixelBuffer(x, 46-9, true); - // } - - // for(uint8_t y = 11; y < 37; y++) { - // UI_DrawPixelBuffer(10, y, true); - // UI_DrawPixelBuffer(117, y, true); - // } - // DrawRectangle(9,9, 118,38, true); - UI_PrintString(string, 9, 118, 2, 8); - UI_PrintStringSmallNormal("Press EXIT", 9, 118, 6); + UI_DisplayClear(); + + // for(uint8_t i = 1; i < 5; i++) { + // memset(gFrameBuffer[i]+8, 0x00, 111); + // } + + // for(uint8_t x = 10; x < 118; x++) { + // UI_DrawPixelBuffer(x, 10, true); + // UI_DrawPixelBuffer(x, 46-9, true); + // } + + // for(uint8_t y = 11; y < 37; y++) { + // UI_DrawPixelBuffer(10, y, true); + // UI_DrawPixelBuffer(117, y, true); + // } + // DrawRectangle(9,9, 118,38, true); + UI_PrintString(string, 9, 118, 2, 8); + UI_PrintStringSmallNormal("Press EXIT", 9, 118, 6); } void UI_DisplayClear() { - memset(gFrameBuffer, 0, sizeof(gFrameBuffer)); + memset(gFrameBuffer, 0, sizeof(gFrameBuffer)); } diff --git a/ui/helper.h b/ui/helper.h index 294c7442b..2dea9ea4a 100644 --- a/ui/helper.h +++ b/ui/helper.h @@ -33,10 +33,10 @@ void UI_DisplayPopup(const char *string); void UI_DrawPixelBuffer(uint8_t (*buffer)[128], uint8_t x, uint8_t y, bool black); #ifdef ENABLE_FEAT_F4HWN - //void UI_DrawLineDottedBuffer(uint8_t (*buffer)[128], int16_t x1, int16_t y1, int16_t x2, int16_t y2, bool black); - void PutPixel(uint8_t x, uint8_t y, bool fill); - void PutPixelStatus(uint8_t x, uint8_t y, bool fill); - void GUI_DisplaySmallest(const char *pString, uint8_t x, uint8_t y, bool statusbar, bool fill); + //void UI_DrawLineDottedBuffer(uint8_t (*buffer)[128], int16_t x1, int16_t y1, int16_t x2, int16_t y2, bool black); + void PutPixel(uint8_t x, uint8_t y, bool fill); + void PutPixelStatus(uint8_t x, uint8_t y, bool fill); + void GUI_DisplaySmallest(const char *pString, uint8_t x, uint8_t y, bool statusbar, bool fill); #endif void UI_DrawLineBuffer(uint8_t (*buffer)[128], int16_t x1, int16_t y1, int16_t x2, int16_t y2, bool black); void UI_DrawRectangleBuffer(uint8_t (*buffer)[128], int16_t x1, int16_t y1, int16_t x2, int16_t y2, bool black); diff --git a/ui/inputbox.c b/ui/inputbox.c index 39a6596a1..2a13a6d45 100644 --- a/ui/inputbox.c +++ b/ui/inputbox.c @@ -24,21 +24,21 @@ uint8_t gInputBoxIndex; void INPUTBOX_Append(const KEY_Code_t Digit) { - if (gInputBoxIndex >= sizeof(gInputBox)) - return; + if (gInputBoxIndex >= sizeof(gInputBox)) + return; - if (gInputBoxIndex == 0) - memset(gInputBox, 10, sizeof(gInputBox)); + if (gInputBoxIndex == 0) + memset(gInputBox, 10, sizeof(gInputBox)); - if (Digit != KEY_INVALID) - gInputBox[gInputBoxIndex++] = (char)(Digit - KEY_0); + if (Digit != KEY_INVALID) + gInputBox[gInputBoxIndex++] = (char)(Digit - KEY_0); } const char* INPUTBOX_GetAscii() { - for(int i = 0; i < 8; i++) { - char c = gInputBox[i]; - inputBoxAscii[i] = (c==10)? '-' : '0' + c; - } - return inputBoxAscii; + for(int i = 0; i < 8; i++) { + char c = gInputBox[i]; + inputBoxAscii[i] = (c==10)? '-' : '0' + c; + } + return inputBoxAscii; } \ No newline at end of file diff --git a/ui/lock.c b/ui/lock.c index 44423bf3f..a34d1a088 100644 --- a/ui/lock.c +++ b/ui/lock.c @@ -31,131 +31,131 @@ static void Render(void) { - unsigned int i; - char String[7]; + unsigned int i; + char String[7]; - memset(gStatusLine, 0, sizeof(gStatusLine)); - UI_DisplayClear(); + memset(gStatusLine, 0, sizeof(gStatusLine)); + UI_DisplayClear(); - UI_PrintString("LOCK", 0, 127, 1, 10); - for (i = 0; i < 6; i++) - String[i] = (gInputBox[i] == 10) ? '-' : '*'; - String[6] = 0; - UI_PrintString(String, 0, 127, 3, 12); + UI_PrintString("LOCK", 0, 127, 1, 10); + for (i = 0; i < 6; i++) + String[i] = (gInputBox[i] == 10) ? '-' : '*'; + String[6] = 0; + UI_PrintString(String, 0, 127, 3, 12); - ST7565_BlitStatusLine(); - ST7565_BlitFullScreen(); + ST7565_BlitStatusLine(); + ST7565_BlitFullScreen(); } void UI_DisplayLock(void) { - KEY_Code_t Key; - BEEP_Type_t Beep; - - gUpdateDisplay = true; - - memset(gInputBox, 10, sizeof(gInputBox)); - - while (1) - { - while (!gNextTimeslice) {} - - // TODO: Original code doesn't do the below, but is needed for proper key debounce - - gNextTimeslice = false; - - Key = KEYBOARD_Poll(); - - if (gKeyReading0 == Key) - { - if (++gDebounceCounter == key_debounce_10ms) - { - if (Key == KEY_INVALID) - { - gKeyReading1 = KEY_INVALID; - } - else - { - gKeyReading1 = Key; - - switch (Key) - { - case KEY_0: - case KEY_1: - case KEY_2: - case KEY_3: - case KEY_4: - case KEY_5: - case KEY_6: - case KEY_7: - case KEY_8: - case KEY_9: - INPUTBOX_Append(Key - KEY_0); - - if (gInputBoxIndex < 6) // 6 frequency digits - { - Beep = BEEP_1KHZ_60MS_OPTIONAL; - } - else - { - uint32_t Password; - - gInputBoxIndex = 0; - Password = StrToUL(INPUTBOX_GetAscii()); - - if ((gEeprom.POWER_ON_PASSWORD) == Password) - { - AUDIO_PlayBeep(BEEP_1KHZ_60MS_OPTIONAL); - return; - } - - memset(gInputBox, 10, sizeof(gInputBox)); - - Beep = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - } - - AUDIO_PlayBeep(Beep); - - gUpdateDisplay = true; - break; - - case KEY_EXIT: - if (gInputBoxIndex > 0) - { - gInputBox[--gInputBoxIndex] = 10; - gUpdateDisplay = true; - } - - AUDIO_PlayBeep(BEEP_1KHZ_60MS_OPTIONAL); - - default: - break; - } - } - - gKeyBeingHeld = false; - } - } - else - { - gDebounceCounter = 0; - gKeyReading0 = Key; - } + KEY_Code_t Key; + BEEP_Type_t Beep; + + gUpdateDisplay = true; + + memset(gInputBox, 10, sizeof(gInputBox)); + + while (1) + { + while (!gNextTimeslice) {} + + // TODO: Original code doesn't do the below, but is needed for proper key debounce + + gNextTimeslice = false; + + Key = KEYBOARD_Poll(); + + if (gKeyReading0 == Key) + { + if (++gDebounceCounter == key_debounce_10ms) + { + if (Key == KEY_INVALID) + { + gKeyReading1 = KEY_INVALID; + } + else + { + gKeyReading1 = Key; + + switch (Key) + { + case KEY_0: + case KEY_1: + case KEY_2: + case KEY_3: + case KEY_4: + case KEY_5: + case KEY_6: + case KEY_7: + case KEY_8: + case KEY_9: + INPUTBOX_Append(Key - KEY_0); + + if (gInputBoxIndex < 6) // 6 frequency digits + { + Beep = BEEP_1KHZ_60MS_OPTIONAL; + } + else + { + uint32_t Password; + + gInputBoxIndex = 0; + Password = StrToUL(INPUTBOX_GetAscii()); + + if ((gEeprom.POWER_ON_PASSWORD) == Password) + { + AUDIO_PlayBeep(BEEP_1KHZ_60MS_OPTIONAL); + return; + } + + memset(gInputBox, 10, sizeof(gInputBox)); + + Beep = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + } + + AUDIO_PlayBeep(Beep); + + gUpdateDisplay = true; + break; + + case KEY_EXIT: + if (gInputBoxIndex > 0) + { + gInputBox[--gInputBoxIndex] = 10; + gUpdateDisplay = true; + } + + AUDIO_PlayBeep(BEEP_1KHZ_60MS_OPTIONAL); + + default: + break; + } + } + + gKeyBeingHeld = false; + } + } + else + { + gDebounceCounter = 0; + gKeyReading0 = Key; + } #ifdef ENABLE_UART - if (UART_IsCommandAvailable()) - { - __disable_irq(); - UART_HandleCommand(); - __enable_irq(); - } + if (UART_IsCommandAvailable()) + { + __disable_irq(); + UART_HandleCommand(); + __enable_irq(); + } #endif - if (gUpdateDisplay) - { - Render(); - gUpdateDisplay = false; - } - } + if (gUpdateDisplay) + { + Render(); + gUpdateDisplay = false; + } + } } #endif diff --git a/ui/lock.h b/ui/lock.h index e42758d8e..d8a7fa982 100644 --- a/ui/lock.h +++ b/ui/lock.h @@ -18,7 +18,7 @@ #define UI_LOCK_H #ifdef ENABLE_PWRON_PASSWORD - void UI_DisplayLock(void); + void UI_DisplayLock(void); #endif #endif diff --git a/ui/main.c b/ui/main.c index 1be334611..6b9d6f317 100644 --- a/ui/main.c +++ b/ui/main.c @@ -20,7 +20,7 @@ #include "app/chFrScanner.h" #include "app/dtmf.h" #ifdef ENABLE_AM_FIX - #include "am_fix.h" + #include "am_fix.h" #endif #include "bitmaps.h" #include "board.h" @@ -39,52 +39,52 @@ #include "audio.h" #ifdef ENABLE_FEAT_F4HWN - #include "driver/system.h" + #include "driver/system.h" #endif center_line_t center_line = CENTER_LINE_NONE; #ifdef ENABLE_FEAT_F4HWN - static int8_t RxBlink; - static int8_t RxBlinkLed = 0; - static int8_t RxBlinkLedCounter; - static int8_t RxLine; - static uint32_t RxOnVfofrequency; - - bool isMainOnlyInputDTMF = false; - - static int16_t map(int16_t x, int16_t in_min, int16_t in_max, int16_t out_min, int16_t out_max) { - return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; - } - - static bool isMainOnly(bool checkGui) - { - if(checkGui) - { - if(((gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) + (gEeprom.CROSS_BAND_RX_TX != CROSS_BAND_OFF) * 2 == 0) || gSetting_set_gui) - return true; - else - return false; - } - else - { - if((gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) + (gEeprom.CROSS_BAND_RX_TX != CROSS_BAND_OFF) * 2 == 0) - return true; - else - return false; - } - } + static int8_t RxBlink; + static int8_t RxBlinkLed = 0; + static int8_t RxBlinkLedCounter; + static int8_t RxLine; + static uint32_t RxOnVfofrequency; + + bool isMainOnlyInputDTMF = false; + + static int16_t map(int16_t x, int16_t in_min, int16_t in_max, int16_t out_min, int16_t out_max) { + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; + } + + static bool isMainOnly(bool checkGui) + { + if(checkGui) + { + if(((gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) + (gEeprom.CROSS_BAND_RX_TX != CROSS_BAND_OFF) * 2 == 0) || gSetting_set_gui) + return true; + else + return false; + } + else + { + if((gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) + (gEeprom.CROSS_BAND_RX_TX != CROSS_BAND_OFF) * 2 == 0) + return true; + else + return false; + } + } #endif const int8_t dBmCorrTable[7] = { - -15, // band 1 - -25, // band 2 - -20, // band 3 - -4, // band 4 - -7, // band 5 - -6, // band 6 - -1 // band 7 - }; + -15, // band 1 + -25, // band 2 + -20, // band 3 + -4, // band 4 + -7, // band 5 + -6, // band 6 + -1 // band 7 + }; const char *VfoStateStr[] = { [VFO_STATE_NORMAL]="", @@ -100,159 +100,159 @@ const char *VfoStateStr[] = { static void DrawSmallAntennaAndBars(uint8_t *p, unsigned int level) { - if(level>6) - level = 6; + if(level>6) + level = 6; - memcpy(p, BITMAP_Antenna, ARRAY_SIZE(BITMAP_Antenna)); + memcpy(p, BITMAP_Antenna, ARRAY_SIZE(BITMAP_Antenna)); - for(uint8_t i = 1; i <= level; i++) { - char bar = (0xff << (6-i)) & 0x7F; - memset(p + 2 + i*3, bar, 2); - } + for(uint8_t i = 1; i <= level; i++) { + char bar = (0xff << (6-i)) & 0x7F; + memset(p + 2 + i*3, bar, 2); + } } #if defined ENABLE_AUDIO_BAR || defined ENABLE_RSSI_BAR static void DrawLevelBar(uint8_t xpos, uint8_t line, uint8_t level) { #ifndef ENABLE_FEAT_F4HWN - const char hollowBar[] = { - 0b01111111, - 0b01000001, - 0b01000001, - 0b01111111 - }; + const char hollowBar[] = { + 0b01111111, + 0b01000001, + 0b01000001, + 0b01111111 + }; #endif - - uint8_t *p_line = gFrameBuffer[line]; - level = MIN(level, 13); + + uint8_t *p_line = gFrameBuffer[line]; + level = MIN(level, 13); - for(uint8_t i = 0; i < level; i++) { + for(uint8_t i = 0; i < level; i++) { #ifdef ENABLE_FEAT_F4HWN - if(gSetting_set_met) - { - const char hollowBar[] = { - 0b01111111, - 0b01000001, - 0b01000001, - 0b01111111 - }; - - if(i < 9) { - for(uint8_t j = 0; j < 4; j++) - p_line[xpos + i * 5 + j] = (~(0x7F >> (i+1))) & 0x7F; - } - else { - memcpy(p_line + (xpos + i * 5), &hollowBar, ARRAY_SIZE(hollowBar)); - } - } - else - { - const char hollowBar[] = { - 0b00111110, - 0b00100010, - 0b00100010, - 0b00111110 - }; - - const char simpleBar[] = { - 0b00111110, - 0b00111110, - 0b00111110, - 0b00111110 - }; - - if(i < 9) { - memcpy(p_line + (xpos + i * 5), &simpleBar, ARRAY_SIZE(simpleBar)); - } - else { - memcpy(p_line + (xpos + i * 5), &hollowBar, ARRAY_SIZE(hollowBar)); - } - } + if(gSetting_set_met) + { + const char hollowBar[] = { + 0b01111111, + 0b01000001, + 0b01000001, + 0b01111111 + }; + + if(i < 9) { + for(uint8_t j = 0; j < 4; j++) + p_line[xpos + i * 5 + j] = (~(0x7F >> (i+1))) & 0x7F; + } + else { + memcpy(p_line + (xpos + i * 5), &hollowBar, ARRAY_SIZE(hollowBar)); + } + } + else + { + const char hollowBar[] = { + 0b00111110, + 0b00100010, + 0b00100010, + 0b00111110 + }; + + const char simpleBar[] = { + 0b00111110, + 0b00111110, + 0b00111110, + 0b00111110 + }; + + if(i < 9) { + memcpy(p_line + (xpos + i * 5), &simpleBar, ARRAY_SIZE(simpleBar)); + } + else { + memcpy(p_line + (xpos + i * 5), &hollowBar, ARRAY_SIZE(hollowBar)); + } + } #else - if(i < 9) { - for(uint8_t j = 0; j < 4; j++) - p_line[xpos + i * 5 + j] = (~(0x7F >> (i+1))) & 0x7F; - } - else { - memcpy(p_line + (xpos + i * 5), &hollowBar, ARRAY_SIZE(hollowBar)); - } + if(i < 9) { + for(uint8_t j = 0; j < 4; j++) + p_line[xpos + i * 5 + j] = (~(0x7F >> (i+1))) & 0x7F; + } + else { + memcpy(p_line + (xpos + i * 5), &hollowBar, ARRAY_SIZE(hollowBar)); + } #endif - } + } } #endif #ifdef ENABLE_AUDIO_BAR unsigned int sqrt16(unsigned int value) -{ // return square root of 'value' - unsigned int shift = 16; // number of bits supplied in 'value' .. 2 ~ 32 - unsigned int bit = 1u << --shift; - unsigned int sqrti = 0; - while (bit) - { - const unsigned int temp = ((sqrti << 1) | bit) << shift--; - if (value >= temp) { - value -= temp; - sqrti |= bit; - } - bit >>= 1; - } - return sqrti; +{ // return square root of 'value' + unsigned int shift = 16; // number of bits supplied in 'value' .. 2 ~ 32 + unsigned int bit = 1u << --shift; + unsigned int sqrti = 0; + while (bit) + { + const unsigned int temp = ((sqrti << 1) | bit) << shift--; + if (value >= temp) { + value -= temp; + sqrti |= bit; + } + bit >>= 1; + } + return sqrti; } void UI_DisplayAudioBar(void) { - if (gSetting_mic_bar) - { - if(gLowBattery && !gLowBatteryConfirmed) - return; + if (gSetting_mic_bar) + { + if(gLowBattery && !gLowBatteryConfirmed) + return; #ifdef ENABLE_FEAT_F4HWN - RxBlinkLed = 0; - RxBlinkLedCounter = 0; - BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, false); - unsigned int line; - if (isMainOnly(false)) - { - line = 5; - } - else - { - line = 3; - } + RxBlinkLed = 0; + RxBlinkLedCounter = 0; + BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, false); + unsigned int line; + if (isMainOnly(false)) + { + line = 5; + } + else + { + line = 3; + } #else - const unsigned int line = 3; + const unsigned int line = 3; #endif - if (gCurrentFunction != FUNCTION_TRANSMIT || - gScreenToDisplay != DISPLAY_MAIN + if (gCurrentFunction != FUNCTION_TRANSMIT || + gScreenToDisplay != DISPLAY_MAIN #ifdef ENABLE_DTMF_CALLING - || gDTMF_CallState != DTMF_CALL_STATE_NONE + || gDTMF_CallState != DTMF_CALL_STATE_NONE #endif - ) - { - return; // screen is in use - } + ) + { + return; // screen is in use + } #if defined(ENABLE_ALARM) || defined(ENABLE_TX1750) - if (gAlarmState != ALARM_STATE_OFF) - return; + if (gAlarmState != ALARM_STATE_OFF) + return; #endif - const unsigned int voice_amp = BK4819_GetVoiceAmplitudeOut(); // 15:0 + const unsigned int voice_amp = BK4819_GetVoiceAmplitudeOut(); // 15:0 - // make non-linear to make more sensitive at low values - const unsigned int level = MIN(voice_amp * 8, 65535u); - const unsigned int sqrt_level = MIN(sqrt16(level), 124u); - uint8_t bars = 13 * sqrt_level / 124; + // make non-linear to make more sensitive at low values + const unsigned int level = MIN(voice_amp * 8, 65535u); + const unsigned int sqrt_level = MIN(sqrt16(level), 124u); + uint8_t bars = 13 * sqrt_level / 124; - uint8_t *p_line = gFrameBuffer[line]; - memset(p_line, 0, LCD_WIDTH); + uint8_t *p_line = gFrameBuffer[line]; + memset(p_line, 0, LCD_WIDTH); - DrawLevelBar(62, line, bars); + DrawLevelBar(62, line, bars); - if (gCurrentFunction == FUNCTION_TRANSMIT) - ST7565_BlitFullScreen(); - } + if (gCurrentFunction == FUNCTION_TRANSMIT) + ST7565_BlitFullScreen(); + } } #endif @@ -260,185 +260,185 @@ void DisplayRSSIBar(const bool now) { #if defined(ENABLE_RSSI_BAR) - const unsigned int txt_width = 7 * 8; // 8 text chars - const unsigned int bar_x = 2 + txt_width + 4; // X coord of bar graph + const unsigned int txt_width = 7 * 8; // 8 text chars + const unsigned int bar_x = 2 + txt_width + 4; // X coord of bar graph #ifdef ENABLE_FEAT_F4HWN - /* - const char empty[] = { - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - }; - */ - - unsigned int line; - if (isMainOnly(false)) - { - line = 5; - } - else - { - line = 3; - } - - //char rx[4]; - //sprintf(String, "%d", RxBlink); - //UI_PrintStringSmallBold(String, 80, 0, RxLine); - - if(RxLine >= 0 && center_line != CENTER_LINE_IN_USE) - { - switch(RxBlink) - { - case 0: - UI_PrintStringSmallBold("RX", 8, 0, RxLine); - break; - case 1: - UI_PrintStringSmallBold("RX", 8, 0, RxLine); - RxBlink = 2; - break; - case 2: - for (uint8_t i = 8; i < 24; i++) - { - gFrameBuffer[RxLine][i] = 0x00; - } - RxBlink = 1; - break; - } - ST7565_BlitLine(RxLine); - } + /* + const char empty[] = { + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + }; + */ + + unsigned int line; + if (isMainOnly(false)) + { + line = 5; + } + else + { + line = 3; + } + + //char rx[4]; + //sprintf(String, "%d", RxBlink); + //UI_PrintStringSmallBold(String, 80, 0, RxLine); + + if(RxLine >= 0 && center_line != CENTER_LINE_IN_USE) + { + switch(RxBlink) + { + case 0: + UI_PrintStringSmallBold("RX", 8, 0, RxLine); + break; + case 1: + UI_PrintStringSmallBold("RX", 8, 0, RxLine); + RxBlink = 2; + break; + case 2: + for (uint8_t i = 8; i < 24; i++) + { + gFrameBuffer[RxLine][i] = 0x00; + } + RxBlink = 1; + break; + } + ST7565_BlitLine(RxLine); + } #else - const unsigned int line = 3; + const unsigned int line = 3; #endif - uint8_t *p_line = gFrameBuffer[line]; - char str[16]; + uint8_t *p_line = gFrameBuffer[line]; + char str[16]; #ifndef ENABLE_FEAT_F4HWN - const char plus[] = { - 0b00011000, - 0b00011000, - 0b01111110, - 0b01111110, - 0b01111110, - 0b00011000, - 0b00011000, - }; + const char plus[] = { + 0b00011000, + 0b00011000, + 0b01111110, + 0b01111110, + 0b01111110, + 0b00011000, + 0b00011000, + }; #endif - if ((gEeprom.KEY_LOCK && gKeypadLocked > 0) || center_line != CENTER_LINE_RSSI) - return; // display is in use + if ((gEeprom.KEY_LOCK && gKeypadLocked > 0) || center_line != CENTER_LINE_RSSI) + return; // display is in use - if (gCurrentFunction == FUNCTION_TRANSMIT || - gScreenToDisplay != DISPLAY_MAIN + if (gCurrentFunction == FUNCTION_TRANSMIT || + gScreenToDisplay != DISPLAY_MAIN #ifdef ENABLE_DTMF_CALLING - || gDTMF_CallState != DTMF_CALL_STATE_NONE + || gDTMF_CallState != DTMF_CALL_STATE_NONE #endif - ) - return; // display is in use + ) + return; // display is in use - if (now) - memset(p_line, 0, LCD_WIDTH); + if (now) + memset(p_line, 0, LCD_WIDTH); #ifdef ENABLE_FEAT_F4HWN - int16_t rssi_dBm = - BK4819_GetRSSI_dBm() + int16_t rssi_dBm = + BK4819_GetRSSI_dBm() #ifdef ENABLE_AM_FIX - + ((gSetting_AM_fix && gRxVfo->Modulation == MODULATION_AM) ? AM_fix_get_gain_diff() : 0) + + ((gSetting_AM_fix && gRxVfo->Modulation == MODULATION_AM) ? AM_fix_get_gain_diff() : 0) #endif - + dBmCorrTable[gRxVfo->Band]; + + dBmCorrTable[gRxVfo->Band]; - rssi_dBm = -rssi_dBm; + rssi_dBm = -rssi_dBm; - if(rssi_dBm > 141) rssi_dBm = 141; - if(rssi_dBm < 53) rssi_dBm = 53; + if(rssi_dBm > 141) rssi_dBm = 141; + if(rssi_dBm < 53) rssi_dBm = 53; - uint8_t s_level = 0; - uint8_t overS9dBm = 0; - uint8_t overS9Bars = 0; + uint8_t s_level = 0; + uint8_t overS9dBm = 0; + uint8_t overS9Bars = 0; - if(rssi_dBm >= 93) { - s_level = map(rssi_dBm, 141, 93, 1, 9); - } - else { - s_level = 9; - overS9dBm = map(rssi_dBm, 93, 53, 0, 40); - overS9Bars = map(overS9dBm, 0, 40, 0, 4); - } + if(rssi_dBm >= 93) { + s_level = map(rssi_dBm, 141, 93, 1, 9); + } + else { + s_level = 9; + overS9dBm = map(rssi_dBm, 93, 53, 0, 40); + overS9Bars = map(overS9dBm, 0, 40, 0, 4); + } #else - const int16_t s0_dBm = -gEeprom.S0_LEVEL; // S0 .. base level - const int16_t rssi_dBm = - BK4819_GetRSSI_dBm() + const int16_t s0_dBm = -gEeprom.S0_LEVEL; // S0 .. base level + const int16_t rssi_dBm = + BK4819_GetRSSI_dBm() #ifdef ENABLE_AM_FIX - + ((gSetting_AM_fix && gRxVfo->Modulation == MODULATION_AM) ? AM_fix_get_gain_diff() : 0) + + ((gSetting_AM_fix && gRxVfo->Modulation == MODULATION_AM) ? AM_fix_get_gain_diff() : 0) #endif - + dBmCorrTable[gRxVfo->Band]; + + dBmCorrTable[gRxVfo->Band]; - int s0_9 = gEeprom.S0_LEVEL - gEeprom.S9_LEVEL; - const uint8_t s_level = MIN(MAX((int32_t)(rssi_dBm - s0_dBm)*100 / (s0_9*100/9), 0), 9); // S0 - S9 - uint8_t overS9dBm = MIN(MAX(rssi_dBm + gEeprom.S9_LEVEL, 0), 99); - uint8_t overS9Bars = MIN(overS9dBm/10, 4); + int s0_9 = gEeprom.S0_LEVEL - gEeprom.S9_LEVEL; + const uint8_t s_level = MIN(MAX((int32_t)(rssi_dBm - s0_dBm)*100 / (s0_9*100/9), 0), 9); // S0 - S9 + uint8_t overS9dBm = MIN(MAX(rssi_dBm + gEeprom.S9_LEVEL, 0), 99); + uint8_t overS9Bars = MIN(overS9dBm/10, 4); #endif #ifdef ENABLE_FEAT_F4HWN - if (isMainOnly(true)) - { - sprintf(str, "%3d", -rssi_dBm); - UI_PrintStringSmallNormal(str, LCD_WIDTH + 8, 0, line - 1); - } - else - { - sprintf(str, "% 4d %s", -rssi_dBm, "dBm"); - GUI_DisplaySmallest(str, 2, 25, false, true); - } - - if(overS9Bars == 0) { - sprintf(str, "S%d", s_level); - } - else { - sprintf(str, "+%02d", overS9dBm); - } - - UI_PrintStringSmallNormal(str, LCD_WIDTH + 38, 0, line - 1); + if (isMainOnly(true)) + { + sprintf(str, "%3d", -rssi_dBm); + UI_PrintStringSmallNormal(str, LCD_WIDTH + 8, 0, line - 1); + } + else + { + sprintf(str, "% 4d %s", -rssi_dBm, "dBm"); + GUI_DisplaySmallest(str, 2, 25, false, true); + } + + if(overS9Bars == 0) { + sprintf(str, "S%d", s_level); + } + else { + sprintf(str, "+%02d", overS9dBm); + } + + UI_PrintStringSmallNormal(str, LCD_WIDTH + 38, 0, line - 1); #else - if(overS9Bars == 0) { - sprintf(str, "% 4d S%d", -rssi_dBm, s_level); - } - else { - sprintf(str, "% 4d %2d", -rssi_dBm, overS9dBm); - memcpy(p_line + 2 + 7*5, &plus, ARRAY_SIZE(plus)); - } - - UI_PrintStringSmallNormal(str, 2, 0, line); + if(overS9Bars == 0) { + sprintf(str, "% 4d S%d", -rssi_dBm, s_level); + } + else { + sprintf(str, "% 4d %2d", -rssi_dBm, overS9dBm); + memcpy(p_line + 2 + 7*5, &plus, ARRAY_SIZE(plus)); + } + + UI_PrintStringSmallNormal(str, 2, 0, line); #endif - DrawLevelBar(bar_x, line, s_level + overS9Bars); - if (now) - ST7565_BlitLine(line); + DrawLevelBar(bar_x, line, s_level + overS9Bars); + if (now) + ST7565_BlitLine(line); #else - int16_t rssi = BK4819_GetRSSI(); - uint8_t Level; - - if (rssi >= gEEPROM_RSSI_CALIB[gRxVfo->Band][3]) { - Level = 6; - } else if (rssi >= gEEPROM_RSSI_CALIB[gRxVfo->Band][2]) { - Level = 4; - } else if (rssi >= gEEPROM_RSSI_CALIB[gRxVfo->Band][1]) { - Level = 2; - } else if (rssi >= gEEPROM_RSSI_CALIB[gRxVfo->Band][0]) { - Level = 1; - } else { - Level = 0; - } - - uint8_t *pLine = (gEeprom.RX_VFO == 0)? gFrameBuffer[2] : gFrameBuffer[6]; - if (now) - memset(pLine, 0, 23); - DrawSmallAntennaAndBars(pLine, Level); - if (now) - ST7565_BlitFullScreen(); + int16_t rssi = BK4819_GetRSSI(); + uint8_t Level; + + if (rssi >= gEEPROM_RSSI_CALIB[gRxVfo->Band][3]) { + Level = 6; + } else if (rssi >= gEEPROM_RSSI_CALIB[gRxVfo->Band][2]) { + Level = 4; + } else if (rssi >= gEEPROM_RSSI_CALIB[gRxVfo->Band][1]) { + Level = 2; + } else if (rssi >= gEEPROM_RSSI_CALIB[gRxVfo->Band][0]) { + Level = 1; + } else { + Level = 0; + } + + uint8_t *pLine = (gEeprom.RX_VFO == 0)? gFrameBuffer[2] : gFrameBuffer[6]; + if (now) + memset(pLine, 0, 23); + DrawSmallAntennaAndBars(pLine, Level); + if (now) + ST7565_BlitFullScreen(); #endif } @@ -446,1017 +446,1017 @@ void DisplayRSSIBar(const bool now) #ifdef ENABLE_AGC_SHOW_DATA void UI_MAIN_PrintAGC(bool now) { - char buf[20]; - memset(gFrameBuffer[3], 0, 128); - union { - struct { - uint16_t _ : 5; - uint16_t agcSigStrength : 7; - int16_t gainIdx : 3; - uint16_t agcEnab : 1; - }; - uint16_t __raw; - } reg7e; - reg7e.__raw = BK4819_ReadRegister(0x7E); - uint8_t gainAddr = reg7e.gainIdx < 0 ? 0x14 : 0x10 + reg7e.gainIdx; - union { - struct { - uint16_t pga:3; - uint16_t mixer:2; - uint16_t lna:3; - uint16_t lnaS:2; - }; - uint16_t __raw; - } agcGainReg; - agcGainReg.__raw = BK4819_ReadRegister(gainAddr); - int8_t lnaShortTab[] = {-28, -24, -19, 0}; - int8_t lnaTab[] = {-24, -19, -14, -9, -6, -4, -2, 0}; - int8_t mixerTab[] = {-8, -6, -3, 0}; - int8_t pgaTab[] = {-33, -27, -21, -15, -9, -6, -3, 0}; - int16_t agcGain = lnaShortTab[agcGainReg.lnaS] + lnaTab[agcGainReg.lna] + mixerTab[agcGainReg.mixer] + pgaTab[agcGainReg.pga]; - - sprintf(buf, "%d%2d %2d %2d %3d", reg7e.agcEnab, reg7e.gainIdx, -agcGain, reg7e.agcSigStrength, BK4819_GetRSSI()); - UI_PrintStringSmallNormal(buf, 2, 0, 3); - if(now) - ST7565_BlitLine(3); + char buf[20]; + memset(gFrameBuffer[3], 0, 128); + union { + struct { + uint16_t _ : 5; + uint16_t agcSigStrength : 7; + int16_t gainIdx : 3; + uint16_t agcEnab : 1; + }; + uint16_t __raw; + } reg7e; + reg7e.__raw = BK4819_ReadRegister(0x7E); + uint8_t gainAddr = reg7e.gainIdx < 0 ? 0x14 : 0x10 + reg7e.gainIdx; + union { + struct { + uint16_t pga:3; + uint16_t mixer:2; + uint16_t lna:3; + uint16_t lnaS:2; + }; + uint16_t __raw; + } agcGainReg; + agcGainReg.__raw = BK4819_ReadRegister(gainAddr); + int8_t lnaShortTab[] = {-28, -24, -19, 0}; + int8_t lnaTab[] = {-24, -19, -14, -9, -6, -4, -2, 0}; + int8_t mixerTab[] = {-8, -6, -3, 0}; + int8_t pgaTab[] = {-33, -27, -21, -15, -9, -6, -3, 0}; + int16_t agcGain = lnaShortTab[agcGainReg.lnaS] + lnaTab[agcGainReg.lna] + mixerTab[agcGainReg.mixer] + pgaTab[agcGainReg.pga]; + + sprintf(buf, "%d%2d %2d %2d %3d", reg7e.agcEnab, reg7e.gainIdx, -agcGain, reg7e.agcSigStrength, BK4819_GetRSSI()); + UI_PrintStringSmallNormal(buf, 2, 0, 3); + if(now) + ST7565_BlitLine(3); } #endif void UI_MAIN_TimeSlice500ms(void) { - if(gScreenToDisplay==DISPLAY_MAIN) { + if(gScreenToDisplay==DISPLAY_MAIN) { #ifdef ENABLE_AGC_SHOW_DATA - UI_MAIN_PrintAGC(true); - return; + UI_MAIN_PrintAGC(true); + return; #endif - if(FUNCTION_IsRx()) { - DisplayRSSIBar(true); - } + if(FUNCTION_IsRx()) { + DisplayRSSIBar(true); + } #ifdef ENABLE_FEAT_F4HWN // Blink Green Led for white... - else if(gSetting_set_eot > 0 && RxBlinkLed == 2) - { - if(RxBlinkLedCounter <= 8) - { - if(RxBlinkLedCounter % 2 == 0) - { - if(gSetting_set_eot > 1 ) - { - BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, false); - } - } - else - { - if(gSetting_set_eot > 1 ) - { - BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, true); - } - - if(gSetting_set_eot == 1 || gSetting_set_eot == 3) - { - switch(RxBlinkLedCounter) - { - case 1: - AUDIO_PlayBeep(BEEP_400HZ_30MS); - break; - - case 3: - AUDIO_PlayBeep(BEEP_400HZ_30MS); - break; - - case 5: - AUDIO_PlayBeep(BEEP_500HZ_30MS); - break; - - case 7: - AUDIO_PlayBeep(BEEP_600HZ_30MS); - break; - } - } - } - RxBlinkLedCounter += 1; - } - else - { - RxBlinkLed = 0; - } - } + else if(gSetting_set_eot > 0 && RxBlinkLed == 2) + { + if(RxBlinkLedCounter <= 8) + { + if(RxBlinkLedCounter % 2 == 0) + { + if(gSetting_set_eot > 1 ) + { + BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, false); + } + } + else + { + if(gSetting_set_eot > 1 ) + { + BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, true); + } + + if(gSetting_set_eot == 1 || gSetting_set_eot == 3) + { + switch(RxBlinkLedCounter) + { + case 1: + AUDIO_PlayBeep(BEEP_400HZ_30MS); + break; + + case 3: + AUDIO_PlayBeep(BEEP_400HZ_30MS); + break; + + case 5: + AUDIO_PlayBeep(BEEP_500HZ_30MS); + break; + + case 7: + AUDIO_PlayBeep(BEEP_600HZ_30MS); + break; + } + } + } + RxBlinkLedCounter += 1; + } + else + { + RxBlinkLed = 0; + } + } #endif - } + } } // *************************************************************************** void UI_DisplayMain(void) { - char String[22]; + char String[22]; - center_line = CENTER_LINE_NONE; + center_line = CENTER_LINE_NONE; - // clear the screen - UI_DisplayClear(); + // clear the screen + UI_DisplayClear(); - if(gLowBattery && !gLowBatteryConfirmed) { - UI_DisplayPopup("LOW BATTERY"); - ST7565_BlitFullScreen(); - return; - } + if(gLowBattery && !gLowBatteryConfirmed) { + UI_DisplayPopup("LOW BATTERY"); + ST7565_BlitFullScreen(); + return; + } #ifndef ENABLE_FEAT_F4HWN - if (gEeprom.KEY_LOCK && gKeypadLocked > 0) - { // tell user how to unlock the keyboard - UI_PrintString("Long press #", 0, LCD_WIDTH, 1, 8); - UI_PrintString("to unlock", 0, LCD_WIDTH, 3, 8); - ST7565_BlitFullScreen(); - return; - } + if (gEeprom.KEY_LOCK && gKeypadLocked > 0) + { // tell user how to unlock the keyboard + UI_PrintString("Long press #", 0, LCD_WIDTH, 1, 8); + UI_PrintString("to unlock", 0, LCD_WIDTH, 3, 8); + ST7565_BlitFullScreen(); + return; + } #else - if (gEeprom.KEY_LOCK && gKeypadLocked > 0) - { // tell user how to unlock the keyboard - uint8_t shift = 3; - - /* - BK4819_ToggleGpioOut(BK4819_GPIO5_PIN1_RED, true); - SYSTEM_DelayMs(50); - BK4819_ToggleGpioOut(BK4819_GPIO5_PIN1_RED, false); - SYSTEM_DelayMs(50); - */ - - if(isMainOnly(false)) - { - shift = 5; - } - //memcpy(gFrameBuffer[shift] + 2, gFontKeyLock, sizeof(gFontKeyLock)); - UI_PrintStringSmallBold("UNLOCK KEYBOARD", 12, 0, shift); - //memcpy(gFrameBuffer[shift] + 120, gFontKeyLock, sizeof(gFontKeyLock)); - - /* - for (uint8_t i = 12; i < 116; i++) - { - gFrameBuffer[shift][i] ^= 0xFF; - } - */ - } + if (gEeprom.KEY_LOCK && gKeypadLocked > 0) + { // tell user how to unlock the keyboard + uint8_t shift = 3; + + /* + BK4819_ToggleGpioOut(BK4819_GPIO5_PIN1_RED, true); + SYSTEM_DelayMs(50); + BK4819_ToggleGpioOut(BK4819_GPIO5_PIN1_RED, false); + SYSTEM_DelayMs(50); + */ + + if(isMainOnly(false)) + { + shift = 5; + } + //memcpy(gFrameBuffer[shift] + 2, gFontKeyLock, sizeof(gFontKeyLock)); + UI_PrintStringSmallBold("UNLOCK KEYBOARD", 12, 0, shift); + //memcpy(gFrameBuffer[shift] + 120, gFontKeyLock, sizeof(gFontKeyLock)); + + /* + for (uint8_t i = 12; i < 116; i++) + { + gFrameBuffer[shift][i] ^= 0xFF; + } + */ + } #endif - unsigned int activeTxVFO = gRxVfoIsActive ? gEeprom.RX_VFO : gEeprom.TX_VFO; + unsigned int activeTxVFO = gRxVfoIsActive ? gEeprom.RX_VFO : gEeprom.TX_VFO; - for (unsigned int vfo_num = 0; vfo_num < 2; vfo_num++) - { + for (unsigned int vfo_num = 0; vfo_num < 2; vfo_num++) + { #ifdef ENABLE_FEAT_F4HWN - const unsigned int line0 = 0; // text screen line - const unsigned int line1 = 4; - unsigned int line; - if (isMainOnly(false)) - { - line = 0; - } - else - { - line = (vfo_num == 0) ? line0 : line1; - } - const bool isMainVFO = (vfo_num == gEeprom.TX_VFO); - uint8_t *p_line0 = gFrameBuffer[line + 0]; - uint8_t *p_line1 = gFrameBuffer[line + 1]; - enum Vfo_txtr_mode mode = VFO_MODE_NONE; + const unsigned int line0 = 0; // text screen line + const unsigned int line1 = 4; + unsigned int line; + if (isMainOnly(false)) + { + line = 0; + } + else + { + line = (vfo_num == 0) ? line0 : line1; + } + const bool isMainVFO = (vfo_num == gEeprom.TX_VFO); + uint8_t *p_line0 = gFrameBuffer[line + 0]; + uint8_t *p_line1 = gFrameBuffer[line + 1]; + enum Vfo_txtr_mode mode = VFO_MODE_NONE; #else - const unsigned int line0 = 0; // text screen line - const unsigned int line1 = 4; - const unsigned int line = (vfo_num == 0) ? line0 : line1; - const bool isMainVFO = (vfo_num == gEeprom.TX_VFO); - uint8_t *p_line0 = gFrameBuffer[line + 0]; - uint8_t *p_line1 = gFrameBuffer[line + 1]; - enum Vfo_txtr_mode mode = VFO_MODE_NONE; + const unsigned int line0 = 0; // text screen line + const unsigned int line1 = 4; + const unsigned int line = (vfo_num == 0) ? line0 : line1; + const bool isMainVFO = (vfo_num == gEeprom.TX_VFO); + uint8_t *p_line0 = gFrameBuffer[line + 0]; + uint8_t *p_line1 = gFrameBuffer[line + 1]; + enum Vfo_txtr_mode mode = VFO_MODE_NONE; #endif #ifdef ENABLE_FEAT_F4HWN - if (isMainOnly(false)) - { - if (activeTxVFO != vfo_num) - { - continue; - } - } + if (isMainOnly(false)) + { + if (activeTxVFO != vfo_num) + { + continue; + } + } #endif #ifdef ENABLE_FEAT_F4HWN - if (activeTxVFO != vfo_num || isMainOnly(false)) + if (activeTxVFO != vfo_num || isMainOnly(false)) #else - if (activeTxVFO != vfo_num) // this is not active TX VFO + if (activeTxVFO != vfo_num) // this is not active TX VFO #endif - { + { #ifdef ENABLE_SCAN_RANGES - if(gScanRangeStart) { + if(gScanRangeStart) { #ifdef ENABLE_FEAT_F4HWN - //if(IS_FREQ_CHANNEL(gEeprom.ScreenChannel[0]) && IS_FREQ_CHANNEL(gEeprom.ScreenChannel[1])) { - if(IS_FREQ_CHANNEL(gEeprom.ScreenChannel[activeTxVFO])) { - - uint8_t shift = 0; - - if (isMainOnly(false)) - { - shift = 3; - } - - UI_PrintString("ScnRng", 5, 0, line + shift, 8); - sprintf(String, "%3u.%05u", gScanRangeStart / 100000, gScanRangeStart % 100000); - UI_PrintStringSmallNormal(String, 56, 0, line + shift); - sprintf(String, "%3u.%05u", gScanRangeStop / 100000, gScanRangeStop % 100000); - UI_PrintStringSmallNormal(String, 56, 0, line + shift + 1); - - if (!isMainOnly(false)) - continue; - } - else - { - gScanRangeStart = 0; - } + //if(IS_FREQ_CHANNEL(gEeprom.ScreenChannel[0]) && IS_FREQ_CHANNEL(gEeprom.ScreenChannel[1])) { + if(IS_FREQ_CHANNEL(gEeprom.ScreenChannel[activeTxVFO])) { + + uint8_t shift = 0; + + if (isMainOnly(false)) + { + shift = 3; + } + + UI_PrintString("ScnRng", 5, 0, line + shift, 8); + sprintf(String, "%3u.%05u", gScanRangeStart / 100000, gScanRangeStart % 100000); + UI_PrintStringSmallNormal(String, 56, 0, line + shift); + sprintf(String, "%3u.%05u", gScanRangeStop / 100000, gScanRangeStop % 100000); + UI_PrintStringSmallNormal(String, 56, 0, line + shift + 1); + + if (!isMainOnly(false)) + continue; + } + else + { + gScanRangeStart = 0; + } #else - UI_PrintString("ScnRng", 5, 0, line, 8); - sprintf(String, "%3u.%05u", gScanRangeStart / 100000, gScanRangeStart % 100000); - UI_PrintStringSmallNormal(String, 56, 0, line); - sprintf(String, "%3u.%05u", gScanRangeStop / 100000, gScanRangeStop % 100000); - UI_PrintStringSmallNormal(String, 56, 0, line + 1); - continue; + UI_PrintString("ScnRng", 5, 0, line, 8); + sprintf(String, "%3u.%05u", gScanRangeStart / 100000, gScanRangeStart % 100000); + UI_PrintStringSmallNormal(String, 56, 0, line); + sprintf(String, "%3u.%05u", gScanRangeStop / 100000, gScanRangeStop % 100000); + UI_PrintStringSmallNormal(String, 56, 0, line + 1); + continue; #endif - } + } #endif - if (gDTMF_InputMode + if (gDTMF_InputMode #ifdef ENABLE_DTMF_CALLING - || gDTMF_CallState != DTMF_CALL_STATE_NONE || gDTMF_IsTx + || gDTMF_CallState != DTMF_CALL_STATE_NONE || gDTMF_IsTx #endif - ) { - char *pPrintStr = ""; - // show DTMF stuff + ) { + char *pPrintStr = ""; + // show DTMF stuff #ifdef ENABLE_DTMF_CALLING - char Contact[16]; - if (!gDTMF_InputMode) { - if (gDTMF_CallState == DTMF_CALL_STATE_CALL_OUT) { - pPrintStr = DTMF_FindContact(gDTMF_String, Contact) ? Contact : gDTMF_String; - } else if (gDTMF_CallState == DTMF_CALL_STATE_RECEIVED || gDTMF_CallState == DTMF_CALL_STATE_RECEIVED_STAY){ - pPrintStr = DTMF_FindContact(gDTMF_Callee, Contact) ? Contact : gDTMF_Callee; - }else if (gDTMF_IsTx) { - pPrintStr = gDTMF_String; - } - } - - UI_PrintString(pPrintStr, 2, 0, 2 + (vfo_num * 3), 8); - - pPrintStr = ""; - if (!gDTMF_InputMode) { - if (gDTMF_CallState == DTMF_CALL_STATE_CALL_OUT) { - pPrintStr = (gDTMF_State == DTMF_STATE_CALL_OUT_RSP) ? "CALL OUT(RSP)" : "CALL OUT"; - } else if (gDTMF_CallState == DTMF_CALL_STATE_RECEIVED || gDTMF_CallState == DTMF_CALL_STATE_RECEIVED_STAY) { - sprintf(String, "CALL FRM:%s", (DTMF_FindContact(gDTMF_Caller, Contact)) ? Contact : gDTMF_Caller); - pPrintStr = String; - } else if (gDTMF_IsTx) { - pPrintStr = (gDTMF_State == DTMF_STATE_TX_SUCC) ? "DTMF TX(SUCC)" : "DTMF TX"; - } - } - else + char Contact[16]; + if (!gDTMF_InputMode) { + if (gDTMF_CallState == DTMF_CALL_STATE_CALL_OUT) { + pPrintStr = DTMF_FindContact(gDTMF_String, Contact) ? Contact : gDTMF_String; + } else if (gDTMF_CallState == DTMF_CALL_STATE_RECEIVED || gDTMF_CallState == DTMF_CALL_STATE_RECEIVED_STAY){ + pPrintStr = DTMF_FindContact(gDTMF_Callee, Contact) ? Contact : gDTMF_Callee; + }else if (gDTMF_IsTx) { + pPrintStr = gDTMF_String; + } + } + + UI_PrintString(pPrintStr, 2, 0, 2 + (vfo_num * 3), 8); + + pPrintStr = ""; + if (!gDTMF_InputMode) { + if (gDTMF_CallState == DTMF_CALL_STATE_CALL_OUT) { + pPrintStr = (gDTMF_State == DTMF_STATE_CALL_OUT_RSP) ? "CALL OUT(RSP)" : "CALL OUT"; + } else if (gDTMF_CallState == DTMF_CALL_STATE_RECEIVED || gDTMF_CallState == DTMF_CALL_STATE_RECEIVED_STAY) { + sprintf(String, "CALL FRM:%s", (DTMF_FindContact(gDTMF_Caller, Contact)) ? Contact : gDTMF_Caller); + pPrintStr = String; + } else if (gDTMF_IsTx) { + pPrintStr = (gDTMF_State == DTMF_STATE_TX_SUCC) ? "DTMF TX(SUCC)" : "DTMF TX"; + } + } + else #endif - { - sprintf(String, ">%s", gDTMF_InputBox); - pPrintStr = String; - } + { + sprintf(String, ">%s", gDTMF_InputBox); + pPrintStr = String; + } #ifdef ENABLE_FEAT_F4HWN - if (isMainOnly(false)) - { - UI_PrintString(pPrintStr, 2, 0, 5, 8); - isMainOnlyInputDTMF = true; - center_line = CENTER_LINE_IN_USE; - } - else - { - UI_PrintString(pPrintStr, 2, 0, 0 + (vfo_num * 3), 8); - isMainOnlyInputDTMF = false; - center_line = CENTER_LINE_IN_USE; - continue; - } + if (isMainOnly(false)) + { + UI_PrintString(pPrintStr, 2, 0, 5, 8); + isMainOnlyInputDTMF = true; + center_line = CENTER_LINE_IN_USE; + } + else + { + UI_PrintString(pPrintStr, 2, 0, 0 + (vfo_num * 3), 8); + isMainOnlyInputDTMF = false; + center_line = CENTER_LINE_IN_USE; + continue; + } #else - UI_PrintString(pPrintStr, 2, 0, 0 + (vfo_num * 3), 8); - center_line = CENTER_LINE_IN_USE; - continue; + UI_PrintString(pPrintStr, 2, 0, 0 + (vfo_num * 3), 8); + center_line = CENTER_LINE_IN_USE; + continue; #endif - } - - // highlight the selected/used VFO with a marker - if (isMainVFO) - memcpy(p_line0 + 0, BITMAP_VFO_Default, sizeof(BITMAP_VFO_Default)); - } - else // active TX VFO - { // highlight the selected/used VFO with a marker - if (isMainVFO) - memcpy(p_line0 + 0, BITMAP_VFO_Default, sizeof(BITMAP_VFO_Default)); - else - memcpy(p_line0 + 0, BITMAP_VFO_NotDefault, sizeof(BITMAP_VFO_NotDefault)); - } - - uint32_t frequency = gEeprom.VfoInfo[vfo_num].pRX->Frequency; - - if(TX_freq_check(frequency) != 0 && gEeprom.VfoInfo[vfo_num].TX_LOCK == true) - { - if(isMainOnly(false)) - memcpy(p_line0 + 14, BITMAP_VFO_Lock, sizeof(BITMAP_VFO_Lock)); - else - memcpy(p_line0 + 24, BITMAP_VFO_Lock, sizeof(BITMAP_VFO_Lock)); - } - - if (gCurrentFunction == FUNCTION_TRANSMIT) - { // transmitting + } + + // highlight the selected/used VFO with a marker + if (isMainVFO) + memcpy(p_line0 + 0, BITMAP_VFO_Default, sizeof(BITMAP_VFO_Default)); + } + else // active TX VFO + { // highlight the selected/used VFO with a marker + if (isMainVFO) + memcpy(p_line0 + 0, BITMAP_VFO_Default, sizeof(BITMAP_VFO_Default)); + else + memcpy(p_line0 + 0, BITMAP_VFO_NotDefault, sizeof(BITMAP_VFO_NotDefault)); + } + + uint32_t frequency = gEeprom.VfoInfo[vfo_num].pRX->Frequency; + + if(TX_freq_check(frequency) != 0 && gEeprom.VfoInfo[vfo_num].TX_LOCK == true) + { + if(isMainOnly(false)) + memcpy(p_line0 + 14, BITMAP_VFO_Lock, sizeof(BITMAP_VFO_Lock)); + else + memcpy(p_line0 + 24, BITMAP_VFO_Lock, sizeof(BITMAP_VFO_Lock)); + } + + if (gCurrentFunction == FUNCTION_TRANSMIT) + { // transmitting #ifdef ENABLE_ALARM - if (gAlarmState == ALARM_STATE_SITE_ALARM) - mode = VFO_MODE_RX; - else + if (gAlarmState == ALARM_STATE_SITE_ALARM) + mode = VFO_MODE_RX; + else #endif - { - if (activeTxVFO == vfo_num) - { // show the TX symbol - mode = VFO_MODE_TX; - UI_PrintStringSmallBold("TX", 8, 0, line); - } - } - } - else - { // receiving .. show the RX symbol - mode = VFO_MODE_RX; - //if (FUNCTION_IsRx() && gEeprom.RX_VFO == vfo_num) { - if (FUNCTION_IsRx() && gEeprom.RX_VFO == vfo_num && VfoState[vfo_num] == VFO_STATE_NORMAL) { + { + if (activeTxVFO == vfo_num) + { // show the TX symbol + mode = VFO_MODE_TX; + UI_PrintStringSmallBold("TX", 8, 0, line); + } + } + } + else + { // receiving .. show the RX symbol + mode = VFO_MODE_RX; + //if (FUNCTION_IsRx() && gEeprom.RX_VFO == vfo_num) { + if (FUNCTION_IsRx() && gEeprom.RX_VFO == vfo_num && VfoState[vfo_num] == VFO_STATE_NORMAL) { #ifdef ENABLE_FEAT_F4HWN - RxBlinkLed = 1; - RxBlinkLedCounter = 0; - RxLine = line; - RxOnVfofrequency = frequency; - if(!isMainVFO) - { - RxBlink = 1; - } - else - { - RxBlink = 0; - } + RxBlinkLed = 1; + RxBlinkLedCounter = 0; + RxLine = line; + RxOnVfofrequency = frequency; + if(!isMainVFO) + { + RxBlink = 1; + } + else + { + RxBlink = 0; + } #else - UI_PrintStringSmallBold("RX", 8, 0, line); + UI_PrintStringSmallBold("RX", 8, 0, line); #endif - } + } #ifdef ENABLE_FEAT_F4HWN - else - { - if(RxOnVfofrequency == frequency && !isMainOnly(false)) - { - UI_PrintStringSmallNormal(">>", 8, 0, line); - //memcpy(p_line0 + 14, BITMAP_VFO_Default, sizeof(BITMAP_VFO_Default)); - } - - if(RxBlinkLed == 1) - RxBlinkLed = 2; - } + else + { + if(RxOnVfofrequency == frequency && !isMainOnly(false)) + { + UI_PrintStringSmallNormal(">>", 8, 0, line); + //memcpy(p_line0 + 14, BITMAP_VFO_Default, sizeof(BITMAP_VFO_Default)); + } + + if(RxBlinkLed == 1) + RxBlinkLed = 2; + } #endif - } - - if (IS_MR_CHANNEL(gEeprom.ScreenChannel[vfo_num])) - { // channel mode - const unsigned int x = 2; - const bool inputting = gInputBoxIndex != 0 && gEeprom.TX_VFO == vfo_num; - if (!inputting) - sprintf(String, "M%u", gEeprom.ScreenChannel[vfo_num] + 1); - else - sprintf(String, "M%.3s", INPUTBOX_GetAscii()); // show the input text - UI_PrintStringSmallNormal(String, x, 0, line + 1); - } - else if (IS_FREQ_CHANNEL(gEeprom.ScreenChannel[vfo_num])) - { // frequency mode - // show the frequency band number - const unsigned int x = 2; - char * buf = gEeprom.VfoInfo[vfo_num].pRX->Frequency < _1GHz_in_KHz ? "" : "+"; - sprintf(String, "F%u%s", 1 + gEeprom.ScreenChannel[vfo_num] - FREQ_CHANNEL_FIRST, buf); - UI_PrintStringSmallNormal(String, x, 0, line + 1); - } + } + + if (IS_MR_CHANNEL(gEeprom.ScreenChannel[vfo_num])) + { // channel mode + const unsigned int x = 2; + const bool inputting = gInputBoxIndex != 0 && gEeprom.TX_VFO == vfo_num; + if (!inputting) + sprintf(String, "M%u", gEeprom.ScreenChannel[vfo_num] + 1); + else + sprintf(String, "M%.3s", INPUTBOX_GetAscii()); // show the input text + UI_PrintStringSmallNormal(String, x, 0, line + 1); + } + else if (IS_FREQ_CHANNEL(gEeprom.ScreenChannel[vfo_num])) + { // frequency mode + // show the frequency band number + const unsigned int x = 2; + char * buf = gEeprom.VfoInfo[vfo_num].pRX->Frequency < _1GHz_in_KHz ? "" : "+"; + sprintf(String, "F%u%s", 1 + gEeprom.ScreenChannel[vfo_num] - FREQ_CHANNEL_FIRST, buf); + UI_PrintStringSmallNormal(String, x, 0, line + 1); + } #ifdef ENABLE_NOAA - else - { - if (gInputBoxIndex == 0 || gEeprom.TX_VFO != vfo_num) - { // channel number - sprintf(String, "N%u", 1 + gEeprom.ScreenChannel[vfo_num] - NOAA_CHANNEL_FIRST); - } - else - { // user entering channel number - sprintf(String, "N%u%u", '0' + gInputBox[0], '0' + gInputBox[1]); - } - UI_PrintStringSmallNormal(String, 7, 0, line + 1); - } + else + { + if (gInputBoxIndex == 0 || gEeprom.TX_VFO != vfo_num) + { // channel number + sprintf(String, "N%u", 1 + gEeprom.ScreenChannel[vfo_num] - NOAA_CHANNEL_FIRST); + } + else + { // user entering channel number + sprintf(String, "N%u%u", '0' + gInputBox[0], '0' + gInputBox[1]); + } + UI_PrintStringSmallNormal(String, 7, 0, line + 1); + } #endif - // ************ + // ************ - enum VfoState_t state = VfoState[vfo_num]; + enum VfoState_t state = VfoState[vfo_num]; #ifdef ENABLE_ALARM - if (gCurrentFunction == FUNCTION_TRANSMIT && gAlarmState == ALARM_STATE_SITE_ALARM) { - if (activeTxVFO == vfo_num) - state = VFO_STATE_ALARM; - } + if (gCurrentFunction == FUNCTION_TRANSMIT && gAlarmState == ALARM_STATE_SITE_ALARM) { + if (activeTxVFO == vfo_num) + state = VFO_STATE_ALARM; + } #endif - if (state != VFO_STATE_NORMAL) - { - if (state < ARRAY_SIZE(VfoStateStr)) - UI_PrintString(VfoStateStr[state], 31, 0, line, 8); - } - else if (gInputBoxIndex > 0 && IS_FREQ_CHANNEL(gEeprom.ScreenChannel[vfo_num]) && gEeprom.TX_VFO == vfo_num) - { // user entering a frequency - const char * ascii = INPUTBOX_GetAscii(); - bool isGigaF = frequency>=_1GHz_in_KHz; - sprintf(String, "%.*s.%.3s", 3 + isGigaF, ascii, ascii + 3 + isGigaF); + if (state != VFO_STATE_NORMAL) + { + if (state < ARRAY_SIZE(VfoStateStr)) + UI_PrintString(VfoStateStr[state], 31, 0, line, 8); + } + else if (gInputBoxIndex > 0 && IS_FREQ_CHANNEL(gEeprom.ScreenChannel[vfo_num]) && gEeprom.TX_VFO == vfo_num) + { // user entering a frequency + const char * ascii = INPUTBOX_GetAscii(); + bool isGigaF = frequency>=_1GHz_in_KHz; + sprintf(String, "%.*s.%.3s", 3 + isGigaF, ascii, ascii + 3 + isGigaF); #ifdef ENABLE_BIG_FREQ - if(!isGigaF) { - // show the remaining 2 small frequency digits - UI_PrintStringSmallNormal(String + 7, 113, 0, line + 1); - String[7] = 0; - // show the main large frequency digits - UI_DisplayFrequency(String, 32, line, false); - } - else + if(!isGigaF) { + // show the remaining 2 small frequency digits + UI_PrintStringSmallNormal(String + 7, 113, 0, line + 1); + String[7] = 0; + // show the main large frequency digits + UI_DisplayFrequency(String, 32, line, false); + } + else #endif - { - // show the frequency in the main font - UI_PrintString(String, 32, 0, line, 8); - } - - continue; - } - else - { - if (gCurrentFunction == FUNCTION_TRANSMIT) - { // transmitting - if (activeTxVFO == vfo_num) - frequency = gEeprom.VfoInfo[vfo_num].pTX->Frequency; - } - - if (IS_MR_CHANNEL(gEeprom.ScreenChannel[vfo_num])) - { // it's a channel - - uint8_t countList = 0; - uint8_t shiftList = 0; - - if(gMR_ChannelExclude[gEeprom.ScreenChannel[vfo_num]] == false) - { - // show the scan list assigment symbols - const ChannelAttributes_t att = gMR_ChannelAttributes[gEeprom.ScreenChannel[vfo_num]]; - - countList = att.scanlist1 + att.scanlist2 + att.scanlist3; - - if(countList == 0) - { - memcpy(p_line0 + 127 - (1 * 6), BITMAP_ScanList0, sizeof(BITMAP_ScanList0)); - } - else - { - shiftList = countList; - - if (att.scanlist1) - { - memcpy(p_line0 + 127 - (shiftList * 6), BITMAP_ScanList1, sizeof(BITMAP_ScanList1)); - shiftList--; - } - if (att.scanlist2) - { - memcpy(p_line0 + 127 - (shiftList * 6), BITMAP_ScanList2, sizeof(BITMAP_ScanList2)); - shiftList--; - } - if (att.scanlist3) - { - memcpy(p_line0 + 127 - (shiftList * 6), BITMAP_ScanList3, sizeof(BITMAP_ScanList3)); - } - } - } - else - { - memcpy(p_line0 + 127 - (1 * 6), BITMAP_ScanListE, sizeof(BITMAP_ScanListE)); - } - - /* - if (att.scanlist1) - memcpy(p_line0 + 107, BITMAP_ScanList1, sizeof(BITMAP_ScanList1)); - if (att.scanlist2) - memcpy(p_line0 + 114, BITMAP_ScanList2, sizeof(BITMAP_ScanList2)); - if (att.scanlist3) - memcpy(p_line0 + 121, BITMAP_ScanList3, sizeof(BITMAP_ScanList3)); - */ - - // compander symbol + { + // show the frequency in the main font + UI_PrintString(String, 32, 0, line, 8); + } + + continue; + } + else + { + if (gCurrentFunction == FUNCTION_TRANSMIT) + { // transmitting + if (activeTxVFO == vfo_num) + frequency = gEeprom.VfoInfo[vfo_num].pTX->Frequency; + } + + if (IS_MR_CHANNEL(gEeprom.ScreenChannel[vfo_num])) + { // it's a channel + + uint8_t countList = 0; + uint8_t shiftList = 0; + + if(gMR_ChannelExclude[gEeprom.ScreenChannel[vfo_num]] == false) + { + // show the scan list assigment symbols + const ChannelAttributes_t att = gMR_ChannelAttributes[gEeprom.ScreenChannel[vfo_num]]; + + countList = att.scanlist1 + att.scanlist2 + att.scanlist3; + + if(countList == 0) + { + memcpy(p_line0 + 127 - (1 * 6), BITMAP_ScanList0, sizeof(BITMAP_ScanList0)); + } + else + { + shiftList = countList; + + if (att.scanlist1) + { + memcpy(p_line0 + 127 - (shiftList * 6), BITMAP_ScanList1, sizeof(BITMAP_ScanList1)); + shiftList--; + } + if (att.scanlist2) + { + memcpy(p_line0 + 127 - (shiftList * 6), BITMAP_ScanList2, sizeof(BITMAP_ScanList2)); + shiftList--; + } + if (att.scanlist3) + { + memcpy(p_line0 + 127 - (shiftList * 6), BITMAP_ScanList3, sizeof(BITMAP_ScanList3)); + } + } + } + else + { + memcpy(p_line0 + 127 - (1 * 6), BITMAP_ScanListE, sizeof(BITMAP_ScanListE)); + } + + /* + if (att.scanlist1) + memcpy(p_line0 + 107, BITMAP_ScanList1, sizeof(BITMAP_ScanList1)); + if (att.scanlist2) + memcpy(p_line0 + 114, BITMAP_ScanList2, sizeof(BITMAP_ScanList2)); + if (att.scanlist3) + memcpy(p_line0 + 121, BITMAP_ScanList3, sizeof(BITMAP_ScanList3)); + */ + + // compander symbol #ifndef ENABLE_BIG_FREQ - if (att.compander) - memcpy(p_line0 + 120 + LCD_WIDTH, BITMAP_compand, sizeof(BITMAP_compand)); + if (att.compander) + memcpy(p_line0 + 120 + LCD_WIDTH, BITMAP_compand, sizeof(BITMAP_compand)); #else - // TODO: // find somewhere else to put the symbol + // TODO: // find somewhere else to put the symbol #endif - switch (gEeprom.CHANNEL_DISPLAY_MODE) - { - case MDF_FREQUENCY: // show the channel frequency - sprintf(String, "%3u.%05u", frequency / 100000, frequency % 100000); + switch (gEeprom.CHANNEL_DISPLAY_MODE) + { + case MDF_FREQUENCY: // show the channel frequency + sprintf(String, "%3u.%05u", frequency / 100000, frequency % 100000); #ifdef ENABLE_BIG_FREQ - if(frequency < _1GHz_in_KHz) { - // show the remaining 2 small frequency digits - UI_PrintStringSmallNormal(String + 7, 113, 0, line + 1); - String[7] = 0; - // show the main large frequency digits - UI_DisplayFrequency(String, 32, line, false); - } - else + if(frequency < _1GHz_in_KHz) { + // show the remaining 2 small frequency digits + UI_PrintStringSmallNormal(String + 7, 113, 0, line + 1); + String[7] = 0; + // show the main large frequency digits + UI_DisplayFrequency(String, 32, line, false); + } + else #endif - { - // show the frequency in the main font - UI_PrintString(String, 32, 0, line, 8); - } - - break; - - case MDF_CHANNEL: // show the channel number - sprintf(String, "CH-%03u", gEeprom.ScreenChannel[vfo_num] + 1); - UI_PrintString(String, 32, 0, line, 8); - break; - - case MDF_NAME: // show the channel name - case MDF_NAME_FREQ: // show the channel name and frequency - - SETTINGS_FetchChannelName(String, gEeprom.ScreenChannel[vfo_num]); - if (String[0] == 0) - { // no channel name, show the channel number instead - sprintf(String, "CH-%03u", gEeprom.ScreenChannel[vfo_num] + 1); - } - - if (gEeprom.CHANNEL_DISPLAY_MODE == MDF_NAME) { - UI_PrintString(String, 32, 0, line, 8); - } - else { + { + // show the frequency in the main font + UI_PrintString(String, 32, 0, line, 8); + } + + break; + + case MDF_CHANNEL: // show the channel number + sprintf(String, "CH-%03u", gEeprom.ScreenChannel[vfo_num] + 1); + UI_PrintString(String, 32, 0, line, 8); + break; + + case MDF_NAME: // show the channel name + case MDF_NAME_FREQ: // show the channel name and frequency + + SETTINGS_FetchChannelName(String, gEeprom.ScreenChannel[vfo_num]); + if (String[0] == 0) + { // no channel name, show the channel number instead + sprintf(String, "CH-%03u", gEeprom.ScreenChannel[vfo_num] + 1); + } + + if (gEeprom.CHANNEL_DISPLAY_MODE == MDF_NAME) { + UI_PrintString(String, 32, 0, line, 8); + } + else { #ifdef ENABLE_FEAT_F4HWN - if (isMainOnly(false)) - { - UI_PrintString(String, 32, 0, line, 8); - } - else - { - if(activeTxVFO == vfo_num) { - UI_PrintStringSmallBold(String, 32 + 4, 0, line); - } - else - { - UI_PrintStringSmallNormal(String, 32 + 4, 0, line); - } - } + if (isMainOnly(false)) + { + UI_PrintString(String, 32, 0, line, 8); + } + else + { + if(activeTxVFO == vfo_num) { + UI_PrintStringSmallBold(String, 32 + 4, 0, line); + } + else + { + UI_PrintStringSmallNormal(String, 32 + 4, 0, line); + } + } #else - UI_PrintStringSmallBold(String, 32 + 4, 0, line); + UI_PrintStringSmallBold(String, 32 + 4, 0, line); #endif #ifdef ENABLE_FEAT_F4HWN - if (isMainOnly(false)) - { - sprintf(String, "%3u.%05u", frequency / 100000, frequency % 100000); - if(frequency < _1GHz_in_KHz) { - // show the remaining 2 small frequency digits - UI_PrintStringSmallNormal(String + 7, 113, 0, line + 4); - String[7] = 0; - // show the main large frequency digits - UI_DisplayFrequency(String, 32, line + 3, false); - } - else - { - // show the frequency in the main font - UI_PrintString(String, 32, 0, line + 3, 8); - } - } - else - { - sprintf(String, "%03u.%05u", frequency / 100000, frequency % 100000); - UI_PrintStringSmallNormal(String, 32 + 4, 0, line + 1); - } -#else // show the channel frequency below the channel number/name - sprintf(String, "%03u.%05u", frequency / 100000, frequency % 100000); - UI_PrintStringSmallNormal(String, 32 + 4, 0, line + 1); + if (isMainOnly(false)) + { + sprintf(String, "%3u.%05u", frequency / 100000, frequency % 100000); + if(frequency < _1GHz_in_KHz) { + // show the remaining 2 small frequency digits + UI_PrintStringSmallNormal(String + 7, 113, 0, line + 4); + String[7] = 0; + // show the main large frequency digits + UI_DisplayFrequency(String, 32, line + 3, false); + } + else + { + // show the frequency in the main font + UI_PrintString(String, 32, 0, line + 3, 8); + } + } + else + { + sprintf(String, "%03u.%05u", frequency / 100000, frequency % 100000); + UI_PrintStringSmallNormal(String, 32 + 4, 0, line + 1); + } +#else // show the channel frequency below the channel number/name + sprintf(String, "%03u.%05u", frequency / 100000, frequency % 100000); + UI_PrintStringSmallNormal(String, 32 + 4, 0, line + 1); #endif - } + } - break; - } - } - else - { // frequency mode - sprintf(String, "%3u.%05u", frequency / 100000, frequency % 100000); + break; + } + } + else + { // frequency mode + sprintf(String, "%3u.%05u", frequency / 100000, frequency % 100000); #ifdef ENABLE_BIG_FREQ - if(frequency < _1GHz_in_KHz) { - // show the remaining 2 small frequency digits - UI_PrintStringSmallNormal(String + 7, 113, 0, line + 1); - String[7] = 0; - // show the main large frequency digits - UI_DisplayFrequency(String, 32, line, false); - } - else + if(frequency < _1GHz_in_KHz) { + // show the remaining 2 small frequency digits + UI_PrintStringSmallNormal(String + 7, 113, 0, line + 1); + String[7] = 0; + // show the main large frequency digits + UI_DisplayFrequency(String, 32, line, false); + } + else #endif - { - // show the frequency in the main font - UI_PrintString(String, 32, 0, line, 8); - } - - // show the channel symbols - const ChannelAttributes_t att = gMR_ChannelAttributes[gEeprom.ScreenChannel[vfo_num]]; - if (att.compander) + { + // show the frequency in the main font + UI_PrintString(String, 32, 0, line, 8); + } + + // show the channel symbols + const ChannelAttributes_t att = gMR_ChannelAttributes[gEeprom.ScreenChannel[vfo_num]]; + if (att.compander) #ifdef ENABLE_BIG_FREQ - memcpy(p_line0 + 120, BITMAP_compand, sizeof(BITMAP_compand)); + memcpy(p_line0 + 120, BITMAP_compand, sizeof(BITMAP_compand)); #else - memcpy(p_line0 + 120 + LCD_WIDTH, BITMAP_compand, sizeof(BITMAP_compand)); + memcpy(p_line0 + 120 + LCD_WIDTH, BITMAP_compand, sizeof(BITMAP_compand)); #endif - } - } - - // ************ - - { // show the TX/RX level - uint8_t Level = 0; - - if (mode == VFO_MODE_TX) - { // TX power level - switch (gRxVfo->OUTPUT_POWER) - { - case OUTPUT_POWER_LOW1: Level = 2; break; - case OUTPUT_POWER_LOW2: Level = 2; break; - case OUTPUT_POWER_LOW3: Level = 2; break; - case OUTPUT_POWER_LOW4: Level = 2; break; - case OUTPUT_POWER_LOW5: Level = 2; break; - case OUTPUT_POWER_MID: Level = 4; break; - case OUTPUT_POWER_HIGH: Level = 6; break; - } - } - else - if (mode == VFO_MODE_RX) - { // RX signal level - #ifndef ENABLE_RSSI_BAR - // bar graph - if (gVFO_RSSI_bar_level[vfo_num] > 0) - Level = gVFO_RSSI_bar_level[vfo_num]; - #endif - } - if(Level) - DrawSmallAntennaAndBars(p_line1 + LCD_WIDTH, Level); - } - - // ************ - - String[0] = '\0'; - const VFO_Info_t *vfoInfo = &gEeprom.VfoInfo[vfo_num]; - - // show the modulation symbol - const char * s = ""; + } + } + + // ************ + + { // show the TX/RX level + uint8_t Level = 0; + + if (mode == VFO_MODE_TX) + { // TX power level + switch (gRxVfo->OUTPUT_POWER) + { + case OUTPUT_POWER_LOW1: Level = 2; break; + case OUTPUT_POWER_LOW2: Level = 2; break; + case OUTPUT_POWER_LOW3: Level = 2; break; + case OUTPUT_POWER_LOW4: Level = 2; break; + case OUTPUT_POWER_LOW5: Level = 2; break; + case OUTPUT_POWER_MID: Level = 4; break; + case OUTPUT_POWER_HIGH: Level = 6; break; + } + } + else + if (mode == VFO_MODE_RX) + { // RX signal level + #ifndef ENABLE_RSSI_BAR + // bar graph + if (gVFO_RSSI_bar_level[vfo_num] > 0) + Level = gVFO_RSSI_bar_level[vfo_num]; + #endif + } + if(Level) + DrawSmallAntennaAndBars(p_line1 + LCD_WIDTH, Level); + } + + // ************ + + String[0] = '\0'; + const VFO_Info_t *vfoInfo = &gEeprom.VfoInfo[vfo_num]; + + // show the modulation symbol + const char * s = ""; #ifdef ENABLE_FEAT_F4HWN - const char * t = ""; + const char * t = ""; #endif - const ModulationMode_t mod = vfoInfo->Modulation; - switch (mod){ - case MODULATION_FM: { - const FREQ_Config_t *pConfig = (mode == VFO_MODE_TX) ? vfoInfo->pTX : vfoInfo->pRX; - const unsigned int code_type = pConfig->CodeType; + const ModulationMode_t mod = vfoInfo->Modulation; + switch (mod){ + case MODULATION_FM: { + const FREQ_Config_t *pConfig = (mode == VFO_MODE_TX) ? vfoInfo->pTX : vfoInfo->pRX; + const unsigned int code_type = pConfig->CodeType; #ifdef ENABLE_FEAT_F4HWN - const char *code_list[] = {"", "CT", "DC", "DC"}; + const char *code_list[] = {"", "CT", "DC", "DC"}; #else - const char *code_list[] = {"", "CT", "DCS", "DCR"}; + const char *code_list[] = {"", "CT", "DCS", "DCR"}; #endif - if (code_type < ARRAY_SIZE(code_list)) - s = code_list[code_type]; + if (code_type < ARRAY_SIZE(code_list)) + s = code_list[code_type]; #ifdef ENABLE_FEAT_F4HWN - if(gCurrentFunction != FUNCTION_TRANSMIT || activeTxVFO != vfo_num) - t = gModulationStr[mod]; + if(gCurrentFunction != FUNCTION_TRANSMIT || activeTxVFO != vfo_num) + t = gModulationStr[mod]; #endif - break; - } - default: - t = gModulationStr[mod]; - break; - } + break; + } + default: + t = gModulationStr[mod]; + break; + } #if ENABLE_FEAT_F4HWN - const FREQ_Config_t *pConfig = (mode == VFO_MODE_TX) ? vfoInfo->pTX : vfoInfo->pRX; - int8_t shift = 0; - - switch((int)pConfig->CodeType) - { - case 1: - sprintf(String, "%u.%u", CTCSS_Options[pConfig->Code] / 10, CTCSS_Options[pConfig->Code] % 10); - break; - - case 2: - sprintf(String, "%03oN", DCS_Options[pConfig->Code]); - break; - - case 3: - sprintf(String, "%03oI", DCS_Options[pConfig->Code]); - break; - - default: - sprintf(String, "%d.%02uK", vfoInfo->StepFrequency / 100, vfoInfo->StepFrequency % 100); - shift = -10; - } - - if (isMainOnly(true)) - { - UI_PrintStringSmallNormal(s, LCD_WIDTH + 22, 0, line + 1); - UI_PrintStringSmallNormal(t, LCD_WIDTH + 2, 0, line + 1); - - if (isMainOnly(false) && !gDTMF_InputMode) - { - if(shift == 0) - { - UI_PrintStringSmallNormal(String, 2, 0, 6); - } - - if((vfoInfo->StepFrequency / 100) < 100) - { - sprintf(String, "%d.%02uK", vfoInfo->StepFrequency / 100, vfoInfo->StepFrequency % 100); - } - else - { - sprintf(String, "%dK", vfoInfo->StepFrequency / 100); - } - UI_PrintStringSmallNormal(String, 46, 0, 6); - } - } - else - { - if ((s != NULL) && (s[0] != '\0')) { - GUI_DisplaySmallest(s, 58, line == 0 ? 17 : 49, false, true); - } - - if ((t != NULL) && (t[0] != '\0')) { - GUI_DisplaySmallest(t, 3, line == 0 ? 17 : 49, false, true); - } - - GUI_DisplaySmallest(String, 68 + shift, line == 0 ? 17 : 49, false, true); - - //sprintf(String, "%d.%02u", vfoInfo->StepFrequency / 100, vfoInfo->StepFrequency % 100); - //GUI_DisplaySmallest(String, 91, line == 0 ? 2 : 34, false, true); - } + const FREQ_Config_t *pConfig = (mode == VFO_MODE_TX) ? vfoInfo->pTX : vfoInfo->pRX; + int8_t shift = 0; + + switch((int)pConfig->CodeType) + { + case 1: + sprintf(String, "%u.%u", CTCSS_Options[pConfig->Code] / 10, CTCSS_Options[pConfig->Code] % 10); + break; + + case 2: + sprintf(String, "%03oN", DCS_Options[pConfig->Code]); + break; + + case 3: + sprintf(String, "%03oI", DCS_Options[pConfig->Code]); + break; + + default: + sprintf(String, "%d.%02uK", vfoInfo->StepFrequency / 100, vfoInfo->StepFrequency % 100); + shift = -10; + } + + if (isMainOnly(true)) + { + UI_PrintStringSmallNormal(s, LCD_WIDTH + 22, 0, line + 1); + UI_PrintStringSmallNormal(t, LCD_WIDTH + 2, 0, line + 1); + + if (isMainOnly(false) && !gDTMF_InputMode) + { + if(shift == 0) + { + UI_PrintStringSmallNormal(String, 2, 0, 6); + } + + if((vfoInfo->StepFrequency / 100) < 100) + { + sprintf(String, "%d.%02uK", vfoInfo->StepFrequency / 100, vfoInfo->StepFrequency % 100); + } + else + { + sprintf(String, "%dK", vfoInfo->StepFrequency / 100); + } + UI_PrintStringSmallNormal(String, 46, 0, 6); + } + } + else + { + if ((s != NULL) && (s[0] != '\0')) { + GUI_DisplaySmallest(s, 58, line == 0 ? 17 : 49, false, true); + } + + if ((t != NULL) && (t[0] != '\0')) { + GUI_DisplaySmallest(t, 3, line == 0 ? 17 : 49, false, true); + } + + GUI_DisplaySmallest(String, 68 + shift, line == 0 ? 17 : 49, false, true); + + //sprintf(String, "%d.%02u", vfoInfo->StepFrequency / 100, vfoInfo->StepFrequency % 100); + //GUI_DisplaySmallest(String, 91, line == 0 ? 2 : 34, false, true); + } #else - UI_PrintStringSmallNormal(s, LCD_WIDTH + 24, 0, line + 1); + UI_PrintStringSmallNormal(s, LCD_WIDTH + 24, 0, line + 1); #endif - if (state == VFO_STATE_NORMAL || state == VFO_STATE_ALARM) - { // show the TX power - uint8_t currentPower = vfoInfo->OUTPUT_POWER % 8; - uint8_t arrowPos = 19; - bool userPower = false; - - if(currentPower == OUTPUT_POWER_USER) - { - currentPower = gSetting_set_pwr; - userPower = true; - } - else - { - currentPower--; - userPower = false; - } - - if (isMainOnly(true)) - { - const char pwr_short[][3] = {"L1", "L2", "L3", "L4", "L5", "M", "H"}; - sprintf(String, "%s", pwr_short[currentPower]); - UI_PrintStringSmallNormal(String, LCD_WIDTH + 42, 0, line + 1); - arrowPos = 38; - } - else - { - const char pwr_long[][5] = {"LOW1", "LOW2", "LOW3", "LOW4", "LOW5", "MID", "HIGH"}; - sprintf(String, "%s", pwr_long[currentPower]); - GUI_DisplaySmallest(String, 24, line == 0 ? 17 : 49, false, true); - } - - if(userPower == true) - { - memcpy(p_line0 + 256 + arrowPos, BITMAP_PowerUser, sizeof(BITMAP_PowerUser)); - } - } - - if (vfoInfo->freq_config_RX.Frequency != vfoInfo->freq_config_TX.Frequency) - { // show the TX offset symbol - const char dir_list[][2] = {"", "+", "-"}; - int i = vfoInfo->TX_OFFSET_FREQUENCY_DIRECTION % 3; + if (state == VFO_STATE_NORMAL || state == VFO_STATE_ALARM) + { // show the TX power + uint8_t currentPower = vfoInfo->OUTPUT_POWER % 8; + uint8_t arrowPos = 19; + bool userPower = false; + + if(currentPower == OUTPUT_POWER_USER) + { + currentPower = gSetting_set_pwr; + userPower = true; + } + else + { + currentPower--; + userPower = false; + } + + if (isMainOnly(true)) + { + const char pwr_short[][3] = {"L1", "L2", "L3", "L4", "L5", "M", "H"}; + sprintf(String, "%s", pwr_short[currentPower]); + UI_PrintStringSmallNormal(String, LCD_WIDTH + 42, 0, line + 1); + arrowPos = 38; + } + else + { + const char pwr_long[][5] = {"LOW1", "LOW2", "LOW3", "LOW4", "LOW5", "MID", "HIGH"}; + sprintf(String, "%s", pwr_long[currentPower]); + GUI_DisplaySmallest(String, 24, line == 0 ? 17 : 49, false, true); + } + + if(userPower == true) + { + memcpy(p_line0 + 256 + arrowPos, BITMAP_PowerUser, sizeof(BITMAP_PowerUser)); + } + } + + if (vfoInfo->freq_config_RX.Frequency != vfoInfo->freq_config_TX.Frequency) + { // show the TX offset symbol + const char dir_list[][2] = {"", "+", "-"}; + int i = vfoInfo->TX_OFFSET_FREQUENCY_DIRECTION % 3; #if ENABLE_FEAT_F4HWN - if (isMainOnly(true)) - { - UI_PrintStringSmallNormal(dir_list[i], LCD_WIDTH + 60, 0, line + 1); - } - else - { - UI_PrintStringSmallNormal(dir_list[i], LCD_WIDTH + 41, 0, line + 1); - } + if (isMainOnly(true)) + { + UI_PrintStringSmallNormal(dir_list[i], LCD_WIDTH + 60, 0, line + 1); + } + else + { + UI_PrintStringSmallNormal(dir_list[i], LCD_WIDTH + 41, 0, line + 1); + } #else - UI_PrintStringSmallNormal(dir_list[i], LCD_WIDTH + 54, 0, line + 1); + UI_PrintStringSmallNormal(dir_list[i], LCD_WIDTH + 54, 0, line + 1); #endif - } + } - // show the TX/RX reverse symbol - if (vfoInfo->FrequencyReverse) + // show the TX/RX reverse symbol + if (vfoInfo->FrequencyReverse) #if ENABLE_FEAT_F4HWN - { - if (isMainOnly(true)) - { - UI_PrintStringSmallNormal("R", LCD_WIDTH + 68, 0, line + 1); - } - else - { - GUI_DisplaySmallest("R", 51, line == 0 ? 17 : 49, false, true); - } - } + { + if (isMainOnly(true)) + { + UI_PrintStringSmallNormal("R", LCD_WIDTH + 68, 0, line + 1); + } + else + { + GUI_DisplaySmallest("R", 51, line == 0 ? 17 : 49, false, true); + } + } #else - UI_PrintStringSmallNormal("R", LCD_WIDTH + 62, 0, line + 1); + UI_PrintStringSmallNormal("R", LCD_WIDTH + 62, 0, line + 1); #endif #if ENABLE_FEAT_F4HWN - if (isMainOnly(true)) - { - const char *bandWidthNames[] = {"W", "N"}; - UI_PrintStringSmallNormal(bandWidthNames[vfoInfo->CHANNEL_BANDWIDTH], LCD_WIDTH + 80, 0, line + 1); - } - else - { - const char *bandWidthNames[] = {"WIDE", "NAR"}; - GUI_DisplaySmallest(bandWidthNames[vfoInfo->CHANNEL_BANDWIDTH], 91, line == 0 ? 17 : 49, false, true); - } + if (isMainOnly(true)) + { + const char *bandWidthNames[] = {"W", "N"}; + UI_PrintStringSmallNormal(bandWidthNames[vfoInfo->CHANNEL_BANDWIDTH], LCD_WIDTH + 80, 0, line + 1); + } + else + { + const char *bandWidthNames[] = {"WIDE", "NAR"}; + GUI_DisplaySmallest(bandWidthNames[vfoInfo->CHANNEL_BANDWIDTH], 91, line == 0 ? 17 : 49, false, true); + } #else - if (vfoInfo->CHANNEL_BANDWIDTH == BANDWIDTH_NARROW) - UI_PrintStringSmallNormal("N", LCD_WIDTH + 70, 0, line + 1); + if (vfoInfo->CHANNEL_BANDWIDTH == BANDWIDTH_NARROW) + UI_PrintStringSmallNormal("N", LCD_WIDTH + 70, 0, line + 1); #endif #ifdef ENABLE_DTMF_CALLING - // show the DTMF decoding symbol - if (vfoInfo->DTMF_DECODING_ENABLE || gSetting_KILLED) - UI_PrintStringSmallNormal("DTMF", LCD_WIDTH + 78, 0, line + 1); + // show the DTMF decoding symbol + if (vfoInfo->DTMF_DECODING_ENABLE || gSetting_KILLED) + UI_PrintStringSmallNormal("DTMF", LCD_WIDTH + 78, 0, line + 1); #endif #ifndef ENABLE_FEAT_F4HWN - // show the audio scramble symbol - if (vfoInfo->SCRAMBLING_TYPE > 0 && gSetting_ScrambleEnable) - UI_PrintStringSmallNormal("SCR", LCD_WIDTH + 106, 0, line + 1); + // show the audio scramble symbol + if (vfoInfo->SCRAMBLING_TYPE > 0 && gSetting_ScrambleEnable) + UI_PrintStringSmallNormal("SCR", LCD_WIDTH + 106, 0, line + 1); #endif #ifdef ENABLE_FEAT_F4HWN - if(isMainVFO) - { - if(gMonitor) - { - sprintf(String, "%s", "MONI"); - } - - if (isMainOnly(true)) - { - if(!gMonitor) - { - sprintf(String, "SQL%d", gEeprom.SQUELCH_LEVEL); - } - UI_PrintStringSmallNormal(String, LCD_WIDTH + 98, 0, line + 1); - } - else - { - if(!gMonitor) - { - sprintf(String, "SQL%d", gEeprom.SQUELCH_LEVEL); - } - GUI_DisplaySmallest(String, 110, line == 0 ? 17 : 49, false, true); - } - } + if(isMainVFO) + { + if(gMonitor) + { + sprintf(String, "%s", "MONI"); + } + + if (isMainOnly(true)) + { + if(!gMonitor) + { + sprintf(String, "SQL%d", gEeprom.SQUELCH_LEVEL); + } + UI_PrintStringSmallNormal(String, LCD_WIDTH + 98, 0, line + 1); + } + else + { + if(!gMonitor) + { + sprintf(String, "SQL%d", gEeprom.SQUELCH_LEVEL); + } + GUI_DisplaySmallest(String, 110, line == 0 ? 17 : 49, false, true); + } + } #endif - } + } #ifdef ENABLE_AGC_SHOW_DATA - center_line = CENTER_LINE_IN_USE; - UI_MAIN_PrintAGC(false); + center_line = CENTER_LINE_IN_USE; + UI_MAIN_PrintAGC(false); #endif - if (center_line == CENTER_LINE_NONE) - { // we're free to use the middle line + if (center_line == CENTER_LINE_NONE) + { // we're free to use the middle line - const bool rx = FUNCTION_IsRx(); + const bool rx = FUNCTION_IsRx(); #ifdef ENABLE_AUDIO_BAR - if (gSetting_mic_bar && gCurrentFunction == FUNCTION_TRANSMIT) { - center_line = CENTER_LINE_AUDIO_BAR; - UI_DisplayAudioBar(); - } - else + if (gSetting_mic_bar && gCurrentFunction == FUNCTION_TRANSMIT) { + center_line = CENTER_LINE_AUDIO_BAR; + UI_DisplayAudioBar(); + } + else #endif #if defined(ENABLE_AM_FIX) && defined(ENABLE_AM_FIX_SHOW_DATA) - if (rx && gEeprom.VfoInfo[gEeprom.RX_VFO].Modulation == MODULATION_AM && gSetting_AM_fix) - { - if (gScreenToDisplay != DISPLAY_MAIN + if (rx && gEeprom.VfoInfo[gEeprom.RX_VFO].Modulation == MODULATION_AM && gSetting_AM_fix) + { + if (gScreenToDisplay != DISPLAY_MAIN #ifdef ENABLE_DTMF_CALLING - || gDTMF_CallState != DTMF_CALL_STATE_NONE + || gDTMF_CallState != DTMF_CALL_STATE_NONE #endif - ) - return; - - center_line = CENTER_LINE_AM_FIX_DATA; - AM_fix_print_data(gEeprom.RX_VFO, String); - UI_PrintStringSmallNormal(String, 2, 0, 3); - } - else + ) + return; + + center_line = CENTER_LINE_AM_FIX_DATA; + AM_fix_print_data(gEeprom.RX_VFO, String); + UI_PrintStringSmallNormal(String, 2, 0, 3); + } + else #endif #ifdef ENABLE_RSSI_BAR - if (rx) { - center_line = CENTER_LINE_RSSI; - DisplayRSSIBar(false); - } - else + if (rx) { + center_line = CENTER_LINE_RSSI; + DisplayRSSIBar(false); + } + else #endif - if (rx || gCurrentFunction == FUNCTION_FOREGROUND || gCurrentFunction == FUNCTION_POWER_SAVE) - { - #if 1 - if (gSetting_live_DTMF_decoder && gDTMF_RX_live[0] != 0) - { // show live DTMF decode - const unsigned int len = strlen(gDTMF_RX_live); - const unsigned int idx = (len > (17 - 5)) ? len - (17 - 5) : 0; // limit to last 'n' chars - - if (gScreenToDisplay != DISPLAY_MAIN + if (rx || gCurrentFunction == FUNCTION_FOREGROUND || gCurrentFunction == FUNCTION_POWER_SAVE) + { + #if 1 + if (gSetting_live_DTMF_decoder && gDTMF_RX_live[0] != 0) + { // show live DTMF decode + const unsigned int len = strlen(gDTMF_RX_live); + const unsigned int idx = (len > (17 - 5)) ? len - (17 - 5) : 0; // limit to last 'n' chars + + if (gScreenToDisplay != DISPLAY_MAIN #ifdef ENABLE_DTMF_CALLING - || gDTMF_CallState != DTMF_CALL_STATE_NONE + || gDTMF_CallState != DTMF_CALL_STATE_NONE #endif - ) - return; + ) + return; - center_line = CENTER_LINE_DTMF_DEC; + center_line = CENTER_LINE_DTMF_DEC; - sprintf(String, "DTMF %s", gDTMF_RX_live + idx); + sprintf(String, "DTMF %s", gDTMF_RX_live + idx); #ifdef ENABLE_FEAT_F4HWN - if (isMainOnly(false)) - { - UI_PrintStringSmallNormal(String, 2, 0, 5); - } - else - { - UI_PrintStringSmallNormal(String, 2, 0, 3); - } + if (isMainOnly(false)) + { + UI_PrintStringSmallNormal(String, 2, 0, 5); + } + else + { + UI_PrintStringSmallNormal(String, 2, 0, 3); + } #else - UI_PrintStringSmallNormal(String, 2, 0, 3); + UI_PrintStringSmallNormal(String, 2, 0, 3); #endif - } - #else - if (gSetting_live_DTMF_decoder && gDTMF_RX_index > 0) - { // show live DTMF decode - const unsigned int len = gDTMF_RX_index; - const unsigned int idx = (len > (17 - 5)) ? len - (17 - 5) : 0; // limit to last 'n' chars + } + #else + if (gSetting_live_DTMF_decoder && gDTMF_RX_index > 0) + { // show live DTMF decode + const unsigned int len = gDTMF_RX_index; + const unsigned int idx = (len > (17 - 5)) ? len - (17 - 5) : 0; // limit to last 'n' chars - if (gScreenToDisplay != DISPLAY_MAIN || - gDTMF_CallState != DTMF_CALL_STATE_NONE) - return; + if (gScreenToDisplay != DISPLAY_MAIN || + gDTMF_CallState != DTMF_CALL_STATE_NONE) + return; - center_line = CENTER_LINE_DTMF_DEC; + center_line = CENTER_LINE_DTMF_DEC; - sprintf(String, "DTMF %s", gDTMF_RX_live + idx); - UI_PrintStringSmallNormal(String, 2, 0, 3); - } - #endif + sprintf(String, "DTMF %s", gDTMF_RX_live + idx); + UI_PrintStringSmallNormal(String, 2, 0, 3); + } + #endif #ifdef ENABLE_SHOW_CHARGE_LEVEL - else if (gChargingWithTypeC) - { // charging .. show the battery state - if (gScreenToDisplay != DISPLAY_MAIN + else if (gChargingWithTypeC) + { // charging .. show the battery state + if (gScreenToDisplay != DISPLAY_MAIN #ifdef ENABLE_DTMF_CALLING - || gDTMF_CallState != DTMF_CALL_STATE_NONE + || gDTMF_CallState != DTMF_CALL_STATE_NONE #endif - ) - return; + ) + return; - center_line = CENTER_LINE_CHARGE_DATA; + center_line = CENTER_LINE_CHARGE_DATA; - sprintf(String, "Charge %u.%02uV %u%%", - gBatteryVoltageAverage / 100, gBatteryVoltageAverage % 100, - BATTERY_VoltsToPercent(gBatteryVoltageAverage)); - UI_PrintStringSmallNormal(String, 2, 0, 3); - } + sprintf(String, "Charge %u.%02uV %u%%", + gBatteryVoltageAverage / 100, gBatteryVoltageAverage % 100, + BATTERY_VoltsToPercent(gBatteryVoltageAverage)); + UI_PrintStringSmallNormal(String, 2, 0, 3); + } #endif - } - } + } + } #ifdef ENABLE_FEAT_F4HWN - if (isMainOnly(false) && !gDTMF_InputMode) - { - sprintf(String, "VFO %s", activeTxVFO ? "B" : "A"); - UI_PrintStringSmallBold(String, 92, 0, 6); - for (uint8_t i = 92; i < 128; i++) - { - gFrameBuffer[6][i] ^= 0x7F; - } - } + if (isMainOnly(false) && !gDTMF_InputMode) + { + sprintf(String, "VFO %s", activeTxVFO ? "B" : "A"); + UI_PrintStringSmallBold(String, 92, 0, 6); + for (uint8_t i = 92; i < 128; i++) + { + gFrameBuffer[6][i] ^= 0x7F; + } + } #endif - ST7565_BlitFullScreen(); + ST7565_BlitFullScreen(); } // *************************************************************************** diff --git a/ui/main.h b/ui/main.h index 16a6ec333..92a1cb364 100644 --- a/ui/main.h +++ b/ui/main.h @@ -18,19 +18,19 @@ #define UI_MAIN_H enum center_line_t { - CENTER_LINE_NONE = 0, - CENTER_LINE_IN_USE, - CENTER_LINE_AUDIO_BAR, - CENTER_LINE_RSSI, - CENTER_LINE_AM_FIX_DATA, - CENTER_LINE_DTMF_DEC, - CENTER_LINE_CHARGE_DATA + CENTER_LINE_NONE = 0, + CENTER_LINE_IN_USE, + CENTER_LINE_AUDIO_BAR, + CENTER_LINE_RSSI, + CENTER_LINE_AM_FIX_DATA, + CENTER_LINE_DTMF_DEC, + CENTER_LINE_CHARGE_DATA }; enum Vfo_txtr_mode{ - VFO_MODE_NONE = 0, - VFO_MODE_TX = 1, - VFO_MODE_RX = 2, + VFO_MODE_NONE = 0, + VFO_MODE_TX = 1, + VFO_MODE_RX = 2, }; typedef enum center_line_t center_line_t; diff --git a/ui/menu.c b/ui/menu.c index 6be784862..e2a8b78c9 100644 --- a/ui/menu.c +++ b/ui/menu.c @@ -40,393 +40,393 @@ const t_menu_item MenuList[] = { // text, menu ID - {"Step", MENU_STEP }, - {"Power", MENU_TXP }, // was "TXP" - {"RxDCS", MENU_R_DCS }, // was "R_DCS" - {"RxCTCS", MENU_R_CTCS }, // was "R_CTCS" - {"TxDCS", MENU_T_DCS }, // was "T_DCS" - {"TxCTCS", MENU_T_CTCS }, // was "T_CTCS" - {"TxODir", MENU_SFT_D }, // was "SFT_D" - {"TxOffs", MENU_OFFSET }, // was "OFFSET" - {"W/N", MENU_W_N }, + {"Step", MENU_STEP }, + {"Power", MENU_TXP }, // was "TXP" + {"RxDCS", MENU_R_DCS }, // was "R_DCS" + {"RxCTCS", MENU_R_CTCS }, // was "R_CTCS" + {"TxDCS", MENU_T_DCS }, // was "T_DCS" + {"TxCTCS", MENU_T_CTCS }, // was "T_CTCS" + {"TxODir", MENU_SFT_D }, // was "SFT_D" + {"TxOffs", MENU_OFFSET }, // was "OFFSET" + {"W/N", MENU_W_N }, #ifndef ENABLE_FEAT_F4HWN - {"Scramb", MENU_SCR }, // was "SCR" + {"Scramb", MENU_SCR }, // was "SCR" #endif - {"BusyCL", MENU_BCL }, // was "BCL" - {"Compnd", MENU_COMPAND }, - {"Mode", MENU_AM }, // was "AM" + {"BusyCL", MENU_BCL }, // was "BCL" + {"Compnd", MENU_COMPAND }, + {"Mode", MENU_AM }, // was "AM" #ifdef ENABLE_FEAT_F4HWN - {"TXLock", MENU_TX_LOCK }, + {"TXLock", MENU_TX_LOCK }, #endif - {"ScAdd1", MENU_S_ADD1 }, - {"ScAdd2", MENU_S_ADD2 }, - {"ScAdd3", MENU_S_ADD3 }, - {"ChSave", MENU_MEM_CH }, // was "MEM-CH" - {"ChDele", MENU_DEL_CH }, // was "DEL-CH" - {"ChName", MENU_MEM_NAME }, - - {"SList", MENU_S_LIST }, - {"SList1", MENU_SLIST1 }, - {"SList2", MENU_SLIST2 }, - {"SList3", MENU_SLIST3 }, - {"ScnRev", MENU_SC_REV }, + {"ScAdd1", MENU_S_ADD1 }, + {"ScAdd2", MENU_S_ADD2 }, + {"ScAdd3", MENU_S_ADD3 }, + {"ChSave", MENU_MEM_CH }, // was "MEM-CH" + {"ChDele", MENU_DEL_CH }, // was "DEL-CH" + {"ChName", MENU_MEM_NAME }, + + {"SList", MENU_S_LIST }, + {"SList1", MENU_SLIST1 }, + {"SList2", MENU_SLIST2 }, + {"SList3", MENU_SLIST3 }, + {"ScnRev", MENU_SC_REV }, #ifdef ENABLE_NOAA - {"NOAA-S", MENU_NOAA_S }, + {"NOAA-S", MENU_NOAA_S }, #endif - {"F1Shrt", MENU_F1SHRT }, - {"F1Long", MENU_F1LONG }, - {"F2Shrt", MENU_F2SHRT }, - {"F2Long", MENU_F2LONG }, - {"M Long", MENU_MLONG }, - - {"KeyLck", MENU_AUTOLK }, // was "AUTOLk" - {"TxTOut", MENU_TOT }, // was "TOT" - {"BatSav", MENU_SAVE }, // was "SAVE" - {"BatTxt", MENU_BAT_TXT }, - {"Mic", MENU_MIC }, + {"F1Shrt", MENU_F1SHRT }, + {"F1Long", MENU_F1LONG }, + {"F2Shrt", MENU_F2SHRT }, + {"F2Long", MENU_F2LONG }, + {"M Long", MENU_MLONG }, + + {"KeyLck", MENU_AUTOLK }, // was "AUTOLk" + {"TxTOut", MENU_TOT }, // was "TOT" + {"BatSav", MENU_SAVE }, // was "SAVE" + {"BatTxt", MENU_BAT_TXT }, + {"Mic", MENU_MIC }, #ifdef ENABLE_AUDIO_BAR - {"MicBar", MENU_MIC_BAR }, + {"MicBar", MENU_MIC_BAR }, #endif - {"ChDisp", MENU_MDF }, // was "MDF" - {"POnMsg", MENU_PONMSG }, - {"BLTime", MENU_ABR }, // was "ABR" - {"BLMin", MENU_ABR_MIN }, - {"BLMax", MENU_ABR_MAX }, - {"BLTxRx", MENU_ABR_ON_TX_RX }, - {"Beep", MENU_BEEP }, + {"ChDisp", MENU_MDF }, // was "MDF" + {"POnMsg", MENU_PONMSG }, + {"BLTime", MENU_ABR }, // was "ABR" + {"BLMin", MENU_ABR_MIN }, + {"BLMax", MENU_ABR_MAX }, + {"BLTxRx", MENU_ABR_ON_TX_RX }, + {"Beep", MENU_BEEP }, #ifdef ENABLE_VOICE - {"Voice", MENU_VOICE }, + {"Voice", MENU_VOICE }, #endif - {"Roger", MENU_ROGER }, - {"STE", MENU_STE }, - {"RP STE", MENU_RP_STE }, - {"1 Call", MENU_1_CALL }, + {"Roger", MENU_ROGER }, + {"STE", MENU_STE }, + {"RP STE", MENU_RP_STE }, + {"1 Call", MENU_1_CALL }, #ifdef ENABLE_ALARM - {"AlarmT", MENU_AL_MOD }, + {"AlarmT", MENU_AL_MOD }, #endif #ifdef ENABLE_DTMF_CALLING - {"ANI ID", MENU_ANI_ID }, + {"ANI ID", MENU_ANI_ID }, #endif - {"UPCode", MENU_UPCODE }, - {"DWCode", MENU_DWCODE }, - {"PTT ID", MENU_PTT_ID }, - {"D ST", MENU_D_ST }, + {"UPCode", MENU_UPCODE }, + {"DWCode", MENU_DWCODE }, + {"PTT ID", MENU_PTT_ID }, + {"D ST", MENU_D_ST }, #ifdef ENABLE_DTMF_CALLING - {"D Resp", MENU_D_RSP }, - {"D Hold", MENU_D_HOLD }, + {"D Resp", MENU_D_RSP }, + {"D Hold", MENU_D_HOLD }, #endif - {"D Prel", MENU_D_PRE }, + {"D Prel", MENU_D_PRE }, #ifdef ENABLE_DTMF_CALLING - {"D Decd", MENU_D_DCD }, - {"D List", MENU_D_LIST }, + {"D Decd", MENU_D_DCD }, + {"D List", MENU_D_LIST }, #endif - {"D Live", MENU_D_LIVE_DEC }, // live DTMF decoder + {"D Live", MENU_D_LIVE_DEC }, // live DTMF decoder #ifndef ENABLE_FEAT_F4HWN - #ifdef ENABLE_AM_FIX - {"AM Fix", MENU_AM_FIX }, - #endif + #ifdef ENABLE_AM_FIX + {"AM Fix", MENU_AM_FIX }, + #endif #endif #ifdef ENABLE_VOX - {"VOX", MENU_VOX }, + {"VOX", MENU_VOX }, #endif #ifdef ENABLE_FEAT_F4HWN - {"SysInf", MENU_VOL }, // was "VOL" + {"SysInf", MENU_VOL }, // was "VOL" #else - {"BatVol", MENU_VOL }, // was "VOL" + {"BatVol", MENU_VOL }, // was "VOL" #endif - {"RxMode", MENU_TDR }, - {"Sql", MENU_SQL }, + {"RxMode", MENU_TDR }, + {"Sql", MENU_SQL }, #ifdef ENABLE_FEAT_F4HWN - {"SetPwr", MENU_SET_PWR }, - {"SetPtt", MENU_SET_PTT }, - {"SetTot", MENU_SET_TOT }, - {"SetEot", MENU_SET_EOT }, - {"SetCtr", MENU_SET_CTR }, - {"SetInv", MENU_SET_INV }, - {"SetLck", MENU_SET_LCK }, - {"SetMet", MENU_SET_MET }, - {"SetGui", MENU_SET_GUI }, - {"SetTmr", MENU_SET_TMR }, + {"SetPwr", MENU_SET_PWR }, + {"SetPtt", MENU_SET_PTT }, + {"SetTot", MENU_SET_TOT }, + {"SetEot", MENU_SET_EOT }, + {"SetCtr", MENU_SET_CTR }, + {"SetInv", MENU_SET_INV }, + {"SetLck", MENU_SET_LCK }, + {"SetMet", MENU_SET_MET }, + {"SetGui", MENU_SET_GUI }, + {"SetTmr", MENU_SET_TMR }, #endif - // hidden menu items from here on - // enabled if pressing both the PTT and upper side button at power-on - {"F Lock", MENU_F_LOCK }, - {"Tx 200", MENU_200TX }, // was "200TX" - {"Tx 350", MENU_350TX }, // was "350TX" - {"Tx 500", MENU_500TX }, // was "500TX" - {"350 En", MENU_350EN }, // was "350EN" + // hidden menu items from here on + // enabled if pressing both the PTT and upper side button at power-on + {"F Lock", MENU_F_LOCK }, + {"Tx 200", MENU_200TX }, // was "200TX" + {"Tx 350", MENU_350TX }, // was "350TX" + {"Tx 500", MENU_500TX }, // was "500TX" + {"350 En", MENU_350EN }, // was "350EN" #ifndef ENABLE_FEAT_F4HWN - {"ScraEn", MENU_SCREN }, // was "SCREN" + {"ScraEn", MENU_SCREN }, // was "SCREN" #endif #ifdef ENABLE_F_CAL_MENU - {"FrCali", MENU_F_CALI }, // reference xtal calibration + {"FrCali", MENU_F_CALI }, // reference xtal calibration #endif - {"BatCal", MENU_BATCAL }, // battery voltage calibration - {"BatTyp", MENU_BATTYP }, // battery type 1600/2200mAh - {"Reset", MENU_RESET }, // might be better to move this to the hidden menu items ? + {"BatCal", MENU_BATCAL }, // battery voltage calibration + {"BatTyp", MENU_BATTYP }, // battery type 1600/2200mAh + {"Reset", MENU_RESET }, // might be better to move this to the hidden menu items ? - {"", 0xff } // end of list - DO NOT delete or move this this + {"", 0xff } // end of list - DO NOT delete or move this this }; const uint8_t FIRST_HIDDEN_MENU_ITEM = MENU_F_LOCK; const char gSubMenu_TXP[][6] = { - "USER", - "LOW 1", - "LOW 2", - "LOW 3", - "LOW 4", - "LOW 5", - "MID", - "HIGH" + "USER", + "LOW 1", + "LOW 2", + "LOW 3", + "LOW 4", + "LOW 5", + "MID", + "HIGH" }; const char gSubMenu_SFT_D[][4] = { - "OFF", - "+", - "-" + "OFF", + "+", + "-" }; const char gSubMenu_W_N[][7] = { - "WIDE", - "NARROW" + "WIDE", + "NARROW" }; const char gSubMenu_OFF_ON[][4] = { - "OFF", - "ON" + "OFF", + "ON" }; const char gSubMenu_SAVE[][4] = { - "OFF", - "1:1", - "1:2", - "1:3", - "1:4" + "OFF", + "1:1", + "1:2", + "1:3", + "1:4" }; const char* const gSubMenu_RXMode[] = { - "MAIN\nONLY", // TX and RX on main only - "DUAL RX\nRESPOND", // Watch both and respond - "CROSS\nBAND", // TX on main, RX on secondary - "MAIN TX\nDUAL RX" // always TX on main, but RX on both + "MAIN\nONLY", // TX and RX on main only + "DUAL RX\nRESPOND", // Watch both and respond + "CROSS\nBAND", // TX on main, RX on secondary + "MAIN TX\nDUAL RX" // always TX on main, but RX on both }; #ifdef ENABLE_VOICE - const char gSubMenu_VOICE[][4] = - { - "OFF", - "CHI", - "ENG" - }; + const char gSubMenu_VOICE[][4] = + { + "OFF", + "CHI", + "ENG" + }; #endif const char gSubMenu_SC_REV[][8] = { - "TIMEOUT", - "CARRIER", - "STOP" + "TIMEOUT", + "CARRIER", + "STOP" }; const char* const gSubMenu_MDF[] = { - "FREQ", - "CHANNEL\nNUMBER", - "NAME", - "NAME\n+\nFREQ" + "FREQ", + "CHANNEL\nNUMBER", + "NAME", + "NAME\n+\nFREQ" }; #ifdef ENABLE_ALARM - const char gSubMenu_AL_MOD[][5] = - { - "SITE", - "TONE" - }; + const char gSubMenu_AL_MOD[][5] = + { + "SITE", + "TONE" + }; #endif #ifdef ENABLE_DTMF_CALLING const char gSubMenu_D_RSP[][11] = { - "DO\nNOTHING", - "RING", - "REPLY", - "BOTH" + "DO\nNOTHING", + "RING", + "REPLY", + "BOTH" }; #endif const char* const gSubMenu_PTT_ID[] = { - "OFF", - "UP CODE", - "DOWN CODE", - "UP+DOWN\nCODE", - "APOLLO\nQUINDAR" + "OFF", + "UP CODE", + "DOWN CODE", + "UP+DOWN\nCODE", + "APOLLO\nQUINDAR" }; const char gSubMenu_PONMSG[][8] = { #ifdef ENABLE_FEAT_F4HWN - "ALL", - "SOUND", + "ALL", + "SOUND", #else - "FULL", + "FULL", #endif - "MESSAGE", - "VOLTAGE", - "NONE" + "MESSAGE", + "VOLTAGE", + "NONE" }; const char gSubMenu_ROGER[][6] = { - "OFF", - "ROGER", - "MDC" + "OFF", + "ROGER", + "MDC" }; const char gSubMenu_RESET[][4] = { - "VFO", - "ALL" + "VFO", + "ALL" }; const char * const gSubMenu_F_LOCK[] = { - "DEFAULT+\n137-174\n400-470", - "FCC HAM\n144-148\n420-450", + "DEFAULT+\n137-174\n400-470", + "FCC HAM\n144-148\n420-450", #ifdef ENABLE_FEAT_F4HWN_CA - "CA HAM\n144-148\n430-450", + "CA HAM\n144-148\n430-450", #endif - "CE HAM\n144-146\n430-440", - "GB HAM\n144-148\n430-440", - "137-174\n400-430", - "137-174\n400-438", + "CE HAM\n144-146\n430-440", + "GB HAM\n144-148\n430-440", + "137-174\n400-430", + "137-174\n400-438", #ifdef ENABLE_FEAT_F4HWN_PMR - "PMR 446", + "PMR 446", #endif #ifdef ENABLE_FEAT_F4HWN_GMRS_FRS_MURS - "GMRS\nFRS\nMURS", + "GMRS\nFRS\nMURS", #endif - "DISABLE\nALL", - "UNLOCK\nALL", + "DISABLE\nALL", + "UNLOCK\nALL", }; const char gSubMenu_RX_TX[][6] = { - "OFF", - "TX", - "RX", - "TX/RX" + "OFF", + "TX", + "RX", + "TX/RX" }; const char gSubMenu_BAT_TXT[][8] = { - "NONE", - "VOLTAGE", - "PERCENT" + "NONE", + "VOLTAGE", + "PERCENT" }; const char gSubMenu_BATTYP[][9] = { - "1600mAh", - "2200mAh", - "3500mAh" + "1600mAh", + "2200mAh", + "3500mAh" }; #ifndef ENABLE_FEAT_F4HWN const char gSubMenu_SCRAMBLER[][7] = { - "OFF", - "2600Hz", - "2700Hz", - "2800Hz", - "2900Hz", - "3000Hz", - "3100Hz", - "3200Hz", - "3300Hz", - "3400Hz", - "3500Hz" + "OFF", + "2600Hz", + "2700Hz", + "2800Hz", + "2900Hz", + "3000Hz", + "3100Hz", + "3200Hz", + "3300Hz", + "3400Hz", + "3500Hz" }; #endif #ifdef ENABLE_FEAT_F4HWN - const char gSubMenu_SET_PWR[][6] = - { - "< 20m", - "125m", - "250m", - "500m", - "1", - "2", - "5" - }; - - const char gSubMenu_SET_PTT[][8] = - { - "CLASSIC", - "ONEPUSH" - }; - - const char gSubMenu_SET_TOT[][7] = // Use by SET_EOT too - { - "OFF", - "SOUND", - "VISUAL", - "ALL" - }; - - const char gSubMenu_SET_LCK[][9] = - { - "KEYS", - "KEYS+PTT" - }; - - const char gSubMenu_SET_MET[][8] = - { - "TINY", - "CLASSIC" - }; + const char gSubMenu_SET_PWR[][6] = + { + "< 20m", + "125m", + "250m", + "500m", + "1", + "2", + "5" + }; + + const char gSubMenu_SET_PTT[][8] = + { + "CLASSIC", + "ONEPUSH" + }; + + const char gSubMenu_SET_TOT[][7] = // Use by SET_EOT too + { + "OFF", + "SOUND", + "VISUAL", + "ALL" + }; + + const char gSubMenu_SET_LCK[][9] = + { + "KEYS", + "KEYS+PTT" + }; + + const char gSubMenu_SET_MET[][8] = + { + "TINY", + "CLASSIC" + }; #endif const t_sidefunction gSubMenu_SIDEFUNCTIONS[] = { - {"NONE", ACTION_OPT_NONE}, + {"NONE", ACTION_OPT_NONE}, #ifdef ENABLE_FLASHLIGHT - {"FLASH\nLIGHT", ACTION_OPT_FLASHLIGHT}, + {"FLASH\nLIGHT", ACTION_OPT_FLASHLIGHT}, #endif - {"POWER", ACTION_OPT_POWER}, - {"MONITOR", ACTION_OPT_MONITOR}, - {"SCAN", ACTION_OPT_SCAN}, + {"POWER", ACTION_OPT_POWER}, + {"MONITOR", ACTION_OPT_MONITOR}, + {"SCAN", ACTION_OPT_SCAN}, #ifdef ENABLE_VOX - {"VOX", ACTION_OPT_VOX}, + {"VOX", ACTION_OPT_VOX}, #endif #ifdef ENABLE_ALARM - {"ALARM", ACTION_OPT_ALARM}, + {"ALARM", ACTION_OPT_ALARM}, #endif #ifdef ENABLE_FMRADIO - {"FM RADIO", ACTION_OPT_FM}, + {"FM RADIO", ACTION_OPT_FM}, #endif #ifdef ENABLE_TX1750 - {"1750Hz", ACTION_OPT_1750}, + {"1750Hz", ACTION_OPT_1750}, #endif - {"LOCK\nKEYPAD", ACTION_OPT_KEYLOCK}, - {"VFO A\nVFO B", ACTION_OPT_A_B}, - {"VFO\nMEM", ACTION_OPT_VFO_MR}, - {"MODE", ACTION_OPT_SWITCH_DEMODUL}, + {"LOCK\nKEYPAD", ACTION_OPT_KEYLOCK}, + {"VFO A\nVFO B", ACTION_OPT_A_B}, + {"VFO\nMEM", ACTION_OPT_VFO_MR}, + {"MODE", ACTION_OPT_SWITCH_DEMODUL}, #ifdef ENABLE_BLMIN_TMP_OFF - {"BLMIN\nTMP OFF", ACTION_OPT_BLMIN_TMP_OFF}, //BackLight Minimum Temporay OFF + {"BLMIN\nTMP OFF", ACTION_OPT_BLMIN_TMP_OFF}, //BackLight Minimum Temporay OFF #endif #ifdef ENABLE_FEAT_F4HWN - {"RX MODE", ACTION_OPT_RXMODE}, - {"MAIN ONLY", ACTION_OPT_MAINONLY}, - {"PTT", ACTION_OPT_PTT}, - {"WIDE\nNARROW", ACTION_OPT_WN}, + {"RX MODE", ACTION_OPT_RXMODE}, + {"MAIN ONLY", ACTION_OPT_MAINONLY}, + {"PTT", ACTION_OPT_PTT}, + {"WIDE\nNARROW", ACTION_OPT_WN}, #endif }; @@ -435,18 +435,18 @@ const uint8_t gSubMenu_SIDEFUNCTIONS_size = ARRAY_SIZE(gSubMenu_SIDEFUNCTIONS); bool gIsInSubMenu; uint8_t gMenuCursor; int UI_MENU_GetCurrentMenuId() { - if(gMenuCursor < ARRAY_SIZE(MenuList)) - return MenuList[gMenuCursor].menu_id; + if(gMenuCursor < ARRAY_SIZE(MenuList)) + return MenuList[gMenuCursor].menu_id; - return MenuList[ARRAY_SIZE(MenuList)-1].menu_id; + return MenuList[ARRAY_SIZE(MenuList)-1].menu_id; } uint8_t UI_MENU_GetMenuIdx(uint8_t id) { - for(uint8_t i = 0; i < ARRAY_SIZE(MenuList); i++) - if(MenuList[i].menu_id == id) - return i; - return 0; + for(uint8_t i = 0; i < ARRAY_SIZE(MenuList); i++) + if(MenuList[i].menu_id == id) + return i; + return 0; } int32_t gSubMenuSelection; @@ -458,712 +458,712 @@ int edit_index; void UI_DisplayMenu(void) { - const unsigned int menu_list_width = 6; // max no. of characters on the menu list (left side) - const unsigned int menu_item_x1 = (8 * menu_list_width) + 2; - const unsigned int menu_item_x2 = LCD_WIDTH - 1; - unsigned int i; - char String[64]; // bigger cuz we can now do multi-line in one string (use '\n' char) + const unsigned int menu_list_width = 6; // max no. of characters on the menu list (left side) + const unsigned int menu_item_x1 = (8 * menu_list_width) + 2; + const unsigned int menu_item_x2 = LCD_WIDTH - 1; + unsigned int i; + char String[64]; // bigger cuz we can now do multi-line in one string (use '\n' char) #ifdef ENABLE_DTMF_CALLING - char Contact[16]; + char Contact[16]; #endif - UI_DisplayClear(); + UI_DisplayClear(); #ifdef ENABLE_FEAT_F4HWN - UI_DrawLineBuffer(gFrameBuffer, 48, 0, 48, 55, 1); // Be ware, status zone = 8 lines, the rest = 56 ->total 64 - //UI_DrawLineDottedBuffer(gFrameBuffer, 0, 46, 50, 46, 1); + UI_DrawLineBuffer(gFrameBuffer, 48, 0, 48, 55, 1); // Be ware, status zone = 8 lines, the rest = 56 ->total 64 + //UI_DrawLineDottedBuffer(gFrameBuffer, 0, 46, 50, 46, 1); - for (uint8_t i = 0; i < 48; i += 2) - { - gFrameBuffer[5][i] = 0x40; - } + for (uint8_t i = 0; i < 48; i += 2) + { + gFrameBuffer[5][i] = 0x40; + } #endif #ifndef ENABLE_CUSTOM_MENU_LAYOUT - // original menu layout - for (i = 0; i < 3; i++) - if (gMenuCursor > 0 || i > 0) - if ((gMenuListCount - 1) != gMenuCursor || i != 2) - UI_PrintString(MenuList[gMenuCursor + i - 1].name, 0, 0, i * 2, 8); + // original menu layout + for (i = 0; i < 3; i++) + if (gMenuCursor > 0 || i > 0) + if ((gMenuListCount - 1) != gMenuCursor || i != 2) + UI_PrintString(MenuList[gMenuCursor + i - 1].name, 0, 0, i * 2, 8); - // invert the current menu list item pixels - for (i = 0; i < (8 * menu_list_width); i++) - { - gFrameBuffer[2][i] ^= 0xFF; - gFrameBuffer[3][i] ^= 0xFF; - } + // invert the current menu list item pixels + for (i = 0; i < (8 * menu_list_width); i++) + { + gFrameBuffer[2][i] ^= 0xFF; + gFrameBuffer[3][i] ^= 0xFF; + } - // draw vertical separating dotted line - for (i = 0; i < 7; i++) - gFrameBuffer[i][(8 * menu_list_width) + 1] = 0xAA; + // draw vertical separating dotted line + for (i = 0; i < 7; i++) + gFrameBuffer[i][(8 * menu_list_width) + 1] = 0xAA; - // draw the little sub-menu triangle marker - if (gIsInSubMenu) - memcpy(gFrameBuffer[0] + (8 * menu_list_width) + 1, BITMAP_CurrentIndicator, sizeof(BITMAP_CurrentIndicator)); + // draw the little sub-menu triangle marker + if (gIsInSubMenu) + memcpy(gFrameBuffer[0] + (8 * menu_list_width) + 1, BITMAP_CurrentIndicator, sizeof(BITMAP_CurrentIndicator)); - // draw the menu index number/count - sprintf(String, "%2u.%u", 1 + gMenuCursor, gMenuListCount); + // draw the menu index number/count + sprintf(String, "%2u.%u", 1 + gMenuCursor, gMenuListCount); - UI_PrintStringSmallNormal(String, 2, 0, 6); + UI_PrintStringSmallNormal(String, 2, 0, 6); #else - { // new menu layout .. experimental & unfinished - const int menu_index = gMenuCursor; // current selected menu item - i = 1; - - if (!gIsInSubMenu) { - while (i < 2) - { // leading menu items - small text - const int k = menu_index + i - 2; - if (k < 0) - UI_PrintStringSmallNormal(MenuList[gMenuListCount + k].name, 0, 0, i); // wrap-a-round - else if (k >= 0 && k < (int)gMenuListCount) - UI_PrintStringSmallNormal(MenuList[k].name, 0, 0, i); - i++; - } - - // current menu item - keep big n fat - if (menu_index >= 0 && menu_index < (int)gMenuListCount) - UI_PrintString(MenuList[menu_index].name, 0, 0, 2, 8); - i++; - - while (i < 4) - { // trailing menu item - small text - const int k = menu_index + i - 2; - if (k >= 0 && k < (int)gMenuListCount) - UI_PrintStringSmallNormal(MenuList[k].name, 0, 0, 1 + i); - else if (k >= (int)gMenuListCount) - UI_PrintStringSmallNormal(MenuList[gMenuListCount - k].name, 0, 0, 1 + i); // wrap-a-round - i++; - } - - // draw the menu index number/count + { // new menu layout .. experimental & unfinished + const int menu_index = gMenuCursor; // current selected menu item + i = 1; + + if (!gIsInSubMenu) { + while (i < 2) + { // leading menu items - small text + const int k = menu_index + i - 2; + if (k < 0) + UI_PrintStringSmallNormal(MenuList[gMenuListCount + k].name, 0, 0, i); // wrap-a-round + else if (k >= 0 && k < (int)gMenuListCount) + UI_PrintStringSmallNormal(MenuList[k].name, 0, 0, i); + i++; + } + + // current menu item - keep big n fat + if (menu_index >= 0 && menu_index < (int)gMenuListCount) + UI_PrintString(MenuList[menu_index].name, 0, 0, 2, 8); + i++; + + while (i < 4) + { // trailing menu item - small text + const int k = menu_index + i - 2; + if (k >= 0 && k < (int)gMenuListCount) + UI_PrintStringSmallNormal(MenuList[k].name, 0, 0, 1 + i); + else if (k >= (int)gMenuListCount) + UI_PrintStringSmallNormal(MenuList[gMenuListCount - k].name, 0, 0, 1 + i); // wrap-a-round + i++; + } + + // draw the menu index number/count #ifndef ENABLE_FEAT_F4HWN - sprintf(String, "%2u.%u", 1 + gMenuCursor, gMenuListCount); - UI_PrintStringSmallNormal(String, 2, 0, 6); + sprintf(String, "%2u.%u", 1 + gMenuCursor, gMenuListCount); + UI_PrintStringSmallNormal(String, 2, 0, 6); #endif - } - else if (menu_index >= 0 && menu_index < (int)gMenuListCount) - { // current menu item -// strcat(String, ":"); - UI_PrintString(MenuList[menu_index].name, 0, 0, 0, 8); -// UI_PrintStringSmallNormal(String, 0, 0, 0); - } + } + else if (menu_index >= 0 && menu_index < (int)gMenuListCount) + { // current menu item +// strcat(String, ":"); + UI_PrintString(MenuList[menu_index].name, 0, 0, 0, 8); +// UI_PrintStringSmallNormal(String, 0, 0, 0); + } #ifdef ENABLE_FEAT_F4HWN - sprintf(String, "%02u/%u", 1 + gMenuCursor, gMenuListCount); - UI_PrintStringSmallNormal(String, 6, 0, 6); + sprintf(String, "%02u/%u", 1 + gMenuCursor, gMenuListCount); + UI_PrintStringSmallNormal(String, 6, 0, 6); #endif - } + } #endif - // ************** - - memset(String, 0, sizeof(String)); - - bool already_printed = false; - - /* Brightness is set to max in some entries of this menu. Return it to the configured brightness - level the "next" time we enter here.I.e., when we move from one menu to another. - It also has to be set back to max when pressing the Exit key. */ - - BACKLIGHT_TurnOn(); - - switch (UI_MENU_GetCurrentMenuId()) - { - case MENU_SQL: - sprintf(String, "%d", gSubMenuSelection); - break; - - case MENU_MIC: - { // display the mic gain in actual dB rather than just an index number - const uint8_t mic = gMicGain_dB2[gSubMenuSelection]; - sprintf(String, "+%u.%01udB", mic / 2, mic % 2); - } - break; - - #ifdef ENABLE_AUDIO_BAR - case MENU_MIC_BAR: - strcpy(String, gSubMenu_OFF_ON[gSubMenuSelection]); - break; - #endif - - case MENU_STEP: { - uint16_t step = gStepFrequencyTable[FREQUENCY_GetStepIdxFromSortedIdx(gSubMenuSelection)]; - sprintf(String, "%d.%02ukHz", step / 100, step % 100); - break; - } - - case MENU_TXP: - if(gSubMenuSelection == 0) - { - strcpy(String, gSubMenu_TXP[gSubMenuSelection]); - } - else - { - sprintf(String, "%s\n%sW", gSubMenu_TXP[gSubMenuSelection], gSubMenu_SET_PWR[gSubMenuSelection - 1]); - } - break; - - case MENU_R_DCS: - case MENU_T_DCS: - if (gSubMenuSelection == 0) - strcpy(String, "OFF"); - else if (gSubMenuSelection < 105) - sprintf(String, "D%03oN", DCS_Options[gSubMenuSelection - 1]); - else - sprintf(String, "D%03oI", DCS_Options[gSubMenuSelection - 105]); - break; - - case MENU_R_CTCS: - case MENU_T_CTCS: - { - if (gSubMenuSelection == 0) - strcpy(String, "OFF"); - else - sprintf(String, "%u.%uHz", CTCSS_Options[gSubMenuSelection - 1] / 10, CTCSS_Options[gSubMenuSelection - 1] % 10); - break; - } - - case MENU_SFT_D: - strcpy(String, gSubMenu_SFT_D[gSubMenuSelection]); - break; - - case MENU_OFFSET: - if (!gIsInSubMenu || gInputBoxIndex == 0) - { - sprintf(String, "%3d.%05u", gSubMenuSelection / 100000, abs(gSubMenuSelection) % 100000); - UI_PrintString(String, menu_item_x1, menu_item_x2, 1, 8); - } - else - { - const char * ascii = INPUTBOX_GetAscii(); - sprintf(String, "%.3s.%.3s ",ascii, ascii + 3); - UI_PrintString(String, menu_item_x1, menu_item_x2, 1, 8); - } - - UI_PrintString("MHz", menu_item_x1, menu_item_x2, 3, 8); - - already_printed = true; - break; - - case MENU_W_N: - strcpy(String, gSubMenu_W_N[gSubMenuSelection]); - break; + // ************** + + memset(String, 0, sizeof(String)); + + bool already_printed = false; + + /* Brightness is set to max in some entries of this menu. Return it to the configured brightness + level the "next" time we enter here.I.e., when we move from one menu to another. + It also has to be set back to max when pressing the Exit key. */ + + BACKLIGHT_TurnOn(); + + switch (UI_MENU_GetCurrentMenuId()) + { + case MENU_SQL: + sprintf(String, "%d", gSubMenuSelection); + break; + + case MENU_MIC: + { // display the mic gain in actual dB rather than just an index number + const uint8_t mic = gMicGain_dB2[gSubMenuSelection]; + sprintf(String, "+%u.%01udB", mic / 2, mic % 2); + } + break; + + #ifdef ENABLE_AUDIO_BAR + case MENU_MIC_BAR: + strcpy(String, gSubMenu_OFF_ON[gSubMenuSelection]); + break; + #endif + + case MENU_STEP: { + uint16_t step = gStepFrequencyTable[FREQUENCY_GetStepIdxFromSortedIdx(gSubMenuSelection)]; + sprintf(String, "%d.%02ukHz", step / 100, step % 100); + break; + } + + case MENU_TXP: + if(gSubMenuSelection == 0) + { + strcpy(String, gSubMenu_TXP[gSubMenuSelection]); + } + else + { + sprintf(String, "%s\n%sW", gSubMenu_TXP[gSubMenuSelection], gSubMenu_SET_PWR[gSubMenuSelection - 1]); + } + break; + + case MENU_R_DCS: + case MENU_T_DCS: + if (gSubMenuSelection == 0) + strcpy(String, "OFF"); + else if (gSubMenuSelection < 105) + sprintf(String, "D%03oN", DCS_Options[gSubMenuSelection - 1]); + else + sprintf(String, "D%03oI", DCS_Options[gSubMenuSelection - 105]); + break; + + case MENU_R_CTCS: + case MENU_T_CTCS: + { + if (gSubMenuSelection == 0) + strcpy(String, "OFF"); + else + sprintf(String, "%u.%uHz", CTCSS_Options[gSubMenuSelection - 1] / 10, CTCSS_Options[gSubMenuSelection - 1] % 10); + break; + } + + case MENU_SFT_D: + strcpy(String, gSubMenu_SFT_D[gSubMenuSelection]); + break; + + case MENU_OFFSET: + if (!gIsInSubMenu || gInputBoxIndex == 0) + { + sprintf(String, "%3d.%05u", gSubMenuSelection / 100000, abs(gSubMenuSelection) % 100000); + UI_PrintString(String, menu_item_x1, menu_item_x2, 1, 8); + } + else + { + const char * ascii = INPUTBOX_GetAscii(); + sprintf(String, "%.3s.%.3s ",ascii, ascii + 3); + UI_PrintString(String, menu_item_x1, menu_item_x2, 1, 8); + } + + UI_PrintString("MHz", menu_item_x1, menu_item_x2, 3, 8); + + already_printed = true; + break; + + case MENU_W_N: + strcpy(String, gSubMenu_W_N[gSubMenuSelection]); + break; #ifndef ENABLE_FEAT_F4HWN - case MENU_SCR: - strcpy(String, gSubMenu_SCRAMBLER[gSubMenuSelection]); - #if 1 - if (gSubMenuSelection > 0 && gSetting_ScrambleEnable) - BK4819_EnableScramble(gSubMenuSelection - 1); - else - BK4819_DisableScramble(); - #endif - break; + case MENU_SCR: + strcpy(String, gSubMenu_SCRAMBLER[gSubMenuSelection]); + #if 1 + if (gSubMenuSelection > 0 && gSetting_ScrambleEnable) + BK4819_EnableScramble(gSubMenuSelection - 1); + else + BK4819_DisableScramble(); + #endif + break; #endif - #ifdef ENABLE_VOX - case MENU_VOX: - if (gSubMenuSelection == 0) - strcpy(String, "OFF"); - else - sprintf(String, "%d", gSubMenuSelection); - break; - #endif - - case MENU_ABR: - if(gSubMenuSelection == 0) - { - sprintf(String, "%s", "OFF"); - } - else if(gSubMenuSelection < 61) - { - sprintf(String, "%02dm:%02ds", (((gSubMenuSelection) * 5) / 60), (((gSubMenuSelection) * 5) % 60)); - } - else - { - sprintf(String, "%s", "ON"); - } - - if(BACKLIGHT_GetBrightness() < 4) - BACKLIGHT_SetBrightness(4); - break; - - case MENU_ABR_MIN: - case MENU_ABR_MAX: - sprintf(String, "%d", gSubMenuSelection); - if(gIsInSubMenu) - BACKLIGHT_SetBrightness(gSubMenuSelection); - else if(BACKLIGHT_GetBrightness() < 4) - BACKLIGHT_SetBrightness(4); - break; - - case MENU_AM: - strcpy(String, gModulationStr[gSubMenuSelection]); - break; - - case MENU_AUTOLK: - strcpy(String, (gSubMenuSelection == 0) ? "OFF" : "AUTO"); - break; - - case MENU_COMPAND: - case MENU_ABR_ON_TX_RX: - strcpy(String, gSubMenu_RX_TX[gSubMenuSelection]); - break; - - #ifndef ENABLE_FEAT_F4HWN - #ifdef ENABLE_AM_FIX - case MENU_AM_FIX: - #endif - #endif - case MENU_BCL: - case MENU_BEEP: - case MENU_S_ADD1: - case MENU_S_ADD2: - case MENU_S_ADD3: - case MENU_STE: - case MENU_D_ST: + #ifdef ENABLE_VOX + case MENU_VOX: + if (gSubMenuSelection == 0) + strcpy(String, "OFF"); + else + sprintf(String, "%d", gSubMenuSelection); + break; + #endif + + case MENU_ABR: + if(gSubMenuSelection == 0) + { + sprintf(String, "%s", "OFF"); + } + else if(gSubMenuSelection < 61) + { + sprintf(String, "%02dm:%02ds", (((gSubMenuSelection) * 5) / 60), (((gSubMenuSelection) * 5) % 60)); + } + else + { + sprintf(String, "%s", "ON"); + } + + if(BACKLIGHT_GetBrightness() < 4) + BACKLIGHT_SetBrightness(4); + break; + + case MENU_ABR_MIN: + case MENU_ABR_MAX: + sprintf(String, "%d", gSubMenuSelection); + if(gIsInSubMenu) + BACKLIGHT_SetBrightness(gSubMenuSelection); + else if(BACKLIGHT_GetBrightness() < 4) + BACKLIGHT_SetBrightness(4); + break; + + case MENU_AM: + strcpy(String, gModulationStr[gSubMenuSelection]); + break; + + case MENU_AUTOLK: + strcpy(String, (gSubMenuSelection == 0) ? "OFF" : "AUTO"); + break; + + case MENU_COMPAND: + case MENU_ABR_ON_TX_RX: + strcpy(String, gSubMenu_RX_TX[gSubMenuSelection]); + break; + + #ifndef ENABLE_FEAT_F4HWN + #ifdef ENABLE_AM_FIX + case MENU_AM_FIX: + #endif + #endif + case MENU_BCL: + case MENU_BEEP: + case MENU_S_ADD1: + case MENU_S_ADD2: + case MENU_S_ADD3: + case MENU_STE: + case MENU_D_ST: #ifdef ENABLE_DTMF_CALLING - case MENU_D_DCD: + case MENU_D_DCD: #endif - case MENU_D_LIVE_DEC: - #ifdef ENABLE_NOAA - case MENU_NOAA_S: - #endif - case MENU_350TX: - case MENU_200TX: - case MENU_500TX: - case MENU_350EN: + case MENU_D_LIVE_DEC: + #ifdef ENABLE_NOAA + case MENU_NOAA_S: + #endif + case MENU_350TX: + case MENU_200TX: + case MENU_500TX: + case MENU_350EN: #ifndef ENABLE_FEAT_F4HWN - case MENU_SCREN: + case MENU_SCREN: #endif #ifdef ENABLE_FEAT_F4HWN - case MENU_SET_TMR: + case MENU_SET_TMR: #endif - strcpy(String, gSubMenu_OFF_ON[gSubMenuSelection]); - break; - - case MENU_MEM_CH: - case MENU_1_CALL: - case MENU_DEL_CH: - { - const bool valid = RADIO_CheckValidChannel(gSubMenuSelection, false, 0); - - UI_GenerateChannelStringEx(String, valid, gSubMenuSelection); - UI_PrintString(String, menu_item_x1, menu_item_x2, 0, 8); - - if (valid && !gAskForConfirmation) - { // show the frequency so that the user knows the channels frequency - const uint32_t frequency = SETTINGS_FetchChannelFrequency(gSubMenuSelection); - sprintf(String, "%u.%05u", frequency / 100000, frequency % 100000); - UI_PrintString(String, menu_item_x1, menu_item_x2, 4, 8); - } - - SETTINGS_FetchChannelName(String, gSubMenuSelection); - UI_PrintString(String[0] ? String : "--", menu_item_x1, menu_item_x2, 2, 8); - already_printed = true; - break; - } - - case MENU_MEM_NAME: - { - const bool valid = RADIO_CheckValidChannel(gSubMenuSelection, false, 0); - - UI_GenerateChannelStringEx(String, valid, gSubMenuSelection); - UI_PrintString(String, menu_item_x1, menu_item_x2, 0, 8); - - if (valid) - { - const uint32_t frequency = SETTINGS_FetchChannelFrequency(gSubMenuSelection); - - //if (!gIsInSubMenu || edit_index < 0) - if (!gIsInSubMenu) - edit_index = -1; - if (edit_index < 0) - { // show the channel name - SETTINGS_FetchChannelName(String, gSubMenuSelection); - char *pPrintStr = String[0] ? String : "--"; - UI_PrintString(pPrintStr, menu_item_x1, menu_item_x2, 2, 8); - } - else - { // show the channel name being edited - //UI_PrintString(edit, menu_item_x1, 0, 2, 8); - UI_PrintString(edit, menu_item_x1, menu_item_x2, 2, 8); - if (edit_index < 10) - //UI_PrintString("^", menu_item_x1 + (8 * edit_index), 0, 4, 8); // show the cursor - UI_PrintString("^", menu_item_x1 - 1 + (8 * edit_index),0, 4, 8); // show the cursor - } - - if (!gAskForConfirmation) - { // show the frequency so that the user knows the channels frequency - sprintf(String, "%u.%05u", frequency / 100000, frequency % 100000); - UI_PrintString(String, menu_item_x1, menu_item_x2, 4 + (gIsInSubMenu && edit_index >= 0), 8); - } - } - - already_printed = true; - break; - } - - case MENU_SAVE: - strcpy(String, gSubMenu_SAVE[gSubMenuSelection]); - break; - - case MENU_TDR: - strcpy(String, gSubMenu_RXMode[gSubMenuSelection]); - break; - - case MENU_TOT: - sprintf(String, "%02dm:%02ds", (((gSubMenuSelection + 1) * 5) / 60), (((gSubMenuSelection + 1) * 5) % 60)); - break; - - #ifdef ENABLE_VOICE - case MENU_VOICE: - strcpy(String, gSubMenu_VOICE[gSubMenuSelection]); - break; - #endif - - case MENU_SC_REV: - strcpy(String, gSubMenu_SC_REV[gSubMenuSelection]); - break; - - case MENU_MDF: - strcpy(String, gSubMenu_MDF[gSubMenuSelection]); - break; - - case MENU_RP_STE: - if (gSubMenuSelection == 0) - strcpy(String, "OFF"); - else - sprintf(String, "%d*100ms", gSubMenuSelection); - break; - - case MENU_S_LIST: - if (gSubMenuSelection == 0) - strcpy(String, "LIST [0]\nNO LIST"); - else if (gSubMenuSelection < 4) - sprintf(String, "LIST [%u]", gSubMenuSelection); - else if (gSubMenuSelection == 4) - strcpy(String, "LISTS\n[1, 2, 3]"); - else if (gSubMenuSelection == 5) - strcpy(String, "ALL"); - break; - - #ifdef ENABLE_ALARM - case MENU_AL_MOD: - sprintf(String, gSubMenu_AL_MOD[gSubMenuSelection]); - break; - #endif + strcpy(String, gSubMenu_OFF_ON[gSubMenuSelection]); + break; + + case MENU_MEM_CH: + case MENU_1_CALL: + case MENU_DEL_CH: + { + const bool valid = RADIO_CheckValidChannel(gSubMenuSelection, false, 0); + + UI_GenerateChannelStringEx(String, valid, gSubMenuSelection); + UI_PrintString(String, menu_item_x1, menu_item_x2, 0, 8); + + if (valid && !gAskForConfirmation) + { // show the frequency so that the user knows the channels frequency + const uint32_t frequency = SETTINGS_FetchChannelFrequency(gSubMenuSelection); + sprintf(String, "%u.%05u", frequency / 100000, frequency % 100000); + UI_PrintString(String, menu_item_x1, menu_item_x2, 4, 8); + } + + SETTINGS_FetchChannelName(String, gSubMenuSelection); + UI_PrintString(String[0] ? String : "--", menu_item_x1, menu_item_x2, 2, 8); + already_printed = true; + break; + } + + case MENU_MEM_NAME: + { + const bool valid = RADIO_CheckValidChannel(gSubMenuSelection, false, 0); + + UI_GenerateChannelStringEx(String, valid, gSubMenuSelection); + UI_PrintString(String, menu_item_x1, menu_item_x2, 0, 8); + + if (valid) + { + const uint32_t frequency = SETTINGS_FetchChannelFrequency(gSubMenuSelection); + + //if (!gIsInSubMenu || edit_index < 0) + if (!gIsInSubMenu) + edit_index = -1; + if (edit_index < 0) + { // show the channel name + SETTINGS_FetchChannelName(String, gSubMenuSelection); + char *pPrintStr = String[0] ? String : "--"; + UI_PrintString(pPrintStr, menu_item_x1, menu_item_x2, 2, 8); + } + else + { // show the channel name being edited + //UI_PrintString(edit, menu_item_x1, 0, 2, 8); + UI_PrintString(edit, menu_item_x1, menu_item_x2, 2, 8); + if (edit_index < 10) + //UI_PrintString("^", menu_item_x1 + (8 * edit_index), 0, 4, 8); // show the cursor + UI_PrintString("^", menu_item_x1 - 1 + (8 * edit_index),0, 4, 8); // show the cursor + } + + if (!gAskForConfirmation) + { // show the frequency so that the user knows the channels frequency + sprintf(String, "%u.%05u", frequency / 100000, frequency % 100000); + UI_PrintString(String, menu_item_x1, menu_item_x2, 4 + (gIsInSubMenu && edit_index >= 0), 8); + } + } + + already_printed = true; + break; + } + + case MENU_SAVE: + strcpy(String, gSubMenu_SAVE[gSubMenuSelection]); + break; + + case MENU_TDR: + strcpy(String, gSubMenu_RXMode[gSubMenuSelection]); + break; + + case MENU_TOT: + sprintf(String, "%02dm:%02ds", (((gSubMenuSelection + 1) * 5) / 60), (((gSubMenuSelection + 1) * 5) % 60)); + break; + + #ifdef ENABLE_VOICE + case MENU_VOICE: + strcpy(String, gSubMenu_VOICE[gSubMenuSelection]); + break; + #endif + + case MENU_SC_REV: + strcpy(String, gSubMenu_SC_REV[gSubMenuSelection]); + break; + + case MENU_MDF: + strcpy(String, gSubMenu_MDF[gSubMenuSelection]); + break; + + case MENU_RP_STE: + if (gSubMenuSelection == 0) + strcpy(String, "OFF"); + else + sprintf(String, "%d*100ms", gSubMenuSelection); + break; + + case MENU_S_LIST: + if (gSubMenuSelection == 0) + strcpy(String, "LIST [0]\nNO LIST"); + else if (gSubMenuSelection < 4) + sprintf(String, "LIST [%u]", gSubMenuSelection); + else if (gSubMenuSelection == 4) + strcpy(String, "LISTS\n[1, 2, 3]"); + else if (gSubMenuSelection == 5) + strcpy(String, "ALL"); + break; + + #ifdef ENABLE_ALARM + case MENU_AL_MOD: + sprintf(String, gSubMenu_AL_MOD[gSubMenuSelection]); + break; + #endif #ifdef ENABLE_DTMF_CALLING - case MENU_ANI_ID: - strcpy(String, gEeprom.ANI_DTMF_ID); - break; + case MENU_ANI_ID: + strcpy(String, gEeprom.ANI_DTMF_ID); + break; #endif - case MENU_UPCODE: - sprintf(String, "%.8s\n%.8s", gEeprom.DTMF_UP_CODE, gEeprom.DTMF_UP_CODE + 8); - break; + case MENU_UPCODE: + sprintf(String, "%.8s\n%.8s", gEeprom.DTMF_UP_CODE, gEeprom.DTMF_UP_CODE + 8); + break; - case MENU_DWCODE: - sprintf(String, "%.8s\n%.8s", gEeprom.DTMF_DOWN_CODE, gEeprom.DTMF_DOWN_CODE + 8); - break; + case MENU_DWCODE: + sprintf(String, "%.8s\n%.8s", gEeprom.DTMF_DOWN_CODE, gEeprom.DTMF_DOWN_CODE + 8); + break; #ifdef ENABLE_DTMF_CALLING - case MENU_D_RSP: - strcpy(String, gSubMenu_D_RSP[gSubMenuSelection]); - break; + case MENU_D_RSP: + strcpy(String, gSubMenu_D_RSP[gSubMenuSelection]); + break; - case MENU_D_HOLD: - sprintf(String, "%ds", gSubMenuSelection); - break; + case MENU_D_HOLD: + sprintf(String, "%ds", gSubMenuSelection); + break; #endif - case MENU_D_PRE: - sprintf(String, "%d*10ms", gSubMenuSelection); - break; + case MENU_D_PRE: + sprintf(String, "%d*10ms", gSubMenuSelection); + break; - case MENU_PTT_ID: - strcpy(String, gSubMenu_PTT_ID[gSubMenuSelection]); - break; + case MENU_PTT_ID: + strcpy(String, gSubMenu_PTT_ID[gSubMenuSelection]); + break; - case MENU_BAT_TXT: - strcpy(String, gSubMenu_BAT_TXT[gSubMenuSelection]); - break; + case MENU_BAT_TXT: + strcpy(String, gSubMenu_BAT_TXT[gSubMenuSelection]); + break; #ifdef ENABLE_DTMF_CALLING - case MENU_D_LIST: - gIsDtmfContactValid = DTMF_GetContact((int)gSubMenuSelection - 1, Contact); - if (!gIsDtmfContactValid) - strcpy(String, "NULL"); - else - memcpy(String, Contact, 8); - break; + case MENU_D_LIST: + gIsDtmfContactValid = DTMF_GetContact((int)gSubMenuSelection - 1, Contact); + if (!gIsDtmfContactValid) + strcpy(String, "NULL"); + else + memcpy(String, Contact, 8); + break; #endif - case MENU_PONMSG: - strcpy(String, gSubMenu_PONMSG[gSubMenuSelection]); - break; + case MENU_PONMSG: + strcpy(String, gSubMenu_PONMSG[gSubMenuSelection]); + break; - case MENU_ROGER: - strcpy(String, gSubMenu_ROGER[gSubMenuSelection]); - break; + case MENU_ROGER: + strcpy(String, gSubMenu_ROGER[gSubMenuSelection]); + break; - case MENU_VOL: + case MENU_VOL: #ifdef ENABLE_FEAT_F4HWN - sprintf(String, "%s\n%s", - AUTHOR_STRING_2, - VERSION_STRING_2 - ); + sprintf(String, "%s\n%s", + AUTHOR_STRING_2, + VERSION_STRING_2 + ); #else - sprintf(String, "%u.%02uV\n%u%%", - gBatteryVoltageAverage / 100, gBatteryVoltageAverage % 100, - BATTERY_VoltsToPercent(gBatteryVoltageAverage)); + sprintf(String, "%u.%02uV\n%u%%", + gBatteryVoltageAverage / 100, gBatteryVoltageAverage % 100, + BATTERY_VoltsToPercent(gBatteryVoltageAverage)); #endif - break; + break; - case MENU_RESET: - strcpy(String, gSubMenu_RESET[gSubMenuSelection]); - break; + case MENU_RESET: + strcpy(String, gSubMenu_RESET[gSubMenuSelection]); + break; - case MENU_F_LOCK: + case MENU_F_LOCK: #ifdef ENABLE_FEAT_F4HWN - if(!gIsInSubMenu && gUnlockAllTxConfCnt>0 && gUnlockAllTxConfCnt<3) + if(!gIsInSubMenu && gUnlockAllTxConfCnt>0 && gUnlockAllTxConfCnt<3) #else - if(!gIsInSubMenu && gUnlockAllTxConfCnt>0 && gUnlockAllTxConfCnt<10) + if(!gIsInSubMenu && gUnlockAllTxConfCnt>0 && gUnlockAllTxConfCnt<10) #endif - strcpy(String, "READ\nMANUAL"); - else - strcpy(String, gSubMenu_F_LOCK[gSubMenuSelection]); - break; - - #ifdef ENABLE_F_CAL_MENU - case MENU_F_CALI: - { - const uint32_t value = 22656 + gSubMenuSelection; - const uint32_t xtal_Hz = (0x4f0000u + value) * 5; - - writeXtalFreqCal(gSubMenuSelection, false); - - sprintf(String, "%d\n%u.%06u\nMHz", - gSubMenuSelection, - xtal_Hz / 1000000, xtal_Hz % 1000000); - } - break; - #endif - - case MENU_BATCAL: - { - const uint16_t vol = (uint32_t)gBatteryVoltageAverage * gBatteryCalibration[3] / gSubMenuSelection; - sprintf(String, "%u.%02uV\n%u", vol / 100, vol % 100, gSubMenuSelection); - break; - } - - case MENU_BATTYP: - strcpy(String, gSubMenu_BATTYP[gSubMenuSelection]); - break; - - case MENU_F1SHRT: - case MENU_F1LONG: - case MENU_F2SHRT: - case MENU_F2LONG: - case MENU_MLONG: - strcpy(String, gSubMenu_SIDEFUNCTIONS[gSubMenuSelection].name); - break; + strcpy(String, "READ\nMANUAL"); + else + strcpy(String, gSubMenu_F_LOCK[gSubMenuSelection]); + break; + + #ifdef ENABLE_F_CAL_MENU + case MENU_F_CALI: + { + const uint32_t value = 22656 + gSubMenuSelection; + const uint32_t xtal_Hz = (0x4f0000u + value) * 5; + + writeXtalFreqCal(gSubMenuSelection, false); + + sprintf(String, "%d\n%u.%06u\nMHz", + gSubMenuSelection, + xtal_Hz / 1000000, xtal_Hz % 1000000); + } + break; + #endif + + case MENU_BATCAL: + { + const uint16_t vol = (uint32_t)gBatteryVoltageAverage * gBatteryCalibration[3] / gSubMenuSelection; + sprintf(String, "%u.%02uV\n%u", vol / 100, vol % 100, gSubMenuSelection); + break; + } + + case MENU_BATTYP: + strcpy(String, gSubMenu_BATTYP[gSubMenuSelection]); + break; + + case MENU_F1SHRT: + case MENU_F1LONG: + case MENU_F2SHRT: + case MENU_F2LONG: + case MENU_MLONG: + strcpy(String, gSubMenu_SIDEFUNCTIONS[gSubMenuSelection].name); + break; #ifdef ENABLE_FEAT_F4HWN - case MENU_SET_PWR: - sprintf(String, "%s\n%sW", gSubMenu_TXP[gSubMenuSelection + 1], gSubMenu_SET_PWR[gSubMenuSelection]); - break; - - case MENU_SET_PTT: - strcpy(String, gSubMenu_SET_PTT[gSubMenuSelection]); - break; - - case MENU_SET_TOT: - case MENU_SET_EOT: - strcpy(String, gSubMenu_SET_TOT[gSubMenuSelection]); // Same as SET_TOT - break; - - case MENU_SET_CTR: - sprintf(String, "%d", gSubMenuSelection); - gSetting_set_ctr = gSubMenuSelection; - ST7565_ContrastAndInv(); - break; - - case MENU_SET_INV: - strcpy(String, gSubMenu_OFF_ON[gSubMenuSelection]); - ST7565_ContrastAndInv(); - break; - - case MENU_TX_LOCK: - if(TX_freq_check(gEeprom.VfoInfo[gEeprom.TX_VFO].pRX->Frequency) == 0) - { - strcpy(String, "Inside\nF Lock\nPlan"); - } - else - { - strcpy(String, gSubMenu_OFF_ON[gSubMenuSelection]); - } - break; - - case MENU_SET_LCK: - strcpy(String, gSubMenu_SET_LCK[gSubMenuSelection]); - break; - - case MENU_SET_MET: - case MENU_SET_GUI: - strcpy(String, gSubMenu_SET_MET[gSubMenuSelection]); // Same as SET_MET - break; + case MENU_SET_PWR: + sprintf(String, "%s\n%sW", gSubMenu_TXP[gSubMenuSelection + 1], gSubMenu_SET_PWR[gSubMenuSelection]); + break; + + case MENU_SET_PTT: + strcpy(String, gSubMenu_SET_PTT[gSubMenuSelection]); + break; + + case MENU_SET_TOT: + case MENU_SET_EOT: + strcpy(String, gSubMenu_SET_TOT[gSubMenuSelection]); // Same as SET_TOT + break; + + case MENU_SET_CTR: + sprintf(String, "%d", gSubMenuSelection); + gSetting_set_ctr = gSubMenuSelection; + ST7565_ContrastAndInv(); + break; + + case MENU_SET_INV: + strcpy(String, gSubMenu_OFF_ON[gSubMenuSelection]); + ST7565_ContrastAndInv(); + break; + + case MENU_TX_LOCK: + if(TX_freq_check(gEeprom.VfoInfo[gEeprom.TX_VFO].pRX->Frequency) == 0) + { + strcpy(String, "Inside\nF Lock\nPlan"); + } + else + { + strcpy(String, gSubMenu_OFF_ON[gSubMenuSelection]); + } + break; + + case MENU_SET_LCK: + strcpy(String, gSubMenu_SET_LCK[gSubMenuSelection]); + break; + + case MENU_SET_MET: + case MENU_SET_GUI: + strcpy(String, gSubMenu_SET_MET[gSubMenuSelection]); // Same as SET_MET + break; #endif - } - - if (!already_printed) - { // we now do multi-line text in a single string - - unsigned int y; - unsigned int lines = 1; - unsigned int len = strlen(String); - bool small = false; - - if (len > 0) - { - // count number of lines - for (i = 0; i < len; i++) - { - if (String[i] == '\n' && i < (len - 1)) - { // found new line char - lines++; - String[i] = 0; // null terminate the line - } - } - - if (lines > 3) - { // use small text - small = true; - if (lines > 7) - lines = 7; - } - - // center vertically'ish - if (small) - y = 3 - ((lines + 0) / 2); // untested - else - y = 2 - ((lines + 0) / 2); - - // only for SysInf - if(UI_MENU_GetCurrentMenuId() == MENU_VOL) - { - sprintf(edit, "%u.%02uV %u%%", - gBatteryVoltageAverage / 100, gBatteryVoltageAverage % 100, - BATTERY_VoltsToPercent(gBatteryVoltageAverage) - ); - - UI_PrintStringSmallNormal(edit, 54, 127, 1); - - #ifdef ENABLE_SPECTRUM - #ifndef ENABLE_FMRADIO - UI_PrintStringSmallNormal("Bandscope", 54, 127, 6); - #endif - #else - UI_PrintStringSmallNormal("Broadcast", 54, 127, 6); - #endif - - y = 2; - } - - // draw the text lines - for (i = 0; i < len && lines > 0; lines--) - { - if (small) - UI_PrintStringSmallNormal(String + i, menu_item_x1, menu_item_x2, y); - else - UI_PrintString(String + i, menu_item_x1, menu_item_x2, y, 8); - - // look for start of next line - while (i < len && String[i] >= 32) - i++; - - // hop over the null term char(s) - while (i < len && String[i] < 32) - i++; - - y += small ? 1 : 2; - } - } - } - - if (UI_MENU_GetCurrentMenuId() == MENU_SLIST1 || UI_MENU_GetCurrentMenuId() == MENU_SLIST2 || UI_MENU_GetCurrentMenuId() == MENU_SLIST3) - { - i = UI_MENU_GetCurrentMenuId() - MENU_SLIST1; - - char *pPrintStr = String; - - if (gSubMenuSelection < 0) { - pPrintStr = "NULL"; - } else { - UI_GenerateChannelStringEx(String, true, gSubMenuSelection); - pPrintStr = String; - } - - // channel number - UI_PrintString(pPrintStr, menu_item_x1, menu_item_x2, 0, 8); - - SETTINGS_FetchChannelName(String, gSubMenuSelection); - pPrintStr = String[0] ? String : "--"; - - // channel name and scan-list - if (gSubMenuSelection < 0 || !gEeprom.SCAN_LIST_ENABLED[i]) { - UI_PrintString(pPrintStr, menu_item_x1, menu_item_x2, 2, 8); - } else { - UI_PrintStringSmallNormal(pPrintStr, menu_item_x1, menu_item_x2, 2); - - if (IS_MR_CHANNEL(gEeprom.SCANLIST_PRIORITY_CH1[i])) { - sprintf(String, "PRI%d:%u", 1, gEeprom.SCANLIST_PRIORITY_CH1[i] + 1); - UI_PrintString(String, menu_item_x1, menu_item_x2, 3, 8); - } - - if (IS_MR_CHANNEL(gEeprom.SCANLIST_PRIORITY_CH2[i])) { - sprintf(String, "PRI%d:%u", 2, gEeprom.SCANLIST_PRIORITY_CH2[i] + 1); - UI_PrintString(String, menu_item_x1, menu_item_x2, 5, 8); - } - } - } - - if ((UI_MENU_GetCurrentMenuId() == MENU_R_CTCS || UI_MENU_GetCurrentMenuId() == MENU_R_DCS) && gCssBackgroundScan) - UI_PrintString("SCAN", menu_item_x1, menu_item_x2, 4, 8); + } + + if (!already_printed) + { // we now do multi-line text in a single string + + unsigned int y; + unsigned int lines = 1; + unsigned int len = strlen(String); + bool small = false; + + if (len > 0) + { + // count number of lines + for (i = 0; i < len; i++) + { + if (String[i] == '\n' && i < (len - 1)) + { // found new line char + lines++; + String[i] = 0; // null terminate the line + } + } + + if (lines > 3) + { // use small text + small = true; + if (lines > 7) + lines = 7; + } + + // center vertically'ish + if (small) + y = 3 - ((lines + 0) / 2); // untested + else + y = 2 - ((lines + 0) / 2); + + // only for SysInf + if(UI_MENU_GetCurrentMenuId() == MENU_VOL) + { + sprintf(edit, "%u.%02uV %u%%", + gBatteryVoltageAverage / 100, gBatteryVoltageAverage % 100, + BATTERY_VoltsToPercent(gBatteryVoltageAverage) + ); + + UI_PrintStringSmallNormal(edit, 54, 127, 1); + + #ifdef ENABLE_SPECTRUM + #ifndef ENABLE_FMRADIO + UI_PrintStringSmallNormal("Bandscope", 54, 127, 6); + #endif + #else + UI_PrintStringSmallNormal("Broadcast", 54, 127, 6); + #endif + + y = 2; + } + + // draw the text lines + for (i = 0; i < len && lines > 0; lines--) + { + if (small) + UI_PrintStringSmallNormal(String + i, menu_item_x1, menu_item_x2, y); + else + UI_PrintString(String + i, menu_item_x1, menu_item_x2, y, 8); + + // look for start of next line + while (i < len && String[i] >= 32) + i++; + + // hop over the null term char(s) + while (i < len && String[i] < 32) + i++; + + y += small ? 1 : 2; + } + } + } + + if (UI_MENU_GetCurrentMenuId() == MENU_SLIST1 || UI_MENU_GetCurrentMenuId() == MENU_SLIST2 || UI_MENU_GetCurrentMenuId() == MENU_SLIST3) + { + i = UI_MENU_GetCurrentMenuId() - MENU_SLIST1; + + char *pPrintStr = String; + + if (gSubMenuSelection < 0) { + pPrintStr = "NULL"; + } else { + UI_GenerateChannelStringEx(String, true, gSubMenuSelection); + pPrintStr = String; + } + + // channel number + UI_PrintString(pPrintStr, menu_item_x1, menu_item_x2, 0, 8); + + SETTINGS_FetchChannelName(String, gSubMenuSelection); + pPrintStr = String[0] ? String : "--"; + + // channel name and scan-list + if (gSubMenuSelection < 0 || !gEeprom.SCAN_LIST_ENABLED[i]) { + UI_PrintString(pPrintStr, menu_item_x1, menu_item_x2, 2, 8); + } else { + UI_PrintStringSmallNormal(pPrintStr, menu_item_x1, menu_item_x2, 2); + + if (IS_MR_CHANNEL(gEeprom.SCANLIST_PRIORITY_CH1[i])) { + sprintf(String, "PRI%d:%u", 1, gEeprom.SCANLIST_PRIORITY_CH1[i] + 1); + UI_PrintString(String, menu_item_x1, menu_item_x2, 3, 8); + } + + if (IS_MR_CHANNEL(gEeprom.SCANLIST_PRIORITY_CH2[i])) { + sprintf(String, "PRI%d:%u", 2, gEeprom.SCANLIST_PRIORITY_CH2[i] + 1); + UI_PrintString(String, menu_item_x1, menu_item_x2, 5, 8); + } + } + } + + if ((UI_MENU_GetCurrentMenuId() == MENU_R_CTCS || UI_MENU_GetCurrentMenuId() == MENU_R_DCS) && gCssBackgroundScan) + UI_PrintString("SCAN", menu_item_x1, menu_item_x2, 4, 8); #ifdef ENABLE_DTMF_CALLING - if (UI_MENU_GetCurrentMenuId() == MENU_D_LIST && gIsDtmfContactValid) { - Contact[11] = 0; - memcpy(&gDTMF_ID, Contact + 8, 4); - sprintf(String, "ID:%4s", gDTMF_ID); - UI_PrintString(String, menu_item_x1, menu_item_x2, 4, 8); - } + if (UI_MENU_GetCurrentMenuId() == MENU_D_LIST && gIsDtmfContactValid) { + Contact[11] = 0; + memcpy(&gDTMF_ID, Contact + 8, 4); + sprintf(String, "ID:%4s", gDTMF_ID); + UI_PrintString(String, menu_item_x1, menu_item_x2, 4, 8); + } #endif - if (UI_MENU_GetCurrentMenuId() == MENU_R_CTCS || - UI_MENU_GetCurrentMenuId() == MENU_T_CTCS || - UI_MENU_GetCurrentMenuId() == MENU_R_DCS || - UI_MENU_GetCurrentMenuId() == MENU_T_DCS + if (UI_MENU_GetCurrentMenuId() == MENU_R_CTCS || + UI_MENU_GetCurrentMenuId() == MENU_T_CTCS || + UI_MENU_GetCurrentMenuId() == MENU_R_DCS || + UI_MENU_GetCurrentMenuId() == MENU_T_DCS #ifdef ENABLE_DTMF_CALLING - || UI_MENU_GetCurrentMenuId() == MENU_D_LIST + || UI_MENU_GetCurrentMenuId() == MENU_D_LIST #endif - ) { - sprintf(String, "%2d", gSubMenuSelection); - UI_PrintStringSmallNormal(String, 105, 0, 0); - } - - if ((UI_MENU_GetCurrentMenuId() == MENU_RESET || - UI_MENU_GetCurrentMenuId() == MENU_MEM_CH || - UI_MENU_GetCurrentMenuId() == MENU_MEM_NAME || - UI_MENU_GetCurrentMenuId() == MENU_DEL_CH) && gAskForConfirmation) - { // display confirmation - char *pPrintStr = (gAskForConfirmation == 1) ? "SURE?" : "WAIT!"; - UI_PrintString(pPrintStr, menu_item_x1, menu_item_x2, 5, 8); - } - - ST7565_BlitFullScreen(); + ) { + sprintf(String, "%2d", gSubMenuSelection); + UI_PrintStringSmallNormal(String, 105, 0, 0); + } + + if ((UI_MENU_GetCurrentMenuId() == MENU_RESET || + UI_MENU_GetCurrentMenuId() == MENU_MEM_CH || + UI_MENU_GetCurrentMenuId() == MENU_MEM_NAME || + UI_MENU_GetCurrentMenuId() == MENU_DEL_CH) && gAskForConfirmation) + { // display confirmation + char *pPrintStr = (gAskForConfirmation == 1) ? "SURE?" : "WAIT!"; + UI_PrintString(pPrintStr, menu_item_x1, menu_item_x2, 5, 8); + } + + ST7565_BlitFullScreen(); } \ No newline at end of file diff --git a/ui/menu.h b/ui/menu.h index 2025cd9cd..a16df43e7 100644 --- a/ui/menu.h +++ b/ui/menu.h @@ -24,126 +24,126 @@ #include "settings.h" typedef struct { - const char name[7]; // menu display area only has room for 6 characters - uint8_t menu_id; + const char name[7]; // menu display area only has room for 6 characters + uint8_t menu_id; } t_menu_item; enum { - MENU_SQL = 0, - MENU_STEP, - MENU_TXP, - MENU_R_DCS, - MENU_R_CTCS, - MENU_T_DCS, - MENU_T_CTCS, - MENU_SFT_D, - MENU_OFFSET, - MENU_TOT, - MENU_W_N, + MENU_SQL = 0, + MENU_STEP, + MENU_TXP, + MENU_R_DCS, + MENU_R_CTCS, + MENU_T_DCS, + MENU_T_CTCS, + MENU_SFT_D, + MENU_OFFSET, + MENU_TOT, + MENU_W_N, #ifndef ENABLE_FEAT_F4HWN - MENU_SCR, + MENU_SCR, #endif - MENU_BCL, + MENU_BCL, #ifdef ENABLE_FEAT_F4HWN - MENU_TX_LOCK, + MENU_TX_LOCK, #endif - MENU_MEM_CH, - MENU_DEL_CH, - MENU_MEM_NAME, - MENU_MDF, - MENU_SAVE, + MENU_MEM_CH, + MENU_DEL_CH, + MENU_MEM_NAME, + MENU_MDF, + MENU_SAVE, #ifdef ENABLE_VOX - MENU_VOX, -#endif - MENU_ABR, - MENU_ABR_ON_TX_RX, - MENU_ABR_MIN, - MENU_ABR_MAX, - MENU_TDR, - MENU_BEEP, + MENU_VOX, +#endif + MENU_ABR, + MENU_ABR_ON_TX_RX, + MENU_ABR_MIN, + MENU_ABR_MAX, + MENU_TDR, + MENU_BEEP, #ifdef ENABLE_VOICE - MENU_VOICE, -#endif - MENU_SC_REV, - MENU_AUTOLK, - MENU_S_ADD1, - MENU_S_ADD2, - MENU_S_ADD3, - MENU_STE, - MENU_RP_STE, - MENU_MIC, + MENU_VOICE, +#endif + MENU_SC_REV, + MENU_AUTOLK, + MENU_S_ADD1, + MENU_S_ADD2, + MENU_S_ADD3, + MENU_STE, + MENU_RP_STE, + MENU_MIC, #ifdef ENABLE_AUDIO_BAR - MENU_MIC_BAR, -#endif - MENU_COMPAND, - MENU_1_CALL, - MENU_S_LIST, - MENU_SLIST1, - MENU_SLIST2, - MENU_SLIST3, + MENU_MIC_BAR, +#endif + MENU_COMPAND, + MENU_1_CALL, + MENU_S_LIST, + MENU_SLIST1, + MENU_SLIST2, + MENU_SLIST3, #ifdef ENABLE_ALARM - MENU_AL_MOD, + MENU_AL_MOD, #endif #ifdef ENABLE_DTMF_CALLING - MENU_ANI_ID, + MENU_ANI_ID, #endif - MENU_UPCODE, - MENU_DWCODE, - MENU_PTT_ID, - MENU_D_ST, + MENU_UPCODE, + MENU_DWCODE, + MENU_PTT_ID, + MENU_D_ST, #ifdef ENABLE_DTMF_CALLING - MENU_D_RSP, - MENU_D_HOLD, -#endif - MENU_D_PRE, -#ifdef ENABLE_DTMF_CALLING - MENU_D_DCD, - MENU_D_LIST, -#endif - MENU_D_LIVE_DEC, - MENU_PONMSG, - MENU_ROGER, - MENU_VOL, - MENU_BAT_TXT, - MENU_AM, + MENU_D_RSP, + MENU_D_HOLD, +#endif + MENU_D_PRE, +#ifdef ENABLE_DTMF_CALLING + MENU_D_DCD, + MENU_D_LIST, +#endif + MENU_D_LIVE_DEC, + MENU_PONMSG, + MENU_ROGER, + MENU_VOL, + MENU_BAT_TXT, + MENU_AM, #ifdef ENABLE_AM_FIX - MENU_AM_FIX, + MENU_AM_FIX, #endif #ifdef ENABLE_NOAA - MENU_NOAA_S, -#endif - MENU_RESET, - MENU_F_LOCK, - MENU_200TX, - MENU_350TX, - MENU_500TX, - MENU_350EN, + MENU_NOAA_S, +#endif + MENU_RESET, + MENU_F_LOCK, + MENU_200TX, + MENU_350TX, + MENU_500TX, + MENU_350EN, #ifndef ENABLE_FEAT_F4HWN - MENU_SCREN, + MENU_SCREN, #endif #ifdef ENABLE_F_CAL_MENU - MENU_F_CALI, // reference xtal calibration + MENU_F_CALI, // reference xtal calibration #endif #ifdef ENABLE_FEAT_F4HWN - MENU_SET_PWR, - MENU_SET_PTT, - MENU_SET_TOT, - MENU_SET_EOT, - MENU_SET_CTR, - MENU_SET_INV, - MENU_SET_LCK, - MENU_SET_MET, - MENU_SET_GUI, - MENU_SET_TMR, -#endif - MENU_BATCAL, // battery voltage calibration - MENU_F1SHRT, - MENU_F1LONG, - MENU_F2SHRT, - MENU_F2LONG, - MENU_MLONG, - MENU_BATTYP + MENU_SET_PWR, + MENU_SET_PTT, + MENU_SET_TOT, + MENU_SET_EOT, + MENU_SET_CTR, + MENU_SET_INV, + MENU_SET_LCK, + MENU_SET_MET, + MENU_SET_GUI, + MENU_SET_TMR, +#endif + MENU_BATCAL, // battery voltage calibration + MENU_F1SHRT, + MENU_F1LONG, + MENU_F2SHRT, + MENU_F2LONG, + MENU_MLONG, + MENU_BATTYP }; extern const uint8_t FIRST_HIDDEN_MENU_ITEM; @@ -158,52 +158,52 @@ extern const char gSubMenu_TOT[11][7]; extern const char* const gSubMenu_RXMode[4]; #ifdef ENABLE_VOICE - extern const char gSubMenu_VOICE[3][4]; + extern const char gSubMenu_VOICE[3][4]; #endif extern const char gSubMenu_SC_REV[3][8]; extern const char* const gSubMenu_MDF[4]; #ifdef ENABLE_ALARM - extern const char gSubMenu_AL_MOD[2][5]; + extern const char gSubMenu_AL_MOD[2][5]; #endif #ifdef ENABLE_DTMF_CALLING extern const char gSubMenu_D_RSP[4][11]; #endif #ifdef ENABLE_FEAT_F4HWN - extern const char gSubMenu_SET_PWR[7][6]; - extern const char gSubMenu_SET_PTT[2][8]; - extern const char gSubMenu_SET_TOT[4][7]; - extern const char gSubMenu_SET_LCK[2][9]; - extern const char gSubMenu_SET_MET[2][8]; + extern const char gSubMenu_SET_PWR[7][6]; + extern const char gSubMenu_SET_PTT[2][8]; + extern const char gSubMenu_SET_TOT[4][7]; + extern const char gSubMenu_SET_LCK[2][9]; + extern const char gSubMenu_SET_MET[2][8]; #endif extern const char* const gSubMenu_PTT_ID[5]; #ifdef ENABLE_FEAT_F4HWN - extern const char gSubMenu_PONMSG[5][8]; + extern const char gSubMenu_PONMSG[5][8]; #else - extern const char gSubMenu_PONMSG[4][8]; + extern const char gSubMenu_PONMSG[4][8]; #endif extern const char gSubMenu_ROGER[3][6]; extern const char gSubMenu_RESET[2][4]; extern const char* const gSubMenu_F_LOCK[F_LOCK_LEN]; extern const char gSubMenu_RX_TX[4][6]; extern const char gSubMenu_BAT_TXT[3][8]; -extern const char gSubMenu_BATTYP[3][9]; +extern const char gSubMenu_BATTYP[3][9]; #ifndef ENABLE_FEAT_F4HWN - extern const char gSubMenu_SCRAMBLER[11][7]; + extern const char gSubMenu_SCRAMBLER[11][7]; #endif typedef struct {char* name; uint8_t id;} t_sidefunction; -extern const uint8_t gSubMenu_SIDEFUNCTIONS_size; +extern const uint8_t gSubMenu_SIDEFUNCTIONS_size; extern const t_sidefunction gSubMenu_SIDEFUNCTIONS[]; - + extern bool gIsInSubMenu; - + extern uint8_t gMenuCursor; extern int32_t gSubMenuSelection; - + extern char edit_original[17]; extern char edit[17]; extern int edit_index; diff --git a/ui/scanner.c b/ui/scanner.c index 6fa7c7443..436f820d9 100644 --- a/ui/scanner.c +++ b/ui/scanner.c @@ -26,58 +26,58 @@ void UI_DisplayScanner(void) { - char String[16] = {0}; - char *pPrintStr = String; - bool bCentered; - uint8_t Start; + char String[16] = {0}; + char *pPrintStr = String; + bool bCentered; + uint8_t Start; - UI_DisplayClear(); + UI_DisplayClear(); - if (gScanSingleFrequency || (gScanCssState != SCAN_CSS_STATE_OFF && gScanCssState != SCAN_CSS_STATE_FAILED)) { - sprintf(String, "FREQ:%u.%05u", gScanFrequency / 100000, gScanFrequency % 100000); - pPrintStr = String; - } else { - pPrintStr = "FREQ:**.*****"; - } + if (gScanSingleFrequency || (gScanCssState != SCAN_CSS_STATE_OFF && gScanCssState != SCAN_CSS_STATE_FAILED)) { + sprintf(String, "FREQ:%u.%05u", gScanFrequency / 100000, gScanFrequency % 100000); + pPrintStr = String; + } else { + pPrintStr = "FREQ:**.*****"; + } - UI_PrintString(pPrintStr, 2, 0, 1, 8); + UI_PrintString(pPrintStr, 2, 0, 1, 8); - if (gScanCssState < SCAN_CSS_STATE_FOUND || !gScanUseCssResult) { - pPrintStr = "CTC:******"; - } else if (gScanCssResultType == CODE_TYPE_CONTINUOUS_TONE) { - sprintf(String, "CTC:%u.%uHz", CTCSS_Options[gScanCssResultCode] / 10, CTCSS_Options[gScanCssResultCode] % 10); - pPrintStr = String; - } else { - sprintf(String, "DCS:D%03oN", DCS_Options[gScanCssResultCode]); - pPrintStr = String; - } + if (gScanCssState < SCAN_CSS_STATE_FOUND || !gScanUseCssResult) { + pPrintStr = "CTC:******"; + } else if (gScanCssResultType == CODE_TYPE_CONTINUOUS_TONE) { + sprintf(String, "CTC:%u.%uHz", CTCSS_Options[gScanCssResultCode] / 10, CTCSS_Options[gScanCssResultCode] % 10); + pPrintStr = String; + } else { + sprintf(String, "DCS:D%03oN", DCS_Options[gScanCssResultCode]); + pPrintStr = String; + } - UI_PrintString(pPrintStr, 2, 0, 3, 8); - memset(String, 0, sizeof(String)); - if (gScannerSaveState == SCAN_SAVE_CHANNEL) { - pPrintStr = "SAVE?"; - Start = 0; - bCentered = 1; - } else { - Start = 2; - bCentered = 0; + UI_PrintString(pPrintStr, 2, 0, 3, 8); + memset(String, 0, sizeof(String)); + if (gScannerSaveState == SCAN_SAVE_CHANNEL) { + pPrintStr = "SAVE?"; + Start = 0; + bCentered = 1; + } else { + Start = 2; + bCentered = 0; - if (gScannerSaveState == SCAN_SAVE_CHAN_SEL) { - strcpy(String, "SAVE:"); - UI_GenerateChannelStringEx(String + 5, gShowChPrefix, gScanChannel); - pPrintStr = String; - } else if (gScanCssState < SCAN_CSS_STATE_FOUND) { - strcpy(String, "SCAN"); - memset(String + 4, '.', (gScanProgressIndicator & 7) + 1); - pPrintStr = String; - } else if (gScanCssState == SCAN_CSS_STATE_FOUND) { - pPrintStr = "SCAN CMP."; - } else { - pPrintStr = "SCAN FAIL."; - } - } + if (gScannerSaveState == SCAN_SAVE_CHAN_SEL) { + strcpy(String, "SAVE:"); + UI_GenerateChannelStringEx(String + 5, gShowChPrefix, gScanChannel); + pPrintStr = String; + } else if (gScanCssState < SCAN_CSS_STATE_FOUND) { + strcpy(String, "SCAN"); + memset(String + 4, '.', (gScanProgressIndicator & 7) + 1); + pPrintStr = String; + } else if (gScanCssState == SCAN_CSS_STATE_FOUND) { + pPrintStr = "SCAN CMP."; + } else { + pPrintStr = "SCAN FAIL."; + } + } - UI_PrintString(pPrintStr, Start, bCentered ? 127 : 0, 5, 8); + UI_PrintString(pPrintStr, Start, bCentered ? 127 : 0, 5, 8); - ST7565_BlitFullScreen(); + ST7565_BlitFullScreen(); } diff --git a/ui/status.c b/ui/status.c index 32d4e480b..f3b1272ae 100644 --- a/ui/status.c +++ b/ui/status.c @@ -18,7 +18,7 @@ #include "app/chFrScanner.h" #ifdef ENABLE_FMRADIO - #include "app/fm.h" + #include "app/fm.h" #endif #include "app/scanner.h" #include "bitmaps.h" @@ -54,205 +54,205 @@ static void convertTime(uint8_t *line, uint8_t type) void UI_DisplayStatus() { - char str[8] = ""; + char str[8] = ""; - gUpdateStatus = false; - memset(gStatusLine, 0, sizeof(gStatusLine)); + gUpdateStatus = false; + memset(gStatusLine, 0, sizeof(gStatusLine)); - uint8_t *line = gStatusLine; - unsigned int x = 0; - // ************** + uint8_t *line = gStatusLine; + unsigned int x = 0; + // ************** - // POWER-SAVE indicator - if (gCurrentFunction == FUNCTION_POWER_SAVE) { - memcpy(line + x, gFontPowerSave, sizeof(gFontPowerSave)); - } - x += 8; - unsigned int x1 = x; + // POWER-SAVE indicator + if (gCurrentFunction == FUNCTION_POWER_SAVE) { + memcpy(line + x, gFontPowerSave, sizeof(gFontPowerSave)); + } + x += 8; + unsigned int x1 = x; #ifdef ENABLE_NOAA - if (gIsNoaaMode) { // NOASS SCAN indicator - memcpy(line + x, BITMAP_NOAA, sizeof(BITMAP_NOAA)); - x1 = x + sizeof(BITMAP_NOAA); - } - x += sizeof(BITMAP_NOAA); + if (gIsNoaaMode) { // NOASS SCAN indicator + memcpy(line + x, BITMAP_NOAA, sizeof(BITMAP_NOAA)); + x1 = x + sizeof(BITMAP_NOAA); + } + x += sizeof(BITMAP_NOAA); #endif #ifdef ENABLE_DTMF_CALLING - if (gSetting_KILLED) { - memset(line + x, 0xFF, 10); - x1 = x + 10; - } - else + if (gSetting_KILLED) { + memset(line + x, 0xFF, 10); + x1 = x + 10; + } + else #endif - { // SCAN indicator - if (gScanStateDir != SCAN_OFF || SCANNER_IsScanning()) { - if (IS_MR_CHANNEL(gNextMrChannel) && !SCANNER_IsScanning()) { // channel mode - switch(gEeprom.SCAN_LIST_DEFAULT) { - case 0: - memcpy(line + 0, BITMAP_ScanList0, sizeof(BITMAP_ScanList0)); - break; - case 1: - memcpy(line + 0, BITMAP_ScanList1, sizeof(BITMAP_ScanList1)); - break; - case 2: - memcpy(line + 0, BITMAP_ScanList2, sizeof(BITMAP_ScanList2)); - break; - case 3: - memcpy(line + 0, BITMAP_ScanList3, sizeof(BITMAP_ScanList3)); - break; - case 4: - memcpy(line + 0, BITMAP_ScanList123, sizeof(BITMAP_ScanList123)); - break; - case 5: - memcpy(line + 0, BITMAP_ScanListAll, sizeof(BITMAP_ScanListAll)); - break; - } - } - else { // frequency mode - memcpy(line + x + 1, gFontS, sizeof(gFontS)); - //UI_PrintStringSmallBufferNormal("S", line + x + 1); - } - x1 = x + 10; - } - } - x += 10; // font character width + { // SCAN indicator + if (gScanStateDir != SCAN_OFF || SCANNER_IsScanning()) { + if (IS_MR_CHANNEL(gNextMrChannel) && !SCANNER_IsScanning()) { // channel mode + switch(gEeprom.SCAN_LIST_DEFAULT) { + case 0: + memcpy(line + 0, BITMAP_ScanList0, sizeof(BITMAP_ScanList0)); + break; + case 1: + memcpy(line + 0, BITMAP_ScanList1, sizeof(BITMAP_ScanList1)); + break; + case 2: + memcpy(line + 0, BITMAP_ScanList2, sizeof(BITMAP_ScanList2)); + break; + case 3: + memcpy(line + 0, BITMAP_ScanList3, sizeof(BITMAP_ScanList3)); + break; + case 4: + memcpy(line + 0, BITMAP_ScanList123, sizeof(BITMAP_ScanList123)); + break; + case 5: + memcpy(line + 0, BITMAP_ScanListAll, sizeof(BITMAP_ScanListAll)); + break; + } + } + else { // frequency mode + memcpy(line + x + 1, gFontS, sizeof(gFontS)); + //UI_PrintStringSmallBufferNormal("S", line + x + 1); + } + x1 = x + 10; + } + } + x += 10; // font character width - // Only for debug - // Only for debug - // Only for debug - - bool debug = false; - if(debug) - { - sprintf(str, "%d", gDebug); - UI_PrintStringSmallBufferNormal(str, line + x + 1); - x += 16; - } - else - { + // Only for debug + // Only for debug + // Only for debug + + bool debug = false; + if(debug) + { + sprintf(str, "%d", gDebug); + UI_PrintStringSmallBufferNormal(str, line + x + 1); + x += 16; + } + else + { - #ifdef ENABLE_VOICE - // VOICE indicator - if (gEeprom.VOICE_PROMPT != VOICE_PROMPT_OFF){ - memcpy(line + x, BITMAP_VoicePrompt, sizeof(BITMAP_VoicePrompt)); - x1 = x + sizeof(BITMAP_VoicePrompt); - } - x += sizeof(BITMAP_VoicePrompt); - #endif + #ifdef ENABLE_VOICE + // VOICE indicator + if (gEeprom.VOICE_PROMPT != VOICE_PROMPT_OFF){ + memcpy(line + x, BITMAP_VoicePrompt, sizeof(BITMAP_VoicePrompt)); + x1 = x + sizeof(BITMAP_VoicePrompt); + } + x += sizeof(BITMAP_VoicePrompt); + #endif - if(!SCANNER_IsScanning()) { - #ifdef ENABLE_FEAT_F4HWN_RX_TX_TIMER - if(gCurrentFunction == FUNCTION_TRANSMIT && gSetting_set_tmr == true) - { - convertTime(line, 0); - } - else if(FUNCTION_IsRx() && gSetting_set_tmr == true) - { - convertTime(line, 1); - } - else - #endif - { - uint8_t dw = (gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) + (gEeprom.CROSS_BAND_RX_TX != CROSS_BAND_OFF) * 2; - if(dw == 1 || dw == 3) { // DWR - dual watch + respond - if(gDualWatchActive) - memcpy(line + x + (dw==1?0:2), gFontDWR, sizeof(gFontDWR) - (dw==1?0:5)); - else - memcpy(line + x + 3, gFontHold, sizeof(gFontHold)); - } - else if(dw == 2) { // XB - crossband - memcpy(line + x + 2, gFontXB, sizeof(gFontXB)); - } - else - { - memcpy(line + x + 2, gFontMO, sizeof(gFontMO)); - } - } - } - x += sizeof(gFontDWR) + 3; - } + if(!SCANNER_IsScanning()) { + #ifdef ENABLE_FEAT_F4HWN_RX_TX_TIMER + if(gCurrentFunction == FUNCTION_TRANSMIT && gSetting_set_tmr == true) + { + convertTime(line, 0); + } + else if(FUNCTION_IsRx() && gSetting_set_tmr == true) + { + convertTime(line, 1); + } + else + #endif + { + uint8_t dw = (gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) + (gEeprom.CROSS_BAND_RX_TX != CROSS_BAND_OFF) * 2; + if(dw == 1 || dw == 3) { // DWR - dual watch + respond + if(gDualWatchActive) + memcpy(line + x + (dw==1?0:2), gFontDWR, sizeof(gFontDWR) - (dw==1?0:5)); + else + memcpy(line + x + 3, gFontHold, sizeof(gFontHold)); + } + else if(dw == 2) { // XB - crossband + memcpy(line + x + 2, gFontXB, sizeof(gFontXB)); + } + else + { + memcpy(line + x + 2, gFontMO, sizeof(gFontMO)); + } + } + } + x += sizeof(gFontDWR) + 3; + } #ifdef ENABLE_VOX - // VOX indicator - if (gEeprom.VOX_SWITCH) { - memcpy(line + x, gFontVox, sizeof(gFontVox)); - x1 = x + sizeof(gFontVox) + 1; - } - x += sizeof(gFontVox) + 3; + // VOX indicator + if (gEeprom.VOX_SWITCH) { + memcpy(line + x, gFontVox, sizeof(gFontVox)); + x1 = x + sizeof(gFontVox) + 1; + } + x += sizeof(gFontVox) + 3; #endif #ifdef ENABLE_FEAT_F4HWN - // PTT indicator - if (gSetting_set_ptt_session) { - memcpy(line + x, gFontPttOnePush, sizeof(gFontPttOnePush)); - x1 = x + sizeof(gFontPttOnePush) + 1; - } - else - { - memcpy(line + x, gFontPttClassic, sizeof(gFontPttClassic)); - x1 = x + sizeof(gFontPttClassic) + 1; - } - x += sizeof(gFontPttClassic) + 3; + // PTT indicator + if (gSetting_set_ptt_session) { + memcpy(line + x, gFontPttOnePush, sizeof(gFontPttOnePush)); + x1 = x + sizeof(gFontPttOnePush) + 1; + } + else + { + memcpy(line + x, gFontPttClassic, sizeof(gFontPttClassic)); + x1 = x + sizeof(gFontPttClassic) + 1; + } + x += sizeof(gFontPttClassic) + 3; #endif - x = MAX(x1, 70u); + x = MAX(x1, 70u); - // KEY-LOCK indicator - if (gEeprom.KEY_LOCK) { - memcpy(line + x + 1, gFontKeyLock, sizeof(gFontKeyLock)); - } - else if (gWasFKeyPressed) { - memcpy(line + x + 1, gFontF, sizeof(gFontF)); - /* - UI_PrintStringSmallBufferNormal("F", line + x + 1); - - for (uint8_t i = 71; i < 79; i++) - { - gStatusLine[i] ^= 0x7F; - } - */ - } - else if (gBackLight) - { - memcpy(line + x + 1, gFontLight, sizeof(gFontLight)); - } - #ifdef ENABLE_FEAT_F4HWN_CHARGING_C - else if (gChargingWithTypeC) - { - memcpy(line + x + 1, BITMAP_USB_C, sizeof(BITMAP_USB_C)); - } - #endif - - // Battery - unsigned int x2 = LCD_WIDTH - sizeof(BITMAP_BatteryLevel1) - 0; + // KEY-LOCK indicator + if (gEeprom.KEY_LOCK) { + memcpy(line + x + 1, gFontKeyLock, sizeof(gFontKeyLock)); + } + else if (gWasFKeyPressed) { + memcpy(line + x + 1, gFontF, sizeof(gFontF)); + /* + UI_PrintStringSmallBufferNormal("F", line + x + 1); + + for (uint8_t i = 71; i < 79; i++) + { + gStatusLine[i] ^= 0x7F; + } + */ + } + else if (gBackLight) + { + memcpy(line + x + 1, gFontLight, sizeof(gFontLight)); + } + #ifdef ENABLE_FEAT_F4HWN_CHARGING_C + else if (gChargingWithTypeC) + { + memcpy(line + x + 1, BITMAP_USB_C, sizeof(BITMAP_USB_C)); + } + #endif + + // Battery + unsigned int x2 = LCD_WIDTH - sizeof(BITMAP_BatteryLevel1) - 0; - UI_DrawBattery(line + x2, gBatteryDisplayLevel, gLowBatteryBlink); + UI_DrawBattery(line + x2, gBatteryDisplayLevel, gLowBatteryBlink); - switch (gSetting_battery_text) { - default: - case 0: - break; + switch (gSetting_battery_text) { + default: + case 0: + break; - case 1: { // voltage - const uint16_t voltage = (gBatteryVoltageAverage <= 999) ? gBatteryVoltageAverage : 999; // limit to 9.99V + case 1: { // voltage + const uint16_t voltage = (gBatteryVoltageAverage <= 999) ? gBatteryVoltageAverage : 999; // limit to 9.99V #ifdef ENABLE_FEAT_F4HWN - sprintf(str, "%u.%02u", voltage / 100, voltage % 100); + sprintf(str, "%u.%02u", voltage / 100, voltage % 100); #else - sprintf(str, "%u.%02uV", voltage / 100, voltage % 100); + sprintf(str, "%u.%02uV", voltage / 100, voltage % 100); #endif - break; - } + break; + } - case 2: // percentage - sprintf(str, "%u%%", BATTERY_VoltsToPercent(gBatteryVoltageAverage)); - break; - } + case 2: // percentage + sprintf(str, "%u%%", BATTERY_VoltsToPercent(gBatteryVoltageAverage)); + break; + } - x2 -= (7 * strlen(str)); - UI_PrintStringSmallBufferNormal(str, line + x2); + x2 -= (7 * strlen(str)); + UI_PrintStringSmallBufferNormal(str, line + x2); - // ************** + // ************** - ST7565_BlitStatusLine(); + ST7565_BlitStatusLine(); } diff --git a/ui/ui.c b/ui/ui.c index 50963aa4a..a64adc720 100644 --- a/ui/ui.c +++ b/ui/ui.c @@ -20,15 +20,15 @@ #include "app/chFrScanner.h" #include "app/dtmf.h" #ifdef ENABLE_FMRADIO - #include "app/fm.h" + #include "app/fm.h" #endif #include "driver/keyboard.h" #include "misc.h" #ifdef ENABLE_AIRCOPY - #include "ui/aircopy.h" + #include "ui/aircopy.h" #endif #ifdef ENABLE_FMRADIO - #include "ui/fmradio.h" + #include "ui/fmradio.h" #endif #include "ui/inputbox.h" #include "ui/main.h" @@ -46,16 +46,16 @@ bool gAskToDelete; void (*UI_DisplayFunctions[])(void) = { - [DISPLAY_MAIN] = &UI_DisplayMain, - [DISPLAY_MENU] = &UI_DisplayMenu, - [DISPLAY_SCANNER] = &UI_DisplayScanner, + [DISPLAY_MAIN] = &UI_DisplayMain, + [DISPLAY_MENU] = &UI_DisplayMenu, + [DISPLAY_SCANNER] = &UI_DisplayScanner, #ifdef ENABLE_FMRADIO - [DISPLAY_FM] = &UI_DisplayFM, + [DISPLAY_FM] = &UI_DisplayFM, #endif #ifdef ENABLE_AIRCOPY - [DISPLAY_AIRCOPY] = &UI_DisplayAircopy, + [DISPLAY_AIRCOPY] = &UI_DisplayAircopy, #endif }; @@ -63,35 +63,35 @@ static_assert(ARRAY_SIZE(UI_DisplayFunctions) == DISPLAY_N_ELEM); void GUI_DisplayScreen(void) { - if (gScreenToDisplay != DISPLAY_INVALID) { - UI_DisplayFunctions[gScreenToDisplay](); - } + if (gScreenToDisplay != DISPLAY_INVALID) { + UI_DisplayFunctions[gScreenToDisplay](); + } } void GUI_SelectNextDisplay(GUI_DisplayType_t Display) { - if (Display == DISPLAY_INVALID) - return; + if (Display == DISPLAY_INVALID) + return; - if (gScreenToDisplay != Display) - { - DTMF_clear_input_box(); + if (gScreenToDisplay != Display) + { + DTMF_clear_input_box(); - gInputBoxIndex = 0; - gIsInSubMenu = false; - gCssBackgroundScan = false; - gScanStateDir = SCAN_OFF; - #ifdef ENABLE_FMRADIO - gFM_ScanState = FM_SCAN_OFF; - #endif - gAskForConfirmation = 0; - gAskToSave = false; - gAskToDelete = false; - gWasFKeyPressed = false; + gInputBoxIndex = 0; + gIsInSubMenu = false; + gCssBackgroundScan = false; + gScanStateDir = SCAN_OFF; + #ifdef ENABLE_FMRADIO + gFM_ScanState = FM_SCAN_OFF; + #endif + gAskForConfirmation = 0; + gAskToSave = false; + gAskToDelete = false; + gWasFKeyPressed = false; - gUpdateStatus = true; - } + gUpdateStatus = true; + } - gScreenToDisplay = Display; - gUpdateDisplay = true; + gScreenToDisplay = Display; + gUpdateDisplay = true; } diff --git a/ui/ui.h b/ui/ui.h index 97289ae2c..ce4d35f36 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -22,20 +22,20 @@ enum GUI_DisplayType_t { - DISPLAY_MAIN = 0, - DISPLAY_MENU, - DISPLAY_SCANNER, + DISPLAY_MAIN = 0, + DISPLAY_MENU, + DISPLAY_SCANNER, #ifdef ENABLE_FMRADIO - DISPLAY_FM, + DISPLAY_FM, #endif #ifdef ENABLE_AIRCOPY - DISPLAY_AIRCOPY, + DISPLAY_AIRCOPY, #endif - DISPLAY_N_ELEM, - DISPLAY_INVALID = 0xFFu + DISPLAY_N_ELEM, + DISPLAY_INVALID = 0xFFu }; typedef enum GUI_DisplayType_t GUI_DisplayType_t; diff --git a/ui/welcome.c b/ui/welcome.c index b6a139cbd..48cd088d2 100644 --- a/ui/welcome.c +++ b/ui/welcome.c @@ -30,123 +30,123 @@ void UI_DisplayReleaseKeys(void) { - memset(gStatusLine, 0, sizeof(gStatusLine)); + memset(gStatusLine, 0, sizeof(gStatusLine)); #ifdef ENABLE_FEAT_F4HWN - ST7565_ContrastAndInv(); + ST7565_ContrastAndInv(); #endif - UI_DisplayClear(); + UI_DisplayClear(); - UI_PrintString("RELEASE", 0, 127, 1, 10); - UI_PrintString("ALL KEYS", 0, 127, 3, 10); + UI_PrintString("RELEASE", 0, 127, 1, 10); + UI_PrintString("ALL KEYS", 0, 127, 3, 10); - ST7565_BlitStatusLine(); // blank status line - ST7565_BlitFullScreen(); + ST7565_BlitStatusLine(); // blank status line + ST7565_BlitFullScreen(); } void UI_DisplayWelcome(void) { - char WelcomeString0[16]; - char WelcomeString1[16]; - char WelcomeString2[16]; + char WelcomeString0[16]; + char WelcomeString1[16]; + char WelcomeString2[16]; - memset(gStatusLine, 0, sizeof(gStatusLine)); + memset(gStatusLine, 0, sizeof(gStatusLine)); #ifdef ENABLE_FEAT_F4HWN - ST7565_ContrastAndInv(); + ST7565_ContrastAndInv(); #endif - UI_DisplayClear(); + UI_DisplayClear(); #ifdef ENABLE_FEAT_F4HWN - ST7565_BlitStatusLine(); - ST7565_BlitFullScreen(); - - if (gEeprom.POWER_ON_DISPLAY_MODE == POWER_ON_DISPLAY_MODE_NONE || gEeprom.POWER_ON_DISPLAY_MODE == POWER_ON_DISPLAY_MODE_SOUND) { - ST7565_FillScreen(0x00); + ST7565_BlitStatusLine(); + ST7565_BlitFullScreen(); + + if (gEeprom.POWER_ON_DISPLAY_MODE == POWER_ON_DISPLAY_MODE_NONE || gEeprom.POWER_ON_DISPLAY_MODE == POWER_ON_DISPLAY_MODE_SOUND) { + ST7565_FillScreen(0x00); #else - if (gEeprom.POWER_ON_DISPLAY_MODE == POWER_ON_DISPLAY_MODE_NONE || gEeprom.POWER_ON_DISPLAY_MODE == POWER_ON_DISPLAY_MODE_FULL_SCREEN) { - ST7565_FillScreen(0xFF); + if (gEeprom.POWER_ON_DISPLAY_MODE == POWER_ON_DISPLAY_MODE_NONE || gEeprom.POWER_ON_DISPLAY_MODE == POWER_ON_DISPLAY_MODE_FULL_SCREEN) { + ST7565_FillScreen(0xFF); #endif - } else { - memset(WelcomeString0, 0, sizeof(WelcomeString0)); - memset(WelcomeString1, 0, sizeof(WelcomeString1)); - - EEPROM_ReadBuffer(0x0EB0, WelcomeString0, 16); - EEPROM_ReadBuffer(0x0EC0, WelcomeString1, 16); - - sprintf(WelcomeString2, "%u.%02uV %u%%", - gBatteryVoltageAverage / 100, - gBatteryVoltageAverage % 100, - BATTERY_VoltsToPercent(gBatteryVoltageAverage)); - - if (gEeprom.POWER_ON_DISPLAY_MODE == POWER_ON_DISPLAY_MODE_VOLTAGE) - { - strcpy(WelcomeString0, "VOLTAGE"); - strcpy(WelcomeString1, WelcomeString2); - } - else if(gEeprom.POWER_ON_DISPLAY_MODE == POWER_ON_DISPLAY_MODE_ALL) - { - if(strlen(WelcomeString0) == 0 && strlen(WelcomeString1) == 0) - { - strcpy(WelcomeString0, "WELCOME"); - strcpy(WelcomeString1, WelcomeString2); - } - else if(strlen(WelcomeString0) == 0 || strlen(WelcomeString1) == 0) - { - if(strlen(WelcomeString0) == 0) - { - strcpy(WelcomeString0, WelcomeString1); - } - strcpy(WelcomeString1, WelcomeString2); - } - } - else if(gEeprom.POWER_ON_DISPLAY_MODE == POWER_ON_DISPLAY_MODE_MESSAGE) - { - if(strlen(WelcomeString0) == 0) - { - strcpy(WelcomeString0, "WELCOME"); - } - - if(strlen(WelcomeString1) == 0) - { - strcpy(WelcomeString1, "BIENVENUE"); - } - } - - UI_PrintString(WelcomeString0, 0, 127, 0, 10); - UI_PrintString(WelcomeString1, 0, 127, 2, 10); + } else { + memset(WelcomeString0, 0, sizeof(WelcomeString0)); + memset(WelcomeString1, 0, sizeof(WelcomeString1)); + + EEPROM_ReadBuffer(0x0EB0, WelcomeString0, 16); + EEPROM_ReadBuffer(0x0EC0, WelcomeString1, 16); + + sprintf(WelcomeString2, "%u.%02uV %u%%", + gBatteryVoltageAverage / 100, + gBatteryVoltageAverage % 100, + BATTERY_VoltsToPercent(gBatteryVoltageAverage)); + + if (gEeprom.POWER_ON_DISPLAY_MODE == POWER_ON_DISPLAY_MODE_VOLTAGE) + { + strcpy(WelcomeString0, "VOLTAGE"); + strcpy(WelcomeString1, WelcomeString2); + } + else if(gEeprom.POWER_ON_DISPLAY_MODE == POWER_ON_DISPLAY_MODE_ALL) + { + if(strlen(WelcomeString0) == 0 && strlen(WelcomeString1) == 0) + { + strcpy(WelcomeString0, "WELCOME"); + strcpy(WelcomeString1, WelcomeString2); + } + else if(strlen(WelcomeString0) == 0 || strlen(WelcomeString1) == 0) + { + if(strlen(WelcomeString0) == 0) + { + strcpy(WelcomeString0, WelcomeString1); + } + strcpy(WelcomeString1, WelcomeString2); + } + } + else if(gEeprom.POWER_ON_DISPLAY_MODE == POWER_ON_DISPLAY_MODE_MESSAGE) + { + if(strlen(WelcomeString0) == 0) + { + strcpy(WelcomeString0, "WELCOME"); + } + + if(strlen(WelcomeString1) == 0) + { + strcpy(WelcomeString1, "BIENVENUE"); + } + } + + UI_PrintString(WelcomeString0, 0, 127, 0, 10); + UI_PrintString(WelcomeString1, 0, 127, 2, 10); #ifdef ENABLE_FEAT_F4HWN - UI_PrintStringSmallNormal(Version, 0, 128, 4); - - for (uint8_t i = 0; i < 128; i++) - { - gFrameBuffer[3][i] ^= 0x80; - } - - for (uint8_t i = 18; i < 110; i++) - { - gFrameBuffer[4][i] ^= 0xFF; - } - - #ifdef ENABLE_SPECTRUM - #ifdef ENABLE_FMRADIO - UI_PrintStringSmallNormal(Based, 0, 127, 5); - UI_PrintStringSmallNormal(Credits, 0, 127, 6); - #else - UI_PrintStringSmallNormal("Bandscope ", 0, 127, 5); - memcpy(gFrameBuffer[5] + 95, BITMAP_Ready, sizeof(BITMAP_Ready)); - UI_PrintStringSmallNormal("Broadcast ", 0, 127, 6); - #endif - #else - UI_PrintStringSmallNormal("Bandscope ", 0, 127, 5); - UI_PrintStringSmallNormal("Broadcast ", 0, 127, 6); - memcpy(gFrameBuffer[6] + 95, BITMAP_Ready, sizeof(BITMAP_Ready)); - #endif + UI_PrintStringSmallNormal(Version, 0, 128, 4); + + for (uint8_t i = 0; i < 128; i++) + { + gFrameBuffer[3][i] ^= 0x80; + } + + for (uint8_t i = 18; i < 110; i++) + { + gFrameBuffer[4][i] ^= 0xFF; + } + + #ifdef ENABLE_SPECTRUM + #ifdef ENABLE_FMRADIO + UI_PrintStringSmallNormal(Based, 0, 127, 5); + UI_PrintStringSmallNormal(Credits, 0, 127, 6); + #else + UI_PrintStringSmallNormal("Bandscope ", 0, 127, 5); + memcpy(gFrameBuffer[5] + 95, BITMAP_Ready, sizeof(BITMAP_Ready)); + UI_PrintStringSmallNormal("Broadcast ", 0, 127, 6); + #endif + #else + UI_PrintStringSmallNormal("Bandscope ", 0, 127, 5); + UI_PrintStringSmallNormal("Broadcast ", 0, 127, 6); + memcpy(gFrameBuffer[6] + 95, BITMAP_Ready, sizeof(BITMAP_Ready)); + #endif #else - UI_PrintStringSmallNormal(Version, 0, 127, 6); + UI_PrintStringSmallNormal(Version, 0, 127, 6); #endif - //ST7565_BlitStatusLine(); // blank status line : I think it's useless - ST7565_BlitFullScreen(); - } + //ST7565_BlitStatusLine(); // blank status line : I think it's useless + ST7565_BlitFullScreen(); + } } diff --git a/version.c b/version.c index 30cf86aba..f9c28ad49 100644 --- a/version.c +++ b/version.c @@ -1,16 +1,16 @@ #ifdef VERSION_STRING - #define VER " "VERSION_STRING + #define VER " "VERSION_STRING #else - #define VER "" + #define VER "" #endif #ifdef ENABLE_FEAT_F4HWN - const char Version[] = AUTHOR_STRING_2 " " VERSION_STRING_2; - const char Based[] = "based on"; - const char Credits[] = AUTHOR_STRING_1 " " VERSION_STRING_1; + const char Version[] = AUTHOR_STRING_2 " " VERSION_STRING_2; + const char Based[] = "based on"; + const char Credits[] = AUTHOR_STRING_1 " " VERSION_STRING_1; #else - const char Version[] = AUTHOR_STRING VER; + const char Version[] = AUTHOR_STRING VER; #endif const char UART_Version[] = "UV-K5 Firmware, " AUTHOR_STRING VER "\r\n"; diff --git a/version.h b/version.h index 8a184dfd6..a19174f5f 100644 --- a/version.h +++ b/version.h @@ -23,6 +23,6 @@ extern const char UART_Version[]; #endif #ifdef ENABLE_FEAT_F4HWN - extern const char Credits[]; - extern const char Based[]; + extern const char Credits[]; + extern const char Based[]; #endif From e64a615359ee0442390e7513f1d0afd2ab24e367 Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Fri, 16 Aug 2024 00:14:26 +0200 Subject: [PATCH 23/30] Check tab only... --- app/main.c | 1462 ++++++++++++++++++++++++++-------------------------- 1 file changed, 731 insertions(+), 731 deletions(-) diff --git a/app/main.c b/app/main.c index 231ec5ffa..5c5d8d437 100644 --- a/app/main.c +++ b/app/main.c @@ -21,7 +21,7 @@ #include "app/chFrScanner.h" #include "app/common.h" #ifdef ENABLE_FMRADIO - #include "app/fm.h" + #include "app/fm.h" #endif #include "app/generic.h" #include "app/main.h" @@ -44,862 +44,862 @@ #include static void toggle_chan_scanlist(void) -{ // toggle the selected channels scanlist setting +{ // toggle the selected channels scanlist setting - if (SCANNER_IsScanning()) - return; + if (SCANNER_IsScanning()) + return; - if(!IS_MR_CHANNEL(gTxVfo->CHANNEL_SAVE)) { + if(!IS_MR_CHANNEL(gTxVfo->CHANNEL_SAVE)) { #ifdef ENABLE_SCAN_RANGES - gScanRangeStart = gScanRangeStart ? 0 : gTxVfo->pRX->Frequency; - gScanRangeStop = gEeprom.VfoInfo[!gEeprom.TX_VFO].freq_config_RX.Frequency; - if(gScanRangeStart > gScanRangeStop) - SWAP(gScanRangeStart, gScanRangeStop); + gScanRangeStart = gScanRangeStart ? 0 : gTxVfo->pRX->Frequency; + gScanRangeStop = gEeprom.VfoInfo[!gEeprom.TX_VFO].freq_config_RX.Frequency; + if(gScanRangeStart > gScanRangeStop) + SWAP(gScanRangeStart, gScanRangeStop); #endif - return; - } - - // Remove exclude - if(gMR_ChannelExclude[gTxVfo->CHANNEL_SAVE] == true) - { - gMR_ChannelExclude[gTxVfo->CHANNEL_SAVE] = false; - return; - } + return; + } + + // Remove exclude + if(gMR_ChannelExclude[gTxVfo->CHANNEL_SAVE] == true) + { + gMR_ChannelExclude[gTxVfo->CHANNEL_SAVE] = false; + return; + } - uint8_t scanTmp = gTxVfo->SCANLIST1_PARTICIPATION | (gTxVfo->SCANLIST2_PARTICIPATION << 1) | (gTxVfo->SCANLIST3_PARTICIPATION << 2); + uint8_t scanTmp = gTxVfo->SCANLIST1_PARTICIPATION | (gTxVfo->SCANLIST2_PARTICIPATION << 1) | (gTxVfo->SCANLIST3_PARTICIPATION << 2); - scanTmp = (scanTmp++ < 7) ? scanTmp: 0; + scanTmp = (scanTmp++ < 7) ? scanTmp: 0; gTxVfo->SCANLIST1_PARTICIPATION = (scanTmp >> 0) & 0x01; gTxVfo->SCANLIST2_PARTICIPATION = (scanTmp >> 1) & 0x01; gTxVfo->SCANLIST3_PARTICIPATION = (scanTmp >> 2) & 0x01; - SETTINGS_UpdateChannel(gTxVfo->CHANNEL_SAVE, gTxVfo, true, true, true); + SETTINGS_UpdateChannel(gTxVfo->CHANNEL_SAVE, gTxVfo, true, true, true); - gVfoConfigureMode = VFO_CONFIGURE; - gFlagResetVfos = true; + gVfoConfigureMode = VFO_CONFIGURE; + gFlagResetVfos = true; } static void processFKeyFunction(const KEY_Code_t Key, const bool beep) { - uint8_t Vfo = gEeprom.TX_VFO; - - if (gScreenToDisplay == DISPLAY_MENU) { - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - return; - } - - gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; - - switch (Key) { - case KEY_0: - #ifdef ENABLE_FMRADIO - ACTION_FM(); - #endif - break; - - case KEY_1: - if (!IS_FREQ_CHANNEL(gTxVfo->CHANNEL_SAVE)) { - gWasFKeyPressed = false; - gUpdateStatus = true; - gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; + uint8_t Vfo = gEeprom.TX_VFO; + + if (gScreenToDisplay == DISPLAY_MENU) { + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + return; + } + + gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; + + switch (Key) { + case KEY_0: + #ifdef ENABLE_FMRADIO + ACTION_FM(); + #endif + break; + + case KEY_1: + if (!IS_FREQ_CHANNEL(gTxVfo->CHANNEL_SAVE)) { + gWasFKeyPressed = false; + gUpdateStatus = true; + gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; #ifdef ENABLE_COPY_CHAN_TO_VFO - if (!gEeprom.VFO_OPEN || gCssBackgroundScan) { - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - return; - } - - if (gScanStateDir != SCAN_OFF) { - if (gCurrentFunction != FUNCTION_INCOMING || - gRxReceptionMode == RX_MODE_NONE || - gScanPauseDelayIn_10ms == 0) - { // scan is running (not paused) - return; - } - } - - const uint8_t vfo = gEeprom.TX_VFO; - - if (IS_MR_CHANNEL(gEeprom.ScreenChannel[vfo])) - { // copy channel to VFO, then swap to the VFO - - gEeprom.ScreenChannel[vfo] = FREQ_CHANNEL_FIRST + gEeprom.VfoInfo[vfo].Band; - gEeprom.VfoInfo[vfo].CHANNEL_SAVE = gEeprom.ScreenChannel[vfo]; - - RADIO_SelectVfos(); - RADIO_ApplyOffset(gRxVfo); - RADIO_ConfigureSquelchAndOutputPower(gRxVfo); - RADIO_SetupRegisters(true); - - //SETTINGS_SaveChannel(channel, gEeprom.RX_VFO, gRxVfo, 1); - - gRequestSaveChannel = 1; - gRequestSaveVFO = true; - gUpdateDisplay = true; - } + if (!gEeprom.VFO_OPEN || gCssBackgroundScan) { + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + return; + } + + if (gScanStateDir != SCAN_OFF) { + if (gCurrentFunction != FUNCTION_INCOMING || + gRxReceptionMode == RX_MODE_NONE || + gScanPauseDelayIn_10ms == 0) + { // scan is running (not paused) + return; + } + } + + const uint8_t vfo = gEeprom.TX_VFO; + + if (IS_MR_CHANNEL(gEeprom.ScreenChannel[vfo])) + { // copy channel to VFO, then swap to the VFO + + gEeprom.ScreenChannel[vfo] = FREQ_CHANNEL_FIRST + gEeprom.VfoInfo[vfo].Band; + gEeprom.VfoInfo[vfo].CHANNEL_SAVE = gEeprom.ScreenChannel[vfo]; + + RADIO_SelectVfos(); + RADIO_ApplyOffset(gRxVfo); + RADIO_ConfigureSquelchAndOutputPower(gRxVfo); + RADIO_SetupRegisters(true); + + //SETTINGS_SaveChannel(channel, gEeprom.RX_VFO, gRxVfo, 1); + + gRequestSaveChannel = 1; + gRequestSaveVFO = true; + gUpdateDisplay = true; + } #endif - return; - } + return; + } #ifdef ENABLE_WIDE_RX - if(gTxVfo->Band == BAND7_470MHz && gTxVfo->pRX->Frequency < _1GHz_in_KHz) { - gTxVfo->pRX->Frequency = _1GHz_in_KHz; - return; - } + if(gTxVfo->Band == BAND7_470MHz && gTxVfo->pRX->Frequency < _1GHz_in_KHz) { + gTxVfo->pRX->Frequency = _1GHz_in_KHz; + return; + } #endif - gTxVfo->Band += 1; - - if (gTxVfo->Band == BAND5_350MHz && !gSetting_350EN) { - // skip if not enabled - gTxVfo->Band += 1; - } else if (gTxVfo->Band >= BAND_N_ELEM){ - // go arround if overflowed - gTxVfo->Band = BAND1_50MHz; - } - - gEeprom.ScreenChannel[Vfo] = FREQ_CHANNEL_FIRST + gTxVfo->Band; - gEeprom.FreqChannel[Vfo] = FREQ_CHANNEL_FIRST + gTxVfo->Band; - - gRequestSaveVFO = true; - gVfoConfigureMode = VFO_CONFIGURE_RELOAD; - - gRequestDisplayScreen = DISPLAY_MAIN; - - if (beep) - gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; - - break; - - case KEY_2: - #ifdef ENABLE_FEAT_F4HWN - gVfoConfigureMode = VFO_CONFIGURE; - #endif - COMMON_SwitchVFOs(); - if (beep) - gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; - break; - - case KEY_3: - #ifdef ENABLE_FEAT_F4HWN - gVfoConfigureMode = VFO_CONFIGURE; - #endif - COMMON_SwitchVFOMode(); - if (beep) - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - - break; - - case KEY_4: - gWasFKeyPressed = false; - - gBackup_CROSS_BAND_RX_TX = gEeprom.CROSS_BAND_RX_TX; - gEeprom.CROSS_BAND_RX_TX = CROSS_BAND_OFF; - gUpdateStatus = true; - if (beep) - gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; - - SCANNER_Start(false); - gRequestDisplayScreen = DISPLAY_SCANNER; - break; - - case KEY_5: - if(beep) { + gTxVfo->Band += 1; + + if (gTxVfo->Band == BAND5_350MHz && !gSetting_350EN) { + // skip if not enabled + gTxVfo->Band += 1; + } else if (gTxVfo->Band >= BAND_N_ELEM){ + // go arround if overflowed + gTxVfo->Band = BAND1_50MHz; + } + + gEeprom.ScreenChannel[Vfo] = FREQ_CHANNEL_FIRST + gTxVfo->Band; + gEeprom.FreqChannel[Vfo] = FREQ_CHANNEL_FIRST + gTxVfo->Band; + + gRequestSaveVFO = true; + gVfoConfigureMode = VFO_CONFIGURE_RELOAD; + + gRequestDisplayScreen = DISPLAY_MAIN; + + if (beep) + gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; + + break; + + case KEY_2: + #ifdef ENABLE_FEAT_F4HWN + gVfoConfigureMode = VFO_CONFIGURE; + #endif + COMMON_SwitchVFOs(); + if (beep) + gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; + break; + + case KEY_3: + #ifdef ENABLE_FEAT_F4HWN + gVfoConfigureMode = VFO_CONFIGURE; + #endif + COMMON_SwitchVFOMode(); + if (beep) + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + + break; + + case KEY_4: + gWasFKeyPressed = false; + + gBackup_CROSS_BAND_RX_TX = gEeprom.CROSS_BAND_RX_TX; + gEeprom.CROSS_BAND_RX_TX = CROSS_BAND_OFF; + gUpdateStatus = true; + if (beep) + gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; + + SCANNER_Start(false); + gRequestDisplayScreen = DISPLAY_SCANNER; + break; + + case KEY_5: + if(beep) { #ifdef ENABLE_NOAA - if (!IS_NOAA_CHANNEL(gTxVfo->CHANNEL_SAVE)) { - gEeprom.ScreenChannel[Vfo] = gEeprom.NoaaChannel[gEeprom.TX_VFO]; - } - else { - gEeprom.ScreenChannel[Vfo] = gEeprom.FreqChannel[gEeprom.TX_VFO]; + if (!IS_NOAA_CHANNEL(gTxVfo->CHANNEL_SAVE)) { + gEeprom.ScreenChannel[Vfo] = gEeprom.NoaaChannel[gEeprom.TX_VFO]; + } + else { + gEeprom.ScreenChannel[Vfo] = gEeprom.FreqChannel[gEeprom.TX_VFO]; #ifdef ENABLE_VOICE - gAnotherVoiceID = VOICE_ID_FREQUENCY_MODE; + gAnotherVoiceID = VOICE_ID_FREQUENCY_MODE; #endif - } - gRequestSaveVFO = true; - gVfoConfigureMode = VFO_CONFIGURE_RELOAD; + } + gRequestSaveVFO = true; + gVfoConfigureMode = VFO_CONFIGURE_RELOAD; #elif defined(ENABLE_SPECTRUM) - APP_RunSpectrum(); - gRequestDisplayScreen = DISPLAY_MAIN; + APP_RunSpectrum(); + gRequestDisplayScreen = DISPLAY_MAIN; #endif - } - else { - toggle_chan_scanlist(); - } + } + else { + toggle_chan_scanlist(); + } - break; + break; - case KEY_6: - ACTION_Power(); - break; + case KEY_6: + ACTION_Power(); + break; - case KEY_7: + case KEY_7: #ifdef ENABLE_VOX - ACTION_Vox(); + ACTION_Vox(); //#else -// toggle_chan_scanlist(); +// toggle_chan_scanlist(); #endif - break; + break; - case KEY_8: - gTxVfo->FrequencyReverse = gTxVfo->FrequencyReverse == false; - gRequestSaveChannel = 1; - break; + case KEY_8: + gTxVfo->FrequencyReverse = gTxVfo->FrequencyReverse == false; + gRequestSaveChannel = 1; + break; - case KEY_9: - if (RADIO_CheckValidChannel(gEeprom.CHAN_1_CALL, false, 0)) { - gEeprom.MrChannel[Vfo] = gEeprom.CHAN_1_CALL; - gEeprom.ScreenChannel[Vfo] = gEeprom.CHAN_1_CALL; + case KEY_9: + if (RADIO_CheckValidChannel(gEeprom.CHAN_1_CALL, false, 0)) { + gEeprom.MrChannel[Vfo] = gEeprom.CHAN_1_CALL; + gEeprom.ScreenChannel[Vfo] = gEeprom.CHAN_1_CALL; #ifdef ENABLE_VOICE - AUDIO_SetVoiceID(0, VOICE_ID_CHANNEL_MODE); - AUDIO_SetDigitVoice(1, gEeprom.CHAN_1_CALL + 1); - gAnotherVoiceID = (VOICE_ID_t)0xFE; + AUDIO_SetVoiceID(0, VOICE_ID_CHANNEL_MODE); + AUDIO_SetDigitVoice(1, gEeprom.CHAN_1_CALL + 1); + gAnotherVoiceID = (VOICE_ID_t)0xFE; #endif - gRequestSaveVFO = true; - gVfoConfigureMode = VFO_CONFIGURE_RELOAD; - break; - } + gRequestSaveVFO = true; + gVfoConfigureMode = VFO_CONFIGURE_RELOAD; + break; + } - if (beep) - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - break; + if (beep) + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + break; #ifdef ENABLE_FEAT_F4HWN // Set Squelch F + UP or Down and Step F + SIDE1 or F + SIDE2 - case KEY_UP: - gEeprom.SQUELCH_LEVEL = (gEeprom.SQUELCH_LEVEL < 9) ? gEeprom.SQUELCH_LEVEL + 1: 9; - gVfoConfigureMode = VFO_CONFIGURE; - gWasFKeyPressed = false; - break; - case KEY_DOWN: - gEeprom.SQUELCH_LEVEL = (gEeprom.SQUELCH_LEVEL > 0) ? gEeprom.SQUELCH_LEVEL - 1: 0; - gVfoConfigureMode = VFO_CONFIGURE; - gWasFKeyPressed = false; - break; - - case KEY_SIDE1: - uint8_t a = FREQUENCY_GetSortedIdxFromStepIdx(gTxVfo->STEP_SETTING); - if (a < STEP_N_ELEM - 1) - { - gTxVfo->STEP_SETTING = FREQUENCY_GetStepIdxFromSortedIdx(a + 1); - } - if (IS_FREQ_CHANNEL(gTxVfo->CHANNEL_SAVE)) - { - gRequestSaveChannel = 1; - } - gVfoConfigureMode = VFO_CONFIGURE; - gWasFKeyPressed = false; - break; - case KEY_SIDE2: - uint8_t b = FREQUENCY_GetSortedIdxFromStepIdx(gTxVfo->STEP_SETTING); - if (b > 0) - { - gTxVfo->STEP_SETTING = FREQUENCY_GetStepIdxFromSortedIdx(b - 1); - } - if (IS_FREQ_CHANNEL(gTxVfo->CHANNEL_SAVE)) - { - gRequestSaveChannel = 1; - } - gVfoConfigureMode = VFO_CONFIGURE; - gWasFKeyPressed = false; - break; + case KEY_UP: + gEeprom.SQUELCH_LEVEL = (gEeprom.SQUELCH_LEVEL < 9) ? gEeprom.SQUELCH_LEVEL + 1: 9; + gVfoConfigureMode = VFO_CONFIGURE; + gWasFKeyPressed = false; + break; + case KEY_DOWN: + gEeprom.SQUELCH_LEVEL = (gEeprom.SQUELCH_LEVEL > 0) ? gEeprom.SQUELCH_LEVEL - 1: 0; + gVfoConfigureMode = VFO_CONFIGURE; + gWasFKeyPressed = false; + break; + + case KEY_SIDE1: + uint8_t a = FREQUENCY_GetSortedIdxFromStepIdx(gTxVfo->STEP_SETTING); + if (a < STEP_N_ELEM - 1) + { + gTxVfo->STEP_SETTING = FREQUENCY_GetStepIdxFromSortedIdx(a + 1); + } + if (IS_FREQ_CHANNEL(gTxVfo->CHANNEL_SAVE)) + { + gRequestSaveChannel = 1; + } + gVfoConfigureMode = VFO_CONFIGURE; + gWasFKeyPressed = false; + break; + case KEY_SIDE2: + uint8_t b = FREQUENCY_GetSortedIdxFromStepIdx(gTxVfo->STEP_SETTING); + if (b > 0) + { + gTxVfo->STEP_SETTING = FREQUENCY_GetStepIdxFromSortedIdx(b - 1); + } + if (IS_FREQ_CHANNEL(gTxVfo->CHANNEL_SAVE)) + { + gRequestSaveChannel = 1; + } + gVfoConfigureMode = VFO_CONFIGURE; + gWasFKeyPressed = false; + break; #endif - default: - gUpdateStatus = true; - gWasFKeyPressed = false; + default: + gUpdateStatus = true; + gWasFKeyPressed = false; - if (beep) - gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; - break; - } + if (beep) + gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; + break; + } } void channelMove(uint16_t Channel) { - const uint8_t Vfo = gEeprom.TX_VFO; + const uint8_t Vfo = gEeprom.TX_VFO; - if (!RADIO_CheckValidChannel(Channel, false, 0)) { - if (gKeyInputCountdown <= 1) { - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - } + if (!RADIO_CheckValidChannel(Channel, false, 0)) { + if (gKeyInputCountdown <= 1) { + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + } - return; - } + return; + } - gBeepToPlay = BEEP_NONE; + gBeepToPlay = BEEP_NONE; - #ifdef ENABLE_VOICE - gAnotherVoiceID = (VOICE_ID_t)Key; - #endif + #ifdef ENABLE_VOICE + gAnotherVoiceID = (VOICE_ID_t)Key; + #endif - gEeprom.MrChannel[Vfo] = (uint8_t)Channel; - gEeprom.ScreenChannel[Vfo] = (uint8_t)Channel; - //gRequestSaveVFO = true; - gVfoConfigureMode = VFO_CONFIGURE_RELOAD; + gEeprom.MrChannel[Vfo] = (uint8_t)Channel; + gEeprom.ScreenChannel[Vfo] = (uint8_t)Channel; + //gRequestSaveVFO = true; + gVfoConfigureMode = VFO_CONFIGURE_RELOAD; - RADIO_ConfigureChannel(gEeprom.TX_VFO, gVfoConfigureMode); - - return; + RADIO_ConfigureChannel(gEeprom.TX_VFO, gVfoConfigureMode); + + return; } void channelMoveSwitch(void) { - if (IS_MR_CHANNEL(gTxVfo->CHANNEL_SAVE)) { // user is entering channel number - uint16_t Channel = 0; - - switch (gInputBoxIndex) - { - case 1: - Channel = gInputBox[0]; - break; - case 2: - Channel = (gInputBox[0] * 10) + gInputBox[1]; - break; - case 3: - Channel = (gInputBox[0] * 100) + (gInputBox[1] * 10) + gInputBox[2]; - break; - } - - if ((Channel == 0) && (gInputBoxIndex != 3)) { - return; - } - - if (gInputBoxIndex == 3) { - gInputBoxIndex = 0; - gKeyInputCountdown = 1; - - channelMove(Channel - 1); - SETTINGS_SaveVfoIndices(); - - return; - } - - channelMove(Channel - 1); - } + if (IS_MR_CHANNEL(gTxVfo->CHANNEL_SAVE)) { // user is entering channel number + uint16_t Channel = 0; + + switch (gInputBoxIndex) + { + case 1: + Channel = gInputBox[0]; + break; + case 2: + Channel = (gInputBox[0] * 10) + gInputBox[1]; + break; + case 3: + Channel = (gInputBox[0] * 100) + (gInputBox[1] * 10) + gInputBox[2]; + break; + } + + if ((Channel == 0) && (gInputBoxIndex != 3)) { + return; + } + + if (gInputBoxIndex == 3) { + gInputBoxIndex = 0; + gKeyInputCountdown = 1; + + channelMove(Channel - 1); + SETTINGS_SaveVfoIndices(); + + return; + } + + channelMove(Channel - 1); + } } static void MAIN_Key_DIGITS(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld) { - if (bKeyHeld) { // key held down - if (bKeyPressed) { - if (gScreenToDisplay == DISPLAY_MAIN) { - if (gInputBoxIndex > 0) { // delete any inputted chars - gInputBoxIndex = 0; - gRequestDisplayScreen = DISPLAY_MAIN; - } - - gWasFKeyPressed = false; - gUpdateStatus = true; - - processFKeyFunction(Key, false); - } - } - return; - } - - if (bKeyPressed) - { // key is pressed - gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; // beep when key is pressed - return; // don't use the key till it's released - } - - if (!gWasFKeyPressed) { // F-key wasn't pressed - - if (gScanStateDir != SCAN_OFF){ - switch(Key) { - case KEY_0...KEY_5: - gEeprom.SCAN_LIST_DEFAULT = Key; - break; - default: - break; - } - return; - } - - const uint8_t Vfo = gEeprom.TX_VFO; - INPUTBOX_Append(Key); - gKeyInputCountdown = key_input_timeout_500ms; - - channelMoveSwitch(); - - gRequestDisplayScreen = DISPLAY_MAIN; - - if (IS_MR_CHANNEL(gTxVfo->CHANNEL_SAVE)) { // user is entering channel number - - gKeyInputCountdown = (key_input_timeout_500ms / 5); // short time... - - #ifdef ENABLE_VOICE - gAnotherVoiceID = (VOICE_ID_t)Key; - #endif - - return; - } - -// #ifdef ENABLE_NOAA -// if (!IS_NOAA_CHANNEL(gTxVfo->CHANNEL_SAVE)) -// #endif - if (IS_FREQ_CHANNEL(gTxVfo->CHANNEL_SAVE)) - { // user is entering a frequency + if (bKeyHeld) { // key held down + if (bKeyPressed) { + if (gScreenToDisplay == DISPLAY_MAIN) { + if (gInputBoxIndex > 0) { // delete any inputted chars + gInputBoxIndex = 0; + gRequestDisplayScreen = DISPLAY_MAIN; + } + + gWasFKeyPressed = false; + gUpdateStatus = true; + + processFKeyFunction(Key, false); + } + } + return; + } + + if (bKeyPressed) + { // key is pressed + gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; // beep when key is pressed + return; // don't use the key till it's released + } + + if (!gWasFKeyPressed) { // F-key wasn't pressed + + if (gScanStateDir != SCAN_OFF){ + switch(Key) { + case KEY_0...KEY_5: + gEeprom.SCAN_LIST_DEFAULT = Key; + break; + default: + break; + } + return; + } + + const uint8_t Vfo = gEeprom.TX_VFO; + INPUTBOX_Append(Key); + gKeyInputCountdown = key_input_timeout_500ms; + + channelMoveSwitch(); + + gRequestDisplayScreen = DISPLAY_MAIN; + + if (IS_MR_CHANNEL(gTxVfo->CHANNEL_SAVE)) { // user is entering channel number + + gKeyInputCountdown = (key_input_timeout_500ms / 5); // short time... + + #ifdef ENABLE_VOICE + gAnotherVoiceID = (VOICE_ID_t)Key; + #endif + + return; + } + +// #ifdef ENABLE_NOAA +// if (!IS_NOAA_CHANNEL(gTxVfo->CHANNEL_SAVE)) +// #endif + if (IS_FREQ_CHANNEL(gTxVfo->CHANNEL_SAVE)) + { // user is entering a frequency #ifdef ENABLE_VOICE - gAnotherVoiceID = (VOICE_ID_t)Key; + gAnotherVoiceID = (VOICE_ID_t)Key; #endif - bool isGigaF = gTxVfo->pRX->Frequency >= _1GHz_in_KHz; - if (gInputBoxIndex < 6 + isGigaF) { - return; - } - - gInputBoxIndex = 0; - uint32_t Frequency = StrToUL(INPUTBOX_GetAscii()) * 100; - - // clamp the frequency entered to some valid value - if (Frequency < frequencyBandTable[0].lower) { - Frequency = frequencyBandTable[0].lower; - } - else if (Frequency >= BX4819_band1.upper && Frequency < BX4819_band2.lower) { - const uint32_t center = (BX4819_band1.upper + BX4819_band2.lower) / 2; - Frequency = (Frequency < center) ? BX4819_band1.upper : BX4819_band2.lower; - } - else if (Frequency > frequencyBandTable[BAND_N_ELEM - 1].upper) { - Frequency = frequencyBandTable[BAND_N_ELEM - 1].upper; - } - - const FREQUENCY_Band_t band = FREQUENCY_GetBand(Frequency); - - if (gTxVfo->Band != band) { - gTxVfo->Band = band; - gEeprom.ScreenChannel[Vfo] = band + FREQ_CHANNEL_FIRST; - gEeprom.FreqChannel[Vfo] = band + FREQ_CHANNEL_FIRST; - - SETTINGS_SaveVfoIndices(); - - RADIO_ConfigureChannel(Vfo, VFO_CONFIGURE_RELOAD); - } - - Frequency = FREQUENCY_RoundToStep(Frequency, gTxVfo->StepFrequency); - - if (Frequency >= BX4819_band1.upper && Frequency < BX4819_band2.lower) - { // clamp the frequency to the limit - const uint32_t center = (BX4819_band1.upper + BX4819_band2.lower) / 2; - Frequency = (Frequency < center) ? BX4819_band1.upper - gTxVfo->StepFrequency : BX4819_band2.lower; - } - - gTxVfo->freq_config_RX.Frequency = Frequency; - - gRequestSaveChannel = 1; - return; - - } - #ifdef ENABLE_NOAA - else - if (IS_NOAA_CHANNEL(gTxVfo->CHANNEL_SAVE)) - { // user is entering NOAA channel - if (gInputBoxIndex != 2) { - #ifdef ENABLE_VOICE - gAnotherVoiceID = (VOICE_ID_t)Key; - #endif - gRequestDisplayScreen = DISPLAY_MAIN; - return; - } - - gInputBoxIndex = 0; - - uint8_t Channel = (gInputBox[0] * 10) + gInputBox[1]; - if (Channel >= 1 && Channel <= ARRAY_SIZE(NoaaFrequencyTable)) { - Channel += NOAA_CHANNEL_FIRST; - #ifdef ENABLE_VOICE - gAnotherVoiceID = (VOICE_ID_t)Key; - #endif - gEeprom.NoaaChannel[Vfo] = Channel; - gEeprom.ScreenChannel[Vfo] = Channel; - gRequestSaveVFO = true; - gVfoConfigureMode = VFO_CONFIGURE_RELOAD; - return; - } - } - #endif - - gRequestDisplayScreen = DISPLAY_MAIN; - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - return; - } - - gWasFKeyPressed = false; - gUpdateStatus = true; - - if(Key == 8) - { - ACTION_BackLightOnDemand(); - return; - } - else if(Key == 9) - { - ACTION_BackLight(); - return; - } - - processFKeyFunction(Key, true); + bool isGigaF = gTxVfo->pRX->Frequency >= _1GHz_in_KHz; + if (gInputBoxIndex < 6 + isGigaF) { + return; + } + + gInputBoxIndex = 0; + uint32_t Frequency = StrToUL(INPUTBOX_GetAscii()) * 100; + + // clamp the frequency entered to some valid value + if (Frequency < frequencyBandTable[0].lower) { + Frequency = frequencyBandTable[0].lower; + } + else if (Frequency >= BX4819_band1.upper && Frequency < BX4819_band2.lower) { + const uint32_t center = (BX4819_band1.upper + BX4819_band2.lower) / 2; + Frequency = (Frequency < center) ? BX4819_band1.upper : BX4819_band2.lower; + } + else if (Frequency > frequencyBandTable[BAND_N_ELEM - 1].upper) { + Frequency = frequencyBandTable[BAND_N_ELEM - 1].upper; + } + + const FREQUENCY_Band_t band = FREQUENCY_GetBand(Frequency); + + if (gTxVfo->Band != band) { + gTxVfo->Band = band; + gEeprom.ScreenChannel[Vfo] = band + FREQ_CHANNEL_FIRST; + gEeprom.FreqChannel[Vfo] = band + FREQ_CHANNEL_FIRST; + + SETTINGS_SaveVfoIndices(); + + RADIO_ConfigureChannel(Vfo, VFO_CONFIGURE_RELOAD); + } + + Frequency = FREQUENCY_RoundToStep(Frequency, gTxVfo->StepFrequency); + + if (Frequency >= BX4819_band1.upper && Frequency < BX4819_band2.lower) + { // clamp the frequency to the limit + const uint32_t center = (BX4819_band1.upper + BX4819_band2.lower) / 2; + Frequency = (Frequency < center) ? BX4819_band1.upper - gTxVfo->StepFrequency : BX4819_band2.lower; + } + + gTxVfo->freq_config_RX.Frequency = Frequency; + + gRequestSaveChannel = 1; + return; + + } + #ifdef ENABLE_NOAA + else + if (IS_NOAA_CHANNEL(gTxVfo->CHANNEL_SAVE)) + { // user is entering NOAA channel + if (gInputBoxIndex != 2) { + #ifdef ENABLE_VOICE + gAnotherVoiceID = (VOICE_ID_t)Key; + #endif + gRequestDisplayScreen = DISPLAY_MAIN; + return; + } + + gInputBoxIndex = 0; + + uint8_t Channel = (gInputBox[0] * 10) + gInputBox[1]; + if (Channel >= 1 && Channel <= ARRAY_SIZE(NoaaFrequencyTable)) { + Channel += NOAA_CHANNEL_FIRST; + #ifdef ENABLE_VOICE + gAnotherVoiceID = (VOICE_ID_t)Key; + #endif + gEeprom.NoaaChannel[Vfo] = Channel; + gEeprom.ScreenChannel[Vfo] = Channel; + gRequestSaveVFO = true; + gVfoConfigureMode = VFO_CONFIGURE_RELOAD; + return; + } + } + #endif + + gRequestDisplayScreen = DISPLAY_MAIN; + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + return; + } + + gWasFKeyPressed = false; + gUpdateStatus = true; + + if(Key == 8) + { + ACTION_BackLightOnDemand(); + return; + } + else if(Key == 9) + { + ACTION_BackLight(); + return; + } + + processFKeyFunction(Key, true); } static void MAIN_Key_EXIT(bool bKeyPressed, bool bKeyHeld) { - if (!bKeyHeld && bKeyPressed) { // exit key pressed - gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; + if (!bKeyHeld && bKeyPressed) { // exit key pressed + gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; #ifdef ENABLE_DTMF_CALLING - if (gDTMF_CallState != DTMF_CALL_STATE_NONE && gCurrentFunction != FUNCTION_TRANSMIT) - { // clear CALL mode being displayed - gDTMF_CallState = DTMF_CALL_STATE_NONE; - gUpdateDisplay = true; - return; - } + if (gDTMF_CallState != DTMF_CALL_STATE_NONE && gCurrentFunction != FUNCTION_TRANSMIT) + { // clear CALL mode being displayed + gDTMF_CallState = DTMF_CALL_STATE_NONE; + gUpdateDisplay = true; + return; + } #endif #ifdef ENABLE_FMRADIO - if (!gFmRadioMode) + if (!gFmRadioMode) #endif - { - if (gScanStateDir == SCAN_OFF) { - if (gInputBoxIndex == 0) - return; - gInputBox[--gInputBoxIndex] = 10; + { + if (gScanStateDir == SCAN_OFF) { + if (gInputBoxIndex == 0) + return; + gInputBox[--gInputBoxIndex] = 10; - gKeyInputCountdown = key_input_timeout_500ms; + gKeyInputCountdown = key_input_timeout_500ms; #ifdef ENABLE_VOICE - if (gInputBoxIndex == 0) - gAnotherVoiceID = VOICE_ID_CANCEL; + if (gInputBoxIndex == 0) + gAnotherVoiceID = VOICE_ID_CANCEL; #endif - } - else { - gScanKeepResult = false; - CHFRSCANNER_Stop(); + } + else { + gScanKeepResult = false; + CHFRSCANNER_Stop(); #ifdef ENABLE_VOICE - gAnotherVoiceID = VOICE_ID_SCANNING_STOP; + gAnotherVoiceID = VOICE_ID_SCANNING_STOP; #endif - } + } - gRequestDisplayScreen = DISPLAY_MAIN; - return; - } + gRequestDisplayScreen = DISPLAY_MAIN; + return; + } #ifdef ENABLE_FMRADIO - ACTION_FM(); + ACTION_FM(); #endif - return; - } - - if (bKeyHeld && bKeyPressed) { // exit key held down - if (gInputBoxIndex > 0 || gDTMF_InputBox_Index > 0 || gDTMF_InputMode) - { // cancel key input mode (channel/frequency entry) - gDTMF_InputMode = false; - gDTMF_InputBox_Index = 0; - memset(gDTMF_String, 0, sizeof(gDTMF_String)); - gInputBoxIndex = 0; - gRequestDisplayScreen = DISPLAY_MAIN; - gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; - } - } + return; + } + + if (bKeyHeld && bKeyPressed) { // exit key held down + if (gInputBoxIndex > 0 || gDTMF_InputBox_Index > 0 || gDTMF_InputMode) + { // cancel key input mode (channel/frequency entry) + gDTMF_InputMode = false; + gDTMF_InputBox_Index = 0; + memset(gDTMF_String, 0, sizeof(gDTMF_String)); + gInputBoxIndex = 0; + gRequestDisplayScreen = DISPLAY_MAIN; + gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; + } + } } static void MAIN_Key_MENU(bool bKeyPressed, bool bKeyHeld) { - if (bKeyPressed && !bKeyHeld) // menu key pressed - gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; - - if (bKeyHeld) { // menu key held down (long press) - if (bKeyPressed) { // long press MENU key - - #ifdef ENABLE_FEAT_F4HWN - // Exclude work with list 1, 2, 3 or all list - if(gScanStateDir != SCAN_OFF) - { - if(FUNCTION_IsRx()) - { - gMR_ChannelExclude[gTxVfo->CHANNEL_SAVE] = true; - - gVfoConfigureMode = VFO_CONFIGURE; - gFlagResetVfos = true; - - lastFoundFrqOrChan = lastFoundFrqOrChanOld; - - CHFRSCANNER_ContinueScanning(); - } - - return; - } - #endif - - gWasFKeyPressed = false; - - if (gScreenToDisplay == DISPLAY_MAIN) { - if (gInputBoxIndex > 0) { // delete any inputted chars - gInputBoxIndex = 0; - gRequestDisplayScreen = DISPLAY_MAIN; - } - - gWasFKeyPressed = false; - gUpdateStatus = true; - - ACTION_Handle(KEY_MENU, bKeyPressed, bKeyHeld); - } - } - - return; - } - - if (!bKeyPressed && !gDTMF_InputMode) { // menu key released - const bool bFlag = !gInputBoxIndex; - gInputBoxIndex = 0; - - if (bFlag) { - if (gScanStateDir != SCAN_OFF) { - CHFRSCANNER_Stop(); - return; - } - - gFlagRefreshSetting = true; - gRequestDisplayScreen = DISPLAY_MENU; - #ifdef ENABLE_VOICE - gAnotherVoiceID = VOICE_ID_MENU; - #endif - } - else { - gRequestDisplayScreen = DISPLAY_MAIN; - } - } + if (bKeyPressed && !bKeyHeld) // menu key pressed + gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; + + if (bKeyHeld) { // menu key held down (long press) + if (bKeyPressed) { // long press MENU key + + #ifdef ENABLE_FEAT_F4HWN + // Exclude work with list 1, 2, 3 or all list + if(gScanStateDir != SCAN_OFF) + { + if(FUNCTION_IsRx()) + { + gMR_ChannelExclude[gTxVfo->CHANNEL_SAVE] = true; + + gVfoConfigureMode = VFO_CONFIGURE; + gFlagResetVfos = true; + + lastFoundFrqOrChan = lastFoundFrqOrChanOld; + + CHFRSCANNER_ContinueScanning(); + } + + return; + } + #endif + + gWasFKeyPressed = false; + + if (gScreenToDisplay == DISPLAY_MAIN) { + if (gInputBoxIndex > 0) { // delete any inputted chars + gInputBoxIndex = 0; + gRequestDisplayScreen = DISPLAY_MAIN; + } + + gWasFKeyPressed = false; + gUpdateStatus = true; + + ACTION_Handle(KEY_MENU, bKeyPressed, bKeyHeld); + } + } + + return; + } + + if (!bKeyPressed && !gDTMF_InputMode) { // menu key released + const bool bFlag = !gInputBoxIndex; + gInputBoxIndex = 0; + + if (bFlag) { + if (gScanStateDir != SCAN_OFF) { + CHFRSCANNER_Stop(); + return; + } + + gFlagRefreshSetting = true; + gRequestDisplayScreen = DISPLAY_MENU; + #ifdef ENABLE_VOICE + gAnotherVoiceID = VOICE_ID_MENU; + #endif + } + else { + gRequestDisplayScreen = DISPLAY_MAIN; + } + } } static void MAIN_Key_STAR(bool bKeyPressed, bool bKeyHeld) { - if (gCurrentFunction == FUNCTION_TRANSMIT) - return; - - if (gInputBoxIndex) { - if (!bKeyHeld && bKeyPressed) - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - return; - } - - if (bKeyHeld && !gWasFKeyPressed){ // long press - if (!bKeyPressed) // released - return; - - ACTION_Scan(false);// toggle scanning - - gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; - return; - } - - if (bKeyPressed) { // just pressed - return; - } - - // just released - - if (!gWasFKeyPressed) // pressed without the F-key - { - if (gScanStateDir == SCAN_OFF + if (gCurrentFunction == FUNCTION_TRANSMIT) + return; + + if (gInputBoxIndex) { + if (!bKeyHeld && bKeyPressed) + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + return; + } + + if (bKeyHeld && !gWasFKeyPressed){ // long press + if (!bKeyPressed) // released + return; + + ACTION_Scan(false);// toggle scanning + + gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; + return; + } + + if (bKeyPressed) { // just pressed + return; + } + + // just released + + if (!gWasFKeyPressed) // pressed without the F-key + { + if (gScanStateDir == SCAN_OFF #ifdef ENABLE_NOAA - && !IS_NOAA_CHANNEL(gTxVfo->CHANNEL_SAVE) + && !IS_NOAA_CHANNEL(gTxVfo->CHANNEL_SAVE) #endif #ifdef ENABLE_SCAN_RANGES - && gScanRangeStart == 0 -#endif - ) - { // start entering a DTMF string - gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; - memcpy(gDTMF_InputBox, gDTMF_String, MIN(sizeof(gDTMF_InputBox), sizeof(gDTMF_String) - 1)); - gDTMF_InputBox_Index = 0; - gDTMF_InputMode = true; - - gKeyInputCountdown = key_input_timeout_500ms; - - gRequestDisplayScreen = DISPLAY_MAIN; - } - else - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - } - else - { // with the F-key - gWasFKeyPressed = false; + && gScanRangeStart == 0 +#endif + ) + { // start entering a DTMF string + gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; + memcpy(gDTMF_InputBox, gDTMF_String, MIN(sizeof(gDTMF_InputBox), sizeof(gDTMF_String) - 1)); + gDTMF_InputBox_Index = 0; + gDTMF_InputMode = true; + + gKeyInputCountdown = key_input_timeout_500ms; + + gRequestDisplayScreen = DISPLAY_MAIN; + } + else + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + } + else + { // with the F-key + gWasFKeyPressed = false; #ifdef ENABLE_NOAA - if (IS_NOAA_CHANNEL(gTxVfo->CHANNEL_SAVE)) { - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - return; - } + if (IS_NOAA_CHANNEL(gTxVfo->CHANNEL_SAVE)) { + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + return; + } #endif - // scan the CTCSS/DCS code - gBackup_CROSS_BAND_RX_TX = gEeprom.CROSS_BAND_RX_TX; - gEeprom.CROSS_BAND_RX_TX = CROSS_BAND_OFF; - SCANNER_Start(true); - gRequestDisplayScreen = DISPLAY_SCANNER; - } - - //gPttWasReleased = true; Fixed issue #138 - gUpdateStatus = true; + // scan the CTCSS/DCS code + gBackup_CROSS_BAND_RX_TX = gEeprom.CROSS_BAND_RX_TX; + gEeprom.CROSS_BAND_RX_TX = CROSS_BAND_OFF; + SCANNER_Start(true); + gRequestDisplayScreen = DISPLAY_SCANNER; + } + + //gPttWasReleased = true; Fixed issue #138 + gUpdateStatus = true; } static void MAIN_Key_UP_DOWN(bool bKeyPressed, bool bKeyHeld, int8_t Direction) { #ifdef ENABLE_FEAT_F4HWN // Set Squelch F + UP or Down - if(gWasFKeyPressed) { - switch(Direction) - { - case 1: - processFKeyFunction(KEY_UP, false); - break; - case -1: - processFKeyFunction(KEY_DOWN, false); - break; - } - return; - } + if(gWasFKeyPressed) { + switch(Direction) + { + case 1: + processFKeyFunction(KEY_UP, false); + break; + case -1: + processFKeyFunction(KEY_DOWN, false); + break; + } + return; + } #endif - uint8_t Channel = gEeprom.ScreenChannel[gEeprom.TX_VFO]; + uint8_t Channel = gEeprom.ScreenChannel[gEeprom.TX_VFO]; - if (bKeyHeld || !bKeyPressed) { // key held or released - if (gInputBoxIndex > 0) - return; // leave if input box active + if (bKeyHeld || !bKeyPressed) { // key held or released + if (gInputBoxIndex > 0) + return; // leave if input box active - if (!bKeyPressed) { - if (!bKeyHeld || IS_FREQ_CHANNEL(Channel)) - return; - // if released long button press and not in freq mode + if (!bKeyPressed) { + if (!bKeyHeld || IS_FREQ_CHANNEL(Channel)) + return; + // if released long button press and not in freq mode #ifdef ENABLE_VOICE - AUDIO_SetDigitVoice(0, gTxVfo->CHANNEL_SAVE + 1); // say channel number - gAnotherVoiceID = (VOICE_ID_t)0xFE; + AUDIO_SetDigitVoice(0, gTxVfo->CHANNEL_SAVE + 1); // say channel number + gAnotherVoiceID = (VOICE_ID_t)0xFE; #endif - return; - } - } - else { // short pressed - if (gInputBoxIndex > 0) { - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - return; - } - gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; - } - - if (gScanStateDir == SCAN_OFF) { + return; + } + } + else { // short pressed + if (gInputBoxIndex > 0) { + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + return; + } + gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; + } + + if (gScanStateDir == SCAN_OFF) { #ifdef ENABLE_NOAA - if (!IS_NOAA_CHANNEL(Channel)) + if (!IS_NOAA_CHANNEL(Channel)) #endif - { - uint8_t Next; - if (IS_FREQ_CHANNEL(Channel)) { // step/down in frequency - const uint32_t frequency = APP_SetFrequencyByStep(gTxVfo, Direction); - - if (RX_freq_check(frequency) < 0) { // frequency not allowed - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - return; - } - gTxVfo->freq_config_RX.Frequency = frequency; - BK4819_SetFrequency(frequency); - BK4819_RX_TurnOn(); - gRequestSaveChannel = 1; - return; - } - - Next = RADIO_FindNextChannel(Channel + Direction, Direction, false, 0); - if (Next == 0xFF) - return; - if (Channel == Next) - return; - gEeprom.MrChannel[gEeprom.TX_VFO] = Next; - gEeprom.ScreenChannel[gEeprom.TX_VFO] = Next; - - if (!bKeyHeld) { + { + uint8_t Next; + if (IS_FREQ_CHANNEL(Channel)) { // step/down in frequency + const uint32_t frequency = APP_SetFrequencyByStep(gTxVfo, Direction); + + if (RX_freq_check(frequency) < 0) { // frequency not allowed + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + return; + } + gTxVfo->freq_config_RX.Frequency = frequency; + BK4819_SetFrequency(frequency); + BK4819_RX_TurnOn(); + gRequestSaveChannel = 1; + return; + } + + Next = RADIO_FindNextChannel(Channel + Direction, Direction, false, 0); + if (Next == 0xFF) + return; + if (Channel == Next) + return; + gEeprom.MrChannel[gEeprom.TX_VFO] = Next; + gEeprom.ScreenChannel[gEeprom.TX_VFO] = Next; + + if (!bKeyHeld) { #ifdef ENABLE_VOICE - AUDIO_SetDigitVoice(0, Next + 1); - gAnotherVoiceID = (VOICE_ID_t)0xFE; + AUDIO_SetDigitVoice(0, Next + 1); + gAnotherVoiceID = (VOICE_ID_t)0xFE; #endif - } - } + } + } #ifdef ENABLE_NOAA - else { - Channel = NOAA_CHANNEL_FIRST + NUMBER_AddWithWraparound(gEeprom.ScreenChannel[gEeprom.TX_VFO] - NOAA_CHANNEL_FIRST, Direction, 0, 9); - gEeprom.NoaaChannel[gEeprom.TX_VFO] = Channel; - gEeprom.ScreenChannel[gEeprom.TX_VFO] = Channel; - } + else { + Channel = NOAA_CHANNEL_FIRST + NUMBER_AddWithWraparound(gEeprom.ScreenChannel[gEeprom.TX_VFO] - NOAA_CHANNEL_FIRST, Direction, 0, 9); + gEeprom.NoaaChannel[gEeprom.TX_VFO] = Channel; + gEeprom.ScreenChannel[gEeprom.TX_VFO] = Channel; + } #endif - gRequestSaveVFO = true; - gVfoConfigureMode = VFO_CONFIGURE_RELOAD; - return; - } + gRequestSaveVFO = true; + gVfoConfigureMode = VFO_CONFIGURE_RELOAD; + return; + } - // jump to the next channel - CHFRSCANNER_Start(false, Direction); - gScanPauseDelayIn_10ms = 1; - gScheduleScanListen = false; + // jump to the next channel + CHFRSCANNER_Start(false, Direction); + gScanPauseDelayIn_10ms = 1; + gScheduleScanListen = false; - gPttWasReleased = true; + gPttWasReleased = true; } void MAIN_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld) { #ifdef ENABLE_FMRADIO - if (gFmRadioMode && Key != KEY_PTT && Key != KEY_EXIT) { - if (!bKeyHeld && bKeyPressed) - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - return; - } + if (gFmRadioMode && Key != KEY_PTT && Key != KEY_EXIT) { + if (!bKeyHeld && bKeyPressed) + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + return; + } #endif - if (gDTMF_InputMode && bKeyPressed && !bKeyHeld) { - const char Character = DTMF_GetCharacter(Key); - if (Character != 0xFF) - { // add key to DTMF string - DTMF_Append(Character); - gKeyInputCountdown = key_input_timeout_500ms; - gRequestDisplayScreen = DISPLAY_MAIN; - gPttWasReleased = true; - gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; - return; - } - } - - // TODO: ??? -// if (Key > KEY_PTT) -// { -// Key = KEY_SIDE2; // what's this doing ??? -// } - - switch (Key) { + if (gDTMF_InputMode && bKeyPressed && !bKeyHeld) { + const char Character = DTMF_GetCharacter(Key); + if (Character != 0xFF) + { // add key to DTMF string + DTMF_Append(Character); + gKeyInputCountdown = key_input_timeout_500ms; + gRequestDisplayScreen = DISPLAY_MAIN; + gPttWasReleased = true; + gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; + return; + } + } + + // TODO: ??? +// if (Key > KEY_PTT) +// { +// Key = KEY_SIDE2; // what's this doing ??? +// } + + switch (Key) { #ifdef ENABLE_FEAT_F4HWN - case KEY_SIDE1: - case KEY_SIDE2: + case KEY_SIDE1: + case KEY_SIDE2: #endif - case KEY_0...KEY_9: - MAIN_Key_DIGITS(Key, bKeyPressed, bKeyHeld); - break; - case KEY_MENU: - MAIN_Key_MENU(bKeyPressed, bKeyHeld); - break; - case KEY_UP: - MAIN_Key_UP_DOWN(bKeyPressed, bKeyHeld, 1); - break; - case KEY_DOWN: - MAIN_Key_UP_DOWN(bKeyPressed, bKeyHeld, -1); - break; - case KEY_EXIT: - MAIN_Key_EXIT(bKeyPressed, bKeyHeld); - break; - case KEY_STAR: - MAIN_Key_STAR(bKeyPressed, bKeyHeld); - break; - case KEY_F: - GENERIC_Key_F(bKeyPressed, bKeyHeld); - break; - case KEY_PTT: - GENERIC_Key_PTT(bKeyPressed); - break; - default: - if (!bKeyHeld && bKeyPressed) - gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; - break; - } + case KEY_0...KEY_9: + MAIN_Key_DIGITS(Key, bKeyPressed, bKeyHeld); + break; + case KEY_MENU: + MAIN_Key_MENU(bKeyPressed, bKeyHeld); + break; + case KEY_UP: + MAIN_Key_UP_DOWN(bKeyPressed, bKeyHeld, 1); + break; + case KEY_DOWN: + MAIN_Key_UP_DOWN(bKeyPressed, bKeyHeld, -1); + break; + case KEY_EXIT: + MAIN_Key_EXIT(bKeyPressed, bKeyHeld); + break; + case KEY_STAR: + MAIN_Key_STAR(bKeyPressed, bKeyHeld); + break; + case KEY_F: + GENERIC_Key_F(bKeyPressed, bKeyHeld); + break; + case KEY_PTT: + GENERIC_Key_PTT(bKeyPressed); + break; + default: + if (!bKeyHeld && bKeyPressed) + gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; + break; + } } From 17d6b44327fd3da001586146bf4a3bc0d3ed29ac Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Fri, 16 Aug 2024 02:02:21 +0200 Subject: [PATCH 24/30] Add missing tab --- ui/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/main.c b/ui/main.c index 6b9d6f317..d9c191507 100644 --- a/ui/main.c +++ b/ui/main.c @@ -1089,7 +1089,7 @@ void UI_DisplayMain(void) case OUTPUT_POWER_LOW3: Level = 2; break; case OUTPUT_POWER_LOW4: Level = 2; break; case OUTPUT_POWER_LOW5: Level = 2; break; - case OUTPUT_POWER_MID: Level = 4; break; + case OUTPUT_POWER_MID: Level = 4; break; case OUTPUT_POWER_HIGH: Level = 6; break; } } From 9b4e59f77672459844ef1fe88407561b776f6823 Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Fri, 16 Aug 2024 02:13:49 +0200 Subject: [PATCH 25/30] Add missing tab --- app/scanner.c | 10 +- app/spectrum.c | 2255 ++++++++++++++++++++++++++---------------------- app/spectrum.h | 141 +-- 3 files changed, 1330 insertions(+), 1076 deletions(-) diff --git a/app/scanner.c b/app/scanner.c index 2d7c523a4..35059eb8b 100644 --- a/app/scanner.c +++ b/app/scanner.c @@ -344,14 +344,14 @@ void SCANNER_Start(bool singleFreq) gScanDelay_10ms = scan_delay_10ms; gScanCssResultCode = 0xFF; gScanCssResultType = 0xFF; - scanHitCount = 0; + scanHitCount = 0; gScanUseCssResult = false; g_CxCSS_TAIL_Found = false; g_CDCSS_Lost = false; gCDCSSCodeType = 0; g_CTCSS_Lost = false; #ifdef ENABLE_VOX - g_VOX_Lost = false; + g_VOX_Lost = false; #endif g_SquelchLost = false; gScannerSaveState = SCAN_SAVE_NO_PROMPT; @@ -365,8 +365,8 @@ void SCANNER_Stop(void) gVfoConfigureMode = VFO_CONFIGURE_RELOAD; gFlagResetVfos = true; gUpdateStatus = true; - gCssBackgroundScan = false; - gScanUseCssResult = false; + gCssBackgroundScan = false; + gScanUseCssResult = false; #ifdef ENABLE_VOICE gAnotherVoiceID = VOICE_ID_CANCEL; #endif @@ -414,7 +414,7 @@ void SCANNER_TimeSlice10ms(void) BK4819_SetScanFrequency(gScanFrequency); gScanCssResultCode = 0xFF; gScanCssResultType = 0xFF; - scanHitCount = 0; + scanHitCount = 0; gScanUseCssResult = false; gScanProgressIndicator = 0; gScanCssState = SCAN_CSS_STATE_SCANNING; diff --git a/app/spectrum.c b/app/spectrum.c index 0896c76a7..64bd6195a 100644 --- a/app/spectrum.c +++ b/app/spectrum.c @@ -28,17 +28,18 @@ #include "ui/main.h" #ifdef ENABLE_FEAT_F4HWN_SCREENSHOT - #include "screenshot.h" +#include "screenshot.h" #endif #ifdef ENABLE_FEAT_F4HWN_SPECTRUM - #include "driver/eeprom.h" +#include "driver/eeprom.h" #endif -struct FrequencyBandInfo { - uint32_t lower; - uint32_t upper; - uint32_t middle; +struct FrequencyBandInfo +{ + uint32_t lower; + uint32_t upper; + uint32_t middle; }; #define F_MIN frequencyBandTable[0].lower @@ -110,36 +111,36 @@ RegisterSpec registerSpecs[] = { uint16_t statuslineUpdateTimer = 0; #ifdef ENABLE_FEAT_F4HWN_SPECTRUM - static void LoadSettings() - { +static void LoadSettings() +{ uint8_t Data[8] = {0}; // 1FF0..0x1FF7 EEPROM_ReadBuffer(0x1FF0, Data, 8); settings.scanStepIndex = ((Data[4] & 0xF0) >> 4); - if(settings.scanStepIndex > 14) + if (settings.scanStepIndex > 14) { - settings.scanStepIndex = S_STEP_25_0kHz; + settings.scanStepIndex = S_STEP_25_0kHz; } settings.stepsCount = ((Data[4] & 0x0F) & 0b1100) >> 2; - if(settings.stepsCount > 3) + if (settings.stepsCount > 3) { - settings.stepsCount = STEPS_64; + settings.stepsCount = STEPS_64; } settings.listenBw = ((Data[4] & 0x0F) & 0b0011); - if(settings.listenBw > 2) + if (settings.listenBw > 2) { - settings.listenBw = BK4819_FILTER_BW_WIDE; + settings.listenBw = BK4819_FILTER_BW_WIDE; } - } +} - static void SaveSettings() - { +static void SaveSettings() +{ uint8_t Data[8] = {0}; // 1FF0..0x1FF7 EEPROM_ReadBuffer(0x1FF0, Data, 8); @@ -147,187 +148,218 @@ uint16_t statuslineUpdateTimer = 0; Data[4] = (settings.scanStepIndex << 4) | (settings.stepsCount << 2) | settings.listenBw; EEPROM_WriteBuffer(0x1FF0, Data); - } +} #endif -static uint8_t DBm2S(int dbm) { - uint8_t i = 0; - dbm *= -1; - for (i = 0; i < ARRAY_SIZE(U8RssiMap); i++) { - if (dbm >= U8RssiMap[i]) { - return i; +static uint8_t DBm2S(int dbm) +{ + uint8_t i = 0; + dbm *= -1; + for (i = 0; i < ARRAY_SIZE(U8RssiMap); i++) + { + if (dbm >= U8RssiMap[i]) + { + return i; + } } - } - return i; + return i; } -static int Rssi2DBm(uint16_t rssi) { - return (rssi / 2) - 160 + dBmCorrTable[gRxVfo->Band]; +static int Rssi2DBm(uint16_t rssi) +{ + return (rssi / 2) - 160 + dBmCorrTable[gRxVfo->Band]; } -static uint16_t GetRegMenuValue(uint8_t st) { - RegisterSpec s = registerSpecs[st]; - return (BK4819_ReadRegister(s.num) >> s.offset) & s.mask; +static uint16_t GetRegMenuValue(uint8_t st) +{ + RegisterSpec s = registerSpecs[st]; + return (BK4819_ReadRegister(s.num) >> s.offset) & s.mask; } void LockAGC() { - RADIO_SetupAGC(settings.modulationType==MODULATION_AM, lockAGC); - lockAGC = true; + RADIO_SetupAGC(settings.modulationType == MODULATION_AM, lockAGC); + lockAGC = true; } -static void SetRegMenuValue(uint8_t st, bool add) { - uint16_t v = GetRegMenuValue(st); - RegisterSpec s = registerSpecs[st]; +static void SetRegMenuValue(uint8_t st, bool add) +{ + uint16_t v = GetRegMenuValue(st); + RegisterSpec s = registerSpecs[st]; - if(s.num == BK4819_REG_13) - LockAGC(); + if (s.num == BK4819_REG_13) + LockAGC(); - uint16_t reg = BK4819_ReadRegister(s.num); - if (add && v <= s.mask - s.inc) { - v += s.inc; - } else if (!add && v >= 0 + s.inc) { - v -= s.inc; - } - // TODO: use max value for bits count in max value, or reset by additional - // mask in spec - reg &= ~(s.mask << s.offset); - BK4819_WriteRegister(s.num, reg | (v << s.offset)); - redrawScreen = true; + uint16_t reg = BK4819_ReadRegister(s.num); + if (add && v <= s.mask - s.inc) + { + v += s.inc; + } + else if (!add && v >= 0 + s.inc) + { + v -= s.inc; + } + // TODO: use max value for bits count in max value, or reset by additional + // mask in spec + reg &= ~(s.mask << s.offset); + BK4819_WriteRegister(s.num, reg | (v << s.offset)); + redrawScreen = true; } // GUI functions #ifndef ENABLE_FEAT_F4HWN - static void PutPixel(uint8_t x, uint8_t y, bool fill) { +static void PutPixel(uint8_t x, uint8_t y, bool fill) +{ UI_DrawPixelBuffer(gFrameBuffer, x, y, fill); - } - static void PutPixelStatus(uint8_t x, uint8_t y, bool fill) { +} +static void PutPixelStatus(uint8_t x, uint8_t y, bool fill) +{ UI_DrawPixelBuffer(&gStatusLine, x, y, fill); - } +} #endif -static void DrawVLine(int sy, int ey, int nx, bool fill) { - for (int i = sy; i <= ey; i++) { - if (i < 56 && nx < 128) { - PutPixel(nx, i, fill); +static void DrawVLine(int sy, int ey, int nx, bool fill) +{ + for (int i = sy; i <= ey; i++) + { + if (i < 56 && nx < 128) + { + PutPixel(nx, i, fill); + } } - } } #ifndef ENABLE_FEAT_F4HWN - static void GUI_DisplaySmallest(const char *pString, uint8_t x, uint8_t y, - bool statusbar, bool fill) { +static void GUI_DisplaySmallest(const char *pString, uint8_t x, uint8_t y, + bool statusbar, bool fill) +{ uint8_t c; uint8_t pixels; const uint8_t *p = (const uint8_t *)pString; - while ((c = *p++) && c != '\0') { - c -= 0x20; - for (int i = 0; i < 3; ++i) { - pixels = gFont3x5[c][i]; - for (int j = 0; j < 6; ++j) { - if (pixels & 1) { - if (statusbar) - PutPixelStatus(x + i, y + j, fill); - else - PutPixel(x + i, y + j, fill); - } - pixels >>= 1; + while ((c = *p++) && c != '\0') + { + c -= 0x20; + for (int i = 0; i < 3; ++i) + { + pixels = gFont3x5[c][i]; + for (int j = 0; j < 6; ++j) + { + if (pixels & 1) + { + if (statusbar) + PutPixelStatus(x + i, y + j, fill); + else + PutPixel(x + i, y + j, fill); + } + pixels >>= 1; + } } - } - x += 4; + x += 4; } - } +} #endif // Utility functions -KEY_Code_t GetKey() { - KEY_Code_t btn = KEYBOARD_Poll(); - if (btn == KEY_INVALID && !GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT)) { - btn = KEY_PTT; - } - return btn; +KEY_Code_t GetKey() +{ + KEY_Code_t btn = KEYBOARD_Poll(); + if (btn == KEY_INVALID && !GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT)) + { + btn = KEY_PTT; + } + return btn; } -static int clamp(int v, int min, int max) { - return v <= min ? min : (v >= max ? max : v); +static int clamp(int v, int min, int max) +{ + return v <= min ? min : (v >= max ? max : v); } static uint8_t my_abs(signed v) { return v > 0 ? v : -v; } -void SetState(State state) { - previousState = currentState; - currentState = state; - redrawScreen = true; - redrawStatus = true; +void SetState(State state) +{ + previousState = currentState; + currentState = state; + redrawScreen = true; + redrawStatus = true; } // Radio functions -static void ToggleAFBit(bool on) { - uint16_t reg = BK4819_ReadRegister(BK4819_REG_47); - reg &= ~(1 << 8); - if (on) - reg |= on << 8; - BK4819_WriteRegister(BK4819_REG_47, reg); -} - -static const BK4819_REGISTER_t registers_to_save[] ={ - BK4819_REG_30, - BK4819_REG_37, - BK4819_REG_3D, - BK4819_REG_43, - BK4819_REG_47, - BK4819_REG_48, - BK4819_REG_7E, +static void ToggleAFBit(bool on) +{ + uint16_t reg = BK4819_ReadRegister(BK4819_REG_47); + reg &= ~(1 << 8); + if (on) + reg |= on << 8; + BK4819_WriteRegister(BK4819_REG_47, reg); +} + +static const BK4819_REGISTER_t registers_to_save[] = { + BK4819_REG_30, + BK4819_REG_37, + BK4819_REG_3D, + BK4819_REG_43, + BK4819_REG_47, + BK4819_REG_48, + BK4819_REG_7E, }; -static uint16_t registers_stack [sizeof(registers_to_save)]; +static uint16_t registers_stack[sizeof(registers_to_save)]; -static void BackupRegisters() { - for (uint32_t i = 0; i < ARRAY_SIZE(registers_to_save); i++){ - registers_stack[i] = BK4819_ReadRegister(registers_to_save[i]); - } +static void BackupRegisters() +{ + for (uint32_t i = 0; i < ARRAY_SIZE(registers_to_save); i++) + { + registers_stack[i] = BK4819_ReadRegister(registers_to_save[i]); + } } -static void RestoreRegisters() { +static void RestoreRegisters() +{ - for (uint32_t i = 0; i < ARRAY_SIZE(registers_to_save); i++){ - BK4819_WriteRegister(registers_to_save[i], registers_stack[i]); - } + for (uint32_t i = 0; i < ARRAY_SIZE(registers_to_save); i++) + { + BK4819_WriteRegister(registers_to_save[i], registers_stack[i]); + } #ifdef ENABLE_FEAT_F4HWN - gVfoConfigureMode = VFO_CONFIGURE; + gVfoConfigureMode = VFO_CONFIGURE; #endif } -static void ToggleAFDAC(bool on) { - uint32_t Reg = BK4819_ReadRegister(BK4819_REG_30); - Reg &= ~(1 << 9); - if (on) - Reg |= (1 << 9); - BK4819_WriteRegister(BK4819_REG_30, Reg); +static void ToggleAFDAC(bool on) +{ + uint32_t Reg = BK4819_ReadRegister(BK4819_REG_30); + Reg &= ~(1 << 9); + if (on) + Reg |= (1 << 9); + BK4819_WriteRegister(BK4819_REG_30, Reg); } -static void SetF(uint32_t f) { - fMeasure = f; +static void SetF(uint32_t f) +{ + fMeasure = f; - BK4819_SetFrequency(fMeasure); - BK4819_PickRXFilterPathBasedOnFrequency(fMeasure); - uint16_t reg = BK4819_ReadRegister(BK4819_REG_30); - BK4819_WriteRegister(BK4819_REG_30, 0); - BK4819_WriteRegister(BK4819_REG_30, reg); + BK4819_SetFrequency(fMeasure); + BK4819_PickRXFilterPathBasedOnFrequency(fMeasure); + uint16_t reg = BK4819_ReadRegister(BK4819_REG_30); + BK4819_WriteRegister(BK4819_REG_30, 0); + BK4819_WriteRegister(BK4819_REG_30, reg); } // Spectrum related bool IsPeakOverLevel() { return peak.rssi >= settings.rssiTriggerLevel; } -static void ResetPeak() { - peak.t = 0; - peak.rssi = 0; +static void ResetPeak() +{ + peak.t = 0; + peak.rssi = 0; } bool IsCenterMode() { return settings.scanStepIndex < S_STEP_2_5kHz; } @@ -337,1068 +369,1261 @@ uint16_t GetScanStep() { return scanStepValues[settings.scanStepIndex]; } uint16_t GetStepsCount() { #ifdef ENABLE_SCAN_RANGES - if(gScanRangeStart) { - return (gScanRangeStop - gScanRangeStart) / GetScanStep(); - } + if (gScanRangeStart) + { + return (gScanRangeStop - gScanRangeStart) / GetScanStep(); + } #endif - return 128 >> settings.stepsCount; + return 128 >> settings.stepsCount; } uint32_t GetBW() { return GetStepsCount() * GetScanStep(); } -uint32_t GetFStart() { - return IsCenterMode() ? currentFreq - (GetBW() >> 1) : currentFreq; +uint32_t GetFStart() +{ + return IsCenterMode() ? currentFreq - (GetBW() >> 1) : currentFreq; } uint32_t GetFEnd() { return currentFreq + GetBW(); } -static void TuneToPeak() { - scanInfo.f = peak.f; - scanInfo.rssi = peak.rssi; - scanInfo.i = peak.i; - SetF(scanInfo.f); +static void TuneToPeak() +{ + scanInfo.f = peak.f; + scanInfo.rssi = peak.rssi; + scanInfo.i = peak.i; + SetF(scanInfo.f); } -static void DeInitSpectrum() { - SetF(initialFreq); - RestoreRegisters(); - isInitialized = false; +static void DeInitSpectrum() +{ + SetF(initialFreq); + RestoreRegisters(); + isInitialized = false; } -uint8_t GetBWRegValueForScan() { - return scanStepBWRegValues[settings.scanStepIndex]; +uint8_t GetBWRegValueForScan() +{ + return scanStepBWRegValues[settings.scanStepIndex]; } -uint16_t GetRssi() { - // SYSTICK_DelayUs(800); - // testing autodelay based on Glitch value - while ((BK4819_ReadRegister(0x63) & 0b11111111) >= 255) { - SYSTICK_DelayUs(100); - } - uint16_t rssi = BK4819_GetRSSI(); +uint16_t GetRssi() +{ + // SYSTICK_DelayUs(800); + // testing autodelay based on Glitch value + while ((BK4819_ReadRegister(0x63) & 0b11111111) >= 255) + { + SYSTICK_DelayUs(100); + } + uint16_t rssi = BK4819_GetRSSI(); #ifdef ENABLE_AM_FIX - if(settings.modulationType==MODULATION_AM && gSetting_AM_fix) - rssi += AM_fix_get_gain_diff()*2; + if (settings.modulationType == MODULATION_AM && gSetting_AM_fix) + rssi += AM_fix_get_gain_diff() * 2; #endif - return rssi; + return rssi; } -static void ToggleAudio(bool on) { - if (on == audioState) { - return; - } - audioState = on; - if (on) { - AUDIO_AudioPathOn(); - } else { - AUDIO_AudioPathOff(); - } +static void ToggleAudio(bool on) +{ + if (on == audioState) + { + return; + } + audioState = on; + if (on) + { + AUDIO_AudioPathOn(); + } + else + { + AUDIO_AudioPathOff(); + } } -static void ToggleRX(bool on) { - isListening = on; +static void ToggleRX(bool on) +{ + isListening = on; - RADIO_SetupAGC(on, lockAGC); - BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, on); + RADIO_SetupAGC(on, lockAGC); + BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, on); - ToggleAudio(on); - ToggleAFDAC(on); - ToggleAFBit(on); + ToggleAudio(on); + ToggleAFDAC(on); + ToggleAFBit(on); - if (on) { - listenT = 1000; - BK4819_WriteRegister(0x43, listenBWRegValues[settings.listenBw]); - } else { - BK4819_WriteRegister(0x43, GetBWRegValueForScan()); - } + if (on) + { + listenT = 1000; + BK4819_WriteRegister(0x43, listenBWRegValues[settings.listenBw]); + } + else + { + BK4819_WriteRegister(0x43, GetBWRegValueForScan()); + } } // Scan info -static void ResetScanStats() { - scanInfo.rssi = 0; - scanInfo.rssiMax = 0; - scanInfo.iPeak = 0; - scanInfo.fPeak = 0; +static void ResetScanStats() +{ + scanInfo.rssi = 0; + scanInfo.rssiMax = 0; + scanInfo.iPeak = 0; + scanInfo.fPeak = 0; } -static void InitScan() { - ResetScanStats(); - scanInfo.i = 0; - scanInfo.f = GetFStart(); +static void InitScan() +{ + ResetScanStats(); + scanInfo.i = 0; + scanInfo.f = GetFStart(); - scanInfo.scanStep = GetScanStep(); - scanInfo.measurementsCount = GetStepsCount(); + scanInfo.scanStep = GetScanStep(); + scanInfo.measurementsCount = GetStepsCount(); } -static void ResetBlacklist() { - for (int i = 0; i < 128; ++i) { - if (rssiHistory[i] == RSSI_MAX_VALUE) - rssiHistory[i] = 0; - } +static void ResetBlacklist() +{ + for (int i = 0; i < 128; ++i) + { + if (rssiHistory[i] == RSSI_MAX_VALUE) + rssiHistory[i] = 0; + } #ifdef ENABLE_SCAN_RANGES - memset(blacklistFreqs, 0, sizeof(blacklistFreqs)); - blacklistFreqsIdx = 0; + memset(blacklistFreqs, 0, sizeof(blacklistFreqs)); + blacklistFreqsIdx = 0; #endif } -static void RelaunchScan() { - InitScan(); - ResetPeak(); - ToggleRX(false); +static void RelaunchScan() +{ + InitScan(); + ResetPeak(); + ToggleRX(false); #ifdef SPECTRUM_AUTOMATIC_SQUELCH - settings.rssiTriggerLevel = RSSI_MAX_VALUE; + settings.rssiTriggerLevel = RSSI_MAX_VALUE; #endif - preventKeypress = true; - scanInfo.rssiMin = RSSI_MAX_VALUE; + preventKeypress = true; + scanInfo.rssiMin = RSSI_MAX_VALUE; } -static void UpdateScanInfo() { - if (scanInfo.rssi > scanInfo.rssiMax) { - scanInfo.rssiMax = scanInfo.rssi; - scanInfo.fPeak = scanInfo.f; - scanInfo.iPeak = scanInfo.i; - } +static void UpdateScanInfo() +{ + if (scanInfo.rssi > scanInfo.rssiMax) + { + scanInfo.rssiMax = scanInfo.rssi; + scanInfo.fPeak = scanInfo.f; + scanInfo.iPeak = scanInfo.i; + } - if (scanInfo.rssi < scanInfo.rssiMin) { - scanInfo.rssiMin = scanInfo.rssi; - settings.dbMin = Rssi2DBm(scanInfo.rssiMin); - redrawStatus = true; - } + if (scanInfo.rssi < scanInfo.rssiMin) + { + scanInfo.rssiMin = scanInfo.rssi; + settings.dbMin = Rssi2DBm(scanInfo.rssiMin); + redrawStatus = true; + } } -static void AutoTriggerLevel() { - if (settings.rssiTriggerLevel == RSSI_MAX_VALUE) { - settings.rssiTriggerLevel = clamp(scanInfo.rssiMax + 8, 0, RSSI_MAX_VALUE); - } +static void AutoTriggerLevel() +{ + if (settings.rssiTriggerLevel == RSSI_MAX_VALUE) + { + settings.rssiTriggerLevel = clamp(scanInfo.rssiMax + 8, 0, RSSI_MAX_VALUE); + } } -static void UpdatePeakInfoForce() { - peak.t = 0; - peak.rssi = scanInfo.rssiMax; - peak.f = scanInfo.fPeak; - peak.i = scanInfo.iPeak; - AutoTriggerLevel(); +static void UpdatePeakInfoForce() +{ + peak.t = 0; + peak.rssi = scanInfo.rssiMax; + peak.f = scanInfo.fPeak; + peak.i = scanInfo.iPeak; + AutoTriggerLevel(); } -static void UpdatePeakInfo() { - if (peak.f == 0 || peak.t >= 1024 || peak.rssi < scanInfo.rssiMax) - UpdatePeakInfoForce(); +static void UpdatePeakInfo() +{ + if (peak.f == 0 || peak.t >= 1024 || peak.rssi < scanInfo.rssiMax) + UpdatePeakInfoForce(); } static void SetRssiHistory(uint16_t idx, uint16_t rssi) { #ifdef ENABLE_SCAN_RANGES - if(scanInfo.measurementsCount > 128) { - uint8_t i = (uint32_t)ARRAY_SIZE(rssiHistory) * 1000 / scanInfo.measurementsCount * idx / 1000; - if(rssiHistory[i] < rssi || isListening) - rssiHistory[i] = rssi; - rssiHistory[(i+1)%128] = 0; - return; - } + if (scanInfo.measurementsCount > 128) + { + uint8_t i = (uint32_t)ARRAY_SIZE(rssiHistory) * 1000 / scanInfo.measurementsCount * idx / 1000; + if (rssiHistory[i] < rssi || isListening) + rssiHistory[i] = rssi; + rssiHistory[(i + 1) % 128] = 0; + return; + } #endif - rssiHistory[idx] = rssi; + rssiHistory[idx] = rssi; } static void Measure() { - uint16_t rssi = scanInfo.rssi = GetRssi(); - SetRssiHistory(scanInfo.i, rssi); + uint16_t rssi = scanInfo.rssi = GetRssi(); + SetRssiHistory(scanInfo.i, rssi); } // Update things by keypress -static uint16_t dbm2rssi(int dBm) { - return (dBm + 160 - dBmCorrTable[gRxVfo->Band]) * 2; -} - -static void ClampRssiTriggerLevel() { - settings.rssiTriggerLevel = - clamp(settings.rssiTriggerLevel, dbm2rssi(settings.dbMin), - dbm2rssi(settings.dbMax)); -} - -static void UpdateRssiTriggerLevel(bool inc) { - if (inc) - settings.rssiTriggerLevel += 2; - else - settings.rssiTriggerLevel -= 2; - - ClampRssiTriggerLevel(); - - redrawScreen = true; - redrawStatus = true; -} - -static void UpdateDBMax(bool inc) { - if (inc && settings.dbMax < 10) { - settings.dbMax += 1; - } else if (!inc && settings.dbMax > settings.dbMin) { - settings.dbMax -= 1; - } else { - return; - } - - ClampRssiTriggerLevel(); - redrawStatus = true; - redrawScreen = true; - SYSTEM_DelayMs(20); -} - -static void UpdateScanStep(bool inc) { - if (inc) { - settings.scanStepIndex = settings.scanStepIndex != S_STEP_100_0kHz ? settings.scanStepIndex + 1 : 0; - } else { - settings.scanStepIndex = settings.scanStepIndex != 0 ? settings.scanStepIndex - 1 : S_STEP_100_0kHz; - } - - settings.frequencyChangeStep = GetBW() >> 1; - RelaunchScan(); - ResetBlacklist(); - redrawScreen = true; -} - -static void UpdateCurrentFreq(bool inc) { - if (inc && currentFreq < F_MAX) { - currentFreq += settings.frequencyChangeStep; - } else if (!inc && currentFreq > F_MIN) { - currentFreq -= settings.frequencyChangeStep; - } else { - return; - } - RelaunchScan(); - ResetBlacklist(); - redrawScreen = true; -} - -static void UpdateCurrentFreqStill(bool inc) { - uint8_t offset = modulationTypeTuneSteps[settings.modulationType]; - uint32_t f = fMeasure; - if (inc && f < F_MAX) { - f += offset; - } else if (!inc && f > F_MIN) { - f -= offset; - } - SetF(f); - redrawScreen = true; -} - -static void UpdateFreqChangeStep(bool inc) { - uint16_t diff = GetScanStep() * 4; - if (inc && settings.frequencyChangeStep < 200000) { - settings.frequencyChangeStep += diff; - } else if (!inc && settings.frequencyChangeStep > 10000) { - settings.frequencyChangeStep -= diff; - } - SYSTEM_DelayMs(100); - redrawScreen = true; -} - -static void ToggleModulation() { - if (settings.modulationType < MODULATION_UKNOWN - 1) { - settings.modulationType++; - } else { - settings.modulationType = MODULATION_FM; - } - RADIO_SetModulation(settings.modulationType); - - RelaunchScan(); - redrawScreen = true; -} - -static void ToggleListeningBW() { - if (settings.listenBw == BK4819_FILTER_BW_NARROWER) { - settings.listenBw = BK4819_FILTER_BW_WIDE; - } else { - settings.listenBw++; - } - redrawScreen = true; -} - -static void ToggleBacklight() { - settings.backlightState = !settings.backlightState; - if (settings.backlightState) { - BACKLIGHT_TurnOn(); - } else { - BACKLIGHT_TurnOff(); - } - // For screenshot - #ifdef ENABLE_FEAT_F4HWN_SCREENSHOT +static uint16_t dbm2rssi(int dBm) +{ + return (dBm + 160 - dBmCorrTable[gRxVfo->Band]) * 2; +} + +static void ClampRssiTriggerLevel() +{ + settings.rssiTriggerLevel = + clamp(settings.rssiTriggerLevel, dbm2rssi(settings.dbMin), + dbm2rssi(settings.dbMax)); +} + +static void UpdateRssiTriggerLevel(bool inc) +{ + if (inc) + settings.rssiTriggerLevel += 2; + else + settings.rssiTriggerLevel -= 2; + + ClampRssiTriggerLevel(); + + redrawScreen = true; + redrawStatus = true; +} + +static void UpdateDBMax(bool inc) +{ + if (inc && settings.dbMax < 10) + { + settings.dbMax += 1; + } + else if (!inc && settings.dbMax > settings.dbMin) + { + settings.dbMax -= 1; + } + else + { + return; + } + + ClampRssiTriggerLevel(); + redrawStatus = true; + redrawScreen = true; + SYSTEM_DelayMs(20); +} + +static void UpdateScanStep(bool inc) +{ + if (inc) + { + settings.scanStepIndex = settings.scanStepIndex != S_STEP_100_0kHz ? settings.scanStepIndex + 1 : 0; + } + else + { + settings.scanStepIndex = settings.scanStepIndex != 0 ? settings.scanStepIndex - 1 : S_STEP_100_0kHz; + } + + settings.frequencyChangeStep = GetBW() >> 1; + RelaunchScan(); + ResetBlacklist(); + redrawScreen = true; +} + +static void UpdateCurrentFreq(bool inc) +{ + if (inc && currentFreq < F_MAX) + { + currentFreq += settings.frequencyChangeStep; + } + else if (!inc && currentFreq > F_MIN) + { + currentFreq -= settings.frequencyChangeStep; + } + else + { + return; + } + RelaunchScan(); + ResetBlacklist(); + redrawScreen = true; +} + +static void UpdateCurrentFreqStill(bool inc) +{ + uint8_t offset = modulationTypeTuneSteps[settings.modulationType]; + uint32_t f = fMeasure; + if (inc && f < F_MAX) + { + f += offset; + } + else if (!inc && f > F_MIN) + { + f -= offset; + } + SetF(f); + redrawScreen = true; +} + +static void UpdateFreqChangeStep(bool inc) +{ + uint16_t diff = GetScanStep() * 4; + if (inc && settings.frequencyChangeStep < 200000) + { + settings.frequencyChangeStep += diff; + } + else if (!inc && settings.frequencyChangeStep > 10000) + { + settings.frequencyChangeStep -= diff; + } + SYSTEM_DelayMs(100); + redrawScreen = true; +} + +static void ToggleModulation() +{ + if (settings.modulationType < MODULATION_UKNOWN - 1) + { + settings.modulationType++; + } + else + { + settings.modulationType = MODULATION_FM; + } + RADIO_SetModulation(settings.modulationType); + + RelaunchScan(); + redrawScreen = true; +} + +static void ToggleListeningBW() +{ + if (settings.listenBw == BK4819_FILTER_BW_NARROWER) + { + settings.listenBw = BK4819_FILTER_BW_WIDE; + } + else + { + settings.listenBw++; + } + redrawScreen = true; +} + +static void ToggleBacklight() +{ + settings.backlightState = !settings.backlightState; + if (settings.backlightState) + { + BACKLIGHT_TurnOn(); + } + else + { + BACKLIGHT_TurnOff(); + } +// For screenshot +#ifdef ENABLE_FEAT_F4HWN_SCREENSHOT getScreenShot(); - #endif -} - -static void ToggleStepsCount() { - if (settings.stepsCount == STEPS_128) { - settings.stepsCount = STEPS_16; - } else { - settings.stepsCount--; - } - settings.frequencyChangeStep = GetBW() >> 1; - RelaunchScan(); - ResetBlacklist(); - redrawScreen = true; -} - -static void ResetFreqInput() { - tempFreq = 0; - for (int i = 0; i < 10; ++i) { - freqInputString[i] = '-'; - } -} - -static void FreqInput() { - freqInputIndex = 0; - freqInputDotIndex = 0; - ResetFreqInput(); - SetState(FREQ_INPUT); -} - -static void UpdateFreqInput(KEY_Code_t key) { - if (key != KEY_EXIT && freqInputIndex >= 10) { - return; - } - if (key == KEY_STAR) { - if (freqInputIndex == 0 || freqInputDotIndex) { - return; - } - freqInputDotIndex = freqInputIndex; - } - if (key == KEY_EXIT) { - freqInputIndex--; - if (freqInputDotIndex == freqInputIndex) - freqInputDotIndex = 0; - } else { - freqInputArr[freqInputIndex++] = key; - } - - ResetFreqInput(); - - uint8_t dotIndex = - freqInputDotIndex == 0 ? freqInputIndex : freqInputDotIndex; - - KEY_Code_t digitKey; - for (int i = 0; i < 10; ++i) { - if (i < freqInputIndex) { - digitKey = freqInputArr[i]; - freqInputString[i] = digitKey <= KEY_9 ? '0' + digitKey - KEY_0 : '.'; - } else { - freqInputString[i] = '-'; - } - } - - uint32_t base = 100000; // 1MHz in BK units - for (int i = dotIndex - 1; i >= 0; --i) { - tempFreq += (freqInputArr[i] - KEY_0) * base; - base *= 10; - } - - base = 10000; // 0.1MHz in BK units - if (dotIndex < freqInputIndex) { - for (int i = dotIndex + 1; i < freqInputIndex; ++i) { - tempFreq += (freqInputArr[i] - KEY_0) * base; - base /= 10; - } - } - redrawScreen = true; -} - -static void Blacklist() { +#endif +} + +static void ToggleStepsCount() +{ + if (settings.stepsCount == STEPS_128) + { + settings.stepsCount = STEPS_16; + } + else + { + settings.stepsCount--; + } + settings.frequencyChangeStep = GetBW() >> 1; + RelaunchScan(); + ResetBlacklist(); + redrawScreen = true; +} + +static void ResetFreqInput() +{ + tempFreq = 0; + for (int i = 0; i < 10; ++i) + { + freqInputString[i] = '-'; + } +} + +static void FreqInput() +{ + freqInputIndex = 0; + freqInputDotIndex = 0; + ResetFreqInput(); + SetState(FREQ_INPUT); +} + +static void UpdateFreqInput(KEY_Code_t key) +{ + if (key != KEY_EXIT && freqInputIndex >= 10) + { + return; + } + if (key == KEY_STAR) + { + if (freqInputIndex == 0 || freqInputDotIndex) + { + return; + } + freqInputDotIndex = freqInputIndex; + } + if (key == KEY_EXIT) + { + freqInputIndex--; + if (freqInputDotIndex == freqInputIndex) + freqInputDotIndex = 0; + } + else + { + freqInputArr[freqInputIndex++] = key; + } + + ResetFreqInput(); + + uint8_t dotIndex = + freqInputDotIndex == 0 ? freqInputIndex : freqInputDotIndex; + + KEY_Code_t digitKey; + for (int i = 0; i < 10; ++i) + { + if (i < freqInputIndex) + { + digitKey = freqInputArr[i]; + freqInputString[i] = digitKey <= KEY_9 ? '0' + digitKey - KEY_0 : '.'; + } + else + { + freqInputString[i] = '-'; + } + } + + uint32_t base = 100000; // 1MHz in BK units + for (int i = dotIndex - 1; i >= 0; --i) + { + tempFreq += (freqInputArr[i] - KEY_0) * base; + base *= 10; + } + + base = 10000; // 0.1MHz in BK units + if (dotIndex < freqInputIndex) + { + for (int i = dotIndex + 1; i < freqInputIndex; ++i) + { + tempFreq += (freqInputArr[i] - KEY_0) * base; + base /= 10; + } + } + redrawScreen = true; +} + +static void Blacklist() +{ #ifdef ENABLE_SCAN_RANGES - blacklistFreqs[blacklistFreqsIdx++ % ARRAY_SIZE(blacklistFreqs)] = peak.i; + blacklistFreqs[blacklistFreqsIdx++ % ARRAY_SIZE(blacklistFreqs)] = peak.i; #endif - SetRssiHistory(peak.i, RSSI_MAX_VALUE); - ResetPeak(); - ToggleRX(false); - ResetScanStats(); + SetRssiHistory(peak.i, RSSI_MAX_VALUE); + ResetPeak(); + ToggleRX(false); + ResetScanStats(); } #ifdef ENABLE_SCAN_RANGES static bool IsBlacklisted(uint16_t idx) { - if(blacklistFreqsIdx) - for(uint8_t i = 0; i < ARRAY_SIZE(blacklistFreqs); i++) - if(blacklistFreqs[i] == idx) - return true; - return false; + if (blacklistFreqsIdx) + for (uint8_t i = 0; i < ARRAY_SIZE(blacklistFreqs); i++) + if (blacklistFreqs[i] == idx) + return true; + return false; } #endif // Draw things // applied x2 to prevent initial rounding -uint8_t Rssi2PX(uint16_t rssi, uint8_t pxMin, uint8_t pxMax) { - const int DB_MIN = settings.dbMin << 1; - const int DB_MAX = settings.dbMax << 1; - const int DB_RANGE = DB_MAX - DB_MIN; +uint8_t Rssi2PX(uint16_t rssi, uint8_t pxMin, uint8_t pxMax) +{ + const int DB_MIN = settings.dbMin << 1; + const int DB_MAX = settings.dbMax << 1; + const int DB_RANGE = DB_MAX - DB_MIN; - const uint8_t PX_RANGE = pxMax - pxMin; + const uint8_t PX_RANGE = pxMax - pxMin; - int dbm = clamp(Rssi2DBm(rssi) << 1, DB_MIN, DB_MAX); + int dbm = clamp(Rssi2DBm(rssi) << 1, DB_MIN, DB_MAX); - return ((dbm - DB_MIN) * PX_RANGE + DB_RANGE / 2) / DB_RANGE + pxMin; + return ((dbm - DB_MIN) * PX_RANGE + DB_RANGE / 2) / DB_RANGE + pxMin; } -uint8_t Rssi2Y(uint16_t rssi) { - return DrawingEndY - Rssi2PX(rssi, 0, DrawingEndY); +uint8_t Rssi2Y(uint16_t rssi) +{ + return DrawingEndY - Rssi2PX(rssi, 0, DrawingEndY); } -static void DrawSpectrum() { - for (uint8_t x = 0; x < 128; ++x) { - uint16_t rssi = rssiHistory[x >> settings.stepsCount]; - if (rssi != RSSI_MAX_VALUE) { - DrawVLine(Rssi2Y(rssi), DrawingEndY, x, true); +static void DrawSpectrum() +{ + for (uint8_t x = 0; x < 128; ++x) + { + uint16_t rssi = rssiHistory[x >> settings.stepsCount]; + if (rssi != RSSI_MAX_VALUE) + { + DrawVLine(Rssi2Y(rssi), DrawingEndY, x, true); + } } - } } -static void DrawStatus() { +static void DrawStatus() +{ #ifdef SPECTRUM_EXTRA_VALUES - sprintf(String, "%d/%d P:%d T:%d", settings.dbMin, settings.dbMax, - Rssi2DBm(peak.rssi), Rssi2DBm(settings.rssiTriggerLevel)); + sprintf(String, "%d/%d P:%d T:%d", settings.dbMin, settings.dbMax, + Rssi2DBm(peak.rssi), Rssi2DBm(settings.rssiTriggerLevel)); #else - sprintf(String, "%d/%d", settings.dbMin, settings.dbMax); + sprintf(String, "%d/%d", settings.dbMin, settings.dbMax); #endif - GUI_DisplaySmallest(String, 0, 1, true, true); + GUI_DisplaySmallest(String, 0, 1, true, true); - BOARD_ADC_GetBatteryInfo(&gBatteryVoltages[gBatteryCheckCounter++ % 4], - &gBatteryCurrent); + BOARD_ADC_GetBatteryInfo(&gBatteryVoltages[gBatteryCheckCounter++ % 4], + &gBatteryCurrent); - uint16_t voltage = (gBatteryVoltages[0] + gBatteryVoltages[1] + - gBatteryVoltages[2] + gBatteryVoltages[3]) / - 4 * 760 / gBatteryCalibration[3]; + uint16_t voltage = (gBatteryVoltages[0] + gBatteryVoltages[1] + + gBatteryVoltages[2] + gBatteryVoltages[3]) / + 4 * 760 / gBatteryCalibration[3]; - unsigned perc = BATTERY_VoltsToPercent(voltage); + unsigned perc = BATTERY_VoltsToPercent(voltage); - // sprintf(String, "%d %d", voltage, perc); - // GUI_DisplaySmallest(String, 48, 1, true, true); + // sprintf(String, "%d %d", voltage, perc); + // GUI_DisplaySmallest(String, 48, 1, true, true); - gStatusLine[116] = 0b00011100; - gStatusLine[117] = 0b00111110; - for (int i = 118; i <= 126; i++) { - gStatusLine[i] = 0b00100010; - } + gStatusLine[116] = 0b00011100; + gStatusLine[117] = 0b00111110; + for (int i = 118; i <= 126; i++) + { + gStatusLine[i] = 0b00100010; + } - for (unsigned i = 127; i >= 118; i--) { - if (127 - i <= (perc + 5) * 9 / 100) { - gStatusLine[i] = 0b00111110; + for (unsigned i = 127; i >= 118; i--) + { + if (127 - i <= (perc + 5) * 9 / 100) + { + gStatusLine[i] = 0b00111110; + } } - } } #ifdef ENABLE_FEAT_F4HWN_SPECTRUM - static void ShowChannelName(uint32_t f) { +static void ShowChannelName(uint32_t f) +{ unsigned int i; memset(String, 0, sizeof(String)); - if ( isListening ) { - for (i = 0; IS_MR_CHANNEL(i); i++) { - if (RADIO_CheckValidChannel(i, false, 0)) { - if (SETTINGS_FetchChannelFrequency(i) == f) { - SETTINGS_FetchChannelName(String, i); - UI_PrintStringSmallBold(String[0] ? String : "--", 8, 127, 1); - break; - } + if (isListening) + { + for (i = 0; IS_MR_CHANNEL(i); i++) + { + if (RADIO_CheckValidChannel(i, false, 0)) + { + if (SETTINGS_FetchChannelFrequency(i) == f) + { + SETTINGS_FetchChannelName(String, i); + UI_PrintStringSmallBold(String[0] ? String : "--", 8, 127, 1); + break; + } + } } - } } - } +} #endif -static void DrawF(uint32_t f) { - sprintf(String, "%u.%05u", f / 100000, f % 100000); - UI_PrintStringSmallNormal(String, 8, 127, 0); +static void DrawF(uint32_t f) +{ + sprintf(String, "%u.%05u", f / 100000, f % 100000); + UI_PrintStringSmallNormal(String, 8, 127, 0); - sprintf(String, "%3s", gModulationStr[settings.modulationType]); - GUI_DisplaySmallest(String, 116, 1, false, true); - sprintf(String, "%4sk", bwOptions[settings.listenBw]); - GUI_DisplaySmallest(String, 108, 7, false, true); + sprintf(String, "%3s", gModulationStr[settings.modulationType]); + GUI_DisplaySmallest(String, 116, 1, false, true); + sprintf(String, "%4sk", bwOptions[settings.listenBw]); + GUI_DisplaySmallest(String, 108, 7, false, true); #ifdef ENABLE_FEAT_F4HWN_SPECTRUM - ShowChannelName(f); + ShowChannelName(f); #endif } -static void DrawNums() { - - if (currentState == SPECTRUM) { - sprintf(String, "%ux", GetStepsCount()); - GUI_DisplaySmallest(String, 0, 1, false, true); - sprintf(String, "%u.%02uk", GetScanStep() / 100, GetScanStep() % 100); - GUI_DisplaySmallest(String, 0, 7, false, true); - } - - if (IsCenterMode()) { - sprintf(String, "%u.%05u \x7F%u.%02uk", currentFreq / 100000, - currentFreq % 100000, settings.frequencyChangeStep / 100, - settings.frequencyChangeStep % 100); - GUI_DisplaySmallest(String, 36, 49, false, true); - } else { - sprintf(String, "%u.%05u", GetFStart() / 100000, GetFStart() % 100000); - GUI_DisplaySmallest(String, 0, 49, false, true); - - sprintf(String, "\x7F%u.%02uk", settings.frequencyChangeStep / 100, - settings.frequencyChangeStep % 100); - GUI_DisplaySmallest(String, 48, 49, false, true); - - sprintf(String, "%u.%05u", GetFEnd() / 100000, GetFEnd() % 100000); - GUI_DisplaySmallest(String, 93, 49, false, true); - } -} - -static void DrawRssiTriggerLevel() { - if (settings.rssiTriggerLevel == RSSI_MAX_VALUE || monitorMode) - return; - uint8_t y = Rssi2Y(settings.rssiTriggerLevel); - for (uint8_t x = 0; x < 128; x += 2) { - PutPixel(x, y, true); - } -} - -static void DrawTicks() { - uint32_t f = GetFStart(); - uint32_t span = GetFEnd() - GetFStart(); - uint32_t step = span / 128; - for (uint8_t i = 0; i < 128; i += (1 << settings.stepsCount)) { - f = GetFStart() + span * i / 128; - uint8_t barValue = 0b00000001; - (f % 10000) < step && (barValue |= 0b00000010); - (f % 50000) < step && (barValue |= 0b00000100); - (f % 100000) < step && (barValue |= 0b00011000); - - gFrameBuffer[5][i] |= barValue; - } - - // center - if (IsCenterMode()) { - memset(gFrameBuffer[5] + 62, 0x80, 5); - gFrameBuffer[5][64] = 0xff; - } else { - memset(gFrameBuffer[5] + 1, 0x80, 3); - memset(gFrameBuffer[5] + 124, 0x80, 3); - - gFrameBuffer[5][0] = 0xff; - gFrameBuffer[5][127] = 0xff; - } -} - -static void DrawArrow(uint8_t x) { - for (signed i = -2; i <= 2; ++i) { - signed v = x + i; - if (!(v & 128)) { - gFrameBuffer[5][v] |= (0b01111000 << my_abs(i)) & 0b01111000; - } - } -} - -static void OnKeyDown(uint8_t key) { - switch (key) { - case KEY_3: - UpdateDBMax(true); - break; - case KEY_9: - UpdateDBMax(false); - break; - case KEY_1: - UpdateScanStep(true); - break; - case KEY_7: - UpdateScanStep(false); - break; - case KEY_2: - UpdateFreqChangeStep(true); - break; - case KEY_8: - UpdateFreqChangeStep(false); - break; - case KEY_UP: +static void DrawNums() +{ + + if (currentState == SPECTRUM) + { + sprintf(String, "%ux", GetStepsCount()); + GUI_DisplaySmallest(String, 0, 1, false, true); + sprintf(String, "%u.%02uk", GetScanStep() / 100, GetScanStep() % 100); + GUI_DisplaySmallest(String, 0, 7, false, true); + } + + if (IsCenterMode()) + { + sprintf(String, "%u.%05u \x7F%u.%02uk", currentFreq / 100000, + currentFreq % 100000, settings.frequencyChangeStep / 100, + settings.frequencyChangeStep % 100); + GUI_DisplaySmallest(String, 36, 49, false, true); + } + else + { + sprintf(String, "%u.%05u", GetFStart() / 100000, GetFStart() % 100000); + GUI_DisplaySmallest(String, 0, 49, false, true); + + sprintf(String, "\x7F%u.%02uk", settings.frequencyChangeStep / 100, + settings.frequencyChangeStep % 100); + GUI_DisplaySmallest(String, 48, 49, false, true); + + sprintf(String, "%u.%05u", GetFEnd() / 100000, GetFEnd() % 100000); + GUI_DisplaySmallest(String, 93, 49, false, true); + } +} + +static void DrawRssiTriggerLevel() +{ + if (settings.rssiTriggerLevel == RSSI_MAX_VALUE || monitorMode) + return; + uint8_t y = Rssi2Y(settings.rssiTriggerLevel); + for (uint8_t x = 0; x < 128; x += 2) + { + PutPixel(x, y, true); + } +} + +static void DrawTicks() +{ + uint32_t f = GetFStart(); + uint32_t span = GetFEnd() - GetFStart(); + uint32_t step = span / 128; + for (uint8_t i = 0; i < 128; i += (1 << settings.stepsCount)) + { + f = GetFStart() + span * i / 128; + uint8_t barValue = 0b00000001; + (f % 10000) < step && (barValue |= 0b00000010); + (f % 50000) < step && (barValue |= 0b00000100); + (f % 100000) < step && (barValue |= 0b00011000); + + gFrameBuffer[5][i] |= barValue; + } + + // center + if (IsCenterMode()) + { + memset(gFrameBuffer[5] + 62, 0x80, 5); + gFrameBuffer[5][64] = 0xff; + } + else + { + memset(gFrameBuffer[5] + 1, 0x80, 3); + memset(gFrameBuffer[5] + 124, 0x80, 3); + + gFrameBuffer[5][0] = 0xff; + gFrameBuffer[5][127] = 0xff; + } +} + +static void DrawArrow(uint8_t x) +{ + for (signed i = -2; i <= 2; ++i) + { + signed v = x + i; + if (!(v & 128)) + { + gFrameBuffer[5][v] |= (0b01111000 << my_abs(i)) & 0b01111000; + } + } +} + +static void OnKeyDown(uint8_t key) +{ + switch (key) + { + case KEY_3: + UpdateDBMax(true); + break; + case KEY_9: + UpdateDBMax(false); + break; + case KEY_1: + UpdateScanStep(true); + break; + case KEY_7: + UpdateScanStep(false); + break; + case KEY_2: + UpdateFreqChangeStep(true); + break; + case KEY_8: + UpdateFreqChangeStep(false); + break; + case KEY_UP: #ifdef ENABLE_SCAN_RANGES - if(!gScanRangeStart) + if (!gScanRangeStart) #endif - UpdateCurrentFreq(true); - break; - case KEY_DOWN: + UpdateCurrentFreq(true); + break; + case KEY_DOWN: #ifdef ENABLE_SCAN_RANGES - if(!gScanRangeStart) + if (!gScanRangeStart) #endif - UpdateCurrentFreq(false); - break; - case KEY_SIDE1: - Blacklist(); - break; - case KEY_STAR: - UpdateRssiTriggerLevel(true); - break; - case KEY_F: - UpdateRssiTriggerLevel(false); - break; - case KEY_5: + UpdateCurrentFreq(false); + break; + case KEY_SIDE1: + Blacklist(); + break; + case KEY_STAR: + UpdateRssiTriggerLevel(true); + break; + case KEY_F: + UpdateRssiTriggerLevel(false); + break; + case KEY_5: #ifdef ENABLE_SCAN_RANGES - if(!gScanRangeStart) + if (!gScanRangeStart) #endif - FreqInput(); - break; - case KEY_0: - ToggleModulation(); - break; - case KEY_6: - ToggleListeningBW(); - break; - case KEY_4: + FreqInput(); + break; + case KEY_0: + ToggleModulation(); + break; + case KEY_6: + ToggleListeningBW(); + break; + case KEY_4: #ifdef ENABLE_SCAN_RANGES - if(!gScanRangeStart) + if (!gScanRangeStart) +#endif + ToggleStepsCount(); + break; + case KEY_SIDE2: + ToggleBacklight(); + break; + case KEY_PTT: + SetState(STILL); + TuneToPeak(); + break; + case KEY_MENU: + break; + case KEY_EXIT: + if (menuState) + { + menuState = 0; + break; + } +#ifdef ENABLE_FEAT_F4HWN_SPECTRUM + SaveSettings(); #endif - ToggleStepsCount(); - break; - case KEY_SIDE2: - ToggleBacklight(); - break; - case KEY_PTT: - SetState(STILL); - TuneToPeak(); - break; - case KEY_MENU: - break; - case KEY_EXIT: - if (menuState) { - menuState = 0; - break; - } - #ifdef ENABLE_FEAT_F4HWN_SPECTRUM - SaveSettings(); - #endif - DeInitSpectrum(); - break; - default: - break; - } -} - -static void OnKeyDownFreqInput(uint8_t key) { - switch (key) { - case KEY_0: - case KEY_1: - case KEY_2: - case KEY_3: - case KEY_4: - case KEY_5: - case KEY_6: - case KEY_7: - case KEY_8: - case KEY_9: - case KEY_STAR: - UpdateFreqInput(key); - break; - case KEY_EXIT: - if (freqInputIndex == 0) { - SetState(previousState); - break; - } - UpdateFreqInput(key); - break; - case KEY_MENU: - if (tempFreq < F_MIN || tempFreq > F_MAX) { - break; - } - SetState(previousState); - currentFreq = tempFreq; - if (currentState == SPECTRUM) { - ResetBlacklist(); - RelaunchScan(); - } else { - SetF(currentFreq); - } - break; - default: - break; - } -} - -void OnKeyDownStill(KEY_Code_t key) { - switch (key) { - case KEY_3: - UpdateDBMax(true); - break; - case KEY_9: - UpdateDBMax(false); - break; - case KEY_UP: - if (menuState) { - SetRegMenuValue(menuState, true); - break; - } - UpdateCurrentFreqStill(true); - break; - case KEY_DOWN: - if (menuState) { - SetRegMenuValue(menuState, false); - break; - } - UpdateCurrentFreqStill(false); - break; - case KEY_STAR: - UpdateRssiTriggerLevel(true); - break; - case KEY_F: - UpdateRssiTriggerLevel(false); - break; - case KEY_5: - FreqInput(); - break; - case KEY_0: - ToggleModulation(); - break; - case KEY_6: - ToggleListeningBW(); - break; - case KEY_SIDE1: - monitorMode = !monitorMode; - break; - case KEY_SIDE2: - ToggleBacklight(); - break; - case KEY_PTT: - // TODO: start transmit - /* BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, false); - BK4819_ToggleGpioOut(BK4819_GPIO5_PIN1_RED, true); */ - break; - case KEY_MENU: - if (menuState == ARRAY_SIZE(registerSpecs) - 1) { - menuState = 1; - } else { - menuState++; + DeInitSpectrum(); + break; + default: + break; + } +} + +static void OnKeyDownFreqInput(uint8_t key) +{ + switch (key) + { + case KEY_0: + case KEY_1: + case KEY_2: + case KEY_3: + case KEY_4: + case KEY_5: + case KEY_6: + case KEY_7: + case KEY_8: + case KEY_9: + case KEY_STAR: + UpdateFreqInput(key); + break; + case KEY_EXIT: + if (freqInputIndex == 0) + { + SetState(previousState); + break; + } + UpdateFreqInput(key); + break; + case KEY_MENU: + if (tempFreq < F_MIN || tempFreq > F_MAX) + { + break; + } + SetState(previousState); + currentFreq = tempFreq; + if (currentState == SPECTRUM) + { + ResetBlacklist(); + RelaunchScan(); + } + else + { + SetF(currentFreq); + } + break; + default: + break; + } +} + +void OnKeyDownStill(KEY_Code_t key) +{ + switch (key) + { + case KEY_3: + UpdateDBMax(true); + break; + case KEY_9: + UpdateDBMax(false); + break; + case KEY_UP: + if (menuState) + { + SetRegMenuValue(menuState, true); + break; + } + UpdateCurrentFreqStill(true); + break; + case KEY_DOWN: + if (menuState) + { + SetRegMenuValue(menuState, false); + break; + } + UpdateCurrentFreqStill(false); + break; + case KEY_STAR: + UpdateRssiTriggerLevel(true); + break; + case KEY_F: + UpdateRssiTriggerLevel(false); + break; + case KEY_5: + FreqInput(); + break; + case KEY_0: + ToggleModulation(); + break; + case KEY_6: + ToggleListeningBW(); + break; + case KEY_SIDE1: + monitorMode = !monitorMode; + break; + case KEY_SIDE2: + ToggleBacklight(); + break; + case KEY_PTT: + // TODO: start transmit + /* BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, false); + BK4819_ToggleGpioOut(BK4819_GPIO5_PIN1_RED, true); */ + break; + case KEY_MENU: + if (menuState == ARRAY_SIZE(registerSpecs) - 1) + { + menuState = 1; + } + else + { + menuState++; + } + redrawScreen = true; + break; + case KEY_EXIT: + if (!menuState) + { + SetState(SPECTRUM); + lockAGC = false; + monitorMode = false; + RelaunchScan(); + break; + } + menuState = 0; + break; + default: + break; } - redrawScreen = true; - break; - case KEY_EXIT: - if (!menuState) { - SetState(SPECTRUM); - lockAGC = false; - monitorMode = false; - RelaunchScan(); - break; - } - menuState = 0; - break; - default: - break; - } } static void RenderFreqInput() { UI_PrintString(freqInputString, 2, 127, 0, 8); } -static void RenderStatus() { - memset(gStatusLine, 0, sizeof(gStatusLine)); - DrawStatus(); - ST7565_BlitStatusLine(); -} - -static void RenderSpectrum() { - DrawTicks(); - DrawArrow(128u * peak.i / GetStepsCount()); - DrawSpectrum(); - DrawRssiTriggerLevel(); - DrawF(peak.f); - DrawNums(); -} - -static void RenderStill() { - DrawF(fMeasure); - - const uint8_t METER_PAD_LEFT = 3; - - memset(&gFrameBuffer[2][METER_PAD_LEFT], 0b00010000, 121); - - for (int i = 0; i < 121; i+=5) { - gFrameBuffer[2][i + METER_PAD_LEFT] = 0b00110000; - } - - for (int i = 0; i < 121; i+=10) { - gFrameBuffer[2][i + METER_PAD_LEFT] = 0b01110000; - } - - uint8_t x = Rssi2PX(scanInfo.rssi, 0, 121); - for (int i = 0; i < x; ++i) { - if (i % 5) { - gFrameBuffer[2][i + METER_PAD_LEFT] |= 0b00000111; - } - } - - int dbm = Rssi2DBm(scanInfo.rssi); - uint8_t s = DBm2S(dbm); - sprintf(String, "S: %u", s); - GUI_DisplaySmallest(String, 4, 25, false, true); - sprintf(String, "%d dBm", dbm); - GUI_DisplaySmallest(String, 28, 25, false, true); - - if (!monitorMode) { - uint8_t x = Rssi2PX(settings.rssiTriggerLevel, 0, 121); - gFrameBuffer[2][METER_PAD_LEFT + x] = 0b11111111; - } - - const uint8_t PAD_LEFT = 4; - const uint8_t CELL_WIDTH = 30; - uint8_t offset = PAD_LEFT; - uint8_t row = 4; - - for (int i = 0, idx = 1; idx <= 4; ++i, ++idx) { - if (idx == 5) { - row += 2; - i = 0; - } - offset = PAD_LEFT + i * CELL_WIDTH; - if (menuState == idx) { - for (int j = 0; j < CELL_WIDTH; ++j) { - gFrameBuffer[row][j + offset] = 0xFF; - gFrameBuffer[row + 1][j + offset] = 0xFF; - } - } - sprintf(String, "%s", registerSpecs[idx].name); - GUI_DisplaySmallest(String, offset + 2, row * 8 + 2, false, - menuState != idx); - sprintf(String, "%u", GetRegMenuValue(idx)); - GUI_DisplaySmallest(String, offset + 2, (row + 1) * 8 + 1, false, - menuState != idx); - } -} - -static void Render() { - UI_DisplayClear(); - - switch (currentState) { - case SPECTRUM: - RenderSpectrum(); - break; - case FREQ_INPUT: - RenderFreqInput(); - break; - case STILL: - RenderStill(); - break; - } - - ST7565_BlitFullScreen(); -} - -bool HandleUserInput() { - kbd.prev = kbd.current; - kbd.current = GetKey(); - - if (kbd.current != KEY_INVALID && kbd.current == kbd.prev) { - if (kbd.counter < 16) - kbd.counter++; - else - kbd.counter -= 3; - SYSTEM_DelayMs(20); - } else { - kbd.counter = 0; - } +static void RenderStatus() +{ + memset(gStatusLine, 0, sizeof(gStatusLine)); + DrawStatus(); + ST7565_BlitStatusLine(); +} - if (kbd.counter == 3 || kbd.counter == 16) { - switch (currentState) { +static void RenderSpectrum() +{ + DrawTicks(); + DrawArrow(128u * peak.i / GetStepsCount()); + DrawSpectrum(); + DrawRssiTriggerLevel(); + DrawF(peak.f); + DrawNums(); +} + +static void RenderStill() +{ + DrawF(fMeasure); + + const uint8_t METER_PAD_LEFT = 3; + + memset(&gFrameBuffer[2][METER_PAD_LEFT], 0b00010000, 121); + + for (int i = 0; i < 121; i += 5) + { + gFrameBuffer[2][i + METER_PAD_LEFT] = 0b00110000; + } + + for (int i = 0; i < 121; i += 10) + { + gFrameBuffer[2][i + METER_PAD_LEFT] = 0b01110000; + } + + uint8_t x = Rssi2PX(scanInfo.rssi, 0, 121); + for (int i = 0; i < x; ++i) + { + if (i % 5) + { + gFrameBuffer[2][i + METER_PAD_LEFT] |= 0b00000111; + } + } + + int dbm = Rssi2DBm(scanInfo.rssi); + uint8_t s = DBm2S(dbm); + sprintf(String, "S: %u", s); + GUI_DisplaySmallest(String, 4, 25, false, true); + sprintf(String, "%d dBm", dbm); + GUI_DisplaySmallest(String, 28, 25, false, true); + + if (!monitorMode) + { + uint8_t x = Rssi2PX(settings.rssiTriggerLevel, 0, 121); + gFrameBuffer[2][METER_PAD_LEFT + x] = 0b11111111; + } + + const uint8_t PAD_LEFT = 4; + const uint8_t CELL_WIDTH = 30; + uint8_t offset = PAD_LEFT; + uint8_t row = 4; + + for (int i = 0, idx = 1; idx <= 4; ++i, ++idx) + { + if (idx == 5) + { + row += 2; + i = 0; + } + offset = PAD_LEFT + i * CELL_WIDTH; + if (menuState == idx) + { + for (int j = 0; j < CELL_WIDTH; ++j) + { + gFrameBuffer[row][j + offset] = 0xFF; + gFrameBuffer[row + 1][j + offset] = 0xFF; + } + } + sprintf(String, "%s", registerSpecs[idx].name); + GUI_DisplaySmallest(String, offset + 2, row * 8 + 2, false, + menuState != idx); + sprintf(String, "%u", GetRegMenuValue(idx)); + GUI_DisplaySmallest(String, offset + 2, (row + 1) * 8 + 1, false, + menuState != idx); + } +} + +static void Render() +{ + UI_DisplayClear(); + + switch (currentState) + { case SPECTRUM: - OnKeyDown(kbd.current); - break; + RenderSpectrum(); + break; case FREQ_INPUT: - OnKeyDownFreqInput(kbd.current); - break; + RenderFreqInput(); + break; case STILL: - OnKeyDownStill(kbd.current); - break; + RenderStill(); + break; } - } - return true; + ST7565_BlitFullScreen(); } -static void Scan() { - if (rssiHistory[scanInfo.i] != RSSI_MAX_VALUE +bool HandleUserInput() +{ + kbd.prev = kbd.current; + kbd.current = GetKey(); + + if (kbd.current != KEY_INVALID && kbd.current == kbd.prev) + { + if (kbd.counter < 16) + kbd.counter++; + else + kbd.counter -= 3; + SYSTEM_DelayMs(20); + } + else + { + kbd.counter = 0; + } + + if (kbd.counter == 3 || kbd.counter == 16) + { + switch (currentState) + { + case SPECTRUM: + OnKeyDown(kbd.current); + break; + case FREQ_INPUT: + OnKeyDownFreqInput(kbd.current); + break; + case STILL: + OnKeyDownStill(kbd.current); + break; + } + } + + return true; +} + +static void Scan() +{ + if (rssiHistory[scanInfo.i] != RSSI_MAX_VALUE #ifdef ENABLE_SCAN_RANGES - && !IsBlacklisted(scanInfo.i) + && !IsBlacklisted(scanInfo.i) #endif - ) { - SetF(scanInfo.f); - Measure(); - UpdateScanInfo(); - } + ) + { + SetF(scanInfo.f); + Measure(); + UpdateScanInfo(); + } } -static void NextScanStep() { - ++peak.t; - ++scanInfo.i; - scanInfo.f += scanInfo.scanStep; +static void NextScanStep() +{ + ++peak.t; + ++scanInfo.i; + scanInfo.f += scanInfo.scanStep; } -static void UpdateScan() { - Scan(); +static void UpdateScan() +{ + Scan(); - if (scanInfo.i < scanInfo.measurementsCount) { - NextScanStep(); - return; - } + if (scanInfo.i < scanInfo.measurementsCount) + { + NextScanStep(); + return; + } - if(scanInfo.measurementsCount < 128) - memset(&rssiHistory[scanInfo.measurementsCount], 0, - sizeof(rssiHistory) - scanInfo.measurementsCount*sizeof(rssiHistory[0])); + if (scanInfo.measurementsCount < 128) + memset(&rssiHistory[scanInfo.measurementsCount], 0, + sizeof(rssiHistory) - scanInfo.measurementsCount * sizeof(rssiHistory[0])); - redrawScreen = true; - preventKeypress = false; + redrawScreen = true; + preventKeypress = false; - UpdatePeakInfo(); - if (IsPeakOverLevel()) { - ToggleRX(true); - TuneToPeak(); - return; - } + UpdatePeakInfo(); + if (IsPeakOverLevel()) + { + ToggleRX(true); + TuneToPeak(); + return; + } - newScanStart = true; + newScanStart = true; } -static void UpdateStill() { - Measure(); - redrawScreen = true; - preventKeypress = false; +static void UpdateStill() +{ + Measure(); + redrawScreen = true; + preventKeypress = false; - peak.rssi = scanInfo.rssi; - AutoTriggerLevel(); + peak.rssi = scanInfo.rssi; + AutoTriggerLevel(); - ToggleRX(IsPeakOverLevel() || monitorMode); + ToggleRX(IsPeakOverLevel() || monitorMode); } -static void UpdateListening() { - preventKeypress = false; - if (currentState == STILL) { - listenT = 0; - } - if (listenT) { - listenT--; - SYSTEM_DelayMs(1); - return; - } +static void UpdateListening() +{ + preventKeypress = false; + if (currentState == STILL) + { + listenT = 0; + } + if (listenT) + { + listenT--; + SYSTEM_DelayMs(1); + return; + } - if (currentState == SPECTRUM) { - BK4819_WriteRegister(0x43, GetBWRegValueForScan()); - Measure(); - BK4819_WriteRegister(0x43, listenBWRegValues[settings.listenBw]); - } else { - Measure(); - } + if (currentState == SPECTRUM) + { + BK4819_WriteRegister(0x43, GetBWRegValueForScan()); + Measure(); + BK4819_WriteRegister(0x43, listenBWRegValues[settings.listenBw]); + } + else + { + Measure(); + } - peak.rssi = scanInfo.rssi; - redrawScreen = true; + peak.rssi = scanInfo.rssi; + redrawScreen = true; - if (IsPeakOverLevel() || monitorMode) { - listenT = 1000; - return; - } + if (IsPeakOverLevel() || monitorMode) + { + listenT = 1000; + return; + } - ToggleRX(false); - ResetScanStats(); + ToggleRX(false); + ResetScanStats(); } -static void Tick() { +static void Tick() +{ #ifdef ENABLE_AM_FIX - if (gNextTimeslice) { - gNextTimeslice = false; - if(settings.modulationType == MODULATION_AM && !lockAGC) { - AM_fix_10ms(vfo); //allow AM_Fix to apply its AGC action + if (gNextTimeslice) + { + gNextTimeslice = false; + if (settings.modulationType == MODULATION_AM && !lockAGC) + { + AM_fix_10ms(vfo); // allow AM_Fix to apply its AGC action + } } - } #endif #ifdef ENABLE_SCAN_RANGES - if (gNextTimeslice_500ms) { - gNextTimeslice_500ms = false; - - // if a lot of steps then it takes long time - // we don't want to wait for whole scan - // listening has it's own timer - if(GetStepsCount()>128 && !isListening) { - UpdatePeakInfo(); - if (IsPeakOverLevel()) { - ToggleRX(true); - TuneToPeak(); - return; - } - redrawScreen = true; - preventKeypress = false; + if (gNextTimeslice_500ms) + { + gNextTimeslice_500ms = false; + + // if a lot of steps then it takes long time + // we don't want to wait for whole scan + // listening has it's own timer + if (GetStepsCount() > 128 && !isListening) + { + UpdatePeakInfo(); + if (IsPeakOverLevel()) + { + ToggleRX(true); + TuneToPeak(); + return; + } + redrawScreen = true; + preventKeypress = false; + } } - } #endif - if (!preventKeypress) { - HandleUserInput(); - } - if (newScanStart) { - InitScan(); - newScanStart = false; - } - if (isListening && currentState != FREQ_INPUT) { - UpdateListening(); - } else { - if (currentState == SPECTRUM) { - UpdateScan(); - } else if (currentState == STILL) { - UpdateStill(); - } - } - if (redrawStatus || ++statuslineUpdateTimer > 4096) { - RenderStatus(); - redrawStatus = false; - statuslineUpdateTimer = 0; - } - if (redrawScreen) { - Render(); - redrawScreen = false; - } -} - -void APP_RunSpectrum() { - // TX here coz it always? set to active VFO - vfo = gEeprom.TX_VFO; + if (!preventKeypress) + { + HandleUserInput(); + } + if (newScanStart) + { + InitScan(); + newScanStart = false; + } + if (isListening && currentState != FREQ_INPUT) + { + UpdateListening(); + } + else + { + if (currentState == SPECTRUM) + { + UpdateScan(); + } + else if (currentState == STILL) + { + UpdateStill(); + } + } + if (redrawStatus || ++statuslineUpdateTimer > 4096) + { + RenderStatus(); + redrawStatus = false; + statuslineUpdateTimer = 0; + } + if (redrawScreen) + { + Render(); + redrawScreen = false; + } +} + +void APP_RunSpectrum() +{ + // TX here coz it always? set to active VFO + vfo = gEeprom.TX_VFO; #ifdef ENABLE_FEAT_F4HWN_SPECTRUM - LoadSettings(); + LoadSettings(); #endif - // set the current frequency in the middle of the display + // set the current frequency in the middle of the display #ifdef ENABLE_SCAN_RANGES - if(gScanRangeStart) { - currentFreq = initialFreq = gScanRangeStart; - for(uint8_t i = 0; i < ARRAY_SIZE(scanStepValues); i++) { - if(scanStepValues[i] >= gTxVfo->StepFrequency) { - settings.scanStepIndex = i; - break; - } + if (gScanRangeStart) + { + currentFreq = initialFreq = gScanRangeStart; + for (uint8_t i = 0; i < ARRAY_SIZE(scanStepValues); i++) + { + if (scanStepValues[i] >= gTxVfo->StepFrequency) + { + settings.scanStepIndex = i; + break; + } + } + settings.stepsCount = STEPS_128; } - settings.stepsCount = STEPS_128; - } - else + else #endif - currentFreq = initialFreq = gTxVfo->pRX->Frequency - - ((GetStepsCount() / 2) * GetScanStep()); + currentFreq = initialFreq = gTxVfo->pRX->Frequency - + ((GetStepsCount() / 2) * GetScanStep()); - BackupRegisters(); + BackupRegisters(); - isListening = true; // to turn off RX later - redrawStatus = true; - redrawScreen = true; - newScanStart = true; + isListening = true; // to turn off RX later + redrawStatus = true; + redrawScreen = true; + newScanStart = true; - ToggleRX(true), ToggleRX(false); // hack to prevent noise when squelch off - RADIO_SetModulation(settings.modulationType = gTxVfo->Modulation); + ToggleRX(true), ToggleRX(false); // hack to prevent noise when squelch off + RADIO_SetModulation(settings.modulationType = gTxVfo->Modulation); - #ifdef ENABLE_FEAT_F4HWN_SPECTRUM +#ifdef ENABLE_FEAT_F4HWN_SPECTRUM BK4819_SetFilterBandwidth(settings.listenBw, false); - #else +#else BK4819_SetFilterBandwidth(settings.listenBw = BK4819_FILTER_BW_WIDE, false); - #endif +#endif - RelaunchScan(); + RelaunchScan(); - memset(rssiHistory, 0, sizeof(rssiHistory)); + memset(rssiHistory, 0, sizeof(rssiHistory)); - isInitialized = true; + isInitialized = true; - while (isInitialized) { - Tick(); - } + while (isInitialized) + { + Tick(); + } } diff --git a/app/spectrum.h b/app/spectrum.h index 1c1cce528..1f155130b 100644 --- a/app/spectrum.h +++ b/app/spectrum.h @@ -41,12 +41,34 @@ static const uint8_t DrawingEndY = 40; static const uint8_t U8RssiMap[] = { - 121, 115, 109, 103, 97, 91, 85, 79, 73, 63, + 121, + 115, + 109, + 103, + 97, + 91, + 85, + 79, + 73, + 63, }; static const uint16_t scanStepValues[] = { - 1, 10, 50, 100, 250, 500, 625, 833, - 1000, 1250, 1500, 2000, 2500, 5000, 10000, + 1, + 10, + 50, + 100, + 250, + 500, + 625, + 833, + 1000, + 1250, + 1500, + 2000, + 2500, + 5000, + 10000, }; static const uint16_t scanStepBWRegValues[] = { @@ -84,71 +106,78 @@ static const uint16_t listenBWRegValues[] = { 0b0100100001011000, // 6.25 }; -typedef enum State { - SPECTRUM, - FREQ_INPUT, - STILL, +typedef enum State +{ + SPECTRUM, + FREQ_INPUT, + STILL, } State; -typedef enum StepsCount { - STEPS_128, - STEPS_64, - STEPS_32, - STEPS_16, +typedef enum StepsCount +{ + STEPS_128, + STEPS_64, + STEPS_32, + STEPS_16, } StepsCount; -typedef enum ScanStep { - S_STEP_0_01kHz, - S_STEP_0_1kHz, - S_STEP_0_5kHz, - S_STEP_1_0kHz, - - S_STEP_2_5kHz, - S_STEP_5_0kHz, - S_STEP_6_25kHz, - S_STEP_8_33kHz, - S_STEP_10_0kHz, - S_STEP_12_5kHz, - S_STEP_15_0kHz, - S_STEP_20_0kHz, - S_STEP_25_0kHz, - S_STEP_50_0kHz, - S_STEP_100_0kHz, +typedef enum ScanStep +{ + S_STEP_0_01kHz, + S_STEP_0_1kHz, + S_STEP_0_5kHz, + S_STEP_1_0kHz, + + S_STEP_2_5kHz, + S_STEP_5_0kHz, + S_STEP_6_25kHz, + S_STEP_8_33kHz, + S_STEP_10_0kHz, + S_STEP_12_5kHz, + S_STEP_15_0kHz, + S_STEP_20_0kHz, + S_STEP_25_0kHz, + S_STEP_50_0kHz, + S_STEP_100_0kHz, } ScanStep; -typedef struct SpectrumSettings { - uint32_t frequencyChangeStep; - StepsCount stepsCount; - ScanStep scanStepIndex; - uint16_t scanDelay; - uint16_t rssiTriggerLevel; - BK4819_FilterBandwidth_t bw; - BK4819_FilterBandwidth_t listenBw; - int dbMin; - int dbMax; - ModulationMode_t modulationType; - bool backlightState; +typedef struct SpectrumSettings +{ + uint32_t frequencyChangeStep; + StepsCount stepsCount; + ScanStep scanStepIndex; + uint16_t scanDelay; + uint16_t rssiTriggerLevel; + BK4819_FilterBandwidth_t bw; + BK4819_FilterBandwidth_t listenBw; + int dbMin; + int dbMax; + ModulationMode_t modulationType; + bool backlightState; } SpectrumSettings; -typedef struct KeyboardState { - KEY_Code_t current; - KEY_Code_t prev; - uint8_t counter; +typedef struct KeyboardState +{ + KEY_Code_t current; + KEY_Code_t prev; + uint8_t counter; } KeyboardState; -typedef struct ScanInfo { - uint16_t rssi, rssiMin, rssiMax; - uint16_t i, iPeak; - uint32_t f, fPeak; - uint16_t scanStep; - uint16_t measurementsCount; +typedef struct ScanInfo +{ + uint16_t rssi, rssiMin, rssiMax; + uint16_t i, iPeak; + uint32_t f, fPeak; + uint16_t scanStep; + uint16_t measurementsCount; } ScanInfo; -typedef struct PeakInfo { - uint16_t t; - uint16_t rssi; - uint32_t f; - uint16_t i; +typedef struct PeakInfo +{ + uint16_t t; + uint16_t rssi; + uint32_t f; + uint16_t i; } PeakInfo; void APP_RunSpectrum(void); From 195881a5e2b4ed609c754deb8fe8f55d96efe87b Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Fri, 16 Aug 2024 02:19:52 +0200 Subject: [PATCH 26/30] Move spectrum Data[4] to Data[3] --- app/spectrum.c | 8 ++++---- settings.c | 4 ++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/spectrum.c b/app/spectrum.c index 64bd6195a..ef05597dd 100644 --- a/app/spectrum.c +++ b/app/spectrum.c @@ -117,21 +117,21 @@ static void LoadSettings() // 1FF0..0x1FF7 EEPROM_ReadBuffer(0x1FF0, Data, 8); - settings.scanStepIndex = ((Data[4] & 0xF0) >> 4); + settings.scanStepIndex = ((Data[3] & 0xF0) >> 4); if (settings.scanStepIndex > 14) { settings.scanStepIndex = S_STEP_25_0kHz; } - settings.stepsCount = ((Data[4] & 0x0F) & 0b1100) >> 2; + settings.stepsCount = ((Data[3] & 0x0F) & 0b1100) >> 2; if (settings.stepsCount > 3) { settings.stepsCount = STEPS_64; } - settings.listenBw = ((Data[4] & 0x0F) & 0b0011); + settings.listenBw = ((Data[3] & 0x0F) & 0b0011); if (settings.listenBw > 2) { @@ -145,7 +145,7 @@ static void SaveSettings() // 1FF0..0x1FF7 EEPROM_ReadBuffer(0x1FF0, Data, 8); - Data[4] = (settings.scanStepIndex << 4) | (settings.stepsCount << 2) | settings.listenBw; + Data[3] = (settings.scanStepIndex << 4) | (settings.stepsCount << 2) | settings.listenBw; EEPROM_WriteBuffer(0x1FF0, Data); } diff --git a/settings.c b/settings.c index 2211a77e3..2145b5b39 100644 --- a/settings.c +++ b/settings.c @@ -348,6 +348,10 @@ void SETTINGS_InitEEPROM(void) gSetting_set_tmr = Data[4] & 1; + // Warning + // Be aware, Data[3] is use by Spectrum + // Warning + // And set special session settings for actions gSetting_set_ptt_session = gSetting_set_ptt; gEeprom.KEY_LOCK_PTT = gSetting_set_lck; From 533262a6dc211de57930526ffe1edaf11ca1536a Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Fri, 16 Aug 2024 02:39:41 +0200 Subject: [PATCH 27/30] Fix README --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 47c335544..56b32ea4d 100644 --- a/README.md +++ b/README.md @@ -64,10 +64,11 @@ Special thanks to Jean-Cyrille F6IWW, Fabrice 14RC123, David F4BPP, Olivier 14RC * CTCSS or DCS value, * KeyLock message, * last RX, - * move BatTxt menu from 34/63 to 30/63 (just after BatSave menu 29/63), + * move BatTxt menu from 34/63 to 30/63 (just after BatSave menu 29/63), * rename BackLt to BLTime, * rename BltTRX to BLTxRx, * improve memory channel input, + * add percent and gauge to Air Copy, * and more... * new menu entries and changes: * add SetPwr menu to set User power (<20mW, 125mW, 250mW, 500mW, 1W, 2W or 5W), @@ -80,6 +81,7 @@ Special thanks to Jean-Cyrille F6IWW, Fabrice 14RC123, David F4BPP, Olivier 14RC * add SetLck menu to set what is locked (Keys or Keys + PTT), * add SetGui menu to set font size on the VFO baseline (Classic or Tiny), * add TXLock menu to open TX on channel, + * add SetTmr menu to set RX and TX timers (Off or On) * rename BatVol menu (52/63) to SysInf, which displays the firmware version in addition to the battery status, * improve PonMsg menu, * improve BackLt menu, From 07d89b9eed1417c136da65997941d7bca9686cb4 Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Fri, 16 Aug 2024 03:27:05 +0200 Subject: [PATCH 28/30] Add screenshot for Air Copy --- app/aircopy.c | 10 ++++++++++ images/AIR_COPY.png | Bin 0 -> 17085 bytes 2 files changed, 10 insertions(+) create mode 100644 images/AIR_COPY.png diff --git a/app/aircopy.c b/app/aircopy.c index 4f0607593..bc844fe13 100644 --- a/app/aircopy.c +++ b/app/aircopy.c @@ -32,6 +32,10 @@ #include "ui/inputbox.h" #include "ui/ui.h" +#ifdef ENABLE_FEAT_F4HWN_SCREENSHOT +#include "screenshot.h" +#endif + static const uint16_t Obfuscation[8] = { 0x6C16, 0xE614, 0x912E, 0x400D, 0x3521, 0x40D5, 0x0313, 0x80E9 }; AIRCOPY_State_t gAircopyState; @@ -73,6 +77,9 @@ bool AIRCOPY_SendMessage(void) if (++gAirCopyBlockNumber >= 0x78) { gAircopyState = AIRCOPY_COMPLETE; + #ifdef ENABLE_FEAT_F4HWN_SCREENSHOT + getScreenShot(); + #endif //NVIC_SystemReset(); } @@ -131,6 +138,9 @@ void AIRCOPY_StorePacket(void) if (Offset == 0x1E00) { gAircopyState = AIRCOPY_COMPLETE; + #ifdef ENABLE_FEAT_F4HWN_SCREENSHOT + getScreenShot(); + #endif } gAirCopyBlockNumber++; diff --git a/images/AIR_COPY.png b/images/AIR_COPY.png new file mode 100644 index 0000000000000000000000000000000000000000..ce749a63378a6344009b9fa5a9ef4c76a7de7492 GIT binary patch literal 17085 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 Mej`;PX&m^!0EL6k`v3p{ literal 0 HcmV?d00001 From bb7c8121363f3fa05cdf901d184734a4c07e6bc6 Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Tue, 20 Aug 2024 05:07:33 +0200 Subject: [PATCH 29/30] Improve audio bar --- ui/main.c | 53 ++++++++++++++++++++++++++--------------------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/ui/main.c b/ui/main.c index d9c191507..321f54a14 100644 --- a/ui/main.c +++ b/ui/main.c @@ -112,7 +112,7 @@ static void DrawSmallAntennaAndBars(uint8_t *p, unsigned int level) } #if defined ENABLE_AUDIO_BAR || defined ENABLE_RSSI_BAR -static void DrawLevelBar(uint8_t xpos, uint8_t line, uint8_t level) +static void DrawLevelBar(uint8_t xpos, uint8_t line, uint8_t level, uint8_t bars) { #ifndef ENABLE_FEAT_F4HWN const char hollowBar[] = { @@ -124,7 +124,7 @@ static void DrawLevelBar(uint8_t xpos, uint8_t line, uint8_t level) #endif uint8_t *p_line = gFrameBuffer[line]; - level = MIN(level, 13); + level = MIN(level, bars); for(uint8_t i = 0; i < level; i++) { #ifdef ENABLE_FEAT_F4HWN @@ -137,9 +137,9 @@ static void DrawLevelBar(uint8_t xpos, uint8_t line, uint8_t level) 0b01111111 }; - if(i < 9) { + if(i < bars - 4) { for(uint8_t j = 0; j < 4; j++) - p_line[xpos + i * 5 + j] = (~(0x7F >> (i+1))) & 0x7F; + p_line[xpos + i * 5 + j] = (~(0x7F >> (i + 1))) & 0x7F; } else { memcpy(p_line + (xpos + i * 5), &hollowBar, ARRAY_SIZE(hollowBar)); @@ -161,7 +161,7 @@ static void DrawLevelBar(uint8_t xpos, uint8_t line, uint8_t level) 0b00111110 }; - if(i < 9) { + if(i < bars - 4) { memcpy(p_line + (xpos + i * 5), &simpleBar, ARRAY_SIZE(simpleBar)); } else { @@ -169,7 +169,7 @@ static void DrawLevelBar(uint8_t xpos, uint8_t line, uint8_t level) } } #else - if(i < 9) { + if(i < bars - 4) { for(uint8_t j = 0; j < 4; j++) p_line[xpos + i * 5 + j] = (~(0x7F >> (i+1))) & 0x7F; } @@ -183,21 +183,13 @@ static void DrawLevelBar(uint8_t xpos, uint8_t line, uint8_t level) #ifdef ENABLE_AUDIO_BAR -unsigned int sqrt16(unsigned int value) -{ // return square root of 'value' - unsigned int shift = 16; // number of bits supplied in 'value' .. 2 ~ 32 - unsigned int bit = 1u << --shift; - unsigned int sqrti = 0; - while (bit) - { - const unsigned int temp = ((sqrti << 1) | bit) << shift--; - if (value >= temp) { - value -= temp; - sqrti |= bit; - } - bit >>= 1; +// Approximation of a logarithmic scale using integer arithmetic +uint8_t log2_approx(unsigned int value) { + uint8_t log = 0; + while (value >>= 1) { + log++; } - return sqrti; + return log; } void UI_DisplayAudioBar(void) @@ -238,17 +230,24 @@ void UI_DisplayAudioBar(void) if (gAlarmState != ALARM_STATE_OFF) return; #endif - const unsigned int voice_amp = BK4819_GetVoiceAmplitudeOut(); // 15:0 + static uint8_t barsOld = 0; + const uint8_t thresold = 18; // arbitrary thresold + //const uint8_t barsList[] = {0, 0, 0, 1, 2, 3, 4, 5, 6, 8, 10, 13, 16, 20, 25, 25}; + const uint8_t barsList[] = {0, 0, 0, 1, 2, 3, 5, 7, 9, 12, 15, 18, 21, 25, 25, 25}; + uint8_t logLevel; + uint8_t bars; + + unsigned int voiceLevel = BK4819_GetVoiceAmplitudeOut(); // 15:0 - // make non-linear to make more sensitive at low values - const unsigned int level = MIN(voice_amp * 8, 65535u); - const unsigned int sqrt_level = MIN(sqrt16(level), 124u); - uint8_t bars = 13 * sqrt_level / 124; + voiceLevel = (voiceLevel >= thresold) ? (voiceLevel - thresold) : 0; + logLevel = log2_approx(MIN(voiceLevel * 16, 32768u) + 1); + bars = barsList[logLevel]; + barsOld = (barsOld - bars > 1) ? (barsOld - 1) : bars; uint8_t *p_line = gFrameBuffer[line]; memset(p_line, 0, LCD_WIDTH); - DrawLevelBar(62, line, bars); + DrawLevelBar(2, line, barsOld, 25); if (gCurrentFunction == FUNCTION_TRANSMIT) ST7565_BlitFullScreen(); @@ -414,7 +413,7 @@ void DisplayRSSIBar(const bool now) UI_PrintStringSmallNormal(str, 2, 0, line); #endif - DrawLevelBar(bar_x, line, s_level + overS9Bars); + DrawLevelBar(bar_x, line, s_level + overS9Bars, 13); if (now) ST7565_BlitLine(line); #else From 1b59d509d348187cce4b0c2be77d86303dbc8063 Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Tue, 20 Aug 2024 18:25:12 +0200 Subject: [PATCH 30/30] Prepare new version --- README.md | 1 + archive/f4hwn.bandscope.packed.v3.3.bin | Bin 0 -> 60706 bytes archive/f4hwn.broadcast.packed.v3.3.bin | Bin 0 -> 58882 bytes archive/f4hwn.voxless.packed.v3.3.bin | Bin 0 -> 61202 bytes 4 files changed, 1 insertion(+) create mode 100644 archive/f4hwn.bandscope.packed.v3.3.bin create mode 100644 archive/f4hwn.broadcast.packed.v3.3.bin create mode 100644 archive/f4hwn.voxless.packed.v3.3.bin diff --git a/README.md b/README.md index 56b32ea4d..5148af637 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,7 @@ Special thanks to Jean-Cyrille F6IWW, Fabrice 14RC123, David F4BPP, Olivier 14RC * rename BltTRX to BLTxRx, * improve memory channel input, * add percent and gauge to Air Copy, + * improve audio bar, * and more... * new menu entries and changes: * add SetPwr menu to set User power (<20mW, 125mW, 250mW, 500mW, 1W, 2W or 5W), diff --git a/archive/f4hwn.bandscope.packed.v3.3.bin b/archive/f4hwn.bandscope.packed.v3.3.bin new file mode 100644 index 0000000000000000000000000000000000000000..b54aadf796507298be26868b8eb7c885a4626571 GIT binary patch literal 60706 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 H^7{V)tr2ID literal 0 HcmV?d00001 diff --git a/archive/f4hwn.broadcast.packed.v3.3.bin b/archive/f4hwn.broadcast.packed.v3.3.bin new file mode 100644 index 0000000000000000000000000000000000000000..384583976599249a19dcd3a61fc0658452ab233e GIT binary patch literal 58882 zcmXtggm z*q?LvIcu-I*50?72Ii%&ubAQi1}{}@sY2$J;n6&Y%CR9$oVz;8 z%@GuRh5fcu=_Y#%{4|~svG7fs4fPXuyIof&Xg6lDhln$I9_xsXiKk5pEjcqh1nKU< zm`!=9&8&6sF~T%QlR62R5U$E|!Ie}W*gntBW-ta%imqaSX+sSZQ_O+*c|d$lApQUl zza5A#55y+|;;RAi)q(gh1BLz86X_-^bNsZEVX<%`)(!Q6s0>8&Sarju&A1iWCopWg zu{ce`d;JNAH+W~6vS`v>OtvixgkTvMP;(c%eax#hhc)(DFU+*(2OPT0>*CTnApZRu zw8>i|(kA&&v1*K39Xz0!>=i*O{bPp4vM#gt`}9^J5lBam+1c+tYTXdtdM!8^`Q+5~ zf=It8`VOiDvp{?qTfO^Go(G}K$X{^#tg&YuF^S=IPNWKNs+L1&dqprf*8VtYwQ7RX z+A^_L=*%TbBUDzRoRN&rI`Ny#+0X~wNR72}F>6uBGF_A)#~;I!R0DLTHYl%4v!&j! zM}cEJN^$OrDL40f^c6-L+A>D%-{Hz1Hj32}TyMI(WwIaoM+wcPoBg9)Xh~vA6=o=M zufO9E*XQy*L3zqYWidGEi)+ z1B36}dXxowg;lqZR|PWE{wz&&4D0^drwFHlv5$8?$FJM6{#p_xofQXLv2S<=Ie1l15Nh+cjMN=PV!WNv zQabD&_CrP~6%utwrSqHOw>_`dXY}AbAdFY;c7p{@(EQmd56TCEJalan6D?0OTJm<_ z{0^7K7zwu>#IM?`2Z#6d41ATB3I({X={g5W$2Hu36AG**Rq8OnycB`+cW}5Rbmd43 z%v&!QZzQ>X#m$(;?CMb?XH-j9{^Pw80~HFG?X``~14rYKnS!PKAPB&IrVB z1mgd!_MoiLiFZZP`HU9=!qeg&`^?8Mr*dmr?7C6md^+NyDJ z>^c?Dj^TZ--pO${Tj-`Y9r!K;B}Qai8D7b8$P6=_MzH9D>1*6bFLQpQg>=LM-+zS0 zETMf#$u7`>rD&(_Z4J%Uy1NAH+ea%>$KjZrdi7BYb4xrO6RqMLTA{Pc7?oGeiON!6 z+uc|r{@!XHX}f;fv)-hmh|=hIX42FNY!!nPO)z&B#aVxrISnYNi> z!27poDwBm?O6SqHsG`=Fdu{FvMa)%vO_WJ7aC3z}v~mek*xqrEN0k(81Lq(7?)#yJ zJP#dfS6+nkke2TnErgSv%MdH^JS)a0;IXz+P1)9)6AitIXMiSXG%!j0hAog0EwQlq zd_mjv-G|~&bR3-Wy{i>9WbjXgV`e@ghC#j-u zZ~=`;=9R)ph+P3C<1YKLGX(*%Px9;tDmVwv78w!tSzqkPsGD3phBkD~s>QpBI98YQ zpqav=0X)GQ;f6Y2CvsZebD%jYNgAA*--7r3zFeU6xM$yWB+7C?Gqyg5P1=V-|4AL? zq|s5^$eT*^w&@k`Af*ZRXlC8pZ#y8%i0;@s4|>X`N#vJf-H9dbua#a=U-71tr4ICX z#zIw^gCi|(Y{FzLh^pr*J!%foe@!C3vGisES(+Aq8<&42i$w5}mo49%B|)S><8JS5+)EzqzMh z&E*{FUYTwP*yfu*Mm~{L;@zD|H+|E`Pm6@K;Zvz6;PU$!>~=U6cMEGb4p16rJk=8# ze*2ixg^UY&`=Bl9#pWtDN?FqS@HezcXWWyW1dU5G-1%~8_uIga3h~x)TNf#ZAqrJC z#m)w3eX;w9dX+Q?=eJ~KcT}@DOt|tum-#^?T}5(aL2u=>@^baq6rWFzbD(grc~J5`Bd(1{S_*w@uPZLedPkV*Pa?Th$jW_ z)k2-6WS{YO!>!BAL4YVItXqrPp9K@nZ3Mv0*K|`bW7D^+YKy?E$*@EQsJ)W zQ%Ok+Bs+Z!ACI%$tP!rE&?Qh5X>aV&`$5fnZea1j8?_E)o1V9M&h!tvW%q)4R)V);UNqR z!1>k0+svH2@c6^pU{!XtiIk-UcP$#Dfyu9KC=C)vleOg#k_b$F6dPM_MKcqKQ9k}w z9u$RXzBJWvBp2%X<@xgOpESi#Hx#QshUv57g~22j1kx#X!RQUM?1Z(9SJSqv-2uA= z${#~vZ$4l(yy<#k<^BMT~3&M~&Y3UC@N<>@C5%96Ey zgNNQspPCyDF>Y1&g_z6QwMd?P;CDBe$bwf2K=8+^FfbZgJ?0dS)>9QLUSfg&7;YQ? z&`-i^`Du6=-h%xdhnsY$zvt9-JPI5b?{t2DmDkSD5e^)IePPL9#N5yv0&()%ka4^YXC5cFJ9G%c0#IX*AMQMRH5<3x#{#o#jQ?>X<1 z+3+NywLz+=z{~xEpI>I=aX3W&4Q=#9O5klSNZS#$y!yWPn`MX$H30WR9QA};J5Nq- zalm2^_zY(&G+Ub^1;ylK!(_+k6CZLCwn&ik;P!xKK!U`_?ZnI1Jji3d^^gn`f{mT> zwCLzf_kAK?5@WeuMKIO`vY76CR)P!Rq`)^tWen2}51qXI%G8?zHC%_6+J8_Fo7sBW zK%M&TK|eg>H^OuiZ4cZn6zl{ozF-;_Z&gR_)8?KBlPLPtN%2=)$wp?3{xNDxlS-8P zJkmKBg14;el|(30G<|{YXZ6vH^7W1OOXM^Psg|BT^8pRKx^pX~!%BDJKgz2_!qji5 z!3$`?dZ>P`tzx-d&dV5%%^&kZdiy24+rg4d_JQ~)G~8UFzt2D1k4D)H)H#(uO}=(| zpD>(HO#?I5h8oHl!{DE@H#Lga;^-R&2^Sx$>r_8b`{ceBsCn@VCzzAv7PcxL+PeZIA(K!O9 zGRp2;9(CT<({yU%j5LEGrRUHb)jf~>eI##**E+w_lTxT>ZsZ~|IbDpA6R_HYB*L%h z;&ZZ5ytfE8;}kDYeXUk+2X8>*{BYmIAw()|Suz>aN(O6ehxb$B^U0&pe3P%&^)hk( z78gqWS`tZ!u2VDGOBDH|nMK?}i;L~h)Gv#P&oo^;xc|7}n)TA|O{HgDG(%?uLp*u< z5DkpSwF8|_bRIare|Pa39;g}SYG#|e)T8;@XNFR(mWuM;gZ%?YoQN%O6g`hX0dpqQ z&p^WmDkCtY(I>kThQSW`PD-}^suyk7fyAk1-o$W4IRxr&>&EfnV z64~;KbSEGB51>79jseMp&&eoOL}rF`N~m>b+DrByBRiGuSsbx{}M zlbzqJ;_9~vjgIuwsZ#XgD?C_{yx3h%DGkSv-+sjYSyC`u0PW5O>VKADsy)`Oxyb(U z#xWs#2tBAtvMec~;H6K1I4mJmQ|u)&;ngJ11&;Ua6ShPf7qt~UnVic80mEWXXlBtm zV!&vqlw);U3ghJqI&N;n8fm=AZzj== z<&^Tl^1Bwfc9N2N@Ak9EEvE*mR`}6posAdar`?hO{(YKh3(WC8iHOXR6$Uf?{a3iY zhv4sI)(%@eDPwp{H{KHMac|vGY?Z9bf6~}$?Acakap4&rLpOE7;a_%Y4*w#RF4^6M zyO?N6BTiY~($hsRooZ+AvV(ETB~0hq^ESY}xI^Xun$If@h13B2_dUS>3Y)35x4OPa z@#b>4CysT{*lu4=G_b4s_^b1$e%HLf+d^2r6*^`2WzGrRGEr z&8MdReC$pbX+J;HHv6C`TS<=8?l#qtJuf{qHc7Zhr)q>Pp`b6Na_>=u+~`Kvekw9u zE?)S8psZaw3mi|ga&^cUPK|Y#X5`tp=jFwdvj^l~?pR6`43@qCLf6E*0tAn%coY9gFWuljenqIe=y zh+T-oHqw>rW)LlnB#fmDw?21j)=nfJz8`2&YPT=Ma>6RlmwdaHU;G8 z-{3#l*St^xeJ;6u|BFM%gri+GbWjm~?D%#=4K(@kHU61)5r-MC1< zZtt%AZC|^y(6s&wBA7hEb9m5eN0AaGrf53d`epfz?`y$N=Rz5Sh^7VFA zjH}5XG%yK-2$SxSP3D?{F4d6yB@<+dXr)V5{Naw1C zV>kXPtR3QK>E-UvFsAsbm^}Bl*xEnyz2(%aDkGhwdjWFG)N3TfToW=kuC%W|eICm# z)wIN7E(FL_ZdTgUCKUnQulV8Q1;-c=B1^ZNSVc1i;AQ`u{&Z}0t*9kXGp`eg^#OJDGiB#N2J z_#2zp^SLOgO?!Hrdn+fY^ym~5PBReKby1Uq)1Aj$aPAWGHb-tD3j5GDZDdyxV%qEV zH@YV1^mq(F{AI(i{5j_MiQ~PvEE6vxe&{T^AsVlgZ2dF-0R6v@_hV^fN9{qhi~ z0rpabnk(9CE1}J{lq?;21yY`^z!P5B+`309f zx_^6DHUSWy`&|&yhWXcm6Q{xz4>y+z)u08;MBw|U(wf@9grCB6QE%f5RKByGp{2n0O0y+Bv2+mR5+)YjP#>ML+bsqaV6Cip5OxpeqfvSnMdUa?*Pq00DDeG5 z+@b@sd4IeQ=^nN?tE0ct9P<5XkB^Hd%1!~qZ+a)q01GmSkZk5+9C0-7YlyCFED=aP z3w~V7s5ZA*UqShe7RNT@k#W__s< z0RCAm(t7mq@vyuS!Uav<^GSwahPY)1Ru3Y2_FMUgc`5$|9sbx(#PAMmf0gszk1^jB z0$H9q4m?y$DV*iGbE{~GK4=^iAedubH+4ZUkMFBI>+KI#j#QWXr+(BgIDKGXYCOf4 z2ISx2)Bfw{{6qh#iw|1lmPuuOdgm>7{AD4<3r*{NDv*D+#BPNNW44RfHnZpZ*8to< z-v>nJ?oTINQF5KK5}0!ZHtb0ig24SRs!;r%Dw)rfMGG-qLI(0r$ULrw@f3wcE!#qN zm+oA!B(?LhMOk z(7NH8h5>z&S2WEfu7gx69`9O#v8p3uPIgavtP%|P{x+3dmJKbmmqYR>b_qP40*+|3 ztp!P~hza_-h9ej$D?fhbvFgK&J%uA_$v00!koXjf*9@6IK;G>7ML?Y48!;CnY~8Uq zna=eA?R@MK1}mT%AA7Oh(60q<4)wtKr)hNG>?s}(x0>t08o1p;C5hqx9=sfK0+M3p zzv{G(K}q6H$ELB{GRoYYF~lhYHqb29b+|GKsnVX`p9g8zFnFq|#st8h$lbH+Q-&2R z(%Hhh4gi0e0wB)jThY(>3&oyc^$cuhh!-4w1l`~AAl+i4!;j-qkA2jpKm|C7&i z{ugDu4TaRL@phiSzjCKB+wDP{S&BDGK}3$G&{YGGTyge65ro2y|1-M@F{45Pg+kqL ze6wIBxyGpky98pJFxF0&cf5YgW9pbld)<@Tv%U5y=UH-ioJqW!6u0_<6>?~3${A&~ z4%b?J-b{<@AGV`*2cT=+=PO0p+U-KIHp2Wx5upxwqElVQNW4J(OSqG(&=6Vq8xGeJ z1IzF=X%0(tM2-fwK}ix-9vwa-|t+6Dj0+5Rj}tHg4K zyS`%cE(|H`X=fmQ0(UFFgUaD!9~7OIp98(ZNwnDnBQ!hl?e^Bd-N#2@I;+mODu9VBnOLqKgexa&TsBozx}-W*5ewUB+a<8 zh+p3>SAqZbs-PoRw8ooF88^mo(9Y%zlKmV%@Fh{XjWUt8I4emObHIjLX zwdrN#kV6h?f~b69?cT@d_h*FHn`%QsoU&UeID{d8dj7%HZnway>8S~bUr(OQx>Gb3 zl^RC{;J@I*=4!9A*rMpM+9%`J5di)+-Sfbo>wlBl`*YZ8RQ1>E?9Z}D8-zgpbM9Fw z$PMmSg_J%0jAl7xTW{dj384e<|8bz%QX`WbMXQWPe5$;K_6&auz<*@N!4cx{7x2-B z{tN{2skun3-r_)}%weGa)9&N1ktY?&P6)cZL(;~&$xSkI6NvQ>Ym^<2xe#K*2jXX` zn$^Kpd&_%mTpZok@le3W(e>^E?r4ut!FUI5{rp^#jL< zsr4JjdWV~EY=cHng0Vd|;T5a+1s6$uV737(o58GgQcW|$ptqT)>pY{SOaoehg~T1g z<-v<^CNH;S!QeNo3UZ^y`HIj7+$Hs+Km1$bko}i3D;KhHcm)@GG$<+$2J&tDmirtVp?}tw)Y8uOyIL5pS^b?O5R~g+~+H&P5>CPxcfd6$#BT%(Ot7Y)D9+wlyM6F0Pcm<$8AK`Tn!53X7TvSIvpO#|81;X-j6gCC+rv zWb-2WfBUIP-7rT0FC_}kRCrW9qn2tXMr_;HYb+3NWwVJPz`e9#u~07Wqy2$UEDRwqIJ8vJxkj>H>6!!Y;^eY_H@Z%yWh0c8}sG zCN`Q_sqC8iG^}Gb|K0h|V6GIc{Q*e^ZUg+|k8O}x?1e3t9)S-~|LLR&FyRFnT%DDz zvlV4teofZ!ERDNFVz!7mBq0AJwy=6`^G^hQ6=(G@$DF&AnE7O{*5RKdHlOPeFI34k z0sl=&u>S?i1|B~_CPhIs)IwM}e&EA+KCAJhi6?IpUiC#TjPm6Er&A(U#X7jlYIp5Y z);#_v!LIS#YbQUffV+>2_Vb|Jw4Pk);6kGLsGq8l1-b5csyWNbTyetvtU{1|*u-R! z0qPc_gUWZgOGcak98L~}O~^4Co~fdcs__YdjT6i@I#$i0-DN% zsf#>j5E3OrbJq@?JX=49yCE>@V77mcGd@E<=6}j7R#@W@)xiqi9^&ZG=aHV!g!>dArLWEC3T}cCMg3 z#|hfo^XEN?tbLAu4#e*s5i7#y-f$aV)Gd2KRG0qK$AhqCI0t2)zG_@*kH8b4f&6nd*cmJ>Bc262J`Z^?G18|wNM+yx3x z`5$2KG?gy6S6MSLT27$N#ZF6b%jgv>?pZalsje>1*pW0+#> zT_hmX(C7s)?2D^G8OiiUm{`D;s;MgAe*ymYfBsu{4-<6HGlR8));*-#z%#lpVrX>Z zbYC#DOu}*X`!C!ikb_iz1{0Mq2BC0rO^IL~!{oe`T|ENI!Ku{vuqUz`eB! zrF$~)*O+J8P2Gk2omN>uGRz9Ve_U`@VjSTrrucmT652g_e?|vot8&$quy)B{p(c2$ zw#rzWa*s;rAV28x7}1I?QChAdRRqD)*GfymM0Q~ziL2;j39aUgefuAkHiowfEH=Lzs|5p$2pKES``)2^uzox!` zzQYam%5K};oL*@62V4)4#j`wCR3j5lXc{ef!>{?@M47 zFZcVrSujw4R@lD3$67K~#mN?j!VC7;qK9mZVg9C(P1eh~U`h93jjBbbzTQbH8Y-nL z)S8}I`@ns|w04cm7~~CML=}O97TOU^)6}Jw6Uz+V!BR;U{qk4#|L6Y??Rkh~>F2SM zYnpgg@nMlCiG?6l{556++q9XT3_g~G=4nz}H<9KxDqf;{IlTk)AGR`%D_2O{GR(t* zT6?Du;9r~vs;0pFP35qWaD`?P5&E}kb?-~hFRZm>-Qjh-+vF03Yb0%}GIkkdvyS*a zbm5dJ8_s^FkTiU@P9XpBm<-n7sdu${iJ2+u$C(_7%F9@Xvk89-Z%K#v>tfM6zA>49gR4{rm)t`gsV|V|rcGW6#LdKLj|_ z4WoNuhHUV>wi$9*Mp>cbp3i-6Jj;gL^ZB7`b=ecg*4mjSu?hqfiWEuk&Ed_8{2%#~=uwE1KwMMzRmSnPV!UV??gkGQYYx*_Vo2$1VC) zcEvX@Kf=-s;i0w&FeO{~q1Y zZmwz%k+$C(tUFaqo=PB)!P!}`BjJNDRm?Yq3U#60iO@n-7jh}p^f;bhT%YAA9*nDa3aXG!CTM6lbp zm3ANJL#jql`s~%0?*g`Hbgdal8H6LLk@=g4aTBaNiBl;)j@>XgDOIJImN>=&j&hq?`9pimjbE)I_W zWe{a4_HnS}B$B5*1P3k)WLbxWL#Y+tUe};01sH`p; zqBqMotuOV5SrWJNx$G!hAX&~=?LVl-sGJrUg9~Rp1b92smBZYySMs!fkDQZ|?CDzb@NiWGu*5yb~=g z`8r#35cKGOeMNw^6r>TDN6jv6Aht76nfAWN{#${fW2#yz*89r(=ub`Ym8``}WbMqu zCONBy%w!X|=^0#D98i|i5a#Vx+G||ttduzX=F9zF@5jYI&+nhoJeOEfJzSnr_E>s} z(#u#&!`f-*@Zz%)!wQ0tqumFp=l4fvph>NxMhG8*UU1Q61-3Vfuo*DGlPb|2`m~od zFjk?GV7JFYt)g9o{oaa;+OPHq;sPP%rhywobq#HK`pAuZO?OYEc;nlr@1G87UTFOI zC{~nUvz?C2a#ZxKem)ky;)&E&T;`TYXjc9;#gB8pCWM{yB@d;wSQN3%?z?_(IZHiq z-mDb4{YxCd6TpABMyGB0kyJSWW{mcrv0LVN4=~FLTY-5e)#SFCdtv)zEuaA4oX3HP5erfr*l$Y` zko3m23_mXQy0|x8PGVo{QcDWHsp0p!eDGPa>wU$pWe+MzDtk*X!(eWwRQiF;!|oaX z=2d|CC*b@YE}?IPbQA)QL`Yc*Xfdb0jqPnbMYPgZ;y5@ z8g(jS4dml7gm@-`rf)JAilDM&K4pM1Z#io+`a`;sb|LGr3ueHBq?Q)lD0k1Ql-FZqv|+EiK^v86_B@itk$4&fE+P-B(6|RDM|dI;n5|x$dX8`IslF`aQAev~s97 z&i5cfCl7VqOA_(8$sGrAWPS=f$tY&3CNkv8d zAdYC(QikU%3-I6A|MA}*xN5l^ZKu+6|FhKt^gpZ{ZVEvC3$%uI4+8#U0Yx4TCoKSp?~R%G=+UIj8N%n zfIj;#QK4nmKca<}ck)$FFKU(sl|J73`B9M5;x5&5a&*D`G#0HRDzt(u&`ZUe#Hw$u zFWs#FxYZPrOBoInc~Ei#{U;(2KL)`6=lL6f`~UNwZ2B-gpgB_ZY5nv8N-52@B;9E){l3%I2@T*9I0Zz zwR_r=-gkvSHOKu#k3n~19XOxmCZu^V*oiA`7J>f1x9naC`3oD!D1oI=Pi)7D4KhNa z5A^?e5qVp5R2~75igns4z}QV!)Ubhk1-}e$T4vdvJ6V9J&&TCy_5KW1@~^Uu?nlK^ z|M6d@Fb@o9H}&w@Rm9mh6cg;EzgiqQ0Zg}HP3GfX!UXrt`)LZR3l{U=^^XG?@H4iU zrFuMUt(~?xBc+$5rp-|1t%Zz7$8FcSOi2a167^o+D0{|0Rq5(y@_)C}*QE}hpIY-f zkbc@dY7(oVxSszYVkVnbpjekDHkZZX?7k1<)iKujQHtWg5BP7--~ZQh{|9`3GQj_R z)}K%)FSz^w{G+on+!U#)A5y>?4U?vJn1Akno%tK0sha1?H0IF~#B3OY2dC5n&pl%p z9SLb#{u#DMVQt&(|AMLfu=mB3zuFSg6JptL)-Vl7t8_~2u1xWlZsU!)rqZ#LY&oRk zeL@ctVw}@FNxYqOlyB;Mi0sf5^qzU~S99oOrc^I5Vf1DP3Ytr*oB`%v!NB}$F~I+P zHUa(z;NP$jUxi81G)ig@t^BbFj(3x4Vj+s*J(Z>s?I~!VMm!gyK>H|F8ouseU87TP}4V-n>+x%A;pOs@vFRV^_>k>R!IOzpWBFi484{Bcg&_e zFgtmZ%|L|1)yE*cUt7;0z6II}z6&-t5bPm?f8!UEs5A&i&{gKkZ>INOb&=}AnMohr z-Fg+L(D$9*EH^HadgXfmZ;qm<2ye#APXc9zVAx<6KNEwIdFo)Ju}Op6Ct5lrgB|)g z!`smn?a$vq4^JmKP9jJxGQOp-MRLi_Uv-DIv%rU^pPu(O3{l!dOP3Apz(FIy?MyzF5{J9Ts}gTi zR_$Lu2*2}|f^YKC;sZ+|0qT>zWQ)Do$_w{)krWpMMlBJ>7+IH4=ga_xRTIqUCAo@k z!iY8RRC$zgx2F@@g)VTcf&1sm#^%=q@E^Z)g-w&vQP(>~Fj6$KTnwl#HyV5hS%0x$ z5iGO?L-iAR?QG;$bVp4oHSDdA^&8`~zG=;(A?@|ZemI^4GJ_9uBVULZ z^K``Y$5VwZ4;D8zR{~X4q`p)fwQL;D+XT&Q3ZZ-wy>nW2xA{k>sTP{dVHV3qc=&KH zh*A8ismI%8Sp}65`xp%qM1E;DVF-)`yKI@mn}#++ zY0N35GgFGzFYs;PL?#j#r;NOCc#Dbgj5fKA&Y^Ln)wQ#zs^&;Gyu7IN7+vG?Uk!Y! zb2Gpb4aA8?^09$`gQ7RMS!m-+ot79AUNI*(bTUMJ!BezLHAtA8l%+QZ?A!Zn|K zgu?ou@yRy_NeP-dEcIGUh;%!~_HS+N(;beYd(LaaLAn(^v=dqDQ*QqspU<8KTF9BH zDG%r)!8erUG>B3dI40i`&(MXFypXWa z6;*TS=F03iZ`}v%et1&{=6pOS8pxtRrJ1?U(UA}nDx(yTVYq2=!uF`7OU@=sm_poa z^%$hzBv7Y*)M^f6sl)vGx4lG*lh|aLl-pxc%jE+Lz9}=}Z_vgiowT6mA8k4qm4}pP z0Z@N%LAdw0l!n*|w`y(nJE)c&bCmjx+a|figoi~z($!KZwq-j=^};TJj<@8468@!$ zkp>A|<^Qse5L0`?un8;ilA#%~WuzLiE5-C5nbMO(*^jsnX>t=l`^J-Y5d6l!Bd6B9 zu8SxoQ5w}*^c;p8f0aF6KDD?oQcR|$uCZ!c^R_4=G({Eoyv-w%jpcf<`k)2XLT1X1 zxtsgz;~(TNyg*-T|CcCQHsF+8_LX9DAqCKX@o8o+_^-Co5B=mN66bnTU4|CSwH!g8 z#big_r8OK@Qm6Daxt&GJnV4fajazV%z@@vKk4duXF1F=j>zHk&L#N$UqtRR>byfB0 zDmPTIHC3BRxhSyxS^rCae*eJynJDo7pYe|ccz5`H+7l6i>9kw*x@W)5N+;@0s5O1pg&~;`~w5fzjlEB+t$r)Fs20BZRHL0 zzd-$G0rcmkR9d0Txex|*p#BU1^#^n4vE&GdAJ&v%*Uodw<;(b9r3ubq@ba<4nB1{| z`kDV_K+~Jt$DK;&?XOIP`$WYQeb|C`D$FifVMWeUW^*NaWw%q5+h+S&W7Ih|5d@t# z1k|N8gBvbM{7*$%ZFR9D@t+UcMIH(F(MW*(6Ea}_`U&)l(xf5r*!BZUlmdqR5r+Cvc!e@|DFB0iLh{Bs_(>ujwb+ggXk z%T4ji^jz4)d39b9iZ_2uQNa=F${sJQuaDIwBV|!@zp*@E@^V#grR~AJW}+MW(*D|{ zszr+G@1wXXSKwGk7E(vA4OevN<<5xo`p_=^zw%p0olF06HemsXB zauIw6vEg?uS2q8~PnU&uy{B%d`v-+h*nYD-O{lT&r?@>V{5ptvzqQv$D)?ELE#Imi zpIK%YVf@uc!r+RGxCrF7R00Z4+?%P^z7NN0XRE*hMnR!T0Mhj<9;PviQID){_H8Iu zO-98K1IG7vuQa~%f{VmlV0I|cm}=QnIos&=g|w=2D4evO^v7(%KC{%HDTTRb%@s!4 z;yR!A@0tV=#KN7EFVrR68TxCS8si7U{YSOen^<>?3geSfxHNaOp91z@q_!P$X}0N=Rs8-!!cx)E$`?uIvK(jK;+B&kZ~by8Lz1Fl4%oi|_Me{j zf9%LB`(HlMiciBa>X}`i^*8wnJdp@Me^dWYf6L=J!}%h&pfH!sUCPV(Em|7sZ85A8 z_B~QEmn(@p5VGLJ2`MIEf=k{$L@|(Sp)P+YWpC-iS!@uY6X&Y#91%I~mf|W}_go!8 zF4_h3ZzCqE!GhbL7i%l-6yFS=T#yM$A{^X>JO{d3k=C#jXU~Q#8Po=!ND4xtt&tgD z$l-9k((wV&mTc>D_4kY_T}aniYecZAqpPN`(ogm(?M*9A4hN3Ulie}Qo43BtMLF?b zP*Kb5K=>X~y+5xj>-DX^Tk1y<9&Y?Ta|A`_4enq@KTVXAnj*JR?1aj83F}@FVr*s# zoiIMA;gP}4xc=dHAv5O1@nc4=l0_fA0KAd!$Xy~yJ*IcHri!8_uSNlLBFvRr_z0@V zg?;#-W{{D@22moMC!=A0#V1YNal2nQP70Ni<4o5Q`g&%gm)N$1Xs_=={P%hjS&yod zE|6ij%grozROTwe)xS-s*dmkAqTo}(Tk!cq$dbrI>6#3yLIqfK@G~4U90snP4Z2BLI0H|o5%#s=1qPC*^Y_TVj1?w|4^oEin zS**~Oq;p#7DXWat^)5WwdUyI|{Zmv)!Snu`Hqie*&mZdp`*){-wB(P|AxIrh#%vb< zfcd}P$B1@7f9pmkgs*+tw6}b+>wAktAGrcDekTvif3=h=1M?5_jCAIz=EI0XL;I(P z`J@#}6WoQ`voEMto%av8Kj*V=-7T@mkI13LD5_eB7a!J%)zV$jwSrS^2l^_w6#|l ze#0BB%d_<=lZeT~793xv^UYtS*VbsL_9mA`5=Q2NwrI|AdbgkFZ|2Bk(ZH%U5T9LC z?)zSrXZ`zs`-lIXAL#$FcJ)N+zDHO>Q>JCOn|qBYGTUOguH%~L!;SUU!HZS3RM!u_ zAwi!nOz!9z0R5kSdDO#*TAT1${|^A_|1OaC&2uf`o6n?fE?r zUEz^DtETKS1?RbP>hQhk_692VOhS#cx_n`6zWxT$4I)Rlj&jzvTk$l!j#v1Tsg?4Q zgPdUb;XXJ3n12BHMD?PRUmSzeIPK8Kf~_gy$eS`+++)nR!v|ZCI30rrTaoNEF0-)jSB`KmX|;0RK4w_|J3yEr3V} zH~eG-eqV3iD~`kwL4WCa1I_R8yr3*O(thD}?k<9zJJnX>%XrAYKD3Y!%(``tN-kpU ztl)NjcTIIYyk&s+`~C!_8D!3%zBb(F{cB#lJPZ9OGsDOk7Z%66l}Vn5$_AD~)Q+O# zU@PQ+Fu>DqkP<9eY>osC2fu zS^Ku@QS!fHct|#u2EM=gE2XB-Chd;>O&hk}B5g2^9M(S7I~DBNGQ4+@D~Xck%{cSM z4`E?R4DGa**sNN@B&M4f;t>!k%#A$zC{e^P;Qe2uIVdOC54up;OQAxW1>6Y>gD#Jd z4Y7t30R8#+QGX<$<{&d67fDtV?XUvYr_72F_PLiPFO(e> z+j?pUvc0#e4qR@~9xKi(SI(lXvs+!^zV*WYEF95EjAkc)spQE2Sk*N zdAI`;_jT7&*XD0>A3rCGdFp5X{ki@>``-|AKz|$-E7~3;RuPR$-a2yz_HP0Fy`{=S zM*{Xgr9eSCNm*GRYSm1D{hR*IOy0kcu#W13oqsdeYXlG6U*z7%^sf3;f5>x#Y_4Qb zaru3>j?2j9a-yJo&D5#vGeNaNL7w1gAx#W^Af9kdT4y=Iq2B@OZ>_@c=ybP~dZ|QH z+s7Vn@zpBST@=OLMAI-p|Mfe_B)=j?^DNY?IMmm~2NB&6elmQKaFY2+VKD7`?zSeM z-^>w+^hc9Tv>cf%KKpC|B3DDS4a26ksGSt`j1I!SkF)v3!qRoL?h2Q~yF`S)-M!^! z2r%cIe`z=ikyGYrtMy$^zXP66u!1*!3lB&OTf3xO3hbL}_F>*# z3mfh#8d-#hsnEQK(F#@?ri@HRR5UzE4 z!S$@aq|mb&NQ)&!vjY9!2%x`-Z-SSYtyLiz3bWB3^vvrn=?KAd2fC;upHiLIoN(^$ zzHE+6Z?(`?;>n~~6O-(nhuS{@`=5D2OdW|(fPZNN`fm+Te{g{QuVamt=K_7fyDi29 zOR1ucG^i=A=ToEZga=5e^o`UhPPpEOQ*M2>AP_pj8LfmOS{XF!NClXGx&!n-mH+L3 zH@dvx{ZdmJuumA$Zl#K|7^(#wS(@?r7S=m67|8nR*BSYbhjIfImP8!;{x;zM0|$RA z6tz(DNnlK+5mj!d-k-ZOotCk%ekPum#aawreK*|F5)AqoP*Y9$c&~TEJt>AcSMZrV zsZ0*3lA)l0&sk|DC|xyE)qo@WC>jayUscagYE!lX1C$Qn&*AKY^7m0;YfMCMw&YIks>e6(i?P9ay8W7TB9w=q+y~!!e~MHe+eKyWpo> z^mUT4nyJt`-v6(E{Xd?*!Xc`#`I-g^X;`|uK~cK98|m(DWN9Ro?p(SAc990@Mo>Vy zTR@a<@VooI@9+ByX7@h#J~MOXoHHCi{|%r2!ST;Ac>g7dnoOflLfnPC(C+j}ERzIk zE$|1DA)DYK$d=Zk`-wH}dUGUc-J)}J0_Ay~qUQ#*dlO%~W&gJ4#<^HW2*-ey?Mnw= z&W+5nk>Xosg`D$$VY3Y128?5iJACX(4jv=QbLyQu6?>T9Ts`@v?M`~x+EF9braxS%Xr%^BmRGcJB~ro{!Scf~{LESbk1>jk+1-g$BuWzT|-4?C3pX zL376hU0XeB1`Y4daY)w@MLY))cKO@T2$Zw_7O-_hX4?&pI7jn$hGvUKbNW)u zlMQ^<7Ax1RQ)$rvk*u!%R{eV+C^yRMCs=AUBT)EE=HcmS z+{DekRRKX_-}uk@m!Ws>MlV)~3I?rU%;P9N5kH-VSVEB4lJFkWbcPT=diWT$mUj@b zH!#=An%yaLfSZZsv(}>RYmc=eyy*1wfp1<8typw5> zP*$l@9w-x)T)QIrr>mGn)hK}s#uGnzMC~FY!tZDE@L(eeT1kzaC}=XSH}yt;xiec* zz)9bzlfy46^##sW9kTlzHxUwrgcrXPwATeKT$eCRvumr*=LaqnQ%N%0q5W;=sl>sD z>jPSX$Y9q$t_fl$QdEsNi0%kKyXi|M4$3V+3V&PHg>}rr1s$k)&(YPk$)A)lp(|mo zE`r1%89yb(wSoG(ZR{tfmo%1w1R`tnwqSLFE&WH!kOF6eQjGVV_I(e{{a!p)2X=AQ$sTj~RrcKcPf(4O@g58+-E zHO)W{Bc1B>N|fzPCEuWvzPDj{)l~V*gL%@&k+=C0a<|H5hOnIW{2&u+At&ax8R)hf*`{yP_-z_V{$Q}`g6V1H z3Co~Pz@^){r(bt8#acl?wY~hMAJJp&`2Ne5vk+ke=SN-Hb2LlZN@4C|mr&88?+NBrn8(Ub6vx?_i^{surs4HGh`JXcXM${61+U`qIn8;|8&g9}kY}!o_ z(<3Ljdnt0MKi5W1Fg*8J1Fxg65Jf--N3vs=KYA0rLo@ff^L;Ks=u{=9TGSQb-E$+eMnHhH?K6y){>H=yy^(F6I0UPfbK5`_?d8CFE~G><2&pE_+vq^R?=l0TV&9D*~w{$6_FLz zg8beYmaF42HK`Q?F+P=YvTNT*n=|Chgl`nZG&ZRaq_2JHR8!sy&Z;>cC~4$#4?nnV z4;NbPp3Gf!$A5*FCaVE>J3(o&)tG?8W^e0?&qGPeA^A6O8?^MzuXAW~Oim=ih$U#LfKMD_YjTwxv#IXE!_p;Q#6!9>U{w zc`QUa#_y74sYS0VXeA|>XL7%+*%YTc0O}9`^u*P|V5U$EOk7*DW-v|Z0 z=#MwCmF`x8S=#Rc|1{2lqK-Aa@aVtkErZqslCR*+9Ri9r(o~vyZB}Dr|R64yH0Q}UqC4B z2LsBF92n@liaLR-cNP2M9Sh*s=z3+c_jY6>>KnhgUmL9$Odq|$yhTZ@zls&O!1&e!Ra)fSPgjL%Acu&GU@uPTprIKwGgl?nHi#eIXVtp*@_8^5(%Q zTHF#fr9er>vG5<7>mctSGFi0;zQ0^lZ7+8I-VJKe>Zxob;iqq8d9|ZNg2O(ADTJ$> zo{?Dd5PWy)U>e7X3@u$7fz0?XdK}C2CM?#!p-L8*E6D0{OV;z+h1k*)st5=sHv^3F zt=@&+ZEk@RjZVL;a=7IOI%tpeZEat6-QX42fM0H9iD+;S&9WU`nVr2)fmjxy>;)PF zh6h-nigisCugg)oguF_sfaun^yj6ol5jyJ(5kI$=;&;^lYTcU%C6i+wjOb15Jy~?q z*>t69{dQFLH3EG)*z>uP<-Ls1dU|VlPL4jf>{w#_C;!Fyyso)#Qzn0fh1>k^m@0~< z``6k?b}U8JbvsjeyU%f3c$Ev#$2rzL=nLJ?pGo1gNb_cNB@ypOJ)5`A)0wkU4w~%@I2(>E9{PQ@7p7L1epc{`QKI`Vy;Zf*(&j$gF8g?^ z9MD#$_55R3NbY^=S-aGqGQzbtV~qJAC1q^XR;D;C)&v*CcwPX1As|9t@%B`<&fb}U zjnQd!>)H4YR$U&t>uwi8axkZ^K0avCCSYh0r?;n18=P zA$d9C85P-weP%$6y-^H@5ks?yW{t zUUDH;dD7oX9NJsZvsE?`U$waO=H_KoF2&P75NtrM#^7yBd2T+PIRQn&K~2r0E^b%| zeE}b9C<9t#f^6Ft{B8}+xOSb6F2{gR6pNPAM#2@`u?u~euQ`kL);2x!v2N8u+w_oj zv~8{O|I$56am(_YSt1FjS;6%eL4`>aMRboncKEw*mFplbfM?qF#|>J2Ho&QYrbS9K zRk35(_KERTc#GelXAXfnnAMH9WHLCD`_4<5eNXN(&-98+o(I7HRNiB`jiP=&R-UWo z8=FgHIU>gm)ly*`@yt{@e2Z;yhD0AETD(WnefG7`I}x{Wk4>!9#%4`@H`X>-2YaIQ z$kzkX8P1$>P^OmH6fZJ*QV^ECt|4joDY=5n-qdvPld5)%Cw*K)6YDQiUpC9Xz3aC% z4A(AT$Wot&3Z?dLo3vl@Ydck~_1v#tk<%Gxvz(E2>qYE+e*@qDtXB^QOk`Wfau?|T zaTTg2l0-AFj}2N8^-&+MV(o@h;Qn90{GkEBpA!N8lLnA~aDe@h`dAl<{%$N=B-Ut=Z2p6}!K{EH0$@ zJNp(b*^PJyH+Xd(*k5&fgs6MFWJx9Vym^RY6ABs$w&J77v3XQAmjLi@qNrYG0euGq zpE%=!Q@Mjbjr4gsD7Hii?}d}s*AOhzV^=T>DmD-pn;R!LxV&zBGtz90_gPb1%YG&R#Q}=xSpPIdZ^KYmcruw4J@DU2=Pyg)g z9QXOldx0WA0xm=(yJkTChrfSt{2QMC*MR*0e!7rld8H@uti6M#(Wd8_DwUiKu782^ z&(hdr4eT{A>$8w~3O#e2t+}iOc<7!oj2PbydYOV1Wxp5}a4yoQHOnvHA2Y5tTr{c+Ix;@)f)7q?Jw{7bcy3}m-FI4^NvwGA~sFhvEN#W z8Glnf>laJW|NQsh{&#Tx>u3EgrVrp}t~OQdd$p5nel|b#lG#?nDSI=n{S&C!Ww@D) zxFu;+<~?ER6xAA`iu_-y)fa&N7w*5eZJnpomN9Cee+K>V-2M1DK~+aEWESu7^HwvB zJK%pscl-8;^=7us)F_*slxXy$Y)s$^)_}ZWPSEOwSA%OdXD)&Lo4lV?hoDRycIuBx z5&xNgv{Ao)`BmyCGdzGkeI zRJ4?()D?uDQLUfBo*xMbsk4FS-`A!MdX?3&EN$=E-Sum6%>2s3kUB7%dNMoQN&JTC z=f}zJopO^?ZUoPgg;${IiW(&R?~0n0!2AoXMHd5d!k?cFzPP*Se9aXKPF~suSy**FR+1PhFaDT9ZI>f8H=-e)*DJYa{DD4)ksaEj5E_(t?M*zl=}7Xt5~^h_;Vq+2_NN+g zFCSM`L0cId)Ta?j&gZq$l0EIF*8w|UTo$Rvt3Lw&-yHb=CWZsbch!9NF7$^0|F(8d zEen;-bcaKIoS&_VAfI%T>6ieWGELBTMfl&l5|Td&k>qg?v)o)8*o*2>{O9~R)2b*fdi&fA2mt+^OsZ;XC^#(e+Xa55@1{ZV3v|XE1NrU13g;em zz411y(Jl;q)tchAcdZUA81vua&97LQTY_mxd4H6$hm8!Ec?Xg?&Y8X>m-J}+jj4H; z0YU2fSh3+uueSNUoy=kie*Xdd#}?rJ3xWpc@pJr_e23>$S=Js3Ywn(!plAtZV*{YXCgRq zGE|)Zp4&30-KNWXp3^+ceV~p_ga~22yIs#H70|y2?WJ0{-NE_ak;+38G6lm=SruPi z_ViZz5Km5}!qm7PYRQ+!hAQHSgV*KU>;`eZUf@whF);rOh5KKYFH0hgi2I6k3fMn) zHI)t~uZ!yJ)Q5A>aRpfV`cTYgA=S#*j>~j@b!Lrm`Faa{e=F3v zU^CT9j#S5+Ts@l^k)Ji}ZOf!;46S0F0=4JqBbiD%Uh^NJ!j$4a>gC6WhAfARwrid? z#t3$|rXOI0?s@pQ>F7_azJ8v`Aat`vP9tq~Ys~{9fd9(;570lt^B=%}%Kjh!u@gA| z81%QNB5VRYc6p>C3NPX!iXmmrtsyR$E(3}mLt&Y{ZbdIQ1CA)r_q24mkB*%4FEU=J zNL4OH^u2c!>il6iD9(l6MEJMAnJjU?TQ5uVAla#rL|D7IzmdDn<@45%fP$PLX!$aP z!DZ5P@jF8X3AiI9967D_IN*+GJ~HS6+xXE!WMCbw!E7@%!oOr&+r-ZzT`fzTt_%h5 z<>1?^-V@s?bSO6@s`Clp`S`@D_EL4lhLc|(Z|W;9eMR(F&#kg{To`-nqr66-v-{R= zth1x~a&4^@zpc;mhtcPY%*qXr(1qN)V1`MP#rKSz!?MFHXC3(s$5Xd>SF6pt_RhWF zY*ESqS{PqijRrlC%Rj4bxDlj_vi~3d2YCPC`Dfuo7xf9iU%G+%lZj&cPy)a|8{qm& zfd6p-hWk%+!Z>E!2Y+n5|2GouEu3u>elw#+E^s%8to=7H`TbO)wsXpTEmz_)`&rJs z4i~+5ZhF(^`K5o3k8{2=eGKhY;H^~uRA6Ovt94Y7rAP`9dsNlU$Ov9?<-z(qqFQt5 zs{CDG4qY;NQJl=vVN4?zWA#`>yVQCGZZ|0i=k~b4L8;NA0N*jA`O;`1W$p2Q^LH4W ze-6w)S^)j4quT@tas1x%`K;!f*E2^GJ{k>${yF~6T0s7Xe}7Uh2IKjyoqxkr46w4y z+`+|xqZfSrD7^nh5Oq66{895?d?bX*@v*0o_l?y9{D*!(|A*pUT0VWv{eU4Qz4?dXLjuN(5dY>Av8vJ%>bTLIBZVV5lxR+|08l6SBy z1s@L(o?8)iX~bw|YPvJWuljJ-K~7`xgxVZa^vk&BoZm@6{fCTRk4!ybd&fK^fdriY zue5Th`)^)=gP1GKcJrs(#Qf()$KWSStfWj)@g|d=K3vq)oRHIFKH39VV0k@4SX>Ot2|LRiI2(%2} z<3B+*FR>Hkxa1^o(U=M5e|I}-iB|y)G&u;|2c^YPM6qVZU-9tT&Ymc)Zd->q^ z-wwdPkO1&68@T^8ZLgO+Fn=ls_@5TQ{EhbCS_0$m*Q2Tk(uM7WcDJ{}(ayzgR1XmH zi?JX2`iHe=IxU9g=b4wI!XI9-Ks3bLzs6NC)8!#P&XQK{j)w~9-@*EVHQwf&2?O;P?$;-fc!jO2h}c4`{p7FC zw4UxvXXy?Br|Y*mM%wWecKUnuUY=ijXl~OkuRqxwvKT<}S$W|4leR51%|4aOHEp z>N$Et{tg~6f9xVpb5k0vv5IRu(sw;yXub_pIGPX0sSMRs##|cIX@5L`~r}F zj~E1*tqzt6+eBq|z#0Smf1t-^70FqE{s{2HM zp4UeVQ)uq|Vzi9Gg~d|s?t_UoM;!u%H{wl|(c3QQI`tKWd$12i$k|v>uFgob5KC^EOUIR#R}&W&88uWa_upeceYiTxTA0<`;z3ecaE4Z<36uYm908_quf=5G|h_um5aU(*iI9{Btju0MJS@V~@>{u{{} zqmd2=ds-y({om30f1Kg3{V3xuSvVU&Pfyc#p>)i0?Zgb&v47?I`$oSJH!3zJ)6z3d zu$8TMxOoKq_TFS)at#&PkwA48Ms;R(W4q@d2aloY?j8D{p0_BQjbsXsZAEP|qo_}~ z+Z}W}=XPI~F^a5{-7x!T^LUJA_=)+2j(<+gcsqAC1H$>j%1|Cszf$OHgis8f({3rZ(iQ zIP^e~3Rcl&Pnbh@sx%xA@zXjYNO7heC$yA^Ve&I$VKN!I+`XP95iGxMwb-j27=z=H zvHT6Q{+PTh_R;Ot13Ajo+%Ep>DadnkZ;8zn_-xH6vA%l~-c4cf&O@c79#igHNU~|s zdrM2opwC4K+m_=INFkE4>PmK4Zab=YZ9ybL-znV5e~X*obT8^jp#HM?7|-|yTI$!< zEe8uNiRgT{9Ad5z>lf>K2In6L>t3aq71Ya&L@zT(-`2abgOsQ^cBqBd3RZm7$^ER0 zQ;PYnzSdnuG>n;fFJa7!%VbPw-RYk($^~-5%G03h7QIQb24n{ZF;Xc?Rc3fdVlgg! zQ^HkRseNc=NqVm?-kUAmb7eg`5%UI7?S3fgSd+GMks;W)>=wL4cR3dqR>gksrXnvT zp2=l)bg%0rCQ}hEz12Vq$TIeSNv>~IkX*(0+_+>JxA0ECYnLp)GH74Yb*7!nvYXN(DciV`?iNp{F`0AfO=-e= z%ZK=0*4}oVv%J|s9vW8=dvN5qO#cD4wNZ=xE!j7%F`*c?P@Q*bhW;z9`c+*LDus1W z;75EWlB`tn`FkwbVhN;R|0$v^b?v0Q=(~5{dsJFv(OUry{HwXSp;f5x3l~HQ41S(< zoNNcDOpW1R?>f;ejh0Y_3HY&6U=|&E$4r_2+s8<=VvJ`kFHiE7%oYvQ*47l zgGJSM98BoH{`O_Xg4F6aC%t-!vY>vUPew}>_X!%oeOGP-eOppeAe~WpLY(<$Ou{FB zamPiHu@Pa3uB|{Q$~(2prx2O4^f^Ib;|XEt>C;NdY6@<^15@b9a9>Ph0k=UiMMTD{ zh)Z-&Yu}{2yaA|TE^w6e{LPG%wIA7Mj&nSCU%e60o`&?lW|}g@@Ox$Qkj9O$vrVhx zNAW{+$*H8IvZg%I|1%G)6bMvp)yL2QXH@!56Snb-fku zi?JBNPk%Tu4_ko4?>mmg3CSj}4NfI*$MJZZzKr z%J<2Gwf#_~)A!@>WXO9-eObk0-u$3@yD(jkQ${&2C0JJb!`jF=$el9WE6>6qnP=Jn zFI?Aj{1+x|ja6z-PFMANb-mRL+BPH7tiXTtNpSwf|M{=LfcdW`fd5$n_x}mNznBH^ z*I@vEbpY=FBjEmT0qTEyfd2$zmn(Vo1~HH$Rg=>D;1ApPKCIaV$q3nnrG=_gW>=q> zS&2HPidJVS(yOHr9#t@_-h9F&od3FlU@i;v|HMH5uL0<9H30rw5fK0Uk93QVK5okj zs%TWt>6SX2|6v2vpPzyJGY#N>egOWv3dGL`@ZT9lW@{4X9#iMx591LpwUa_PDA7Oi zw$V6_2WPywW&hS*oeGgT7bz#Nu0Lo2{0CKcY=Qhc3*i@I>V7j!HS z^y}5{N{T!D{74?D=q}@Icffd8fc|*aKSh0PaNV#L?*EMEn9FS%tRx537H$x&(nnuj zny;#D`^*5zR2z!Tq;6I_&mgc3lhFN!Hv1=rzbZI-i^M-6%EL zz>Mh0LH!%E@889keugSqBBc{0hR@kg7{UD)^dJ`X~ z^hj;5Qui_W&!hGW#$tU8d~Qn!W}l|ze6g4_jV#Hqf0O|F&tJACDV@vGcGBH0e=d#A zzEd}E&xy#|3ChMpQipwymm>iGZ~K}~OjsBE{8OIk*V~QLBtr;$zCPE*ss>1S=13c8 z0!vh6f%%szaR1U@CF7@Sm8wUxD)w|hEdl=-)z4?OtY9{LrhcBGWek&ldT#{O7?~-E zuz$3SZyz}^%6kF$s~x!e(lU$>H;Re)K~O}_QV^n8^L<2oC!k~WC_nYTM5qksZ^2tYMV^*ZGjrE}+3$J~y?Q;dh${nU?gNafE z=)dz8+KjWA2Hb1hk$b-B{v=)&C56giv&-GDjP(KjCmJt;TI@p4EYbMBe3vq#wh`{O z8@wln71*}dsC9^3>A+Yjqg|Y6-oB&@dZgdDd!_PujQJ+&*}x23ckJ~rA&9L4`2Smr zn20yB2GFDZaM{%Q*IerPuDunixROqU_F-L_t&~?R5MA|}xS=~hm;3Oj?_<-I&FE*V z?cJg1uha|}G8tAwl>0d1b^&`Bzl#XnZAsiyE)6BL75aK2D_Bq&ilc2DcK^1sckV4> zuKjf8WG%Ki{-+<-qm$&3cTCs$Ez=e~HAeMzb_R0Cem?MZZnw(SpwU`7KbP}}#wBlQ zdLF_n8iSyEjZj~KqRW6cnV;Nzg=^X1w0UGqEI-gm+atwVZr;=p;r6YsEJnO9+lsOn z;GfDF>&SEp6y4~6P!XRt&@9fMqi2^eqvw-vYdow;A1QzQF1Zh+)5$mt`ePWW2d0xi zW{sKP<-3IpZfpA)yssz)d2Tjosp`+>E0MTjJKIA^ zw#jlUGIm--|2(n9T|y{c9u|Q}tR~Al;sE`%CqxGDzbtPyI)e33k1FwobJ25dPo@2O z$30E^uRI)Wz!kEGcU4!zVw$N7&KCO;#5~HIRwdUqOKbLx@VB~(1(pkn#zC0yybDhy zfOgirfi9jQux&j{#`;rd6o{s7+p{sa7HNw<2n z=VTSrZyW&sA)x=wj-F3|*I)4GpMa)U2#+6@a82FUus`-qU%t1CO(x$O@P9dY5b|+e zOu1lJli#mlXx8X5_99j5%O@wbH#dPPk&B&Otx75EzX$wBx{2)XAN&rj9?ha=ZumkU zFFBpH;r_>r6lHeV3G(!P_a%^Q=Tr>G6!(5}(FgVgI=b)5y)E4FF%rFgu8ksa|4&Sn z;!66Y|MP#yI*Mn$eiu>p&Y=WJk$8U}&>y|t<2j}WrJ_pQF7-OHN68z1FEET}!MUBQ zOA-2OIlP97w;nL$Lu*x*8N8zBR}kbRwzOGC@SJSqLf>O4&C=L{cRWxowzDR_ojMPB zEy_4hF*J*jvBUA^UO7vV5Cjf~g}+Y-gFpWze|Hqlm(8({q?eq-!zfi;uHwVnI+{ff=ycU z2he{5_z$j8mS_@_5269&!sVd61*UpdR~Wh& z!o^Nl3WMD+;Qy$$Dc8NxqsWc(#&5+Uqkwmn^JPtdis?_*Zw%X^X|+SV2a5-~>75fn zr4~Ey!0XCCL9Z!=sLt}xE4~J_Q`ZD$nwk1oUYH?M1u+=Nuhn-{v^L8hCoxSg=Cg`# zuD*S=4HjpGxeXA9#Uxquke_X#8Fi`Ri8N%yt1)eS;Y*hJ>R>527Zla)L77WV#2hzy z-Qve~_+;YBHW)pX_B9*u-_g)fY$AtRtYqn{fajI_6S#gimB?YCCfU*GFxLbMcmVqc zw&n1`T(LWC4I2RbuNvK;MKEU%VI$$hRC2F(LJa8?zwp>o zdU)@QFpAweLX>uH$3Og3mNG)7c&y(Xq^>~d`YTRO3tm7k5hMWk&(3;^O-gewCuQ=kO-UlABc3pr?9m?eDpz`&C$B$cz+sCR%_i28B`vBQn4eKp^~v()OOiwxhn-VcUuD%R`yL5*8rD#ALn(3s z+WYmLmdnEJp43)$iC4#Hro@Ov#>m|r2NR9v;|KJ}hTDGaFTP@U$b@x=jh+9anh|Un z&`de6_~?;ne;v`TLusMJxz{0i&FR)3(#dU$Vk=M~fDv7OVyW$GSGJ%VSnEWH6-NJ6 z-jg_=u3s_L2zL<0jO7=y*%BMI+UT)52{(NIUOm8nGywK*!TUc(#{cr)T>CU6!GTFb z(sijUN;++hko2LN?dR|nAxiVbUfNny-{HT}srgcrR>;7_hj)+DuJN?<7u%)5(>y3a zk6~U1KL73w+fO;HH$z#pm^U`YhBUN75Oli)^jRD{)j*1~tr0N3ThNid_i}NZbU}Ke z=UR2+koWTHwu=IzXeJf`H08+06CXC#%wlXI^#a=c&{tJaIsUn9U7o#TK?1143yw4kOi6E&7t2niyMuOM*?HYI z4eLkqEz8$E_9OB5&mYsvg#w(F?SFXId*QsJ%AyHc3c4~!do)VE?W2lmEw$X**A(=e z@os1!KYj8|t{j!XYGm=?6F67EB8>>;vReJ81JM@SiOgGao=O;}Xs5yuM>M-G{=5y( zKZ$XiFen>e$ISnpzf592pugnQLvRgxBO+)0<~<=aW6JOw0a7ZCooWd&fK#4z$yYV+idIloR~oo|*7f=AJ&4{QUUb)-5y0J| zK!(x+8ULlB3hNPD^{AHlTd|Jm z!5~tyyYqLF?LsLk1Kp6mEZEPU`lCKW=BuqM9&s zk6?bAuD{gj$A$ zi=rD0b;Z^vbT7i+N{#Hf&UBJ~Ym|1gyd{GO!)2!Bw+Yl=+UqxT;j}BYJ9wrJamF|p zj1`*CrDy7pI2z((XQ&8E1vZm)-G>zvJqXK=YXK6=aIW|%g46bnj zs9dBw8ebP}TYT;JY(W1nK!@U)ZSDWy&5ecDKy&#-ucvj2YIDIF2#{Q@fd1E`Ua<=X z^B4V=@Lo{r^+J_(8)*$qT^d$;tb`rWWOGJG9QIGx_#Ss(u!2xG$>!7`4={ft>#;#} z8AUzBd!-AJtaX2@{iR>^xr>F>QV}urgj(Pn&22Xf;2)%6)sT*~)LldJwZy#X81|Ya zZ$QC~{(0+WKOj#W8m{sPUn~_^G&YX$TE$Ek+)PdWEM{}12)2kf6+ zsR8h}pMd@i&VQu^-hVj%j#2AgJ!s94ya@HQJBJou{N8_^d6_!bi;uUMrm;8|iC)r} z3*P_1`Cq+7nxax~`0E=eu7Uk4o_S~A*?c|HYZKh*#mb#(roCVq3YhLws&%TL7pi89 zn1TR@?E0B%VRaF?p(Us+B|8C7|Mtc7<7S^JX4%>NWNdjTx*Yd9bHy;01N@)nE)AtU zAQ2o<2D@c8aSGnse+78{?9%@*x_c4>G0AmY4uz`${!24HybZ(;FU=ZRE{u$D7+9DK zyzm`u=@D24y;3cde);6787$^~a7{~RnoxZ~k<;_dY;Ih*+^~uSdp2rfd$%tJ30D@4 zUY(#FxATS!+3GFxEWp38n~d+gxTIRSD#$ zqSLyqc^tjj3*u!{&Dr~b`7_l7ttfADRhib?W*Y;Gbfqk1ra)91;Qkr+q{n2MRDFS) zlfMJ_zj~A#R#Q_(6>42{FVV}7$)ihNe?E_I(BYT4AL-UcO;M>}6A{p#XmBNy1 z=a;XB0=HK{UwTtBL17tTl2t~lLs$p)%RBXXZ)yPiXCJ_S;QI#)|HnUo>whC#Najm; zw>hVtZ?Sj~SrhSJWd;qeO>3(fyi12zc&>!(n1aWYM-u3Mf7_f|j176UU4-)Rw%rjb ztH=%$fROe2mgROL)+{~(?DRmZtcNd;$;8=RZ~|3?Ce7`Xpv$K22R159IBe9|nO9=NCf zVo&hLTzEJ9xm7*4ZOGbTdVMI3%U1T4`2k9o{LpBvo0A@H`Q6S3P2pN7Js{O}+D@oP zeQ;MA>LwV&-q};-mW##kgqWIc{vZEIJ1!5_&BH3D=cqot>U=F0L_Va7dcqholm228 z@g+zt`*VcRuF+6nY+|dmQEoQpI@MnyslLW4hlVxMYDQLyp57Z@?zMF1uX-RHh=E*BYQ4fJZaC%c^7V4eA1{>M6bvUI382=<&Z7d%|qp78x?)9fc;Z||JGH4 zC!qfu%tNg2>A&*z4)B561NVQYSn2%+H)YCT<5ELb8)s(PpWs$hvmzYfJD1*n1RNu< zea|vgL{#zctq!36qaMxS3+JHc(@=bp3@~Pp#FLA6)~z4YX*mEsmShA zbbPB+-#cXdt8$VPPSUW4JBfQTHQuSd4LAB}4>3EPRU=dz4u49MJa+1ZwnZ#Xfd745 z)cvE!Vh5-{n&XhaWRq`=p);W`1A@gEW_SGk3!#(u6fd_5cajV5e<_I}{k%|ZRX>BSdV$d3hpNkYc&zmarsfWtF%W2^XHw`*rfriNEpuDTjAnVH zz_~3fB(<9;?SN@ingtL*M+;Hp$!-x#b{Rp{yQyAU)90fYWQ7KmDKhg8zw+55)f)3q6|Q zp9;}^d)Jw=0_cC$p0`EcS@oW(Gnu0;IEceO68FBx?-*U|Blolwc0QncenCg^FFezc zBC)i?%Z5b4BEm)Tz(WM@+2Pl)y$eu(J>JbgKJld0JG=D0*Ne7D2k=Km^Qv}SRIz`( zuK6kG?n|MnC20Zb)Jn>fRBOL!W6+4D(cV7W2Nj@C`8W8j2&Cd`#23V(-n&Lr#A?3md=SmH_tO z$)NrEkN@NiFn{&=AOH2z;lKN*>w*3o2hjgY(PdR#2c^)`uX+LRpFJdx4?ARgfnV1n z*}I@w@e<9;it<7n@PDSiJRdOC9`&U6RYdHB}R+5ay-3&h^EX$nNjD#js6%-k~BWiRn;H_)EP3YJB`uJNZIEHSJJNEe?$xpyXv z4HFsC72*xW+4NtM6jUJUz8e?rGOQ)R{!uZ0boAtbI+c1RmTnt@iwgX7Z=v-iWMoFl zL3Q!iONA&!FFn=V1#rEKuvssg4rN3{PQO=gY2-kMzZA(zba!=-&8ZXxS{3OPu2!Sd zLzE+$<;C#cg1hzuJ~y&rYl~dqirdhc@pZ@?jey6=smlk-(6mw?*`byH$>l6^WX4jF>Y_^Hm?Vo=Mm0vYm z9A^nP-S_$Ry%xCtPya>p!SOFS0Dl?+@GmRD)P$G)y#W7Eu?c_Qa^)?uDtOd&KEd

k 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 literal 0 HcmV?d00001 diff --git a/archive/f4hwn.voxless.packed.v3.3.bin b/archive/f4hwn.voxless.packed.v3.3.bin new file mode 100644 index 0000000000000000000000000000000000000000..026486101b25f8b6c12c9a6d894fbb0f975ba4e7 GIT binary patch literal 61202 zcmX_ngECHfJk?DcXu5+MM@e4q`Om^b7(kHA}JvPhwetCJHLl}@B94& z&;0h@Gi%nYSx+lvkEfoVLaMuk#bV8-O5mIlESBq#aZP0&E~I-?2Wej@0|a)(yoZo& z48PKo-|sk;YOy!RN#`0CiLmooS37aD+i`IMccYcL3xP=TnTNHFJ#12`NEl(E2=|Xh zEJ}+VrtJeyQ6{+>6v>EqFcq!~_T+{j=o~AH{x4W^YzK4q#e=`ebI$Y>W33jE${dbZa`p%cp8pa~-;nfQG@ zFZ2`NMVLoe)`kyC3{D;M_9FSNU4RTnZ>-I-CF8(ahb}?SVQ3v&Jwiq@@l@WLt0Cfr zh<8=t-z8)I$+b_6?0lQ?F_pofrzJX&dScLQ-HNVDD7R3q+-)%QP@#e=^@_}2yAaYz zGIUg6>dq1`p`COJjT3A7DqPp8$y5ZvC@V&E`S3~CIfedKD1-qyxn32$H(Z@s4{=s{<^L$(BTR6eg(`0ikQj)^s6$wQvoAS(D?u z%b$(0o6vv;8=RH7lXZ~fqgWamYf|M=2}rGm(j~t&Vxjrd5d;IyA2VyB=M;$dT)NJv zC4M4ucVy1$BT$rFNvYdwF-ViV*~{!v%3OpcIxGsS{DHAu{$U=@yzfAVao0VQ#tKhF zty?>IhEz$uuZbpMsFw9${l4YqoDBJ|pruz!QlY}Z&|t=as)bu!_6>Uyiq~H%0Yq*| z8RADH)Uw5npqKj(>(+p^odo5qcq&cxjQK!Bgy1n`JOzQ z%yD}^Qu(7{yk>l}b$g*MyV0VK#xy=}MHkd`Fm=aGc8!K0Ic^ z38e@70%DC;tg+_6mU?S^BtGs+Qn`H&7rIbiajxSeFJ23J5GV7uNB-!8uP5?2yByUY z)vd4@wt7`n%R=Y${VH&RmcRVPe4p_v>PxqVh=nyCsEq*omr_!si5NOPKg*?^vpPIa zvype3SEKY-5l~NI4yvPwGs46eisBsxHQsOV#vbV?D-`?Joa^K60R=>61d>D-+0{1K z%s$M&Md0$j^1VtEe7T~9!C+L^a=Wlr54pPrUiUZH^Z8Y;#5P&BE80|tsTFYl*|}C6 zzKWD}xrl2fzKQm~M676-+secEyy$v71@sk~AQl$)E*0v0;au^tYc0Cp0Q@tT=GH-4 zbB|u3e}(zGZKS1`QKgMaA6vRb-W<`6h4(ujMvkScAVW}Y8=J!a&wuot(kLAe83`7x z;iFWSQd+3%ccPoxo3XhaZGQK~BU*`xCI;;aQ|Q~&Jv<^ zE_kWGs@gBk*rY!wtjVdk?~yYRikGoT^Rz#ju0=fPj1cyk*-oOu>TwGxLwL$&eJa5` z4BLvYR7!@)btrl$S?TQ212;#_e)~s!E~#S_R-cc3sy9oOUKYwwj&j9Z1n_@ftWth| zL`LJ$$()GlbeLl(2j?cESDk6ACVNjxBm&O=9ZB-6VqH$(S?Yt7L2B3}TdRV8(rHJ0 zXliI#SdD^-7mX$?&MG2_yJ2qc=lC98DRBOOw7~g+`|o6NNpg#qoZ7~NI zs+8X1AbG}Mv$i&xC*!f+PG##Y8FM#Eft<~AiKD+h{CLZ>?kenNH_*`z?uOxh@Fh*k z#~}zelzPL|nT18G|46@TX8o?Zki$FRq0=uQ(dY$#hqx{ol(wSKxt^-j4O0vg+bAsA$rK%3Y%+4M|r}Cj6S(0utJ}9lFw^Zd$nE9-{ z&&}s@bq~%Aw8kO7-4+f@X;Vex4iC_0{R5GG{SPZ%lXq@$mZbgC_31H(qON;fXC~H! zjr05WH}??1=x?)BJgXfb=?MF==IIR*k$Up02o@m~-9O=E@(5Y&2{E+}-L;v|AkCmo&C}yM<%aC z`EIwqbx{>-YDh@n@m4c#DR#!^cod`6N_j%W3h@*X5h^Cr$q?@tE5y$Nnp0y zyVI*C^<#}{G(+HMKddP}v&Bz{dU)Z)$A(#R3w#U5h zt+$ct72~UF*!OA)Fegh#6}t(5+U%yMaM-fskhDd5BTG=N4mpZ`SIM|ZY(HS^!ARG?jgz8MCB)m8o$8Q0cy4g!GVg& zOaF}k@K@!IB&1%?OnuWUd{cxS^G#9q=3Sr7;15+AlT`a)w3X9HE^p|6@hxI|qxE&F z1f-+}sy4Qn=gg>Lxt6`Pgqa6LN zf*d;0?`$|P559oFY9a%zU-oW?0_?fNKZ{p6n~T>zZD5;{qb%@=JSmJFLb>vB%0Bw{ zS!@gAYl9TqzBBjSoYrm7bm_8GmGnuf|J&2kk#Xm@o8o!wSi8XVpwmxWy`jlrki{F8 zzWL!HPpF1-Kxe05v6+>#;5a%og+bfbD)vUi;*|^&)pF8Ffvb93C@t&cVE+wvr<35N zzRl0CCq~2(2xi~4-nr?mR7y$P&6oKvBy!tc;TIUnwV?DHU#c6u7Vb1{e~FL!Z&fc- zMu1;;D&R3}ZB)lM5-H{Tsd5M^_DPBSd1Rwlh=Q!pC)sm19^RZ!Rxo2(45U7j8#0l` zo^iQ~#eWjI-EngVWc#cgoNPa&X~NPT%wNx3KJ8drn0>Yt=-%nCcdB}LEd?f3e5QI8 zs$G)~PNf!3KUM%&c1pAGrl(MaB>v!QwzHg+Q+}m(2z{Irqkr$ffF&s_psnPyPo_=;!@Q8=n`RvulF(6mom+}<9IdY> z$~;|pTo27bQteU%tepBoT#!v-hLPx~Z58C!JBk!%59OWt#c5KmaYoN_Fof@(%gb(e8H&~K1M>FQP4qh_W;dy zELkHg+RYo(M-#};K|Hy~2rRSEZjJYzQ)I9@#Pe>yqyXA75Nk9yECmb^B5HQiFZS99 zbX0KdaW?rq6+b*dZb>F94X@b#VOO4fBk8pD8gowAV1q1KrRp^GbWB6W9Lx04NSGSG zb=_8|%fA1frJZS{3`*B=Q$QfhW^4eK=`_MXiOG8R*u{f)V`&-`bxEAHqCM)J8J}9e zzsK&Ao6&N$Y_K5 zU`^;E5Kdm`siAdRu~s>aVmB`X=a;adYM)LA1yr80mFC~L<980FeJA_ST-1U?8g~9K zlx2inuQBPQGG1-q)-J3Y8BUv?RQG*)Qr1Ou@O#&7g}W`` zD$3b!Ul+O`={;pPQw$66Hz1RSz3B~4lz>Wd{mF6Avi$l?9FA>85s*#JH!g6n zH&CulRN1BXU_$#g-Ff&Z7tQSq@n>c^d9qVt_rN=M(s9A8S)Q6g^rX~C66*14H_oQA zRT`#_UpCvfrN^D_6yE2ktOoJCPP4p$&^@64=!zuAzVIK`2!+(p&lZd3Tq=QwC9qgH zL)x`rNBBQYy@5!FUO71`8ED`pji>eljHUg`Bza{0jfvj@WFirV0REA`btwn0Heckg zB#asE<|C1kgkCkQzH-r8=%3#G%WjH`&UMi&16;)! zr_bFq5*mgSBMgvpo5Z)9s>h9(M3X!wy5GE)1p_vpTb^dXt#D0>IM|1n_xLAOpoV0u);3VV?Ca3cCw z6))pX5qB}nT2FHNI8_}OwV1>5aSFwy-kwh2*iygE3nKGXBt%bw3)=S{T|0yEmoyr@ zSwUv?8Bf21bW=Cx9GEV&L(ElQr>n!NpV@qLlu$vW^stu}Ro>2Szy#obuqaRWYWFl7 zw0CTLkO&fkKi83pOs(jWSy^rIwvSJ>A603L|3u=#>cP*>2`F|KZ&>;C1#&AlrSYfm z?f4B^E7=Pj$G+%^G2{$Xd|HKlGwCJ#_|rRKEM(U%yG_XOovJK5$=QAAAAv{#g~UCj4x90tfk4Z8 zpp}xPSA9IQwOR1JXIB*PVamhU(6bN;M*{jU#KA5nk*YC#Ze;n_kRex{VahvV=%&1E zC0Qwkde+{n5{-@RfhgT#=(K5zg%^Ta+U!x}u$ZL_8NmO{^Oz*$qNKFeN#ku;-<6DJ zrc!eZ!Qg4>mRqx3*?Ee$POqx{R6Flq;%ls8OnvPL%8_Gd@#C@1u5Oz_tyMiRplwjF z!EpE`TeAv3KKl-nu3D$4+~iwf^_g0KG^~kHC!+KXT>u{>x}Jkhszurir{x;xzXZ;E zC@d(x+SPBg3TFBf#@KfA5rwpkWObR=j~Q4$b1twer6n0dD05ih{XfsrRI)geXJ30= z;NUGRP31`zzg|IRP8zf5`Gop9JkIFDO_rOmNbj%`v-1o8FcE|+=PKex!R}R+M0Y15mc4^TBKC+unolb+s#E16gJYNoAn}@Z22Uz zjGjLm=-A;EO^hsDcmXoc*qThNr#W-}gc6u9iUUW^2!m|8(f!2><_A3>&`U!T3D?36 zoGv#}>%W$`wLizeQD`t<`E-L~k*V9hd<-qpdd=`z7I{w5FAxXm`aqPJtaHuP(oOa& z&m3FpzilV~Ecb$DR@@JGYS!tylU<+alDhmAT-gPRZA_m#!*MkD)Be1^NHw^`+&Yz8 zWMNen=T1BQYooM`_kq9FdZj?R(KSFz{OQf*CPqE-rv{rI!R~V{*>&Muw(lxxZB3fV zfktZPiMuiRVwn|5j;k>gKS4RPs09H3)L(^U{|wXfg~oKM^Ju&CBwvWSKfr_};q%H? z|1e~|w>8u4FMO!~%kUrw(-<6|(pea|p-^P9z_Up%biV!R9xT2%n`QBGev9x0hs#Zp zL%#otwjrkM@C(mSpCGk}1nPKQBv&)<)_)&V!#Jvh$`T?$ zcyc!^d;jFU;g8{oZfRY2DuhWx4T6}Kt7fj6Q@~NI%pOW zt{)Eq@vWB#oD#E3C=+SLdTR4DLWxV?Na50#?~lfFB>r3GCB(^)NW+YVqgM@ue0Hch<8`H{(y6EI*o>n zHd`pkvcb0{lC3gMwB77v4dmadt~gXjX@qoiftZvTiI05EN3NI5A@@1))k3BrD1Z^b zzpw?V7QX{AAph3@) z#0GZ+x>1)9U)KERSEH^IWv_Wb5~b`mfWaG=b5 zJ~R3bND~a?KMGq?_ng>&?>~oI-9Hd?xamcomRi4dO%Wq2C8LhUMzu`q?%OuQ1mJ(n zALk;AMQXjJ(IutyN`orVO4q4j3{47Uko z%7U)vm?FCyd#Ao_RPQjgFftClFr5yIzuuZmY2;UVT~_MU+`aG*Om}OUWk%kUdD}`! z6}x^LHzm|!0F5arCJJnO?&?`VHEo0((N>LL;`p$*{z74$Eu4RogeynaK-`3}57LUshT)3K*C6Zp~jARi5ynhPTe2eBy`_G+L9qh&$+di2p1`5uHAKjPh zYUr+Z1BC$pDEg27l+8>)A`Rew_Rb$z@Fh2*6M#RSMHT~3-x`7Q8$5Br3UDzNHPl^@ zF<4mq81llzOz8~7(QJR8tnJzC`P!IWB8;&H{sr*wMSq>p(?A;YXke-&Vu(}wr^LIa zCpj#O9HksbQ!{-|`um(5eK7xL<`!k5lDdMnp*vCLaHKOS!H>RB;QmqG3;_B6dpdEk z!y|-vZ!CL>SS0S^{tYzX0?y4UI-A|PNWW3|RYXH3)rW5nMW?ShPsJOVL|t)+P!&(fc3%Z7otkekR%N-~#&7*?;QK;j1Jb-_7fc|8U;tv%-V-281PHdFL?g=w=Yqgfo zW4TWx4E{6=njLC4a{=%#HJs{^8W^XtXl~hGL*oGaRjT3z&Tpk8XD$=t8pHmLjLaX) zfJ5k8B?$7MPK-zrNvn0!v$hTW*W=RchzS?J*hzbRU?;cFaNrE zJ#IWQ*(pg=a$@)cbgE);!VE^Hd*l`ZV zweQY%h8>$aw9a2rZ#w!3ygDGal74!;RZt5F2K!OwU)SrRx>V_S=RY&0NPzm68WeNK zYa7b#CJQkw${wctH1`<(2Oeg0Q@J=omBZZ?1l0e!SI!Y_>aRmNaQt)cwIqXnhHrh+pXoJu;3f zpixYor7W}d&-zdR^q$rQzcv#;2#ej6B8&g zrt^a0kwxA!d+;jrVA;DjV9~tT4Kalh=%nVAjQEM=+B=*>V&{1^mbbc5G>X}?%cV~K zi60)+;cx}rxtV32AlIgLo<}fiA&7kd=I^w`9TiFLiVN?nP4@b()79#( z)e}oc{_mw*li?6!w{jixyd#N!90o$`#kt7bQ(B>DEL;4k)?gt*h=C92SLSYIf=D^`08|HTE&F|&S@WQ0sOfOCvj98%KKNUWt&|()&cMz z_Wl-7quM#9`}S_ASkWS`&~N1?n-I@l}43= z#PG3b(;k1Qm#uzckgZ}DFbDXD$)*&dAgsJ6bS6fYTvk1GZiBWvJ@!ZPoKQ(&rh}BU z)w!G4ck@!X_%F7JjAMbQ0lc}PGfWL1c#o%02vZ=RDZ~P+Z1$m+PLcl1IBnOYEjA7= z;@mi!T>)yODRjWWmqzXpETLxYu&X%| zngq8t?kZ8bBss9ibgQ>nZjDQIJ~Bu1R=aFW6spB)W}cFoWF&{t8*A>`%fv%xjgCL0 zTDst`Dwtiz#0@!z|JFG<(3-$xK>=fVjLSr(-0Dqe8=^j}?v0Y}U%#A@t|5QUch2^z zN$T*ONF4~oA(=;#(eP|C(rWFX9D*NSl<@ct&yu*Ua!gFS`>lHGH^qnZMb2o6OM)1< zz^~%SEYW)0i8L-Y7i8$94jW-=+Ka&cBe3V)EG~Ze(^`Hn+?Hdkx{Ke3NJztAcvzuV zK)9Vy{@kGgcR%q^+6RF*M)~~3OcGgBbqO~56NJ?u7f}-ZK z>%Sd>7!Sf5Yxlp_mur_o%S$9Y3j6KQJw|fKi3_8J)2{~lANc@3(EmD+lW-};JgdJM z%OamCtDB>=J_&LMZcYAe1omIM=6MzJrzG+TFtZ$_ZBM96hfU<#Ms5^6ca)L^Pxbz^ zyxhOL$=zS%ESLys8u-u7kEgCTONOIf%84$456eT;{(6?FNfrg{3luU6%kZ9p0`u*~ z?Wp`eUiROXycr-BVE;BxxG~JPDL<+-C6i(A|7O7!$OKQ@Gb|ED*{E;?2*=j3ybzbv zOaIZm${6#pwX(cvT=Z$FCD zDMa$N__TK|P+Yc?zsS5f+1op6xq~Fr{!O&8M}hIm<2|||(^$a2gYO^?@IjP^jCde14oipGe6mv|b&Mj{mO_a~Docpq_Ip_x9e^H(V?mtOqV_4E#-{gA-VqLRY^z=0eyCAh$ z5T`w|XQ>GklJHIn9N1BqXWMdwzLeq>SV}1l_%Q@g;SA%2z{A+rd|D?_4K!5sp3*X}MF~OPUCGz>*M(cB&0`Xt= zkCU5PW%IF8dA48K|6Omq*V&pxfe5PD{gfstyjYsC@PNLN(G%460rrnn@2*jb5wON3 zHO@;asT_%xqQbj_IW4^2!9F4Enh^f@a4Jgni;@1H$3v?2?_P zdDc`F9%HyEb(l}Q;%OS6i5jXM4j{k$W~)1B*rVO?^oV~nGhMgPLPd)xzNhK@r34Rr zvHA-QZ()8?E{j@oq=;F7g88q-YcA2h3Jep`^a`ZsC;{u2rC&zJb$f&JS{{X?C(0sn(8$K&4&$%ZcMd62_vZ&C)Qa=0&2xjqS) zO-o@+7c@p4dX`?Ue2tQ=Rs&H!3mrV3SEK=uLL)CM;o)NYZGlH8vhb1)KUboNyYQB{ zF=vHgbB)1|Q{IV|Cya(qV8QIxYX(CX-4g?a?ozN^VY#M=4ap5lASvF$kPKRsX!|<} zwPD3skQeXqN3ft_=bqj-3t41NrS>*Q>eXST-0exx2BBxQ9kV<==|S;D`s+m^3!WYH*H+==%LmF zi(f`bgi4{Od}0Xge`}5#IR(Nc2t#l7NiPlvDBs4Y|GVJr@v+GnQ3*Ri1pGgJLn5X2 zZ`WN%7wiXPXtGXcXQYHWgj<~6Sb~v?x06UTK=xDXiaZy!qLQ{ z<-RRm`5^ISzLHA5oX~OuIR8ui<#1nMVnBm(UiimyrHeP?RgczKv~p_vkj3JZvPxiE zAuRUo4&$2YB3#JRx(?Dm_hg!4IF<8ImJ^7j>r!{|KF{fk|LGr~|5LdLz7v+W<}amn z82p*{?!$(mS(+1J4u51CmB5SthDV`nHISjh$BF1_EEc9{W#vt9QQ==_CoIZ{aDrh@W5USvl#BbIiv@Va6oOlDOUxeLI5 z&U93pHYQn9Qn-^8z)v|-AS9p z?lysPaft;P4AtJW?Cn=29mQ0BR1YTHFG!$1B}WPq7Jabvskm)t7u1^W2UmQ}#?cG$ zKmqV~U^bL)eX}+%ZL!(3NlEpCcE?oG+hIR0wFTR{JmKmX9+ZfkxB zQMbats%nhI0<#4cPqFV5l=IC(l9XRG6 z%=EV_IK}cX+oI|ACaaBlmZW@e&G*U!?7byg0MtJ#f+4CKJ6p-k?$`1!`E`FKp75>< zaM2eH)KznQEMSFbZ1@$}pd1Ze!qB)IXT19)Lf23_C!*MKa$SlB&isgn>Z-G_fkb(5 zt37!V*`DBdmF4BsKjtX})u~27&b6XHy?&r{x81?tO6{EjTHb>p&o&6xC@4{8!W?+TuEOix~2ohRIge}%lx%uo% zlny}tZ~2Xp^HMk_J;fwb>o8=IIp*3YV=k)yo8T8O`UmJwp6OW?y-xd|FiW>5*&1k= zGx6HfdkY3dzK;2CML5H=8XJLS){e(GLOEzT3{az!WvkRh?kl2HP4pcC@E+^d&=+r1 zz99Fm)KrRGayYloNYs4uCP>8q{9iBmw+_7j%l=feyzt86v>>jr+*kyVwK{Uu2z4@k^jHW(+ zHq|o58A5>mf2jOl{8zoh9qFh<3Ml^gld_@f9FueV%v-!jmp~HGUjYAU%Wj}(A+GZo z6A8OdR25Ch?DlTlL6vX@NbsGO(7^)|<^Ez=Sn*0PO9OQOeMsMSYz&1&kzWZ}`gP*7 za{#{YJqfBjcxMz>3`nMUPb(kQYrp@ffXwrRb}dDtq@R;C+xMVY830=EN5Xg zHPrXBja-_zm4i7*-<+QlKJMe?Lz_&VDL!d$>?;wraD8c$k2s{S{NR`wwxcu+sUTQ_tID_6wx^`-Mo zP)-eK^D9cOpR#`326r4{|zdbiw&BBEqyMz#x#ux*WUpD(KxVw!$_fOA4znrEtKkT zTmEH&R%}s#Y=DQs<-vsPfJxi>#3KPOVFmCn4Iux2%zmrf3nYfslNUVrW)oV&Tb%>> zpJd!NgIjAF!YXqsO^~Tu>Bl9lg|!uVC?4~+C+qd_=8F8kgAAoNm~|V4xzMU|0RN^i z*6K@*#9PZVwmy?EZK?^&*$Y>C-ql-t$D{w8KchnS!KesauN#m$;o*qhG=oruOzx*o z{#XdkB`|Lz|58VbUY~CZ=M&>1*r-Y`n-pvB((7;Z^a}6}4YH~A@;^sfAngx|HhU_L-aZ5EtoY*sS{FU4 zWd%r?c*9(qusnpf-0&}cn= zROuZz{1@m<^&wo;emlp;(23bH8Vra-hAY0Pxkp%`kcDgNrzzT0NzI=9N)FrY_ox5S zKN0Y*W`X`M4aA?w{YzP9CwU=Fhd>cequN~vu|3y#*AS}?fmMF}CZ4FwIuO=5p|f=*HYd0+jVtLjdXWSy(`UY~oCd%QjOy8sVx z;awFbZSFnmWbv&VyFl62_Vm$Qp0v4vH61Jr@mR+%D;U&|@rlA6hKeQ!|Blh5Ri#@3 zY!50h+v5*JjJpt;2q`&CMt?2?^v6BwbHh@qbjUR8Q~NYiJJmb%?~+5MoawW}KfH36 z@cG6`#!4kS61#hKM}FEr=Oc@Gl|^B@BB*Xv=Uf2fktO7GUAD&4Cz9!s8YR!orj6thQK)4E6Qm}{AeV{zoQ zP$XXTjo@>ERCiT1`*9`VGpq>$5PfmH+OznqZ`2rPl2 zgp@H2oFb83KTME_$HJ3fFZ^#~U8|HjBsArRMQR{3F#q5&b>*Pksj#qX0Qsk;5N^Wm zDRYdzO83Ud@Lnbl`TVhO!8oF9b%{x)N>}9hTh#Zuzqxn9u$syQDw`3NFT!oCfz-%3 z=h7IEFACn_(@yqS*ls=Mm`jsm=e&dT+$hO#rm{cOgGxLB{*f#m4&m-3{ShQ90G*VT zV=cUF;Ro(tZiS*9ocO{&7l%cnxjk4&UX_q}kPCfUe&uj_7dpjH_PZ)fq$BYC4xERt z&EY-TN4C62E(YJvvi_1^#!>X$*V|*|;h>iC%t0%uY#!RS&#}65$yAlaW;C7*2jnQ< z-Cy{RQ|^A!)nZeq)o|A9cB(8iNzSZ_Dd(e4uO|qY{;HXp+qw1_RP#@B5Mn@MGV1BH zjn}}W{sH*k9?<`|oH+{{`JO+;0{uVjU4}A~8|ES#`NqDFp8Rn0p;XJBDNZ^Xsz?L| z{JL6WpxutS4tW<{jXRk=UOqD!;6H%__%9biD8dckKUW9({~y5rP6o`sj*6DnoeD?x zewof7CRRN=wz@C9*okvg2`mbo)eyhr@;nvY<(!!!9+8**D`)70nJQ8`Mm_;p{^re$ z_*p0kos?s9JK}&{@X`9!o^&gM9$F=x8|iEXJ~)HX+lH!B^UpVYvJ_-VuNAY;|HJ=^ zm-z?4-{&--{{!{^fRU=Wy5hjD1%}$&w{eJQT;2fc%YIv`t^``C<{yxPP-9tYtw@s11fTpPdI|xpK8KXH97J8 z@GeYcE~)bRX955FBGX@Pt+8|Z9#0Wq{{FxDw^SNd&Hv&*1@>PB6*Aycsa9sN+^aWr zK>zCvk`a_erct&FJlx&&rjAg0ea}bYMlu7%FL@}~6%NQDnIj@#`_%XH|Ht`5 zzn1rkIot+TqXudXZM@zfAQ$-uY53-NI*Agn2619Tfc%dK@}HwHnZ)MaZAhhN!IL!* zgWv!~s6|BvT%lS1dx9*fd1g4FF!0Lqx;}axbkoLukRow(?>l~)%)+SS?XN$ zJ6P#x;d<-W+zD>mC?ZLC#^xnKJKA%oj9sQG17{PPtA>YbkAJTnSbwrVHBjF0&AV2T zjbD|>KbLxz9jKM(D0QH_^)=^|NWiLz1R2+K7@t3>>rFQARk13c)5YCuCrU~eE-am9 zek>b#kawYUp8S?7ZM)Z{m1JB)KiAy7O|$tSu{Z10EwiPF`5`smHA?hZIGi_JB6>Vg zN9%Hwf7fY}As2exBbTkKic?Uc$Stckey%^DfAn~S=vVCJXn9r77NOS6Ib6o_{KONq zIv~U8>J3zTr(7SK!BEiN@uNSSfJ3ei$|{vs-ImoFJlr}!cCl$Q+HK!orjT^?6Dvin zagTex0oXq*fk=dTY{DzvMJzfoqeAVvy`R5_wSF7>v4!_owZ3cT8=5|PXfRty%$`ya z-G6Lp9wH?Jmikz&vT3E>#{(-o6JhLoYmPLbZl>n5SCkdCEWxKz(m4uyR?T@hi!NjFs56|iIBJQA45e1oA+y#3{TP$*o@EIQ$P zW2eQv8)B@9AD_k~2uJV!k|feZ8L`J!I|*?1dCL`Bgr{o0%>UHD{8P{T zU;n@UYFGDJ2ynR(s~>>>nudn1S|`)IMv(Y-!%q$X_!1n*vA9RpRr zAsiWzbpT9v7VONQF+ugjs?gmHc1`?}O-v~DzB&1NfJ0!m$ofrJubJApQXUPRuU>rb zw>xmJkK9n3!_N z;m}&w{B?-*rp~Ja;Up)h8^T>7`Q6Zhe*V7oDX8_M+1rePA=F5AW&yR=t|q(wPUGEi zrJ}-*q~lDATAc2~X||+svv7#z56i6N3;ZS*gB8&$d03R32r9E@+_fCPZ)Q$hbQ^dp z_}=$WC=FUhvNT(_W%eare;UjE2=CVmiolxEFTyLJt{740lF5+j>P`Y5cs_x%-%3y3 zH=d#lNObS8 zKX|2oP~U!kqmYw(Ven7iCnp#r0yh`sUu)@1Vc2UK3Labii)wKboT;iipA&h)y;@e4 zFZStuZw0c8u&ij@7=t@_)6>1s1|m}22PIumb}sZt2vZ)HP@4)$iovg)rg0p|>jX(7 zJRdqck)mPKcsXn3<>3a=O-J57Cb7`{qfHv!n?52YhnB1VUoml@w3g`}zsYM;{1kIumwbVZX7>>qI(!?71I@N@e+X5{W{1WQ za-05gb@+z0ic9M&3l!yaosac0(xE&iAFS*t3%I9y&>U2oO}w>I3xWQhNC*qttevjl9{+=)es`Z4 zT0x;MwY*Bxp-$-4cA&y@Pc~>wmi$lCjF5k+rUnD(&f|rj)eDofdiz z8wt5Ejn`Z4<=h1)ym85i&O{4_=arr3ux<@8C&VT0sDLp$dR^TU6l;I*tGudSwEk^U zCrU)GWH$XI=2x!#VFL^<1m#H8`NcH0RHp? z{DT;nKfeL`gDIfDLIM6W3&VpEZ(p$c0Q>_5@E^l~`KJNszc2oWG=P6(0s8Y>fPW4B zW9(@L;;ZW|H$Ms`gCNi77$a+I!{fn@0^1#QH!uFH71G!}aKAU(K$j&aVQC5MUxezC#=r2|} zoBY0#$}>wcNG?;|WW7?|owM9F;_98^QoUE?wN273XjF2{6;8ndL3pr9LMf3;OFzTi z+Iz6dFAoz($P%9O*_j08H+VoIGTJ>4SdF3{(6l`~j?1we&M#N^(c&!)GT2JL`5tlU zWt3|2wkck6@(eW}}90t4B2s!8CC8E>x=e6KWS zs^O`34eD4V?x~@xw2yKYo_&JU7DVUlf`hWVb#J3q;jaE3r+|A|YqbjIDEzt>P z``XvA9*|+qWFz&po;g|zx>!>P84B9NK&A~@l2dbmu+~X0k6;DLZfQ>Jr&MYI9NODk z`d@me&g=)@EC+rKG_DwodeISFX${K2;*%etKUQFMW8Bc#4+x@VcePZjqZ0ll?mfC9 zaqtsEW8_dWCon&8^k(H5cJGBB2#@g|{JD3UjFo@5&1${sI}IjM>h$hCbu)t28m_eu zq93TIhcA9ia6=54dPvKwVpbc7|9Eq^WYTD`P(t-)2hrooPA6J~9(B5=`k&huSprG1 z1`R*q=|o&JOVKi+T8mVbjAfc+!Y|QlN^F5R#8_*pH;*wDBz9`!Lh+zw)7Rnff?w~a zI8FXmoM>MLQ^>dceCqYmSX$uYSF#(cg?<`nUGl&WAEFc_|KMAxZmqI|L)&@_5B|2w zP9t9xEBaL4wl!tu_lI#KPT>;84`d6RKc!}sHpD%|sK?914Fk4MTj-cfcot;yozzC-FN!1Ev)6# z+bNLYx?5@-3!Ptje$oG5^e0AO{$Y6g6!kKHguKFoaRdI>_LLy#I}R58HH75YSf(B= zjt%qGat>&z%aBYBb0?qAi~k40j9@N7xbct`ouOF7NYz^HbP~3}Nny;|C~KD&OugJS zZ2Rg?m`zZ~^dX}N@So8e8w+KyMVga+FfUTKezSRcS?u|P45Hx#=uf6E`$s_kJow-I z)881B6ASp?7ObOtv|PwJOq>AF*k}cc~OkPH}jG z>Ax`!6)7?#g8uOx$Yp6-$MH6VaOqLCHze5u{!1cB0j)1R?ZUPCdrdj~F~I+4|9AeE z|Bt=B&d0t^58Db#N@UdIyO{2r1cCg>4Q$)Tb9!ZD2sljxm1M!%jrBFDDuDk*&qrvS zwpz~+_domRm;XOs_&*YWzmQFx;>xzUC0AyGo9zf6K61>ne2Z6dJ0^KC(mVYcLUPB` zi$dDvQPm)70W8|(2ewrW>tDvu;Dpw%!iBjOfc`<0>&?Z)YqMBCwFLbC`SSnaC4j$< zdJ0WQ0RF!G|1sylB=+iCp@ymw2~J#vh4Q&l34>}@0-V~vEBhQg~1_bGGBZP7cXh?9&%wE=|{#$zx zJ#10$t+sx{>(A_lGllza8)7?VzEqlcmu!Yv_}n7@*26qdVy(bh;Y$pj7g4QAu}9h` zc{He^;=jLSy=lMGLs%#b^>3kde!Vj~9MB4{_eTxKBrrY2X)#V@>W5n4fBX-U@ZeTi zqfl_*W#cOc)Qn{LswuH|mKpi~eSh*7{R?=1450tmPbbH=X82HP=~o{L{I)!C=20^j z7FZST(PZd*NIgO}Ns{B(+sw!zOL~RzX8Uw_R&QdT|8%yc&s-u2koy&&0%95 z)rF+ZwRldHftrwJyEGxe*(=1|zp|bCR^0@#4k63bX6tuz)}f|&qIXAyh^N5AzsIP7 z8qiu4DeMrKe{(dzDcjm8Q3`n1Z2lCG|Svn@hNkt*n%s@!~IDDQQ*gqUOQVVW_VNa?LL>aCh}_LOkJBEC$nWD++RfrsxaB&I;FKuUeqJ{}sx7QT1*=|#w277T? zTMFeurh%_y8t(eq0wYw+9eWdcX>4kXJ<#>uA13KAcY4H=f|U)yhH_M5Rh2Sclc#(U zc2285Pqv11$>3`cQH@o1qRGHHS_b}ZdpfGfIgMxH-58d5ef&!9KgLHRy%z(7g zDJ3W^T@uob!1v5~&$+(eU$C!dX778id);fT9c1}IpN;9251OMn9VLbLV$;P#iL-~Q z{$$SM!vq$?&kScIHR#CSUpgzLNDXMGI9{83qhdv81oL+%DEJgOxFbL5x4z10Rta5x z%P*Ar<~|hZRp{u@Y)I~JQkc7jYH|J;_7k}!OdjAri|kA{zh~}f3ex^0xT>q(Glj@) z$aEuG$KzBbm*HQCmbElEr|xJAYY#ZhiLYeM*G!PRlfk&&e!@lZL;V9P1@?c%mb>f3 z=)PrOQn!`RP@26KoCL~8<+JETO!4{u^AF(jpC17J zascpG+}8HbhG|4rKLCIAKd|T%A|yjj?0djBIspG+W$|DJ;4gUof$`~6f$I5CL&}y3 zFP2<}WK-8E4$tQ10Ud34acX?zJ%GR3Za`XgWVmPfB5L^e7K|T82I4&q5i%JX$leb<1)s0DqlT1`b+eT|^Fc`j`=J|X%oAzyR-!1J2xVG|(`GQ0f>Gvc zM2Pt2FH|KTR}rr!##F9DI$De&8`2S^$95ZpT`!y9D-|S5md|&SZXa6)BNNLRx&4s& zZv^}gOoFAaGqg8kzppg{zT0db1FqJiR!YUt3%) zt894&PAO;k_#XwXZ!87}i*8+@stKPv!_?1kX0~U!df$D+`vFnSwM)P&WeCu}UZ3`a z1=!<7Cd4iejsU8V&XEF&o(*1P8E+4dlssxlX2znmaRy=2ZJ&xqUz zI(;rCT2kH=UsLVCUuWa$R`f@hqCVhthM}AgFIdhQ^I=CpK*`x+-NHae494*$!ac+J zvqdHTuOSnUG)FqmKHO(m!DSpo_U&s~oB7HMa+&zjh3)UBUih>euK^h-Go=&L5L~ zuUytHyC9J0UiB~fE4eP?`z5E`*^FjN<-d3We$egkjwNZk*>;Ab%R|uyvg>uJtKn|_l zps*Ujrr&f6JYF0ASQV+%(#0-Z=iZ~ft0JuHD&EH^G%mpt+)8wLw-mniz2+bA(V}l(+JZQ@IQ6YM^EHj zvgjX5J>f3}tb&h@zZK0+V(HUeZM16)_Kgm6DYb6WSV{d$j>%e@p09FFqa9Pj%(1uC z(#vmB;rrZpr5Oej*d$$q*#qBStb+KGX!iE#hkB4&h?_D+x#qPR`&Pwqm@`Al#A{u)%Y8tF?e@= z+fy~;fcX;&6r$VA88}4{imG~UU!VK*Ikv**w=>%tX(+qFchWdY%o59Z={&atgyxF} z4xAL5=X_zEZ#u;WP@w<*p(lT`u&`Gu_L(rcD}%)lS(1U<|BZ}})zWY^sxUfiEaXS^|&h<_G(<^Psx-9bc6ceaac8{+!4T21Q2V99^^^p<^& ze5`LS=n567d@X_@qD^Dyy4m#5>CO|VKbfRp?AWR07GJe+3`f2zWHpdWqwFb+{OU;l$+X~~)YPRP zPy2FXouk-uG4877pr@eF9P0ajzrB<$?!-?ye8kf_AnVQ}#f5c4bI^AGTkpanvp{rN z$nsU!tzOYf(UKJHd_H=`#TthNE-tP1roJEr9%cfC)V+_%tItBZ!8NE zGUmsg!o^8cNK0VtP!=}|;n;H$rA>`FdvO0B>Ydg3fmpRj>`gL@^cbEGF7l1m{Zx*m zFGb2z+T{uQ{hJ~cVL29d(mR#%VzJ6-)9uA+#R3?J$`X?mzZ^XAHxW2+*k9ipm0nnO zQt4s_PuhDiE8vLB`;#GBA_=+gHiS5-C?Xpx3nzhEnT55Dcbjea*D+}~p5%X1;-T9q5!I@q*F)ut>HJsl-WLm!qr^8#Gf z4xxw90QHaIc~m&d`Is36JAXa$PybNxej_4-s<}BHddi>IKH|T_kZtI7cVnCy8He6z z3QL_(ERuUTX~WQkh0d>vkZ5t6=3P1JD{Qu#C$f$j4&UAqUUCzZ*aS2OZo~= z21sp@UvYuL^Ht@@V7xH!KqRlDlMvK zh((aDA2KOZ<@aA4?;G{c1s9L&3A3yF@QT}cc^hUS7lX(J!dnoV5d%O}!gOLWUa*{;%w6ky#R zrasEei<;K#jg;&;@ca{fxc~SGA^3zw2UY27y7Q>>|Keitp> zUffVW0`8y7aA*k6<3wL8?>YeY?6b?ytw<^Dz9N=$!YZ3&!l%oFNY^#OY5q1Fi{Dr zmidj(AfE6{uY*brOFGrkJbUd6#APAVW-C?L)MebT6PBsJzv-O~vi*@$Zw#(%ArqRJ z3rz$5|GAQ7K_Gty)$`g?Q^JWB_a=eoveQSpP_EUgiHq(r&FG}2-P@o7?EIR&us^X! z19#C4-1DV`)_XkJ7>%OHadw9^M(ro(yO!nd+*fHl%=B?-9aWhM#JGKV=s6*8J!H9{~RUhPRY| zr0g_Ee_`BcWmkT71^iEd{uiUg2>m$AUb@uIX3FD5=V+Qbst7B8|E!*PX&N{Ai{wY; zi#ASbTPj3PeVg--FD;H~gGb8jU5|s3#O?%4U;|z=s$;>Gq?)&rXifTm$o0Z-9TG)l&Qtrmg))_l;^GKCu6dP#M=n zc@Tmj8#;_hq8TbLf&8O!%FTV<4uySUO6ivBlzt=A3DMG1VE#k~_|G-heq5ICJ4*{z z7T}PDGbX87Cj$Ln(3JpsCg#RNlX)hu;>Td;gI#u&zqGX@wYF%u2Kv9w z3fC1Cio5Nw5Q^e_4sDO`W(oXeapy8KU@N*r8|Ra}wf(xT@m zdVH}dqWhL9CWu)rces=A_C^?NFcf2vOF{1MUzMEtj{T@Ul!J-0Xw8Z7_EiC|!271$ z+QaiZp1C-lISztwAAVCZMOz`W5M=qL4X}`%6h$g{xNc0YOO>=bD5Xwk5^tUxr<3QOMir^#AoUiM!rvXNjX&Dw>Io6 zTjRR#x(#Q#Q8m+J8aM;`harM|bmc^2&$?@!f1@N9rs>ovs9ePG0d9X zCEsmwJvBd+dj#m~SpoTnH5+!iZjBzXtwFz`rwz_7-ZcNme@!@AJh=6-2>y8<-{f7D z2u-U35wBJe%hLy3)AMn#&{sP9%ghE!@z4aw#9jSOd%3kGsvD-=fezcV8!zb)791|v zjONLVs3m)EQdC1tO=n?~6G}I4e3!US!`{{QR2!liYvm=>Z{sU}EVt7f=p>HKN8^^i z)+=w+6JQplbObf5a&$`p$gB_Z7d(SN{#OyA{5vgO-&*f!=Jy0RGf!g`5spg=y-lHF$@e627D4(u!T=t#a)AlmNA6jsbc+i>AToROp+>=U>fw4dIzUZbc*^&MOl9=F6{ViE*HJ@gg`EgBN`Yl zg1d$&-W(}cm?skB{0s*MFemW}J*hNA687&HH)Xcd)OOBTHr>!o?b1l}Q&^aXv%YEi3^bBro;_{Gy=TQormrXZ<2p_hOrSYz3^~ za1$?s-##SEqR!uQ>%!j574eG(7pQH`OzfoEw5`0&P|4y87g{g=HxAc72m$j4ZD9TY z*B|~be-1u>=mq@G%5@|eRL?5fux4@46%**+;0hQEy4+!s$s7Hla63cLdx_x6;e)89 zO&?Xi01`_){ng#`wo$fP!p?3Ntljx`Aj2JX(KBw;x^6PHzL3beb5!T|U(#>RQ6|)o zM6!d!0IE)^LtM2qIcAEv$4yZ~0@M-pb%3yGv=$jR**gpQSV;GQ zX3pp=={AWivg>blREy@IAI*oNIHhZVe-F(3Wv;?S4djoiAUZQXaTR_6^oLoZ#mrbD z{5KG%^Ohpj1q{=dX_e=vLtls-Io) zo1nRMzkW&=g34cwY?vCu)P9N>mTv~UeY7Hzas29ML(N|n!mlH)jGUb>D~Yk3sq`_c zSIbN@X)zh(Vx~=CI$=DY{nA)F7|7qD2lUsxe)Q{8IcT-r0S)IrhSE>@IdJG3$k6s1 z=Km!n|8yM8W%ga;nB0SqGslVzXVz01=Pk)_fARseL)^x4wS)ud@RKWD=`JnQnQM+pR4kC3d+Y-L`VT%3 zr3sFyA|RNgZCMH4D_;^e0^bi6!tAo*mY-Q~BDhgAr!C!XUwfp&-N<;Ws=BMJ9P)W~ zR!g{17{2~;?934gsOso13mc;h3x7$I&2hw|2?gN4mSTN@$4S(NXVw@N``Xls-Z?+J z%8pL7Ot_Z)s0mo#9aw)KSU)9|`@iek0qgq^!F2W7H;pmdHo4`1-(NaS&3v;3w{t5X5p?|ulU@j8wu`D4LjXeS+2z49wO_S@uw(K}x~et6`c^t^ z3U#fPDCs@Pie}?0db|u`RZ_&pd6^I{s$j%@-ZNE3> z?V{tly6XH+e#t@gd*c^WJ&TO84abA4IjNs$@4TS%As`u4D?G~3hOx66MJ=+J==Jt~ zgt_6cM#}E!$vpI%6~!Mc*X?@AJ(KbAphWT8lr>U4*&19|d=FDS&s4Px6k7LQzd%)- z=^ED5rBP>0M76FTIot$?8OrBO*x3EM1p6VRsKwPk16u6O@KLeFJwB47&IlE`|L!U> z0P=q$Wz?D~-Lm665Ih^bnYG69BhRG~EvKrI!(UkolzkWr;5Bmcu8ghsR`V~{4U85+ z8jXbi{=UHP|DmqtZ;d1Vsk^YM*$pzqKk-S%Uh^Ep`mPx@x&5LFgDR@}uwtT>t=q#C;%HE4a}d&bQDHkTuG<%n*#o)G0{?&sSWkd!2Ev&=s)m)`(GJ7 zpBV)3Uul5;@f?`{Ed%qvDq#Kv&;LDTbY=2u}1F#pj&I0NI` zYuH%lNG{v=1_g$Fm=5?yg1RpIz#F{sQ~Qd$w?HY&jk!tf?>n9iJ&m!HGyh17hA*!3 zqp!>Pm`Xm17W||%Qck`29;M@bPipler`lhbh&saP48KGv^rJYrmq8A(TpT4*@ee5* zE#$z&gn)4>j$_jc4nrvdwoA7_uH_z&Ys|(L70Elt$E_h7MeF~-j=xF zeTOJv0#JV-LOr8(Hab~a(Q0}2k?76YkJOjdsKOfOex^gL3o42-X2?|vsHjaf5w_zL}q5P@{}x^X$8a5 z(^c6iknY&-koHm9j53(g+J@K7>)6`mNW*SSA*r4-q=UyM7U^Xh)0m;_sEj;yN@FC}`DEUD zPLd|l4ls+6p3eLP1VmQ=M$#uq6|y8-I^OIL3Q`GjtOt-b=+V^|wURg&3Adty!2EkWQ` z$*{Fo#$(9xq&54^8O@dhcO{JEvHs5$zDbV{_Ef4N1=c3!x(!&MS=ZVv^*8%H)O}R3 z?vQ`Ja7{GBqC))V#Qdn{;vpzqGmJVo7W}wzSn2AUDMPFrCS~rr;!-TyKz;L5P*|=@ zkm$h1U^pLHrBkF%Z}tmaV#RaYze)k9`ci_i-yG*F?Efxu zo&L>;G60m@TzfCfdx8&9QOdAl=f1`@rj2 ze~Y*+N9v8gsU^aRS9g8!L+?*-Au0;v<>!0K7W0P_bx#&=6iqTuJ7M-MYLUw=C*LYE zE9<%>T7j!?byr~xqh{WV7<1w>C}VPW%4en0?>S&)DbQ7mo&;Ha(mkCh?L?WXRg(4U z`6}{K{F={&IWN0r)a7WRS6J8`=P#`*#RHIO6b3tJm8#W=aW)>?Url1@t-ET1CX!Sr z-x(~QxB=@=2_+JSqTqR>fdAwXIkv^DPempb6JOUcoCyTT>DeiUe`}VP9kadL{b4KE zNi32Z`e2B#20Qeh@zu^3L&KRJ72KN8=d?0@u*#BPv{sC{XBWMyh|MbB8 zby2A!Pt3TC@9`qVG}Ee4G&WD$Wz*3}=$-<+t)3Cj|AA0`(`Q5;Q1BIxIT8 zHW9Uzcop3zSXigugS^lMd6Ecz%^a=6#2WqCxylU#yKrayP@b|DzrRB{HS;5mxMQ(s zA;nx|Ya7F-rwpmDcJdLOl-h3*QB$;SJYZ>-+60q?QtcW>$Qf9Tjy*oFEN_35KKLPT z@y-U2ygov>zN5L)dSOfc4oJI-@3yOey3uoVG)-?3yOrR8fnalR{ z@h*`2LD#Q^I6V}U&69m5MV(XW?#941UO_}C_s_!ZzLcU9nl$9Y@Vi5_Non58+jDVs z^JJcDUzMKUOHrs(vih^wY-Ce|qDuswU4vma*sBu}kYC$pq%F0R7uNl)W+?zrA*rnefQ22A@#o+gBF-;Y&|Ugr z{V!a9DqLI|zhS$vXS5KCL`PaSf5s+PJn$Ovy|YWhR{zB@t9vi@Pkfm$*(tMcx@N%q zwN;%kz;PY1_VE%dx=-)5_{hJT4{>?uf)MOrj|LDYdK%Ckf?Fak^s~6JgDM0^& z1gsC&Ur__=>p4RUc!BdL4XnQf@bA5}P6eTEG-<4r4Pqk9j;OnWOLvMz$*UTniy37&_YY$*Eeco{}eIcj#T za3=Hn8Lv~lOV}rqA>7yDU0P!Cmk-=HtQQ>7*)~pvS_w!oc}jEgFp2ldkqMoRZ9|Dy z_sb{>)JG7E)$p2p=b2!J2Uk>naO#ChRwL@yYC<1NWb;fj;)JA6ZFsn~llBnO=3O9v z)@G&n&M$E&uzaaAe3&*&H}NCq40Sl)qA|A9B9}8_V%tFQ+GZqurKgLB1aEmOPny$y zSl}2FYq`z0z03y#FnW+_e6&xKngw<-vR{zQ?F{I(54Wo9K5ejsmI*WA#8kQ_G4fio z(fSU6zb4LqD7L(!@L6%4Zfe2T+fsO`U?)+i*!wT<+fU3wht#+bHdUbiA`|YoIhE3G zF~a%YUt$_KxM)Q7gD}@1V-QYV%r`!~L#G{d1IncSD+8)aPt!g5SgPC4g{1p%NZ2z$g z+loRe8Es`{a&%5<~8)cf;%FQ2S+;Q6hc%%j&k=M4gvv`pW28QO3*I3xNJtdm^^R zjMiKI5~2PRiaY8wrs`sg91i`b$Lhb$uZ)Vz|JX0ujx(p@ic1HfyV9!D`<2CGvn1FL zjxYO1ju~PY$NGDURiGy>%>`T;qI}R;yd9--jwQ=4%w1r4=D{#aFu+>|shBPkj&d-2 z@s<=SJbZ3`0aa|B&~mPMjS{4@kP`3WfXz6lyT}oov8A0JzoO4M4xIm(|Ki_RAb<2G z20tAS(7&Q_Y`6_1q-?FTba%%`A-!)4C6eHMoonW+N*RJdi~1k}%R^5^?jAH9GHxk} zXgHL7G`woz`Q%Pqy%#IoM8j>gokX}J-1EUC$}qL@o+vZ!LC5mPdz>QyzwId1bM*S= zDsxvax;$EX4qPDrcE2jd_jR?|z6@u-^RGmgAqk4NdSva?DI^H+`!`Z2YxtA)40Ffc zl(!Tujkcd%coKDsjh%97$E4xsou?3d%_y(8V>WeUGnc+BAL);H8&z(qlFRkZvo&;W z3JzVVbrXGZ)J_&G$BlW1U3h{QkxjdXY@8x7Ka+d>##t)R+B(ccQ1H6n4@1eW#B{qD z?XShZ*>GY_u2|jq(@xOs0*uM&UTRL;9^L7kZL`fS=s^m<8eTL zJoGD+E(E|Id;tEK1N1NO{1LeS$>7sDhkv8xHN7oMFe6$!#Khr?r7DZoHcZC5Ry6|# z^qNsfD(5g-3(o(7UC2Vx3Xd&Yzb18z!Z)lRk7w;pUIOULu%=9DnQOAmW>n3 zf3a#fXl#8*`(qMsd0RCwlfw8GO81y(EQd%>lMYpC1ryeZl029Pf^OLYnTeK0K4V6S zA@J)mOVcNi6)~391NZ+y&-lv%d}3)J|54lV`cSlt#8pPr^2Dj`Jtdhz2mJm6-k;$D z?jK~J|LX(hzni{Y^V8QtSDqk4|e@NK#B++-*nqLvkp024Y6@3Q)p3G1{R`ocoZ{%h2=6~S!7 z_HCDSUBIiRR0iLK387uzo;Cn~!t*D_fc`Tb=)cl|{?lgrm_IpJha%yUmZjvwC5nf& zTjvWhes2256m2;~A{w;=#pV|F2*=j!JiGy_@su|e%+m&yhM1Bs=k7>>^B)1^zf1u4 z{}sSL0(Qc5Y*M=)&xfL))~9Q}{M2x-8|A1T9x4SZ7h3+)4`IJUJUsg6P}xx8efLSo z(20Ym+%G`92d;mGwD9I81nlVe0sadbOI8}XoA3t(u}XKZfr= zxc?2V|AhPBI4V0w`}t-dUPX*!SeStRh73%;bC{~~B_9DPL38HcJd}M zj0y>p<=B9|`{d)-Zl;;SHSP?EljE?L2dVB$~AHKi@AQyc4+Vty~|%Jy9?` zuhg4pT=(`Ul>f559#jl_ThVRyNa|0rJ1}b0imW%S&aI}fJ8aaVVPp1r;{AFTGgZmo z82NrG!9%o6C81Aw$SFv2)yzWrmT5D3V&Q==cB^{o=k*)o#?gTM&1LqKDm};S8C8nZ zEvO8n_6|kO^oKHQ;0nP^YKM4_&??;j0PtU|0RQm`sQ*;}|0NI1U&#UdrvUID@cBcQ zE5LsM_16o)U*CZJkF{&0rEV>|x9J>B16E9QNPKQLm5*50Qwbw56OqQrZ4BDc$?5UE zmB0{U7RpWPsL`FKn|q}#+uCMvYR7*fK9l{cayg$KLHhi@Uh<{Y{U1R8M4k~SU#QpD zETc8M+u5&peL_J!dlyb|8Vx3@;-P(&*U#2JE(%`g@8J1(&CXqO`!*$m1e4bAp1Ebn z!~@Vjqy1O^41a&+KlKODzYgabQfLF`PXRL~{G+}=MKwso(S1arwi$8a0%Pq7tbC4I zk-J4Ca4wx88Qpa$pG?+tzs4m$oI`t7Y3GBj{%h3pKj#mE`pV6&lPUi(V(V z{*S?jivJvqag+Wh#%&i8hK%h|zIo*qKz#xF6NVqF#)Z0Oo!-FtqkHr+wxNr+l;>9L zc7jPSyZ0cdj|pEwf&l%m+TFisSqfbyER}sl?YB5TaK6`sk+I764bV#F{fIxctQU;7 ze#=xJv>eS?_dpCy#qiY@e)^C8JGm$&l}e;#JJ|~}*3SBSS;xBvVsuYuTW<<`TH~E& z=p2V%(i=d3jHOS1)7P#C-lCa-I;Gx#JxkQK5Y!i}=Z)!eAJNT=5OkdQ{7|2jFO;54 zi6I{!dqyK{bdx%k4eTUe*n{1A_+xFj!9n1WAuglaVvJcgIb=t@~fKlA&x(Q)6sHN zF9-nro7AsAq_4@Lswd$&&Rd&fe9-&ys-<iIl_xZj zX?MOTUZO`>BcED<*(#d3lBz@i|G7A~VtXFU^3;Y;K(H7&?woh1M~I*j$>b_U&=+$h zP2DgC|A%XTRC|Bd{?DX%=N#QN5qw0N`qNEHgA6$;hVkQ>%$ZXdj5B-^` zc3D{Z0asVZ#@KWXs2z5HW%R?l`CZ;Kd*@CBl4KNh#O6SO=FDQaHmD zN3aDeUkLOHe81H>`qVMF8slMaRex?WKu66LLp{&ZH}}mLX0|VfHm!2jMx1`PKWI&k zyOCcLZ98yC3(NXFE9m*C6T!@8sf6jiOU3sKeLzDg(g-;Zi=4^kj;j84&X(wIcj(_Y9VbN!0TKBaz75dRc_GyZ7#gm|EGf%C2#O79`|l58jdn#bKg;H`*6w_AiXKJ7H25j`hb<^cJnW-}`7! zKG8nahO3G_c(W0p56)lVzqu8<{B114Oj=(%C=cr^)~r&(hp7Z&xokNpELzTKJ7BXf zsGVU{;75N%?GYwfRLxpIhVgBJKEo8oqB~?V9yvtQVfT!eWT+iDhSalR>z}(bhI}oS zF@5rJcw&yoa#96B$~Hk)IjBYmNm!5$t)a%Ij$D6=&zD;)Q9NhAlU3=mL|JJA`LPQj z3W(qRWc5+XUjy%7$={jTK&bX0w3Ck0nn_LM9Yosq4=X_uFw<>{Hr~w_R4wvLm}!cD z{u{${Xq00d3#C-7i-K*w!KhgS#n^+eV?=Y9nZ7Wx(e=&q#TA?9GMN$f{NGtF{T4LK zux=4|ZyNpeTuHM3)L*#&DjnGW@b_o7f%>Zg)Zf|-Rg*=BX9&X4B8eK^Y*tqQq}TQHu}H%WLw`9E z^E{vdlf_jEGPcSpPV|-{Xjp@_%h?Y3RXr|gzSk$vm~5an%r&p!;kRkedy`0*^~+q# z+wr9NY+MP{`=2>fiJjsIy50Q4Tl+*A9W>Fn3t)$Jq1zh8-YOcTf0z9D-);%tG>|`7 zRkFGJ&m9^29}cH)nL+vUZpP)v;ei8D73y|eZT&nR_$^YFW4Mz=f_ zTZ*P{-R zL35mhzyGI0^VATox_EECL&W4izGEqu{n43^fGwB~zsTi}VNZ~0q`Nm%!vb3!Mcv$6 z=vTnj3+5LIjC}gt{K}go6Cz2KXCDh2v3@v|Mq_%+=Vi72{s~H< z7m51pC}jjc6Ipv;qV8^*No3sWtemoRSw8M=n6ZJ1Y^wIV?CcM8bKtwi<)#1Nj~F$u z_=VzFsm%Npx`ee^r}=;Ir=5{4U9YF3E#Fc(D5dJO2)lO4Hq)4={~xdWqJ=6vfA8$@ z993C^;X(0l3-6E~Ut#iDrxZ(t?`LI*sOgzlv2GWqodm>#?Qt(qTewa5`XvIr2ua_+ zNc-uzX5O7y`P0O^LQb3QmB{2=TW)6ne@ITwb4Z2Sj)`HtqmqXr=q^A|Zjorio10Pf zMtS)%F~>Es9sF50LfZB~{^%RW>AA1GLZ5gIJC+koU9KKgL(IJ>$a#_LWjVQw z`EKV1jy3%?b{-qGZRoB5{H?OH`P%AkAk|m!=;QbU&lE|rdzF4>B+&nmOk||TxZwi+ zPpUVYdI3v?F_tYx!1^m~`d7TVv0_`%YP*SsHN#H;5)g8b>mm32;8~TrbE3x5vO~Xy z;bbS;;b%iUWf|VAIbpi};tKly!0v00 zc^5px96V}(|LiiwjN#csUZPQz8d~G@mup5(VJyDSU?`~#|LYB@h&4I>Mu9}M{XjLX z)5QF-gS7mK`0w3jZBKRU+)XT=P%b*ohDrGSZ%d1B;rw6zCkLMY`TyL%U_k%Hp{tns zzx>H@#km?9Lx~zK-wjy(3KQ{3egd4tw(x z)EnR+)HdU$hr)>e?Ki1t75U9lt%#(ZKzDRVwP#(XHN@rZL_RSpD8bU^+ep#Ox|zXm++n}M?1 z*RR%6A-B?Y>AG3deX}xFU-5@-NKJR#&FZ$Vh%NCr8TSjzVmC ze)qwy@-Y6<_u{}i$^PI}*2>sQjdFAnan#|yl=S-5&)FHypd6gaBAZiXu0Tsd;`P7- zGIX&b!&%no1aj!r>weElvOHn+wJce*uZp%G@$oRl6@zQ*M%9tr^9lA+H!d?yn&?=K zvY(Yf{rullH8lAqLTCx|-Wv^zUJ>6#aGK`>vsQ8SRo+d1w6S+77GtYsH1FS_FZRB7 z)Z~QMe^% zpDG~#`DpTP%r7s<`OPFtARSto3!_m9ooSGwEPu!cfd3_#g!8|Xczt` zT^~Y2H|KJjbPo%%1^CbZ<$jwMl7MAyEw7M0#`IWs zN7-$h7Risn^=W91`7AD{q$Cfpimh=t{|48e!1D*Tf&1qTVV{7Atc^gS%GUx+VEsQv z70i6vWs$p%pPtU|N`KP*FuFq*>--q?<%tsBe}NRS>Mz4C(fzHdfcuvvvYIEen#Q5m zF>;4}+v2syt>nBr&VoZ@PaU>Yjj9Y8w$w|n2kI5)T;ud$N|@j#2nJ_8 zb_3G2B1b-UA#@k59|Wb1_v;e$oM=DjqtpM&n28y*zX0B!{Xj0H39mo0G*4AAs@@c) zJec(jpx#Hnf*>c~skuU1mP1zs{GKpUm~(1@c0h^yh+SPaVp1P_>PN8Z`Kx-07#*&M z!&aa-Lt6aG2EAowkS2}5wrueWqAB~^jy5H(8zss_Z9gbOnPNB)nW8B34F7)M{&z!t zg6BW4AgN6zU3Yx;pjn9w|7N9U%7anft+8xxH)uN{j`^#QojbA09q2zpphg|Ac1tny zEv2~Urg2|3LJ2B8X0p&SO7(|}fzN5xiA$&{JFNm5RlCGCctuJ! z3mmA;Gc=@y3=)Rrb}W~6>PzF)9XEE^SfU@PkY3D_G6Wab3n2ysT1xYIFU9j00QfUZ zIYhqi*KG9~yZgJ2HL-@m>SjmPyaJ{IO84-?=60W4qEu=a!($jOpg+&Atv-8Dtug(4la$<^F~(B4q-be5Q7KV=#F8(k7{b&KvX5-?02o z5o1&|K zbR57x`O}|0C+`Gil2$p;NyT}xbOYOh$Fs~|ww|uSao7IDXq0bDc=j)Ij zxB~Urx4%09H~7D1S2&Wz9bW)y@7e1ALe{pf(N$6)Ki)d2Y|z<-dKewGW8QG0XGvT_A|Xci~rd}3zXMhu=((QCNJO9EuyW9`64?mup0_2mH7B4_O@gLtmS-wyi06fc&v19(Rtw zGt=`|z$2QhX(bS3qEWU~eVO?>)_^6NTy?cItiL1LdBp3uK>pzKtiIf$bcRzCXG81< z+nbOjef6aJcBLzM^P@dH@#27^9A)0InDW9`0RQ{H`Nt<<{=l6M%%1@Li_wJDQ5`$ea{S3i$lT1ekve1NDy_=zrk+6Fq=G>J$}IrDiu0|7fe97$D9-B#s!o6qRxH z8~NDOFQqf&+q>~B*lag92O_^wSz^g^c5q@aq5Hh0rg|mJD=upzSg5S5IBgsY8r8;O z4w*MRD5!w@&%XAAWjgYe_ z7*yZveTm9w6_g};XHR)rl~P1>G5XOwUZD*JeHLM<%s>SE$3`}|j8m!@ahYBII$Zk) z)NzgKGUP=98=x>i|8IHiXl*_4>-c(8SeI-r3CgNqCGZ6d%NP!fow(Ub!A1)+I)HVf zkBsFvYtVi&Le9jl54PF6e@9>)K;cd6x6>?ng`e9WrOGr-M)9Bg!*h|c&1%Kg=KG6w zXa5Y8MN4%f&?I7wo@r`k_vrTQxQE3qiwS&jc0P)Klwzex>lxnY_h{q-bFj?5&C2v zEJ%dF{dfKdnW48cLQcZY`kKQ#7ZBccfmr49;!0J)$=-{0cUS_62H;;Z2!84P-}je= zW^s5@YV4i7AHU!kqT^A00P_F*hZXh@a%0uA6cJM`Hn)FA%6kF+4|{tLZ24;;_4nj> z8wDcqRzdejjSPBARWeDS+<8btQ6!QJ70(Sis*-=W5mF*nr@J`xsjTq$ht`GK$I1rk z%f|rixk32-KPgZHQ2_FPW~w|>p^|wV+myj5%$D;;JX6GpYWF1=-8~ZC(yA`G%xSpG z%769vdVT4BlSVpD+WX)ukg^VYw=H4SgBh=K0shx5R@$=&o__)UGLC%dy)M3WA2oyY zShA+W_|-J$_(^{yK$G9@=L@w4^2>kRy1_L1WUsmD?$eFCXW8maeAMuY2{SpODH_4E zIoA+AiZ%)?@tbH~Dy{r!;b>B&EHz}Mzrq5Kur8{4%uXr)3jB^6Qi&pdCerq-M7D+> z%8H8N#xWBY>%ZJLOGo2EQ}<3%xcskpQQuD`N_M=nA>OtRZ_=D_-zGRU7|xjXVznL> z!)ks>|BzzTIa}CZOXmB#;6)|}8I_s|{kL?F@YWUozMGS1Nz4N+6s(W*dVOSY7@%N%4v+8 zjhsi^(&Z8fig2XRM#k!{uXb^6&3+bXUp<%%xw-5C@BFv_ zS^)T`fH!l6JfgJd8q(&fWjQ+BCkGiy)l^E*ES6g}k)jM@(irJH^8{R6j#kkI+-rW< zw^w4jO$X52=2?3A4*v9O(1_uo)8EgINnK%?h&jgCeGMHSEloJj!y1~LA(vTPxdDf= zILo#_2Up|k>7F3QfpjC5kt|BxWiaUy*HP2jON394{Nsxx{~t?N!B*Axbm^t|k3sd+%a%L5G&{E6D%WQ$_7x3#q<)5PllX>Fj%9 z2rHH$<^73Y|B~u03{w%OBQTfyJTQMdIM1D#3ZwSvuJy{G?r5@+2-6XFQq{+yez#1x zYNJP#g~VB&oavI!+ffQxsyjV2J?8y`)DLh;JT|ollox%z@`C=)q{05N$8t&> z)#kNe{uzhxKLGd73Alf{HS;jXI27><7idP0ax(lh+cTYh1OKONz`yWdk)!lRrJRRz z9j(l&;+KiHy@X!^yA_q5p%YZ|@h1h?h@_<0~0#!qLe0LRpJZ z$nMfJ3IDWxwlR_!43p5Q4(}#_`o390akN12|FL{AFbZP5$;N#Z;*6R?O*qp7%jHZs zHGjs&A3+F)8MuR+`fka#aFeq55+5yga{j%YXb$|WMeLX!|IxYW^p51zMOR5o5GJ%* zU>vAFDDFa_JDN^G=~SOOnm{dx&mW4SsbIpKz1-npLH$r2rK0}IlKUCs#$-f-b-Z!M zOEdN|Ki2qC_)WjFx+S!&uFLA)v6oQ1O9RCJG^9dp2QBV`=2D*e(Di+KGu}r`^08zZ&)q-0^! zsohhCysf79}f=%hWV`Kz9Nai@mIfqds;l{?^@~49hvptkBM~^11MfE-w$V zU-bRY^Kkeih+MAsNOOVzPq3W2*g@Eio{{;+RcZCW?|Ih_(0^@mZaA^NwchoKh4-WY z{S^w}AKLFK3M2O4++l=59xp0cxkn`#JNS5>mav8z;gPhH34__E~rY!8^f$AJ8YsQ;@X@NN>p`>%uj3vKP0qXD!e zbB(c9L(9nt*oghx@#|eZ($CCD+l4Y2-JY3-ayavoo-_WtqP^_l|B>J_xn7Co{`Fj;fs-~QJJwij zpCW=S3ICBszR-t#p@KJ0g=fvyL`^8?zEueG;e!2ZB7fhMn!Z(&;3qhXDJ4yQkIbg+ zTAWNudL;YyVoMgV(`bRi3tx0(DsI0CRTW-rUUeUn&k!ACXU7^rV5)+xnRkfD2d~eRQ zUeUyvh2aR__TLv6IqUc2yO1~E<}z*W8oBl)$`K28rJg8_4>F zIXvUQ`vM>DjUn1b>575YqdJ&IGoHY>ULcwLSP{Cl_R2r50`qUz!!DqIA#*jH zEJ#UIXxlOAh?nSe>hZXH7KN!1`pX31e{T1;ZY(Q>ynt>`cb5o*+8=0|PPSOO<(dC+ z^eLDwlTsdAe)W7_?P8~<$48xe58HhSe%D9&W@vLv5a{0rPNh=Q4ni1D3iJt_3O=L=rpNP-WVTc z78&#&SuH?AFO_&|Ak}c?(Qr%54vc-9p{jj}%K8N{x)_q!kuMkHhGT=OqpE36qr`9w z;o+4=P8Y#VbtJysOVX25CVFO_l67l_w&Cp`40-yTT5)*K3D2sk!<-Z&<&Q013csMc zT{H}~9qTpll<2u_)mWA*R4}SN$t#NI`>dN>a9j8W6;Z@bK@_Tp(WTuB#4r$WvcpI|qZk1~NYVClnDQ@{FIW`Cyx z&x%leL;W+cCzZ02^|MmR0DnY3IT>(YTRsLWORQ9jGn3>F|2Rms@>X9^_(=6}ap2Uo7j6lhCRi=A9sriY8 zh||mOo3s9W&(NwYF3B-ldsSuku#yKFb01JO?;b)2f=h&2znI*&wmxo&K4hAFioUTb zsGUIwNmEb&A2DXU#KasQ^uNWR|D6QiUl{N&xs5xFiP`TXKYOWDih};v1oXdAp#QzQ zW7Y$^31e#k|7@a5Az2^H|K0-rJ5Kg|YzGFzk3(Lh;C!I}Z~T(xumJA=-T(5RYFW>* z*R+{Cs_Mm#pw3gYLuWB23u3gyqQoK3r;P7xvmG%p*d`-@|C}=5e?C!w;db745?Xwu z{9c(2<9GWC*$xVO>EjjZ89#nWdVrX}e`7|>-}|07O}bn;_d5oxv{$)*rkJ6Yxd!-q zukQ1I!sqmA8I%|^dQ(lo8ppda$4!#M1?VlOLYe;Q$(yTY&#gRZ-qbl||8c8`A+`I` z@kv9y-YW8ENjft8>79N5Apv?Mte0I z!TGC`ig&6l|2i2a%n~p}m|3L<_+RC`2dW7ETT#zHJlM~JgBB0fQKU9026L+;^P`u- zWpB{-oZmBL5bmVPE7%x1$0(JsIb4DIyHlo8YriIxg^i&d-X^DP>!k-*^LmwQ~ZwR)LBFC>YnAg|3 zZQUK~%8=zec5619wq8FK`tHjE_Wy{U+NtX0oXZYJDNqK~$^BgU zB0I+Z%Dn<6gk+Q)9<%woAX#~z9rLD5WaC}mh=OG2XqTi@F@9rznDr?`-{IV=GuB#O zW?kpLD9^&Sz2hZ_upC(i=)YyzLs{85%$YOx%;{eLzR(MBIN9}pXyw(CcHg?Oy2pwx zxmHkt@2^(Z2j-s>9xXRklD7rWYKO|MDZwf6EYF08Xc2Pb+<#K)lJJ%SiYN_4{*f1? zAvC$O9RBttybYoqVYq&Xn;4-No-n(C6@4+i)XBhdd+fc%T-zc4`ltq6hl5CQ)o-ha7FpA8K) zeuMb?^C}c2%-@i?o~zv$5AaX>f&Z839^t(B@+tdYgTRiwer7#CfPZ?A^=jGz|L>?+ zvt@Y^XaJ;(+Ldcilq)t7ZRdIBi2U7Q_E9D9zbly7+C!m|aqWHs8-6oFyz{9YveRL; znOjI>HB^4}UEgRfW))fMt!f>iMn3re8%Lv2Ulltxtun4Njf1<8U5~7d#CjECLu&rV zzZ_keX7=dirU(5;ev_)6OPT$wHPBzPWNp#=_cKRCR}E$%l|3!Lf^s6I56EYbqiozA zYOZtsE-V23zj~bL|MTy^rj|ap2=ISOe|P8+Hx;;z^oC69n3sMI3On9LCg;$AwLVVF zG*05i3flWVqWi`tBDrVpCmvdjE3sgMt*X|AqEPGHZaHkyFF8R{V)=byL#$-|&>O+e z=zUNn+TizFT6x4%vWe}{Vem?eth1&x11#Z zZrLzWk3hZ}^#skmA0*VBehn{ZgrUvjn*FuaejV}-C}E#U5UG?u`NfZYg96SUcP0IS zmymK>mbPA)YU2$3YYE#vZR>p0iVj{%PAZk1?Wu1iR!nYm@1Gv7;C*T9-QF*FCgnEK z3ach{W~@FH8uF2SbIm0zW5D0mP#-b!@#R*1IPl*IlZdZtc~ZYo(vCtnEvKGv(f;0) zDQk);8(TAtLRw(b_qfp|9xZlb8c9z&FTvkuZBJ7}k7TtzK9?4{r5f-S^}qNhWy+&O zJ1ZZPAKr{m?i_IbStlsu5BJ7AlEs(=_#;OuWfx@$(MRew;j|LuS+9-ru}4u;S3l0o zpSVik)L~#>-ub~%P=Noz9#aPJAHCFz!E~Xt^ViL*K|uxnH^g`JnwXSAs7Dqp1F-_`KRqu^%-_u!?b^afuA=x$=F zsa(c)v~cp_J-TfLNm&f28b|BrFNpd#7U++#BCL0_L*YF_z<*uwB$sKS)zI}gn3{A1 zp)w@N{9PuDccWgEZmf=OT$N@XsgW)PY*Irp9r?$TDDLtf0B^Ex@ zdeEIFlG>ndX=*;SSpG?m60IrMBRcY(`p3P1;GZLvzD765)AkB?d-VK!SqtAL!HA2^ ze$Usdho8=P)+#)r1-Vat_@{7K^I5-d&K8PbgV5`5pb2XkXqA7X+Oy>dc2(s>ce}2rAwmuL1*iFZT*v44i}6~mMw7He=f<zDA=qLo2d7rRV7RgpLvb0m*IV#N)rSjlBM zIAs6Lza^>}yKuaCPdv+^SZKMOKH5xs*jh>sD<^n#JCtJhRRQ~{{U+0HCsnBz8=^Yf z!=>mVD(;@U5VPD*L+%BMl6j#1D2beOAPPT+K9QgY_17)!H8FyJ9tCyQRaT-7G8h@0 zeJ8shhi(D%2lt7vivC_-{YcmKXcplzGv)T!tHwD3uIcArYc7|k;L4RJ-9xt7Hz@*% z&bLeXLU79Xm=3b$J9P2&OY?Deg2i7IX2eR>H}X^|jie zXLT}IM4^NG?0W2fj>R->e0#dZ*6)Tiu2XM%!WFufKgQPR__MfAGpJJ`Sv4eOtr6hQ zA&K*`#bEx^w1Q;1A)<{A0r__k;C}(fn`0S(e>V;Ehb6I(Q$Nv(Mlb^XFQ0<-ZZC-c zp8$VL?9FBR*kkA#4C4Q@U?@t|Qy8-dsDJN3{d?xEPKnrm{0+o^3Gkn&9bneu5l)Qd z1o3a|D<=~M{5P$5)qd{V0{r_G`gfIUVUr#gEA)LbyX@u!yoH|eK2U!^h1%@hlM(Ze zg@3QgNHI57DV(i`Ombu;hs5|E#|nF=koy?sC)Ci0+y#Xu(5)4(`!XPPyuQBAx8Y2? zR)=`}jN-ajsZ#byH?k+89-YpiubV5cHJS8n2K6V7+LDUt!sa|F^Ay8CJ?BJd^+3+n zfUua7ar9%e5W&sOz9^fo9kZ@!VE=g&wpf(kpWbP79Ps}?LYCKu#PluOd2`Q&?O>V* zP1La`XTfLDsQG~Z)$?BZ!~Ex^ABgWy&sJSEgzudZXixK$#RGbgNU9Li3ml(U?N!qR zAuj**KXZmJN1k&va5}y%Dpw2KCroWu%diInLB#vZ3Cd#7L4%2i{#4f!!h8lqv4wP_PV#k*4i7(I~fkIDAComn&8# zsqL4nT4T++W=zsqz(2`CBF9Mp^_LAlN07e*=a2WN?^u44W}bRVh0B<;5922m~E%!`0Fy7>~;d8Q+5D5DQu!M zdXqXkK@zFQ@LpBd8F%-=?rUdlX}r)1MbL9w^%rg}s(M=ApcMDlZ?SISA~bPHl0GK)7Z0XoI_+R$T|J zCMX_oL~Vt$99$-;zRBk&Ho6NCc-(bPN;GxeH-@GqV=i2vao9ujpbPvz!T&F3NL{Rz zC8d2|sQisw(K4o?-RlGK`eaxcF6D0niiIxkwrR1YHusUO*Jt<^R* z|Ax~o=^O<9HgX8&-=P2a1n{3rfd4;lz`HR7_a6t~{}@q7H4_5;H9ENeMnL~B0`zwl zk>LLGauH^o&Sm-u>K`&FHR-i*D9RD2f21F^8y^Dv>Aj0OW!(bdJUi(B104c8MC%dy zvsA+ryJc3y{2dZf7vEi}NyKK%m}FbcM1af46@bHNm|SI%57;-QJqr7UfbAEyV9kZCetF z<-GBikS$CYGN*Bb6HiSPRI?W8>9D=)PU~~g#PyB+oos?c@7i@G!F{};5_!L$R@}G$ z@bA~W3w%I-0IMwK7~s7@`t_k-PmE*=Jzg$D480uauf+=pNjO_2nv12qU9CdeK2xGy zGy25seB!44v@jg)a1i-2@`lFUMty04a!-f30)_of7dwe1@Je~C*c1B|24IbhB@bw zJFEO|ApcwlYiViLVUp6LafQ-SHz+fgHlX~?=Em{$<YY0RM!HGU6$Et|PXpwP&e@s)Dbnp=+60E)IG4Zdwx_vc?hP(+9@a+RPskTR*)N znF9X9<~mxaKOxj(7cB_%Bf(60m~>_)^B>)O{*?eppXzn6 zaYmJPBKZFa85roZLBnigM>f*q?O)CAYkogQ=HaB867StXqj>J|k;k5`Y<)U)Jr3Y+ z=Ky~vd_qII4dM@*5XM{&>W?0d|Ly+~1o#^kh`$<>z>Yhhe;Nk)F9YO1sSbtYvNp5j zE-YxkMd^I(2&jL&Um^vwJ=R8l4DjDU;Qwj^;(sSjet!zYe-_}sT!8r_!}x}3aI^Jp zbOXF+;O(7jq)@mTg*7ivgO%6L_xU&!&K3Q|XvTNO*2BJ^8+;dZE);OOJ-ArLPp%%0 zIV9Wl+NN=LCr5h7)~Pjb>y*rJk1-ZAijZ~tStA(6p;$qgeU*AI_IJ@fPBCH4)J-I_ zchN|J`X8!A-0rdZK3rmoY9I$)o*^4~8Zvp#B}wHnr}bVfTC3NN`8wz>CQoh$)|mHs zKk-=y<%g)r>$#pw9HmU&>MF$kV}E-E3w3Itnk2X!Hkhl`i>;$Yy^1HV&?NeVjDgB# zMf8Ix6D4k(=4;Cgm=D(H=3~AiclIywmL;2cWY@g&+hQGY{(jG}HQ&ZQs{I3L%UPYm zUpd#jaKsXM=V~@7c6WL)swmSUDG?7AHz0p_nOo%hQs>dON8bDS7IVFNy{|@QYx(au zk9*%JeW$C+XSID2VI2RsQjh3TNhS8`l!-v~`M>mwK5SJkY2ZKQg*9sLd0ik>fJ?B| zDwS*V@xiSygv=c3Ok3f|_!7BLVWQ<(k9$SCi1@%0S3C7O3_Dgl$ij3D$UY_8uKtt36t*hdbjn-_#P{|8PWQw3!RBms1Eg_8}Vr z{?E*A{;rL+KmHEAV5eXmt<%#zYL7snzb*bWr||-D{&PnW_irHcBf!6e{2p?u0`mtq zaQ>FS`I8q0#t7j2`64m=AO`1e8JxevZ)pzr0RO@S`u`^2KWq>De`*2$^c{m}M9;&9 zY7{tsGT{74D7px9pXM^fg8Extg_=|g%paP-`4>WIH*N&=w<*vceECZ_AA11$Z=1l5 zxMOC$OZ>!GpUYm&Cm$4&^!Tj%=zbL^h zi7}HcPtSzbx4maQ?eh#IVE^+lnP@>Capp1OovJC(pD$OUwc6){!2&8)#M%kc1H&JM z4>C!6os2CtwH`dAHQ2aUl+Va9&1FP?5_xZPn6J-O-DshboSypLQMT*6g&xc>2Qy*x z_agTH8bv8Knn!6B=K%flm(00xu3--D*GrF7^S1Pv?ra8;GmkKTV+o=@k!C3heb7rp$i|I3HE zP{L5jPWO<;s63^1B~UDgX#{Jkdre@kO1#QFLH;v8QsGtA+sy2q;-PeyD!TrnPTpH9Ft^En1KO^u|7fvEwA~CgKNL6m; z(lVRRj1k`$vyaD0CH7U-;;YK$d*%9Xi9L$TFZXFuuyX5H3cY-*#{L&pFH71h-n+-M z`DmpP8HHSzmbIcvoKf~bs4T1XK6x2Trw;QVc zfd6*^=AZQ7{NVunwGh-lNP>Z`hR6Gf1~LL%(?{p z(=WjPA#b2p^D*#$sQqBJTnFZFXrTYNMq&7o0M4HWIR961iL{l(|7M!Tcf+(m|51?r z{n&f+^Os)Wzl(Uj@^_0}Q>j|#`8`7^A=tZ%-^G|Qbu9#%8>Mjy+#j?p!m1icyqk|E zAaTlKpivm3B@zQ~Ebkwcmyb7j)p?gRV(^uhW64g9~yLH~mZ>OTbk z`vZ7?H^6`V2l(G%;QbeY{{kP_KRXHhueOqYp$j;7eC$S*S9oJUB|J&m#Pmji!j*5H zs=sd@Q-Y4xfO))kmzr{ZB(f+%^OxDxjFsL8K6`hd|53|keF2$Is!NIQb;}QwhE|)I zKbU_qQtao6O1Uyw98*I=0{SZ*hK#62$+m9BKFjjUtThy(Kn&bM6W zEfO_qH{vLdqLAlfD%}Z}Sp&V3lG|w|mrZA7(e`mxM+tvn&Bzug26Y#i%8d%Q!P0A z{%l}D{k&5m4g4Ph^pOGoNNQV@bY{MRi*-6wFT4n1#6R+Ts36;q)7-z!s?&X*-4y75 zKe31qAA(^-Rf+s}63v{hOup!$g)0qBNaqaSrIj||_w<%|P)`LW)v0jYRFQul z6Dzdo>EN}w?`%{aY)any8_Xe1ueqwl zYQv6F4BP@fgZg*JojxVG_QwTfsH~sF*ji>aB-bjS^E-bDU9~<71EblpI4v}Q`9WTU z{THvYUIE#Uk|4d5-&LtsO?P+;@QITHqh}-I@y8j>fi&1?2eGfTDR6FcVbIAR`8~(k z!{JrYaQf^9s$S?`10LlbgflW@PwgF-l3jzxYwGDnbx!@}UcIL(t(75M+eZPmH0Yv{ zv}dic#ug*J63=X9;fBgt&XY3Li{@VpUwR?@fACZ)3$*9<(90BCKC<34#BgzL_(=)X z>(g#pJCHoqjh!$8`+stAp?$>#4e?1c9$BIvr_wvgeW3Yut+=BHDs%w<+O-eGS(1Kz zaH5-xp-F4WLWR*OdJRS}`rLnG zO|T|&D|ly&*sNnu1x=$+ZR>8suURN&R*BLB2T=TW7PP6mHePe}C=ZqQ79ETvB(Hu7 z&&E3s^EY;u2@oOSK0v2ucEvRpO@K8#T`O_+*AUmDf2LMlQ|mNx7VuH5o(Jmk`PEqC zb+5r#LmOfdBpLAoa+@x2b7HehFS$g8loEZ|V#iG_ zFAhs7vh(Zkj5QYLNBVpSi9pLYZbLDtiml=s^^L@ZF<~SX5gmP=;J=yBY$a%R5a5`* ztKj-|=Xi!M@R)i;mN9id&%1>DT`ABD&$8PP8dJRgKNv+^GPcILSq8@7*&0$V5>FLH!%bXXlDx z;nT&=H=JTBOP|_t;5py$S=%u+KQxt*sckhk}{YJ}gt*TH20gx91{|`Y9%b?)r%;(e+v;yN&b+;lG z{|XMf48)FA+`i*xH5BN3zr8MwzCF>KQN!vMbN>x>`tE%xfW;$#-2J3t(tL}jmohWC z=%3kTfQ$a$Rl3_zp7)s1!kB2 zMS*(qi1cwhVO2`fg5uvq@(TSf`M<>~aiS}Se*;1PO+VU_X~n)(q`+c;0c2C529!Uh+V zWix(YPz#fYF;~@7L-6`jWCgU-wqt0vcW3k(r_xWzX%z-elS}Mj?ZUqtZK)**2iCV) z_ev}6mq*4N+B?RHgKJ77!_(9S+!yBs`u+L%$ZrCa1s51S=uT3r<>`lE{ut{~Lp=AU0g_#8i^s4C(4t#r_%^Mym*9c0zF z7})Fqk+CS@x4(xXr*w87?1@~x)H9N4_H3Eq${#;!NYpLAqjoO6EqQk;Rc9ta-dwEz z**ReLE|Z^aHUAxRL#z$m%aZGg;Kogs6!u9fC*wc%o(_V)81g4p30~KtYVQ!+#yh~n z@hCDt{UK%`Pu6~{c%E+h*vu(daK;N<6*2aPPmyg#Rf-9ox3jOnf{|^ zL3eZy8ny|GbyQaUXTzPpYPY;m$WyC$9vnxb!em5P=}8!8GbS$e#6RiiN`Gs!aLBUx zAuswxb#;R47kxf-21C5}S=IGEYXVy(-fY^^Gx+M@{>w<@Qlhq#MC*|} zC0PYj{RuB*tsbTV3e!zF%bE>bi0^Gy{SQlrlJCN)O~$NhsZMU6oCc<dDlbpY~Dnyn_*27vEs^qRjjmJ zca}p>cdOdO%0`R-Su}K81~ySDPY7$u^<4`eJMw8sBCoHxYW=9mvM?Yw#E#z+ZcpUS z_KR=qpK|92#T@oW;2%`>dWiYk-84)JMWAH+6XrTAjnUC7k+xVN_(FwmS#T;xq5@Zk zi(23wVOocJoEG3efcZ}(8`jTu1BCuYE}q%!GqTBsm3X&!b^Q}~%CJY*a=UPZo(iet zRm?gy&k-g?AkBiomD3&_V*2H5)b`Bn%|M-`z7=O}=jS>8tIj;t- z@ajyW#3)D?fw$n~SCTi3Xr^*RAy>px`-uc`*Ld*VwB5+@_h&Qc1@ zaSY)+RPuOZSp`hsKWDj_i}|;hH%7)XV(VP8-H#E>U*nG^-e+*H1bI5tY)JzBaTUe+ ztye~%!|)iX9{pt^@ZS{D7m4F8MCaVJjT( zW=C~%?EDvf7|L1}DL->E{1N{X9@c%l18oI`pQIiS-{h=oCKTMeD zr1BiRFC~#wr;NcRJdavEWtTS%?0A9CtcMTyH}V6$^~NH}sR^8B%Yk72_#X6sE1>^M z1pSu}=)dYf|8))euY17%i39%sQlS6h0{xdE;2%&h{=^>)$sqd&`p-!m1phuhmQD*6 z`ot>=Tx{rYa|2Z6>KVV*zX8v;(W^AQ}>RN533GiP+1peC= zBda4Vf>Z8km77@EK37_~>aEan#!8zJl%=AUf%8ZRlKp&k^5mlCp+Z;;wA=c=91Dv1 z_FFf#fpEddu2;!6LA-0Zz_&_stxxq8lx#3xxjRlolc!(pFVZSOqXEoCmf^qszvOq` z=J9MlOXb1*nNP(`XJs3b`5yRxxmmA@ohqdh>K-+T7Yj({@qvYB$35xZI8 zvop*$tuzMwO;D;7_cwrl`{^+>V54k4))krI$MqwmV7VP_28&l|%IQsbH`#rgW6>S* z`-lJUKaJp@Q1Ji6XH&J=eGmS>NuG-^9eWQj9&y}b0q0Dsb$WsZxe`a0j zp^239FdZ4--`S{twY@Te>@6(doZld&9&I(fE`=^Y|A6hk=JDr2Y%%M`9+n@`_45d+ zRuE;18s?MIuhm4JMJk@r6~>DxbTjsj`hgTZ(XZl$c4cFu2jN>v{EpR zX}7p9x~^GOi=ZIO&A-`@Jhp1TRTTIShqoZ~hlV)_|2uCBd!wPX`KoUasEa&KZ@3EF z$bExd8u%YTKP`L$`r~%+{@6I_q5sX_(>j{oVVPB0`~>rVdHe*xzq5(^=ki$0Ho(+j z9Ppnl`BNd~Bf}qD4`u!`E|I%Xh-7X*vYpB`>R_QGiR2-6xLS-h64Elep z@fIYHB=O@fby)Lil_sR(wx4$-Q$*;@utU(*`TJ2V#+YC7+tv;sYq#;3emE9S>(+{< z`BK-9^5W~7{CN3+bhb_0SC>1<7oij<0_9ZC&x%FZtPI?Kx*Ry%yY~u_DPR}&81|t- zR4)4{GM!xibr?gb?jsTY7kyyUt6@Q*Km{+krwZ*d_0I062)4esAi zaQ|K}BblCp`*#i8zsUgqV*&N&F~Gmr0sm4RG5-hn8->6IKBE501@ZR-@IN}h{AC@? zUvNSFB?<2Tu@e~c9MC_!`Yyni_$yJD8TCU%2bt`xSK>Rcf4TbEM>O_cd88%QKs{te z`Lsg1ZFHzEN2ZYDOOXGHm_B7dbF?{k4j{Bu#CnQ#+&iS6|LtFswE0H#ZT|x39|+MB zxoz2HtqT<4Ilt$WnarFWz7$o|L^?T93ti89oTZ@sowjBdE_B*4n9Qd%V9NLC2Jgk#A+!G#dN)e=+Prr^~c5)v*OFxvE z`L3$n(~Jbm70p6BO4l8)l;OYn!^NS=Qe>U(F3V7k%QR9mJH;i}2vhNai>=r*>nLzo~lpT$NF+ zWydpy@yp-w0cLP5t;@;AgcIn@f zmNP7SR9F?U$nPMogXh(?J9uIb&(-dB9nbvH$wUtJKftZfe-vkbQ*7=acpa_vmn2#$ zZ=gp-UEIu_;NpkRzZS;Z?xNQkFDALZX)I`)$C1kI7~RIxyLLGDD{g6Dx{f{Odp?K} zk4;h=Yuuvf8-*(Z_Rpr>#RuDXVwRd8`-weJDabU26%TXX7oy=jKQGSj5I2qb`@^Sw zjB&(|_;tZoI>LwXd3w@Vau_ym@1u6pkHLe9DjKgW+=-z1BvxGB@v>)}EQBOtHCqdE z1O-oIm=w!+=~A$I(M-@5&HR87ym_a}9v=-Bn)ZwR!=Ml4470&{x6@(Bs%m}qEK+jy z1!Jj#{68bUEpgVJ#)t1Zr>OL7{n_*J8FTouQ=NZ>ONmaok-}=mxTcGf^hbl$|HJmV zx5M_v+f!_Ingu@lSb+cj7k>c%#sl-8F=K^Bh`rejf`79I;tv8&9JtoNCOe4VN}ZYt4}h&6{n`e6zRGIg;EKBF5$&flB7v{fXC{b#o^ z8{qt@VVEgc4q_HQT)(R8N#0rAi5~tmqEyJvqxoylkLrEwcaxjrZ;c0kZJ6&N!d=$} zCpW5llY6fL z3n?*9g=cE~R?d9h@k|qz7SCS`mQMFVNx#$at1C(#vISMa3c$8BHi`5%G(0|lYjNEZw+6{=Kvq#ZiC&KRgBS!FVV|5G=4E7r6d}{29{WjtV0>g2`o;WMJ#fTQ73PNv!C}_CH7&JCdn{7 znc7KBiks|0^dGBQzzzcBKV{H=>`#hC%y4Wt9p+__MLRe4{L1$bPNvFaLiisW1OI=F z^-wy$I~bM)$bS!D{zU`kulpeXCWHCcV~~I4!2D|)#Q!T0|BN92VuSn}1@i9{@PG3M z@ef^k@F@fQqYDuKfX#e^i2qc;zii)-IbR3)w-oRXJ^}q9E@mR3Vv1Uh=O0(Ei}ity?FXr7 ze&n0oRl(DaEft#LdO?1L_p;KUzOq)pK^Y zc-O$E)gIGV`tq5Ov=YO7>rucF>Ck)u-?c%&+=I!%AzFoIYMoCGvQKsK>Q0Z)GUfgK@ zsOt+*5bXUOKla)aP5yV?tLCxf8!;hSE3qOl|0VHsC+$Pi>Lm~v^RAbGX#S`PWk%(o z<&!RM^Y$g#z7MMjtFd!`dRx6W`JetP@`~A$=R7>NbFRO}*fS9L@8K2&jH*^2A}_SD zW;65)41LE^ChEV3t|I&=YAADb`wurbRYTjCOs&1B@Z@L0Id3WO2y-DMHs9P9D?bm$ zxo>7^y)`BGStzJ$#uwb0_dC15fZ^6x%`kZXX3`DoRss0OAa}PL-JRK`f+4`FH{m{+hBBo{$CB$pQT{`UoGhWi^2Ji0rh7)a#wQ` z;NSfP=l_UrLzNBik1e|4J&OQ;*a!9J$B%}t_dx$y1o#ihK>t|_^apuRME_Bh>k9ne zS-<>5^0vS*)YA|F^MAWEc~o+a()>~9RRXiC-s*qkMlWt#mRb(X-vO@E4%|yU7*S?$T}`hbMpa;BYN)LDygP(Wy9CM>qTT zJA{ReA%8vk`4(|N_ias>O39(j-5vz~8F|@JmHCKKgE@#BWAC377N|c1A{@F;9N3f$H_IYR4+ z{0eJDr+Gx+($g<0K{iA^0a`X_Q@GAb|Rb@ zT;r@R<8I3DyZIVq968~hp=^&6{2BVG^wUD+#LfZ3u7bh_bU{GPoLiw=eK{={~Niu(m{`&g8kJHvHw}?PfduJWDka& zryWiE>pPC)qW|)LJ@9`jowfVVfA(FZ_<#I2<8WC@g#O_*P9jmn+i?qNLx#a-E|u+1 zQ!$p>%r=K%v}}Z2Uqt$e#b#@J@xws>-v#bJ#Qfa{@Xt|!{woFaA6KCNpauR9p`ibG z4gNn4(4X`J{7Dkrzga@}k&U4Lc>?$czrp=03hrOT{)yP^P*gcWME$LTUqott9LSsI zKbm{fiIp5$g)<}(tf+ATWudE}kj)rGuLt^%TSmDtD8{+UEfEp5<21ic)SGM2|GgFv zfgt<`+zvW~(ZK!NC&u<2fxoPL?P!)%AGd4w5+%WPWi?ahW15ZnumAM0*!vIvbHc#r z{R;Hg#sP*hbSw^_|CFv)LYe=^HOR>wP=Ku0!mA_36P--~mwn6%XW{OWrqs@8Uv;;( z34FWyTe1Cfh=CiPaCaghQ=-7XomCgYwlOM4WHv)sgAAo0CM5J>0q6Z}!lej_eDm+~ zn|WzRJVlh!nkR2<-t?ma|83p>{HJ72UY0y5SLpl=Phl7Qzox$XpX&epUsj3Cv0WE6YHshGt5`EU``b8jav!M%U~ zKP347s2g0}-_yH5Xf(ZVlJSj$y}9CDG3H374EHJ_Bn|W*G)u>U{^M~lf0F-tv-pRE zjxQG9SD^mb_nF%?dP~zO$DsbFg{xIF_XSz?*QBgb)=P7RAD^T{E6uPggQ<2)Eh-&? zWK8-p&ALero0Ru>@RvnL9{t9P=SvAh-fct-_>!^gBR@UCn|vNTR41KG(dx^2QE}8+ z@}bHkqTzwJyvKr}qgdN^_!u>BXQTQ>v_5%s7|U0&ymWwn5kP-)1N?Ib{Npjmzm@|2 zZvpC$X+Zolg8t(Y5dViD{;L81_zL)k6~I4Ez&~`s{2@!w|2PlgU-Eza;~LN(si6MR z1?c}$z&~05|F8l4<6M6z1N|`p_=i2v|L6Vh;sAfS+-V3p!2ZN_&5+`R8#!?R|9;;U z*d@C;7s|~UTZx0d+WQXT57)om0}V2`@M4C>**hnGbo#RUC^qvI|K7ykszhDN!)U|K zs<*6LCt(TYR0?b^(cdp-y)yA01@(WTfz{gXn$g+1@`7!skS<`q72yACVE-Kd7eM~u z2-vs5=&!y4_umotzZYZLZ6*H7Oj=1|NnE^^tdUq9-Sqai3mnN9+|-AFL}!7H2QdF9 zEAR`O*kF6gXRN)JGFeg9+w>&AP)eH9Fm7*zAHHCimdEUx)0*OFjiEJlK&OdQ-{a>N)o4{Rm8>lwsV^Z&%CSK}BRrEn{97YX+R6V{D?$ujb(p+7d zUuhK~Pp|F)iAVa1VO5dpGu$`0#2sWzN1t%GZ=Bjbd2Bfld3jr^Lvr!a#l2`+4Jz2n z81YB)`qYYdorv$DYn~M^RIp`$gUk7XseN7X6;^R;-I26xy;X=lKwm6q}$I0%%3qS#XYyLeykP> z8y4rpo()ck9M%q?Uz)ud1+H|!9+qTb^nXdRL24NEKfl(Q z*!2SQk5wKYeuFZzR;+k=E`9W=?s#7sq--uwC`eF52D@T8Alx$vq~_fYu(wk<)Uyv~ zDJ4Y~?04lD@bXf-qNTW)7F!V*B5^DW^Ny?2YBS0pXUxc%5U`*Z{nMxx^Lc%EUX7p` zjhJh^Ag7`4AL^B~0!r`1#a_2F>FyhK+_WYuIOtQq%gp~nQ^YrXw=TAZg=A z8#bsx&Zd|%LAjbX+Uf-!Q%Au+_d${*u4B%MW{Ic9W^8N6KDb5a=8ti^-XkZiMlUp7 z?m@q564<|J_A$kCsm`^o;}fvo4EisrY#oEEb2uP-VE%>FDGK(8fI|g>{)2XG)xx9@ z1D;f7KxnY~Lr01Ty;Z>&B14xu!WL~Elv(FiHls4PcPHI&Bg6go+>bqiOGMk899f&v z{>|$*Z=SNVBES0E++EN5WYn+0g2=7vcTdt5Xf|^*R)4obc{n;aWk-`G?lR%s-A6PF z41H?L5W8m>_jfKp7C+NXcfo#xadT8!(<&>O=|uFPB)VBcXoW@XzgA2W*Dw_dVf($t z*_kN)PoVI}~f6w%PNrvmvs`o;(9xX^PGGFuT zjM|X6{loC*J|<&Z9XcRVeH9A-7($*q426y*UeGvm6ZteT@f*x{h8kTC4C;mW(YyVT6`tSk|&9%kx%)r& zRM?SalAOzudtm3f>E&R>o{-b^L1aIx99x`Xp&m@*Es!ViTbgKNO~gZqt$0A|~9{ge|*gs%}LV)=X&ioV9z<;7) zDn@es3o&+*B#vy}6!?Ga(-1&&yb2-qgZcNXxGk;5zVrQ0;Qiw@n17!N=1&PaR~H$B z{&yUtQ1Ctu`S1JtYb20z0sC^&IFwiKSqdMRKM_vGfG3;W6$SgxTGBdU2w{8{=J-pe zl{K&*k?KtF0QPA>{Hd(-&t-%7t6Q+9kQ>eOYX|mic8L9hz`iv^t1%qJ9|f0c(q#~T z)ON_SWu8I8ZWWc`c--G;b9P3v)tqUGc>JQY)hP}(K)_k3_2yDeVHMeh$aE5SC7mKf zYE2oQO$6|!yvJ{R^-rpuY%|6_zY|9odXX6oGrWX(WLHB>Cp?ZZ&*{3zr0nL~<-d3c z=Md0jt zXF0$M2o1!u5xTGH+G@Rb5Z@7Nv{R0%rXMMEwTF2 zbdZ!aD~Cgj1$*EL!B#nk5H@@uDgLwy=1r(`1O;dJ9z8R>?n5d&o+>pXhOD!|U4gON zvW%Cek@Kd&nQYk}FS{sDQ4y75oQxgQN`KYPf1k*YWg;$-qg1SYBLioTyxA1{t|LlU zY&TCD3ej|OfBT>2uw~4dWqEp<*7$O?^x=sPWepaa56IF~P&}3-vxP2VUf?QB8cEI9cM8Iw>Pa zT}SxE-AY4E$)=N2G<5Sgv~~{lSuItEMR!}P@s`u_v)cq9kJ2K0YE0{x#NayV2e>?|d*n9)f}kZG(^dLI@H;%^(wUuaa!!h9R( zwEEm^kaKG3oQGNtR|ERe9MkB@6Sw!`ya5x+F)HZzkomG=?-7h!M~^`&|-Nc&Sf&$ZKQUcJW;Q9=)KDT!E! zjjS;PKAXOm9a?LWdRYgCpkF9i(&yQ8y{T-F6YuOy2waGbo-o2=C_wz1OqwhGS%?Go z59e1MfUMm^gZl@eY*}e%ZiKNK0{r#btXClBKj*&BG?mS*#zZJZ{nu7P&Nm-IOCR%F>;qg2_U-15qJRtU~fcMu{VBgk9 zqdfnYDmv|1xIS{Sc!-(Jp2e0vGIDmhZ{rHiq z>>)OG$w$FWqVi`_z&?!K>tPq>9RIE{GJMLHlzkZZoG1;^pM*jlD+~sa+F2XLV37gKu+k1ms+{uu30Fh zz47a=i&b+%zqKUSaA=<8P=p}Hu}-FI1Y}X=cn>kq9cFmkt!VeL z!%t<#RM>H8l;7V+?_5;Q6;pNQD6F~(2*erFTEPukh`oxRY6r|2cc3kIQ(_6r;`TuL9jT z8`3m+rOfLiP8_18BzR4$sGZ}F`8obP3DL&6k*BCW(TiuHZrT#0RJqm zNrkyqtw-+)%1+aNu{4E+2R83-fcxi4MMr)-LhU@R8h-`S8imhvd+447TO)B_k7ssy zK$RE1Ly6A+6i57USDh>!pQF{pr=WR||5g=a;Co-qJkayQj=AZzQ7}gL#hFDR-Oj7@;pE4& z7oD+uDRPo6-1sc_oZu>@N|LbCyIi*SP4XhQ>F!kZ2N0LiHTcf?PX(WX@!zCo)f{7= zhhzqqJURW`{2wXT(J{43;44F0JRibZN$h^VC*d!S&C}jBLsx)lc< zUn*6TXsoAjStc3e3GbWT$QcPH9z7QKBBXU`-IWoPDC_>CT4V0i6-ABq{FaT5FG~Cp zbmcJOr+btJQf6n**923ZU=;L3$n*yR7w8W7AMk$x?BB#UNgjxXR)&|#$%{D&e0YXM z^7L4t?Cp~~oINIem$mNnY2hEruJCV~bdg6t-$q{CSI&qniDTVr`o>{ZQRlV3B_@CaXj?fkrptNPE#HCmV7#@U!NXcS6I;%%lTe)BdU8o z5BtE5CYqi3Ycf4Wj>wAog2fc8 z@7ojIt83~-k-oGIE!$RH7SABLMf+CB!~zyG`CU=Bbf07qAzBVpQ89*3s?SzK z{?6=)oEG38#!&!&^3L(!o2|(Ax-=B>V9IxDQ`MGxnNSUEZ0t z+i9fFx5XAmw!!V3lK&(eWwb4Gze#VxZhs|hR^e8JvFD9`reyCxT03cGJ>-_ciBHSi z9)|z@dacaAf@1ALY$wr%0v|apvS~@(v*j=~cy=v(@@SB|BoM*2x7lTq&Mpwoc}tl8 zWij*CS#MdeVmp0?J`@g>9L#}2cgB)QUE84E!v#1ex6ZSa7k%Ug)MNo!YoP<8=KD&2 zS%m1BJhOgb;=*z$nGv#uExxVCJTga*T*(>4A!`d_u3J8IS}yR=1wD%5q!IzXEPL5S#WgS zu6Mh!=dB~Vxi)uhwq!NASH4nPCW(at5M_}GgVw`ykP&;IsO9un}vBlHDC+$Z(gIn zH{jm}L0mY%{}zRo%_m9za+2lzFjUU-sSBk0QgdO3S8cGaIk*NZpmD zcoy+hJz4Kuj&00_sE)E2G&t`=bvOSSO#&b#>`(AYR{J*ZP3``E1jr#9n zE0F;j(Ky`g_lm;6|D}?D{1<6?uK%6a(C6o`HSqx48|U<9Nw4<{*5p4`3*0uvO#jBJXtl=$2HJ-A%ih1vKW9b;cXf5YcE6*yEJgtb37BOp$WGPFW}yEwokliw zVdgEfpq7;%!2k5@w{r^mHo`0#$9!?PTdkkIi^2syr==SR_c_2V>%AM?{dtSlwL`z@ z4c{N2cPYIzO&(Oe=6GdZ+AnWc*x+vi^RIvT2dyi5(hEI#nTK7n=~ub0*G5SQKpj0g zfc-c*93-ExgaG*uECb8YdH&;1`Pk#>dK>@#KPhp})uMiM%#+1Z2f|Uf1pR;CfAU$P zIk5lyjm2UG7CYt){2$j94!003W3R^3#dQ#oml=Aq1M9PPPudxOb`4s#FstA0HR7}& z`IrA%nEGL)kzF`n<=R>|S)1Ogj)f9j9j$|Evl!_=zy7G_DK#QqG+Jxp*L8OHp7UGC zdH$nVV^$_=0pZ8a1w=uVM^Ju3wfmdT%>>p&-=JI-)s8 zz?<>fg@5^XWqDRY~EuMO)wn+ z`JZ$B3G!dsyJdz`2>%XG@||{O4!QX-FRI8h)Am3FNv47jd#Q@vb3<9LfQ`2SLFlDq zi(Wm>ObJG$b!>2`y5fkuCWY88ocqaCehgN5s^lKlf+-sKANXyI24VHAHOR%86SW!; z?nOFR`^-)s#9!c8;DY}n*>nB1DEwRJ-2Ou7Duwb(woUPn52i~*!wd3WOAVWv)qV)N z+#R{j^ZcWptaHH9jkHJTCEaSd21uqLvtvtUX1)5M^kfF`-$u|>y{n3SE!CDr!3J*22Ig`=O`|aNIzA=e~PW-ucm%NBL8QB z%5IhOrTv(-(3iwmVp?jH>tt$@)}b_$cJ9cLU6MNGcVRXo=A|9;v5sHyH!jUUCT^oi zU62JhS?P(BH>55Vtc)#NkHXE?&%SqmX66mCu*#dKfA1oQjaiBI_6&E=BYg7VNg;ty z-m3Xvrn}~lYod`(wf;`Go8&S13lf!+>Hy7w%cbOJ0chMZdZIs>i5ic4N&d%+k>_Lm z{ae8Qc|Wuf^Ot1W(+S zUYwE~=48U!&4T(fcgw@~Wnq?J|0CPQo=hI@hbrY9{1ed94ecU|va64*<9=2`j9v%7 z=h{;+tKT#z@6VDGY8lJb%C;8fuKRRin8Z((WfrL5IZ^0)n!l1urhK5bCg>O@Zrz=u zB0o`9B}g+U1gl?5g&8dj*6m|&`=A8e@oCmmRQmCkHZ^EW*m)8NL!>+zOmqke!e1fh z`|4FbkO|tmy$}+$7+C zW;*oOU(PZQbu>?@1Ib` z5#`#E{mmhC#f$z$+dFBVwQyL(&C+;g@~45lFsswZ#WQ3ndd}zdWru-!>wo9}CqSt0 zyX>bwyS(}XIo(oEw1QQCjIXNp!yV`Ss8OVteDnARCHSD*yO2&n4Tazv38f)^+xdN# zVbd2N1H-$FI%)5}k7LbT@0wRxypSo6Q=e-UiOh}alO1B9nLdQS ziQlm`J}$tj5cEvRa?8?#x*Tqonnm&o_pV8-uJ`U}gl*VQf}JoNYTE=jYCES--~SD# z=Z8X^G~IJ7{zG{*N=JZF+CAA%ROUeC$k!t}8n*nr)tBkO6XABJ6l;xG3oN74I3&&M zRi0)Tb6JtqZy5KK`#@WQtQIpR{6SXrY`TVgzPbb9c z&V2l$H3YWndNVTmWvVk@mTC#DQBkDFfo<> z@BAOw-9Bz)HthEv^4n3S>DY!AW3%Y=-yD~@9>Ffrbyuz4`D)