diff --git a/Makefile b/Makefile index 9c3e0bf..38d56a7 100644 --- a/Makefile +++ b/Makefile @@ -17,11 +17,10 @@ ENABLE_TX_WHEN_AM := 0 ENABLE_CTCSS_TAIL_PHASE_SHIFT := 1 ENABLE_MAIN_KEY_HOLD := 1 ENABLE_BOOT_BEEPS := 0 -ENABLE_DTMF_DECODER := 1 ENABLE_COMPANDER := 1 ENABLE_SHOW_CHARGE_LEVEL := 1 -ENABLE_STATUSBAR_VOLTAGE := 0 -ENABLE_STATUSBAR_PERCENTAGE := 1 +ENABLE_STATUSBAR_VOLTAGE := 1 +ENABLE_STATUSBAR_PERCENTAGE := 0 #ENABLE_SINGLE_VFO_CHAN := 1 #ENABLE_BAND_SCOPE := 1 @@ -201,9 +200,6 @@ endif ifeq ($(ENABLE_STATUSBAR_PERCENTAGE),1) CFLAGS += -DENABLE_STATUSBAR_PERCENTAGE endif -ifeq ($(ENABLE_DTMF_DECODER),1) - CFLAGS += -DENABLE_DTMF_DECODER -endif ifeq ($(ENABLE_SINGLE_VFO_CHAN),1) CFLAGS += -DENABLE_SINGLE_VFO_CHAN endif diff --git a/README.md b/README.md index c09c6cc..5bcf675 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,6 @@ ENABLE_TX_WHEN_AM := 0 allow TX (always FM) when RX is set to ENABLE_CTCSS_TAIL_PHASE_SHIFT := 1 standard CTCSS tail phase shift rather than QS's own 55Hz tone method ENABLE_MAIN_KEY_HOLD := 1 initial F-key press not needed, instead hold down keys 0-9 ENABLE_BOOT_BEEPS := 0 give user audio feedback on volume knob position at boot-up -ENABLE_DTMF_DECODER := 1 live on-screen DTMF decoder ENABLE_COMPANDER := 1 compander option - setting not yet saved ENABLE_SHOW_CHARGE_LEVEL := 1 show the charge level when the radio is on charge ENABLE_STATUSBAR_VOLTAGE := 0 show the battery voltage on the top status bar - when possible diff --git a/app/app.c b/app/app.c index 4398c29..541be93 100644 --- a/app/app.c +++ b/app/app.c @@ -901,7 +901,7 @@ void APP_CheckRadioInterrupts(void) if (gCurrentFunction == FUNCTION_RECEIVE) { - #ifdef ENABLE_DTMF_DECODER + { // live DTMF decoder gDTMF_RecvTimeoutSaved = DTMF_RX_timeout_saved_500ms; size_t len = strlen(gDTMF_ReceivedSaved); // shift the RX buffer down one - if need be @@ -910,7 +910,7 @@ void APP_CheckRadioInterrupts(void) gDTMF_ReceivedSaved[len++] = c; gDTMF_ReceivedSaved[len] = '\0'; gUpdateDisplay = true; - #endif + } DTMF_HandleRequest(); } @@ -1788,6 +1788,14 @@ void APP_TimeSlice500ms(void) gBatteryVoltageIndex = 0; BATTERY_GetReadings(true); + + #if defined(ENABLE_STATUSBAR_VOLTAGE) || defined(ENABLE_STATUSBAR_PERCENTAGE) + // regular statusbar updates (once per sec) if battery voltage or percentage is enabled + gUpdateStatus = true; + #else + if (gChargingWithTypeC) + gUpdateDisplay = true; + #endif } if (gCurrentFunction != FUNCTION_POWER_SAVE) @@ -1977,16 +1985,14 @@ void APP_TimeSlice500ms(void) } } - #ifdef ENABLE_DTMF_DECODER - if (gDTMF_RecvTimeoutSaved > 0) + if (gDTMF_RecvTimeoutSaved > 0) + { + if (--gDTMF_RecvTimeoutSaved == 0) { - if (--gDTMF_RecvTimeoutSaved == 0) - { - gDTMF_ReceivedSaved[0] = '\0'; - gUpdateDisplay = true; - } + gDTMF_ReceivedSaved[0] = '\0'; + gUpdateDisplay = true; } - #endif + } } #ifdef ENABLE_ALARM diff --git a/app/dtmf.c b/app/dtmf.c index f530ec4..fc70b0c 100644 --- a/app/dtmf.c +++ b/app/dtmf.c @@ -40,10 +40,8 @@ uint8_t gDTMF_WriteIndex = 0; uint8_t gDTMF_PreviousIndex = 0; uint8_t gDTMF_RecvTimeout = 0; -#ifdef ENABLE_DTMF_DECODER - char gDTMF_ReceivedSaved[17]; - uint8_t gDTMF_RecvTimeoutSaved = 0; -#endif +char gDTMF_ReceivedSaved[17]; +uint8_t gDTMF_RecvTimeoutSaved = 0; bool gIsDtmfContactValid; char gDTMF_ID[4]; diff --git a/app/dtmf.h b/app/dtmf.h index 7a39b18..fdcf614 100644 --- a/app/dtmf.h +++ b/app/dtmf.h @@ -61,10 +61,8 @@ extern uint8_t gDTMF_WriteIndex; extern uint8_t gDTMF_PreviousIndex; extern uint8_t gDTMF_RecvTimeout; -#ifdef ENABLE_DTMF_DECODER - extern char gDTMF_ReceivedSaved[17]; - extern uint8_t gDTMF_RecvTimeoutSaved; -#endif +extern char gDTMF_ReceivedSaved[17]; +extern uint8_t gDTMF_RecvTimeoutSaved; extern bool gIsDtmfContactValid; extern char gDTMF_ID[4]; diff --git a/app/menu.c b/app/menu.c index b88dd0b..6cb758b 100644 --- a/app/menu.c +++ b/app/menu.c @@ -103,12 +103,13 @@ VOICE_ID_INVALID, VOICE_ID_INVALID, VOICE_ID_INVALID, + VOICE_ID_INVALID, #ifdef ENABLE_NOAA VOICE_ID_INVALID, #endif VOICE_ID_DELETE_CHANNEL, VOICE_ID_INITIALISATION, - + // hidden items VOICE_ID_INVALID, @@ -118,6 +119,7 @@ VOICE_ID_INVALID, VOICE_ID_INVALID, + VOICE_ID_INVALID, VOICE_ID_INVALID }; #endif @@ -257,6 +259,7 @@ int MENU_GetLimits(uint8_t Cursor, int32_t *pMin, int32_t *pMax) case MENU_STE: case MENU_D_ST: case MENU_D_DCD: + case MENU_D_LIVE_DEC: case MENU_AM: #ifdef ENABLE_NOAA case MENU_NOAA_S: @@ -613,6 +616,11 @@ void MENU_AcceptSetting(void) gRequestSaveChannel = 1; return; + case MENU_D_LIVE_DEC: + gSetting_live_DTMF_decoder = gSubMenuSelection; + gRequestSaveSettings = true; + return; + case MENU_D_LIST: gDTMFChosenContact = gSubMenuSelection - 1; if (gIsDtmfContactValid) @@ -982,6 +990,10 @@ void MENU_ShowCurrentSetting(void) gSubMenuSelection = gDTMFChosenContact + 1; break; + case MENU_D_LIVE_DEC: + gSubMenuSelection = gSetting_live_DTMF_decoder; + break; + case MENU_PONMSG: gSubMenuSelection = gEeprom.POWER_ON_DISPLAY_MODE; break; diff --git a/app/uart.c b/app/uart.c index cb34c71..343f458 100644 --- a/app/uart.c +++ b/app/uart.c @@ -139,9 +139,11 @@ typedef struct { static const uint8_t Obfuscation[16] = { 0x16, 0x6C, 0x14, 0xE6, 0x2E, 0x91, 0x0D, 0x40, 0x21, 0x35, 0xD5, 0x40, 0x13, 0x03, 0xE9, 0x80 }; -static union { +static union +{ uint8_t Buffer[256]; - struct { + struct + { Header_t Header; uint8_t Data[252]; }; @@ -149,7 +151,7 @@ static union { static uint32_t Timestamp; static uint16_t gUART_WriteIndex; -static bool bIsEncrypted = true; +static bool bIsEncrypted = true; static void SendReply(void *pReply, uint16_t Size) { @@ -158,21 +160,24 @@ static void SendReply(void *pReply, uint16_t Size) uint8_t *pBytes; uint16_t i; - if (bIsEncrypted) { + if (bIsEncrypted) + { pBytes = (uint8_t *)pReply; - for (i = 0; i < Size; 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) { + if (bIsEncrypted) + { Footer.Padding[0] = Obfuscation[(Size + 0) % 16] ^ 0xFF; Footer.Padding[1] = Obfuscation[(Size + 1) % 16] ^ 0xFF; - } else { + } + else + { Footer.Padding[0] = 0xFF; Footer.Padding[1] = 0xFF; } @@ -208,11 +213,9 @@ static bool IsBadChallenge(const uint32_t *pKey, const uint32_t *pIn, const uint IV[2] = 0; IV[3] = 0; AES_Encrypt(pKey, IV, pIn, IV, true); - for (i = 0; i < 4; i++) { - if (IV[i] != pResponse[i]) { + for (i = 0; i < 4; i++) + if (IV[i] != pResponse[i]) return true; - } - } return false; } @@ -232,12 +235,11 @@ static void CMD_0514(const uint8_t *pBuffer) 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; + REPLY_051B_t Reply; + bool bLocked = false; - if (pCmd->Timestamp != Timestamp) { + if (pCmd->Timestamp != Timestamp) return; - } #ifdef ENABLE_FMRADIO gFmRadioCountdown_500ms = fm_radio_countdown_500ms; @@ -248,13 +250,11 @@ static void CMD_051B(const uint8_t *pBuffer) Reply.Data.Offset = pCmd->Offset; Reply.Data.Size = pCmd->Size; - if (bHasCustomAesKey) { + if (bHasCustomAesKey) bLocked = gIsLocked; - } - if (!bLocked) { + if (!bLocked) EEPROM_ReadBuffer(pCmd->Offset, Reply.Data.Data, pCmd->Size); - } SendReply(&Reply, pCmd->Size + 8); } @@ -266,44 +266,37 @@ static void CMD_051D(const uint8_t *pBuffer) bool bReloadEeprom; bool bIsLocked; - if (pCmd->Timestamp != Timestamp) { + if (pCmd->Timestamp != Timestamp) return; - } bReloadEeprom = false; #ifdef ENABLE_FMRADIO gFmRadioCountdown_500ms = fm_radio_countdown_500ms; #endif - Reply.Header.ID = 0x051E; + Reply.Header.ID = 0x051E; Reply.Header.Size = sizeof(Reply.Data); Reply.Data.Offset = pCmd->Offset; - bIsLocked = bHasCustomAesKey; - if (bHasCustomAesKey) { - bIsLocked = gIsLocked; - } + bIsLocked = bHasCustomAesKey ? gIsLocked : bHasCustomAesKey; - if (!bIsLocked) { + if (!bIsLocked) + { uint16_t i; + for (i = 0; i < (pCmd->Size / 8); i++) + { + const uint16_t Offset = pCmd->Offset + (i * 8U); - for (i = 0; i < (pCmd->Size / 8U); i++) { - uint16_t Offset = pCmd->Offset + (i * 8U); - - if (Offset >= 0x0F30 && Offset < 0x0F40) { - if (!gIsLocked) { + if (Offset >= 0x0F30 && Offset < 0x0F40) + if (!gIsLocked) bReloadEeprom = true; - } - } - if ((Offset < 0x0E98 || Offset >= 0x0EA0) || !bIsInLockScreen || pCmd->bAllowPassword) { + if ((Offset < 0x0E98 || Offset >= 0x0EA0) || !bIsInLockScreen || pCmd->bAllowPassword) EEPROM_WriteBuffer(Offset, &pCmd->Data[i * 8U]); - } } - if (bReloadEeprom) { + if (bReloadEeprom) BOARD_EEPROM_Init(); - } } SendReply(&Reply, sizeof(Reply)); @@ -347,25 +340,30 @@ static void CMD_052D(const uint8_t *pBuffer) bIsLocked = bHasCustomAesKey; - if (!bIsLocked) { + if (!bIsLocked) bIsLocked = IsBadChallenge(gCustomAesKey, gChallenge, pCmd->Response); - } - if (!bIsLocked) { + + if (!bIsLocked) + { bIsLocked = IsBadChallenge(gDefaultAesKey, gChallenge, pCmd->Response); - if (bIsLocked) { + if (bIsLocked) gTryCount++; - } } - if (gTryCount < 3) { - if (!bIsLocked) { + + if (gTryCount < 3) + { + if (!bIsLocked) gTryCount = 0; - } - } else { + } + else + { gTryCount = 3; bIsLocked = true; } - gIsLocked = bIsLocked; + + gIsLocked = bIsLocked; Reply.Data.bIsLocked = bIsLocked; + SendReply(&Reply, sizeof(Reply)); } diff --git a/bitmaps.c b/bitmaps.c index c8bf72c..58eb6fa 100644 --- a/bitmaps.c +++ b/bitmaps.c @@ -439,19 +439,19 @@ const uint8_t BITMAP_ScanList[6] = const uint8_t BITMAP_ScanList1[6] = { // 1 symbol 0b00000000, - 0b01000001, - 0b01111111, - 0b01000001, + 0b01000010, + 0b01111110, + 0b01000010, 0b00000000, 0b00000000 }; const uint8_t BITMAP_ScanList2[6] = { // 2 symbol - 0b01000001, - 0b01111111, - 0b01000001, - 0b01111111, - 0b01000001, - 0b00000000 + 0b00000000, + 0b01000010, + 0b01111110, + 0b01000010, + 0b01111110, + 0b01000010 }; diff --git a/board.c b/board.c index 1115888..cd98cf9 100644 --- a/board.c +++ b/board.c @@ -706,15 +706,16 @@ void BOARD_EEPROM_Init(void) // 0F40..0F47 EEPROM_ReadBuffer(0x0F40, Data, 8); - gSetting_F_LOCK = (Data[0] < 6) ? Data[0] : F_LOCK_OFF; - gSetting_350TX = (Data[1] < 2) ? Data[1] : false; // was true - gSetting_KILLED = (Data[2] < 2) ? Data[2] : false; - 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_ScrambleEnable = (Data[6] < 2) ? Data[6] : true; - gSetting_TX_EN = (Data[7] & (1u << 0)) ? true : false; - + gSetting_F_LOCK = (Data[0] < 6) ? Data[0] : F_LOCK_OFF; + gSetting_350TX = (Data[1] < 2) ? Data[1] : false; // was true + gSetting_KILLED = (Data[2] < 2) ? Data[2] : false; + 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_ScrambleEnable = (Data[6] < 2) ? Data[6] : true; + gSetting_TX_EN = (Data[7] & (1u << 0)) ? true : false; + gSetting_live_DTMF_decoder = (Data[7] & (1u << 1)) ? true : false; + if (!gEeprom.VFO_OPEN) { gEeprom.ScreenChannel[0] = gEeprom.MrChannel[0]; diff --git a/firmware b/firmware index f2fa5cf..dc2d852 100644 Binary files a/firmware and b/firmware differ diff --git a/firmware.bin b/firmware.bin index 0741317..bfe812e 100644 Binary files a/firmware.bin and b/firmware.bin differ diff --git a/firmware.packed.bin b/firmware.packed.bin index f145ae3..8a33328 100644 Binary files a/firmware.packed.bin and b/firmware.packed.bin differ diff --git a/functions.c b/functions.c index a71ba8c..a3d9e76 100644 --- a/functions.c +++ b/functions.c @@ -59,10 +59,8 @@ void FUNCTION_Init(void) gDTMF_WriteIndex = 0; memset(gDTMF_Received, 0, sizeof(gDTMF_Received)); - #ifdef ENABLE_DTMF_DECODER -// gDTMF_RecvTimeoutSaved = 0; -// gDTMF_ReceivedSaved[0] = '\0'; - #endif +// gDTMF_RecvTimeoutSaved = 0; +// gDTMF_ReceivedSaved[0] = '\0'; g_CxCSS_TAIL_Found = false; g_CDCSS_Lost = false; diff --git a/misc.c b/misc.c index 80f2a43..dd7e3fb 100644 --- a/misc.c +++ b/misc.c @@ -65,6 +65,8 @@ bool gSetting_TX_EN; uint8_t gSetting_F_LOCK; bool gSetting_ScrambleEnable; +bool gSetting_live_DTMF_decoder; + uint32_t gCustomAesKey[4]; bool bHasCustomAesKey; uint32_t gChallenge[4]; diff --git a/misc.h b/misc.h index 1a362cd..c9c82a8 100644 --- a/misc.h +++ b/misc.h @@ -122,6 +122,8 @@ extern bool gSetting_TX_EN; extern uint8_t gSetting_F_LOCK; extern bool gSetting_ScrambleEnable; +extern bool gSetting_live_DTMF_decoder; + extern const uint32_t gDefaultAesKey[4]; extern uint32_t gCustomAesKey[4]; extern bool bHasCustomAesKey; diff --git a/settings.c b/settings.c index 01426b3..212c59d 100644 --- a/settings.c +++ b/settings.c @@ -170,8 +170,8 @@ void SETTINGS_SaveSettings(void) State[4] = gSetting_500TX; State[5] = gSetting_350EN; State[6] = gSetting_ScrambleEnable; - State[7] = 0xff; - if (!gSetting_TX_EN) State[7] &= ~(1u << 0); + if (!gSetting_TX_EN) State[7] &= ~(1u << 0); + if (!gSetting_live_DTMF_decoder) State[7] &= ~(1u << 1); EEPROM_WriteBuffer(0x0F40, State); } diff --git a/ui/main.c b/ui/main.c index c140bc9..e3c49c0 100644 --- a/ui/main.c +++ b/ui/main.c @@ -447,34 +447,29 @@ void UI_DisplayMain(void) UI_PrintStringSmall("SCR", LCD_WIDTH + 106, 0, Line + 1); } - #ifdef ENABLE_DTMF_DECODER - if (center_line_is_free) - { - if (gDTMF_ReceivedSaved[0] >= 32) - { // show live DTMF decode - UI_PrintStringSmall(gDTMF_ReceivedSaved, 8, 0, 3); - } - else - #else - if (center_line_is_free) - { - #endif - if (gChargingWithTypeC) - { // charging .. show the battery state - #ifdef ENABLE_SHOW_CHARGE_LEVEL - const uint16_t volts = (gBatteryVoltageAverage < gMin_bat_v) ? gMin_bat_v : - (gBatteryVoltageAverage > gMax_bat_v) ? gMax_bat_v : - gBatteryVoltageAverage; - - sprintf(String, "Charge %u.%02uV %u%%", - gBatteryVoltageAverage / 100, - gBatteryVoltageAverage % 100, - (100 * (volts - gMin_bat_v)) / (gMax_bat_v - gMin_bat_v)); - - UI_PrintStringSmall(String, 2, 0, 3); - #endif - } + if (center_line_is_free) + { + if (gSetting_live_DTMF_decoder && gDTMF_ReceivedSaved[0] >= 32) + { // show live DTMF decode + UI_PrintStringSmall(gDTMF_ReceivedSaved, 8, 0, 3); } + else + if (gChargingWithTypeC) + { // charging .. show the battery state + #ifdef ENABLE_SHOW_CHARGE_LEVEL + const uint16_t volts = (gBatteryVoltageAverage < gMin_bat_v) ? gMin_bat_v : + (gBatteryVoltageAverage > gMax_bat_v) ? gMax_bat_v : + gBatteryVoltageAverage; + + sprintf(String, "Charge %u.%02uV %u%%", + gBatteryVoltageAverage / 100, + gBatteryVoltageAverage % 100, + (100 * (volts - gMin_bat_v)) / (gMax_bat_v - gMin_bat_v)); + + UI_PrintStringSmall(String, 2, 0, 3); + #endif + } + } ST7565_BlitFullScreen(); } diff --git a/ui/menu.c b/ui/menu.c index 6f24d23..227fd6b 100644 --- a/ui/menu.c +++ b/ui/menu.c @@ -90,6 +90,7 @@ const char MenuList[][7] = "PTT-ID", "D-DCD", "D-LIST", + "D-LIVE", // live DTMF decoder "PONMSG", "ROGER", "BATVOL", // was "VOL" @@ -427,6 +428,7 @@ void UI_DisplayMenu(void) case MENU_STE: case MENU_D_ST: case MENU_D_DCD: + case MENU_D_LIVE_DEC: #ifdef ENABLE_NOAA case MENU_NOAA_S: #endif diff --git a/ui/menu.h b/ui/menu.h index f5e8932..e130b31 100644 --- a/ui/menu.h +++ b/ui/menu.h @@ -73,6 +73,7 @@ enum MENU_PTT_ID, MENU_D_DCD, MENU_D_LIST, + MENU_D_LIVE_DEC, MENU_PONMSG, MENU_ROGER, MENU_VOL,