14 Commits
v0.1 ... v0.2

Author SHA1 Message Date
Krzysiek Egzmont
5c413eb7cd Calibration description readme 2023-10-01 14:12:37 +02:00
Krzysiek Egzmont
e092145542 Remove Alarm function to save space 2023-10-01 13:44:20 +02:00
Krzysiek Egzmont
5ba5b9f2eb Merge OneOfEleven at commit 'b7241f77efb42bca8443b1b129678c64bdb6dbab' 2023-10-01 13:42:05 +02:00
Krzysiek Egzmont
4fb8f7b0e7 Spectrum analyzer updated
ffe1573a4b
2023-10-01 12:38:55 +02:00
Krzysiek Egzmont
0f210ff872 Battery calibration function added 2023-10-01 12:17:49 +02:00
OneOfEleven
b7241f77ef Forgot to save/update radio.c 2023-10-01 00:30:13 +01:00
OneOfEleven
ae6cf797cb Adjusted rssi bar to start at S4, end at S9+30 2023-10-01 00:10:45 +01:00
OneOfEleven
618a184bf1 S0 meter now -147dBm 2023-10-01 00:04:51 +01:00
OneOfEleven
b0f6be2c7c Make all 10 squelch settings slightly more sensitive 2023-09-30 23:56:31 +01:00
OneOfEleven
aba9e435f2 Fix lower squelch-1 setting bug 2023-09-30 20:21:37 +01:00
OneOfEleven
6546f9d4ce s-meter now shows S9+ in 1dB increments 2023-09-30 20:03:09 +01:00
OneOfEleven
1eac6018ba Even easier to change 'S0' base dBm level on the s-meter. 2023-09-30 17:14:48 +01:00
Krzysiek Egzmont
f32eeda636 README changed 2023-09-30 16:12:47 +02:00
OneOfEleven
9493f34c23 Various DTMF bug fixes and renames 2023-09-30 11:22:19 +01:00
22 changed files with 468 additions and 279 deletions

View File

@@ -10,7 +10,7 @@ ENABLE_AIRCOPY := 0
ENABLE_FMRADIO := 0
ENABLE_NOAA := 0
ENABLE_VOICE := 0
ENABLE_ALARM := 1
ENABLE_ALARM := 0
ENABLE_BIG_FREQ := 1
ENABLE_SMALL_BOLD := 1
ENABLE_KEEP_MEM_NAME := 1
@@ -25,7 +25,7 @@ ENABLE_REVERSE_BAT_SYMBOL := 1
ENABLE_NO_SCAN_TIMEOUT := 1
ENABLE_AM_FIX := 1
ENABLE_AM_FIX_SHOW_DATA := 1
ENABLE_SQUELCH1_LOWER := 0
ENABLE_SQUELCH_LOWER := 1
ENABLE_RSSI_BAR := 1
ENABLE_AUDIO_BAR := 1
ENABLE_SPECTRUM := 1
@@ -233,8 +233,8 @@ endif
ifeq ($(ENABLE_AM_FIX_TEST1),1)
CFLAGS += -DENABLE_AM_FIX_TEST1
endif
ifeq ($(ENABLE_SQUELCH1_LOWER),1)
CFLAGS += -DENABLE_SQUELCH1_LOWER
ifeq ($(ENABLE_SQUELCH_LOWER),1)
CFLAGS += -DENABLE_SQUELCH_LOWER
endif
ifeq ($(ENABLE_RSSI_BAR),1)
CFLAGS += -DENABLE_RSSI_BAR

View File

@@ -1,10 +1,23 @@
# Main features:
- OneOfEleven mods, including AM fix
- fagci spectrum analyzer
- better battery percentage calculation (based on real measurement)
- fagci spectrum analyzer (**F+5** to turn on)
- better battery percentage calculation (based on real measurement, battery calibration recommended)
- battery calibration option available available in the menu (instructions below)
- there is no FM radio nor Aircopy, not enough memory space
<img src="images/main.jpg" width=300 /><img src="images/spectrum.jpg" width=300 /><img src="images/audiobar.jpg" width=300 /><img src="images/rssibar.jpg" width=300 />
❗❗❗You can now calibrate the battery voltage reading in the radio menu.
<img src="images/batcal.jpg" width=300 />
To enter the calibration:
1. turn the radio on holding PTT and the first side button
2. imediately go to BATVOL option and adjust the voltage with UP/DOWN buttons
3. confirm the setting, calibration will be saved to EEPROM
The calibration option becomes unavailable if you leave the menu screen and you have to repeat from step 1.
# Open reimplementation of the Quan Sheng UV-K5 v2.1.27 firmware
@@ -16,9 +29,10 @@ https://github.com/fagci/uv-k5-firmware-fagci-mod/tree/refactor
All is a cloned and customized version of DualTachyon's open firmware found here ..
https://github.com/DualTachyon/uv-k5-firmware
https://github.com/DualTachyon/uv-k5-firmware .. a cool achievement !
A cool achievement
Use this firmware at your own risk (entirely). There is absolutely no guarantee that it will work in any way shape or form on your radio(s), it may even brick your radio(s), in which case, you'd need to buy another radio.
Anyway, have fun.
# Radio performance
@@ -59,7 +73,7 @@ ENABLE_REVERSE_BAT_SYMBOL := 1 mirror the battery symbol on the status
ENABLE_NO_SCAN_TIMEOUT := 1 remove the 32 sec timeout from the CTCSS/DCS scan (press exit butt to end scan)
ENABLE_AM_FIX := 1 dynamically adjust the front end gains when in AM mode to helo prevent AM demodulator saturation - ignore the on-screen RSSI (for now)
ENABLE_AM_FIX_SHOW_DATA := 1 show debug data for the AM fix
ENABLE_SQUELCH1_LOWER := 0 adjusts squelch setting '1' to be more sensitive - I plan to let user adjust it in the menu
ENABLE_SQUELCH_LOWER := 1 squelch settings more sensitive - plan to let user adjust it in the menu
ENABLE_RSSI_BAR := 1 enable a dBm/Sx RSSI bar graph level
ENABLE_AUDIO_BAR := 0 experimental, display an audo bar level when TX'ing
#ENABLE_COPY_CHAN_TO_VFO := 1 not yet implemented - copy the channel into the VFO

View File

@@ -14,6 +14,8 @@
* limitations under the License.
*/
#include <string.h>
#include "app/action.h"
#include "app/app.h"
#include "app/dtmf.h"
@@ -167,6 +169,11 @@ void ACTION_Scan(bool bRestart)
gMonitor = false;
DTMF_clear_RX();
gDTMF_RX_live_timeout = 0;
memset(gDTMF_RX_live, 0, sizeof(gDTMF_RX_live));
RADIO_SelectVfos();
#ifdef ENABLE_NOAA

162
app/app.c
View File

@@ -73,10 +73,10 @@ static void updateRSSI(const int vfo)
if (gEeprom.VfoInfo[vfo].AM_mode && gSetting_AM_fix)
rssi -= rssi_gain_diff[vfo];
#endif
if (gCurrentRSSI[vfo] == rssi)
return; // no change
gCurrentRSSI[vfo] = rssi;
UI_UpdateRSSI(rssi, vfo);
@@ -119,7 +119,7 @@ static void APP_CheckForIncoming(void)
updateRSSI(gEeprom.RX_CHANNEL);
gUpdateRSSI = true;
}
return;
}
@@ -182,6 +182,10 @@ static void APP_HandleIncoming(void)
if (!g_SquelchLost)
{ // squelch is closed
if (gDTMF_RX_index > 0)
DTMF_clear_RX();
if (gCurrentFunction != FUNCTION_FOREGROUND)
{
FUNCTION_Select(FUNCTION_FOREGROUND);
@@ -214,12 +218,13 @@ static void APP_HandleIncoming(void)
if (!bFlag)
return;
DTMF_HandleRequest();
if (gScanState == SCAN_OFF && gCssScanMode == CSS_SCAN_MODE_OFF)
{ // not scanning
if (gRxVfo->DTMF_DECODING_ENABLE || gSetting_KILLED)
{ // DTMF is enabled
{ // DTMF DCD is enabled
// DTMF_HandleRequest();
if (gDTMF_CallState == DTMF_CALL_STATE_NONE)
{
if (gRxReceptionMode == RX_MODE_DETECTED)
@@ -234,7 +239,6 @@ static void APP_HandleIncoming(void)
gUpdateStatus = true;
gUpdateDisplay = true;
return;
}
}
@@ -531,7 +535,7 @@ void APP_StartListening(FUNCTION_Type_t Function, const bool reset_am_fix)
}
// ******************************************
// original setting
uint8_t lna_short = orig_lna_short;
uint8_t lna = orig_lna;
@@ -777,34 +781,40 @@ void APP_CheckRadioInterrupts(void)
// g_CTCSS_Lost = true;
if (interrupt_status_bits & BK4819_REG_02_DTMF_5TONE_FOUND)
{ // save the new DTMF RX'ed character
// fetch the RX'ed char
{ // save the RX'ed DTMF character
const char c = DTMF_GetCharacter(BK4819_GetDTMF_5TONE_Code());
if (c != 0xff)
{
if (gCurrentFunction == FUNCTION_RECEIVE ||
gCurrentFunction == FUNCTION_INCOMING ||
gCurrentFunction == FUNCTION_MONITOR)
if (gCurrentFunction != FUNCTION_TRANSMIT)
{
gDTMF_RequestPending = true;
gDTMF_RecvTimeout = DTMF_RX_timeout_500ms;
// shift the RX buffer down one - if need be
if (gDTMF_WriteIndex >= sizeof(gDTMF_Received))
memmove(gDTMF_Received, &gDTMF_Received[1], --gDTMF_WriteIndex);
gDTMF_Received[gDTMF_WriteIndex++] = c;
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;
}
// live DTMF decoder
size_t len = strlen(gDTMF_RX_live);
// shift the RX buffer down one - if need be
if (len >= (sizeof(gDTMF_RX_live) - 1))
memmove(&gDTMF_RX_live[0], &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 (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;
DTMF_HandleRequest();
DTMF_HandleRequest();
}
}
}
}
@@ -1257,7 +1267,7 @@ void APP_CheckKeys(void)
while (i-- > 0)
{
SYSTEM_DelayMs(1);
if (!GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT))
{ // PTT pressed
if (count > 0)
@@ -1666,9 +1676,9 @@ void cancelUserInputModes(void)
gKeyInputCountdown = 0;
if (gDTMF_InputMode || gInputBoxIndex > 0)
{
memset(gDTMF_String, 0, sizeof(gDTMF_String));
gDTMF_InputMode = false;
gDTMF_InputIndex = 0;
memset(gDTMF_String, 0, sizeof(gDTMF_String));
gInputBoxIndex = 0;
gRequestDisplayScreen = DISPLAY_MAIN;
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
@@ -1692,11 +1702,18 @@ void APP_TimeSlice500ms(void)
{
if (--gDTMF_RX_live_timeout == 0)
{
gDTMF_RX_live[0] = 0;
gUpdateDisplay = true;
if (gDTMF_RX_live[0] != 0)
{
memset(gDTMF_RX_live, 0, sizeof(gDTMF_RX_live));
gUpdateDisplay = true;
}
}
}
if (gDTMF_RX_timeout > 0)
if (--gDTMF_RX_timeout == 0)
DTMF_clear_RX();
// Skipped authentic device check
#ifdef ENABLE_FMRADIO
@@ -1711,8 +1728,16 @@ void APP_TimeSlice500ms(void)
if (gReducedService)
{
BOARD_ADC_GetBatteryInfo(&gBatteryCurrentVoltage, &gBatteryCurrent);
if (gBatteryCurrent > 500 || gBatteryCalibration[3] < gBatteryCurrentVoltage)
overlay_FLASH_RebootToBootloader();
{
#ifdef ENABLE_OVERLAY
overlay_FLASH_RebootToBootloader();
#else
NVIC_SystemReset();
#endif
}
return;
}
@@ -1892,7 +1917,7 @@ void APP_TimeSlice500ms(void)
if (gScreenToDisplay == DISPLAY_SCANNER && gScannerEditState == 0 && gScanCssState < SCAN_CSS_STATE_FOUND)
{
gScanProgressIndicator++;
#ifndef ENABLE_NO_SCAN_TIMEOUT
if (gScanProgressIndicator > 32)
{
@@ -1900,15 +1925,28 @@ void APP_TimeSlice500ms(void)
gScanCssState = SCAN_CSS_STATE_FOUND;
else
gScanCssState = SCAN_CSS_STATE_FAILED;
gUpdateStatus = true;
}
#endif
gUpdateDisplay = true;
}
if (gDTMF_CallState != DTMF_CALL_STATE_NONE && gCurrentFunction != FUNCTION_TRANSMIT && gCurrentFunction != FUNCTION_RECEIVE)
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)
{
if (gDTMF_AUTO_RESET_TIME > 0)
{
@@ -1918,15 +1956,6 @@ void APP_TimeSlice500ms(void)
gUpdateDisplay = true;
}
}
if (gDTMF_DecodeRing && gDTMF_DecodeRingCountdown_500ms > 0)
{
if ((--gDTMF_DecodeRingCountdown_500ms % 3) == 0)
AUDIO_PlayBeep(BEEP_440HZ_500MS);
if (gDTMF_DecodeRingCountdown_500ms == 0)
gDTMF_DecodeRing = false;
}
}
if (gDTMF_IsTx && gDTMF_TxStopCountdown_500ms > 0)
@@ -1937,15 +1966,6 @@ void APP_TimeSlice500ms(void)
gUpdateDisplay = true;
}
}
if (gDTMF_RecvTimeout > 0)
{
if (--gDTMF_RecvTimeout == 0)
{
gDTMF_WriteIndex = 0;
memset(gDTMF_Received, 0, sizeof(gDTMF_Received));
}
}
}
#ifdef ENABLE_ALARM
@@ -2022,9 +2042,13 @@ static void APP_ProcessKey(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
if (Key == KEY_EXIT && bKeyPressed && bKeyHeld && gDTMF_RX_live[0] != 0)
{ // clear the live DTMF decoder if the EXIT key is held
gDTMF_RX_live_timeout = 0;
gDTMF_RX_live[0] = 0;
gUpdateDisplay = true;
if (gDTMF_RX_live[0] != 0)
{
gDTMF_RX_live_timeout = 0;
memset(gDTMF_RX_live, 0, sizeof(gDTMF_RX_live));
gUpdateDisplay = true;
}
}
if (!bKeyPressed)
@@ -2065,10 +2089,12 @@ static void APP_ProcessKey(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
BACKLIGHT_TurnOn();
if (gDTMF_DecodeRing)
{
gDTMF_DecodeRing = false;
if (gDTMF_DecodeRingCountdown_500ms > 0)
{ // cancel the ringing
gDTMF_DecodeRingCountdown_500ms = 0;
AUDIO_PlayBeep(BEEP_1KHZ_60MS_OPTIONAL);
if (Key != KEY_PTT)
{
gPttWasReleased = true;
@@ -2115,7 +2141,8 @@ static void APP_ProcessKey(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
Key != KEY_EXIT &&
Key != KEY_SIDE1 &&
Key != KEY_SIDE2 &&
Key != KEY_STAR)
Key != KEY_STAR &&
Key != KEY_MENU)
{
if (gScanState != SCAN_OFF || gCssScanMode != CSS_SCAN_MODE_OFF)
{ // frequency or CTCSS/DCS scanning
@@ -2147,7 +2174,8 @@ static void APP_ProcessKey(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
}
}
if (gWasFKeyPressed && Key > KEY_9 && Key != KEY_F && Key != KEY_STAR && Key != KEY_MENU)
if (gWasFKeyPressed && Key > KEY_9 && Key != KEY_F && Key != KEY_STAR)
// if (gWasFKeyPressed && Key > KEY_9 && Key != KEY_F && Key != KEY_STAR && Key != KEY_MENU)
{
gWasFKeyPressed = false;
gUpdateStatus = true;
@@ -2203,7 +2231,7 @@ static void APP_ProcessKey(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
else
{
if (gEeprom.DTMF_SIDE_TONE)
{
{ // user will here the DTMF tones in speaker
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
gEnableSpeaker = true;
}
@@ -2416,7 +2444,7 @@ Skip:
if (gFlagStartScan)
{
gMonitor = false;
#ifdef ENABLE_VOICE
AUDIO_SetVoiceID(0, VOICE_ID_SCANNING_BEGIN);
AUDIO_PlaySingleVoice(true);

View File

@@ -22,6 +22,7 @@
#endif
#include "app/scanner.h"
#include "bsp/dp32g030/gpio.h"
#include "audio.h"
#include "driver/bk4819.h"
#include "driver/eeprom.h"
#include "driver/gpio.h"
@@ -33,12 +34,16 @@
#include "ui/ui.h"
char gDTMF_String[15];
char gDTMF_InputBox[15];
char gDTMF_Received[16];
uint8_t gDTMF_WriteIndex = 0;
char gDTMF_InputBox[15];
uint8_t gDTMF_InputIndex = 0;
bool gDTMF_InputMode = false;
uint8_t gDTMF_PreviousIndex = 0;
uint8_t gDTMF_RecvTimeout = 0;
char gDTMF_RX[17];
uint8_t gDTMF_RX_index = 0;
uint8_t gDTMF_RX_timeout = 0;
bool gDTMF_RX_pending = false;
char gDTMF_RX_live[20];
uint8_t gDTMF_RX_live_timeout = 0;
@@ -48,12 +53,9 @@ char gDTMF_ID[4];
char gDTMF_Caller[4];
char gDTMF_Callee[4];
DTMF_State_t gDTMF_State;
bool gDTMF_DecodeRing;
uint8_t gDTMF_DecodeRingCountdown_500ms;
uint8_t gDTMFChosenContact;
uint8_t gDTMF_AUTO_RESET_TIME;
uint8_t gDTMF_InputIndex;
bool gDTMF_InputMode;
DTMF_CallState_t gDTMF_CallState;
DTMF_ReplyState_t gDTMF_ReplyState;
DTMF_CallMode_t gDTMF_CallMode;
@@ -61,14 +63,22 @@ bool gDTMF_IsTx;
uint8_t gDTMF_TxStopCountdown_500ms;
bool gDTMF_IsGroupCall;
bool DTMF_ValidateCodes(char *pCode, uint8_t Size)
void DTMF_clear_RX(void)
{
gDTMF_RX_timeout = 0;
gDTMF_RX_index = 0;
gDTMF_RX_pending = false;
memset(gDTMF_RX, 0, sizeof(gDTMF_RX));
}
bool DTMF_ValidateCodes(char *pCode, const unsigned int size)
{
unsigned int i;
if (pCode[0] == 0xFF || pCode[0] == 0)
return false;
for (i = 0; i < Size; i++)
for (i = 0; i < size; i++)
{
if (pCode[i] == 0xFF || pCode[i] == 0)
{
@@ -121,16 +131,16 @@ bool DTMF_FindContact(const char *pContact, char *pResult)
return false;
}
char DTMF_GetCharacter(const uint8_t code)
char DTMF_GetCharacter(const unsigned int code)
{
const char list[] = "0123456789ABCD*#";
return (code < ARRAY_SIZE(list)) ? list[code] : 0xFF;
}
bool DTMF_CompareMessage(const char *pMsg, const char *pTemplate, uint8_t Size, bool bCheckGroup)
bool DTMF_CompareMessage(const char *pMsg, const char *pTemplate, const unsigned int size, const bool bCheckGroup)
{
unsigned int i;
for (i = 0; i < Size; i++)
for (i = 0; i < size; i++)
{
if (pMsg[i] != pTemplate[i])
{
@@ -140,58 +150,69 @@ bool DTMF_CompareMessage(const char *pMsg, const char *pTemplate, uint8_t Size,
}
}
return DTMF_CALL_MODE_NOT_GROUP;
return true;
}
DTMF_CallMode_t DTMF_CheckGroupCall(const char *pMsg, uint32_t Size)
DTMF_CallMode_t DTMF_CheckGroupCall(const char *pMsg, const unsigned int size)
{
uint32_t i;
for (i = 0; i < Size; i++)
unsigned int i;
for (i = 0; i < size; i++)
if (pMsg[i] == gEeprom.DTMF_GROUP_CALL_CODE)
break;
return (i != Size) ? DTMF_CALL_MODE_GROUP : DTMF_CALL_MODE_NOT_GROUP;
return (i < size) ? DTMF_CALL_MODE_GROUP : DTMF_CALL_MODE_NOT_GROUP;
}
void DTMF_Append(char Code)
void DTMF_Append(const char code)
{
if (gDTMF_InputIndex == 0)
{
memset(gDTMF_InputBox, '-', sizeof(gDTMF_InputBox));
gDTMF_InputBox[sizeof(gDTMF_InputBox) - 1] = 0;
}
else
if (gDTMF_InputIndex >= sizeof(gDTMF_InputBox))
return;
gDTMF_InputBox[gDTMF_InputIndex++] = Code;
if (gDTMF_InputIndex < sizeof(gDTMF_InputBox))
gDTMF_InputBox[gDTMF_InputIndex++] = code;
}
void DTMF_HandleRequest(void)
{
char String[20];
uint8_t Offset;
{ // proccess the RX'ed DTMF characters
if (!gDTMF_RequestPending)
return;
char String[20];
unsigned int Offset;
gDTMF_RequestPending = false;
if (!gDTMF_RX_pending)
return; // nothing new received
if (gScanState != SCAN_OFF || gCssScanMode != CSS_SCAN_MODE_OFF)
{ // 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;
}
gDTMF_RX_pending = false;
if (gDTMF_RX_index >= 9)
{ // look for the KILL code
if (gDTMF_WriteIndex >= 9)
{
Offset = gDTMF_WriteIndex - 9;
sprintf(String, "%s%c%s", gEeprom.ANI_DTMF_ID, gEeprom.DTMF_SEPARATE_CODE, gEeprom.KILL_CODE);
if (DTMF_CompareMessage(gDTMF_Received + Offset, String, 9, true))
{
Offset = gDTMF_RX_index - strlen(String);
if (DTMF_CompareMessage(gDTMF_RX + Offset, String, strlen(String), true))
{ // bugger
if (gEeprom.PERMIT_REMOTE_KILL)
{
gSetting_KILLED = true;
gSetting_KILLED = true; // oooerr !
DTMF_clear_RX();
SETTINGS_SaveSettings();
@@ -212,82 +233,117 @@ void DTMF_HandleRequest(void)
gDTMF_CallState = DTMF_CALL_STATE_NONE;
gUpdateDisplay = true;
gUpdateStatus = true;
gUpdateDisplay = true;
gUpdateStatus = true;
return;
}
}
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);
if (DTMF_CompareMessage(gDTMF_Received + Offset, String, 9, true))
{
Offset = gDTMF_RX_index - strlen(String);
if (DTMF_CompareMessage(gDTMF_RX + Offset, String, strlen(String), true))
{ // shit, we're back !
gSetting_KILLED = false;
DTMF_clear_RX();
SETTINGS_SaveSettings();
gDTMF_ReplyState = DTMF_REPLY_AB;
gDTMF_CallState = DTMF_CALL_STATE_NONE;
gUpdateDisplay = true;
gUpdateStatus = true;
return;
}
}
if (gDTMF_WriteIndex >= 2)
{
if (DTMF_CompareMessage(gDTMF_Received + (gDTMF_WriteIndex - 2), "AB", 2, true))
{
gDTMF_State = DTMF_STATE_TX_SUCC;
gUpdateDisplay = true;
return;
if (gDTMF_RX_index >= 2)
{ // look for ACK reply
strcpy(String, "AB");
Offset = gDTMF_RX_index - strlen(String);
if (DTMF_CompareMessage(gDTMF_RX + Offset, String, strlen(String), 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_CallState == DTMF_CALL_STATE_CALL_OUT && gDTMF_CallMode == DTMF_CALL_MODE_NOT_GROUP && gDTMF_WriteIndex >= 9)
{
Offset = gDTMF_WriteIndex - 9;
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");
if (DTMF_CompareMessage(gDTMF_Received + Offset, String, 9, false))
{
Offset = gDTMF_RX_index - strlen(String);
if (DTMF_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 (gDTMF_WriteIndex >= 7)
{
Offset = gDTMF_WriteIndex - 7;
sprintf(String, "%s%c", gEeprom.ANI_DTMF_ID, gEeprom.DTMF_SEPARATE_CODE);
if (gDTMF_RX_index >= 7)
{ // see if we're being called
gDTMF_IsGroupCall = false;
if (DTMF_CompareMessage(gDTMF_Received + Offset, String, 4, true))
{
sprintf(String, "%s%c", gEeprom.ANI_DTMF_ID, gEeprom.DTMF_SEPARATE_CODE);
Offset = gDTMF_RX_index - strlen(String) - 3;
if (DTMF_CompareMessage(gDTMF_RX + Offset, String, strlen(String), true))
{ // it's for us !
gDTMF_CallState = DTMF_CALL_STATE_RECEIVED;
memmove(gDTMF_Callee, gDTMF_Received + Offset + 0, 3);
memmove(gDTMF_Caller, gDTMF_Received + Offset + 4, 3);
memset(gDTMF_Callee, 0, sizeof(gDTMF_Callee));
memset(gDTMF_Caller, 0, sizeof(gDTMF_Caller));
memmove(gDTMF_Callee, gDTMF_RX + Offset + 0, 3);
memmove(gDTMF_Caller, gDTMF_RX + Offset + 4, 3);
DTMF_clear_RX();
gUpdateDisplay = true;
switch (gEeprom.DTMF_DECODE_RESPONSE)
{
case 3:
gDTMF_DecodeRing = true;
case DTMF_DEC_RESPONSE_BOTH:
gDTMF_DecodeRingCountdown_500ms = DTMF_decode_ring_countdown_500ms;
// Fallthrough
case 2:
case DTMF_DEC_RESPONSE_REPLY:
gDTMF_ReplyState = DTMF_REPLY_AAAAA;
break;
case 1:
gDTMF_DecodeRing = true;
case DTMF_DEC_RESPONSE_RING:
gDTMF_DecodeRingCountdown_500ms = DTMF_decode_ring_countdown_500ms;
break;
default:
gDTMF_DecodeRing = false;
case DTMF_DEC_RESPONSE_NONE:
gDTMF_DecodeRingCountdown_500ms = 0;
gDTMF_ReplyState = DTMF_REPLY_NONE;
break;
}
@@ -346,12 +402,14 @@ void DTMF_Reply(void)
return;
Delay = gEeprom.DTMF_PRELOAD_TIME;
if (gEeprom.DTMF_SIDE_TONE)
{
{ // the will also hear the transmitted tones
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
gEnableSpeaker = true;
Delay = (gEeprom.DTMF_PRELOAD_TIME < 60) ? 60 : gEeprom.DTMF_PRELOAD_TIME;
}
SYSTEM_DelayMs(Delay);
BK4819_EnterDTMF_TX(gEeprom.DTMF_SIDE_TONE);

View File

@@ -36,6 +36,13 @@ enum DTMF_CallState_t {
DTMF_CALL_STATE_RECEIVED
};
enum DTMF_DecodeResponse_t {
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 {
@@ -56,12 +63,16 @@ enum DTMF_CallMode_t {
typedef enum DTMF_CallMode_t DTMF_CallMode_t;
extern char gDTMF_String[15];
extern char gDTMF_InputBox[15];
extern char gDTMF_Received[16];
extern uint8_t gDTMF_WriteIndex;
extern char gDTMF_InputBox[15];
extern uint8_t gDTMF_InputIndex;
extern bool gDTMF_InputMode;
extern uint8_t gDTMF_PreviousIndex;
extern uint8_t gDTMF_RecvTimeout;
extern char gDTMF_RX[17];
extern uint8_t gDTMF_RX_index;
extern uint8_t gDTMF_RX_timeout;
extern bool gDTMF_RX_pending;
extern char gDTMF_RX_live[20];
extern uint8_t gDTMF_RX_live_timeout;
@@ -71,25 +82,23 @@ extern char gDTMF_ID[4];
extern char gDTMF_Caller[4];
extern char gDTMF_Callee[4];
extern DTMF_State_t gDTMF_State;
extern bool gDTMF_DecodeRing;
extern uint8_t gDTMF_DecodeRingCountdown_500ms;
extern uint8_t gDTMFChosenContact;
extern uint8_t gDTMF_AUTO_RESET_TIME;
extern uint8_t gDTMF_InputIndex;
extern bool gDTMF_InputMode;
extern DTMF_CallState_t gDTMF_CallState;
extern DTMF_ReplyState_t gDTMF_ReplyState;
extern DTMF_CallMode_t gDTMF_CallMode;
extern bool gDTMF_IsTx;
extern uint8_t gDTMF_TxStopCountdown_500ms;
bool DTMF_ValidateCodes(char *pCode, uint8_t Size);
void DTMF_clear_RX(void);
bool DTMF_ValidateCodes(char *pCode, const unsigned int size);
bool DTMF_GetContact(const int Index, char *pContact);
bool DTMF_FindContact(const char *pContact, char *pResult);
char DTMF_GetCharacter(const uint8_t code);
bool DTMF_CompareMessage(const char *pDTMF, const char *pTemplate, uint8_t Size, bool bFlag);
DTMF_CallMode_t DTMF_CheckGroupCall(const char *pDTMF, uint32_t Size);
void DTMF_Append(char Code);
char DTMF_GetCharacter(const unsigned int code);
bool DTMF_CompareMessage(const char *pDTMF, const char *pTemplate, const unsigned int size, const bool bFlag);
DTMF_CallMode_t DTMF_CheckGroupCall(const char *pDTMF, const unsigned int size);
void DTMF_Append(const char vode);
void DTMF_HandleRequest(void);
void DTMF_Reply(void);

View File

@@ -458,9 +458,17 @@ static void MAIN_Key_DIGITS(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
static void MAIN_Key_EXIT(bool bKeyPressed, bool bKeyHeld)
{
if (!bKeyHeld && bKeyPressed)
{
{ // exit key pressed
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
if (gDTMF_CallState != DTMF_CALL_STATE_NONE && gCurrentFunction != FUNCTION_TRANSMIT)
{ // clear CALL mode being displayed
gDTMF_CallState = DTMF_CALL_STATE_NONE;
gUpdateDisplay = true;
return;
}
#ifdef ENABLE_FMRADIO
if (!gFmRadioMode)
#endif
@@ -499,7 +507,8 @@ static void MAIN_Key_EXIT(bool bKeyPressed, bool bKeyHeld)
}
if (bKeyHeld && bKeyPressed)
{
{ // exit key held down
if (gInputBoxIndex > 0)
{ // cancel key input mode (channel/frequency entry)
gDTMF_InputMode = false;
@@ -515,7 +524,7 @@ static void MAIN_Key_EXIT(bool bKeyPressed, bool bKeyHeld)
static void MAIN_Key_MENU(const bool bKeyPressed, const bool bKeyHeld)
{
if (bKeyHeld)
{ // key held down (long press)
{ // menu key held down (long press)
if (bKeyPressed)
{
@@ -566,6 +575,7 @@ static void MAIN_Key_MENU(const bool bKeyPressed, const bool bKeyHeld)
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
// TODO: finish this
//gEeprom.RX_CHANNEL = () & 1; // swap to the VFO
@@ -583,13 +593,13 @@ static void MAIN_Key_MENU(const bool bKeyPressed, const bool bKeyHeld)
return;
}
if (!bKeyPressed)
{
bool bFlag;
if (!bKeyPressed && !gDTMF_InputMode)
{ // menu key released
const bool bFlag = (gInputBoxIndex == 0);
gInputBoxIndex = 0;
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
bFlag = (gInputBoxIndex == 0);
gInputBoxIndex = 0;
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
if (bFlag)
{
gFlagRefreshSetting = true;

View File

@@ -32,6 +32,7 @@
#include "driver/gpio.h"
#include "driver/keyboard.h"
#include "frequencies.h"
#include "helper/battery.h"
#include "misc.h"
#include "settings.h"
#if defined(ENABLE_OVERLAY)
@@ -109,11 +110,15 @@ int MENU_GetLimits(uint8_t Cursor, int32_t *pMin, int32_t *pMax)
break;
case MENU_TDR:
case MENU_XB:
*pMin = 0;
*pMax = ARRAY_SIZE(gSubMenu_CHAN) - 1;
break;
case MENU_XB:
*pMin = 0;
*pMax = ARRAY_SIZE(gSubMenu_XB) - 1;
break;
#ifdef ENABLE_VOICE
case MENU_VOICE:
*pMin = 0;
@@ -264,6 +269,11 @@ int MENU_GetLimits(uint8_t Cursor, int32_t *pMin, int32_t *pMax)
*pMax = ARRAY_SIZE(gSubMenu_PTT_ID) - 1;
break;
case MENU_VOL:
*pMin = 0;
*pMax = 2300;
break;
case MENU_BAT_TXT:
*pMin = 0;
*pMax = ARRAY_SIZE(gSubMenu_BAT_TXT) - 1;
@@ -585,19 +595,26 @@ void MENU_AcceptSetting(void)
gRequestSaveChannel = 1;
return;
case MENU_VOL:
if(gF_LOCK) {
EEPROM_WriteBuffer(0x1F40, gBatteryCalibration);
}
break;
case MENU_BAT_TXT:
gSetting_battery_text = gSubMenuSelection;
break;
case MENU_D_DCD:
gTxVfo->DTMF_DECODING_ENABLE = gSubMenuSelection;
gRequestSaveChannel = 1;
DTMF_clear_RX();
gRequestSaveChannel = 1;
return;
case MENU_D_LIVE_DEC:
gDTMF_RX_live_timeout = 0;
gDTMF_RX_live[0] = '\0';
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;
@@ -988,6 +1005,10 @@ void MENU_ShowCurrentSetting(void)
gSubMenuSelection = gTxVfo->DTMF_PTT_ID_TX_MODE;
break;
case MENU_VOL:
gSubMenuSelection = gBatteryCalibration[3];
return;
case MENU_BAT_TXT:
gSubMenuSelection = gSetting_battery_text;
return;
@@ -1317,9 +1338,13 @@ static void MENU_Key_MENU(const bool bKeyPressed, const bool bKeyHeld)
gAskForConfirmation = 0;
gIsInSubMenu = true;
gInputBoxIndex = 0;
edit_index = -1;
// if (gMenuCursor != MENU_D_LIST)
{
gInputBoxIndex = 0;
edit_index = -1;
}
return;
}

View File

@@ -14,6 +14,7 @@
* limitations under the License.
*/
#include "app/dtmf.h"
#include "app/generic.h"
#include "app/scanner.h"
#include "audio.h"
@@ -399,12 +400,13 @@ void SCANNER_Start(void)
gUpdateStatus = true;
}
DTMF_clear_RX();
gScanDelay_10ms = scan_delay_10ms;
gScanCssResultCode = 0xFF;
gScanCssResultType = 0xFF;
gScanHitCount = 0;
gScanUseCssResult = false;
gDTMF_RequestPending = false;
g_CxCSS_TAIL_Found = false;
g_CDCSS_Lost = false;
gCDCSSCodeType = 0;

View File

@@ -57,8 +57,8 @@ PeakInfo peak;
ScanInfo scanInfo;
KeyboardState kbd = {KEY_INVALID, KEY_INVALID, 0};
const char *bwOptions[] = {"25k", "12.5k", "6.25k"};
const char *modulationTypeOptions[] = {"FM", "AM", "USB"};
const char *bwOptions[] = {" 25k", "12.5k", "6.25k"};
const char *modulationTypeOptions[] = {" FM", " AM", "USB"};
const uint8_t modulationTypeTuneSteps[] = {100, 50, 10};
const uint8_t modTypeReg47Values[] = {1, 7, 5};
@@ -66,7 +66,7 @@ SpectrumSettings settings = {STEPS_64,
S_STEP_25_0kHz,
80000,
3200,
0,
150,
true,
BK4819_FILTER_BW_WIDE,
BK4819_FILTER_BW_WIDE,
@@ -259,8 +259,9 @@ static void SetF(uint32_t 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, 0xbff1);
BK4819_WriteRegister(BK4819_REG_30, reg);
}
// Spectrum related
@@ -294,12 +295,16 @@ static void DeInitSpectrum() {
isInitialized = false;
}
uint8_t GetBWRegValueForScan() { return scanStepBWRegValues[0]; }
uint8_t GetBWRegValueForScan() {
return scanStepBWRegValues[settings.scanStepIndex];
}
uint16_t GetRssi() {
SYSTICK_DelayUs(settings.scanDelay);
/* while ((BK4819_ReadRegister(0x63) & 0b11111111) >= 255)
; */
// SYSTICK_DelayUs(800);
// testing autodelay based on Glitch value
while ((BK4819_ReadRegister(0x63) & 0b11111111) >= 255) {
SYSTICK_DelayUs(100);
}
return BK4819_GetRSSI();
}
@@ -361,7 +366,9 @@ static void RelaunchScan() {
InitScan();
ResetPeak();
ToggleRX(false);
#ifdef SPECTRUM_AUTOMATIC_SQUELCH
settings.rssiTriggerLevel = RSSI_MAX_VALUE;
#endif
preventKeypress = true;
scanInfo.rssiMin = RSSI_MAX_VALUE;
}
@@ -409,6 +416,7 @@ static void UpdateRssiTriggerLevel(bool inc) {
else
settings.rssiTriggerLevel -= 2;
redrawScreen = true;
redrawStatus = true;
}
static void UpdateDBMax(bool inc) {
@@ -419,8 +427,8 @@ static void UpdateDBMax(bool inc) {
} else {
return;
}
// RelaunchScan();
redrawStatus = true;
redrawScreen = true;
SYSTEM_DelayMs(20);
}
@@ -435,7 +443,7 @@ static void UpdateScanStep(bool inc) {
settings.frequencyChangeStep = GetBW() >> 1;
RelaunchScan();
ResetBlacklist();
redrawStatus = true;
redrawScreen = true;
}
static void UpdateCurrentFreq(bool inc) {
@@ -511,7 +519,7 @@ static void ToggleStepsCount() {
settings.frequencyChangeStep = GetBW() >> 1;
RelaunchScan();
ResetBlacklist();
redrawStatus = true;
redrawScreen = true;
}
static void ResetFreqInput() {
@@ -584,14 +592,15 @@ static void Blacklist() {
// 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;
const int DB_MAX = settings.dbMax;
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;
int dbm = clamp(Rssi2DBm(rssi), DB_MIN, DB_MAX);
int dbm = clamp(rssi - (160 << 1), DB_MIN, DB_MAX);
return ((dbm - DB_MIN) * PX_RANGE + DB_RANGE / 2) / DB_RANGE + pxMin;
}
@@ -610,8 +619,14 @@ static void DrawSpectrum() {
}
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));
#else
sprintf(String, "%d/%d", settings.dbMin, settings.dbMax);
GUI_DisplaySmallest(String, 0, 2, true, true);
#endif
GUI_DisplaySmallest(String, 0, 1, true, true);
for (int i = 0; i < 4; i++) {
BOARD_ADC_GetBatteryInfo(&gBatteryVoltages[i], &gBatteryCurrent);
}
@@ -653,19 +668,15 @@ static void DrawStatus() {
static void DrawF(uint32_t f) {
sprintf(String, "%u.%05u", f / 100000, f % 100000);
UI_PrintStringSmall(String, 0, 127, 0);
UI_PrintStringSmall(String, 8, 127, 0);
sprintf(String, "%s", modulationTypeOptions[settings.modulationType]);
GUI_DisplaySmallest(String, 115, 1, false, true);
GUI_DisplaySmallest(String, 116, 1, false, true);
sprintf(String, "%s", bwOptions[settings.listenBw]);
GUI_DisplaySmallest(String, 107, 7, false, true);
GUI_DisplaySmallest(String, 108, 7, false, true);
}
static void DrawNums() {
sprintf(String, "P:%d", Rssi2DBm(peak.rssi));
GUI_DisplaySmallest(String, 32, 8, false, true);
sprintf(String, "T:%d", Rssi2DBm(settings.rssiTriggerLevel));
GUI_DisplaySmallest(String, 64, 8, false, true);
if (currentState == SPECTRUM) {
sprintf(String, "%ux", GetStepsCount());
@@ -966,8 +977,6 @@ static void RenderStill() {
GUI_DisplaySmallest(String, 4, 25, false, true);
sprintf(String, "%d dBm", dbm);
GUI_DisplaySmallest(String, 28, 25, false, true);
sprintf(String, "V: %d", scanInfo.rssi);
GUI_DisplaySmallest(String, 64, 25, false, true);
if (!monitorMode) {
uint8_t x = Rssi2PX(settings.rssiTriggerLevel, 0, 121);
@@ -1107,7 +1116,6 @@ static void UpdateListening() {
}
if (currentState == SPECTRUM) {
SetF(fMeasure);
BK4819_WriteRegister(0x43, GetBWRegValueForScan());
Measure();
BK4819_WriteRegister(0x43, listenBWRegValues[settings.listenBw]);
@@ -1167,7 +1175,7 @@ void APP_RunSpectrum() {
redrawScreen = false; // we will wait until scan done
newScanStart = true;
ToggleRX(false);
ToggleRX(true), ToggleRX(false); // hack to prevent noise when squelch off
SetModulation(settings.modulationType = MOD_FM);
BK4819_SetFilterBandwidth(settings.listenBw = BK4819_FILTER_BW_WIDE, false);

15
audio.c
View File

@@ -76,7 +76,12 @@ void AUDIO_PlayBeep(BEEP_Type_t Beep)
uint16_t ToneFrequency;
uint16_t Duration;
if (Beep != BEEP_880HZ_60MS_TRIPLE_BEEP && Beep != BEEP_500HZ_60MS_DOUBLE_BEEP && Beep != BEEP_440HZ_500MS && !gEeprom.BEEP_CONTROL)
if (Beep != BEEP_880HZ_60MS_TRIPLE_BEEP &&
Beep != BEEP_500HZ_60MS_DOUBLE_BEEP &&
Beep != BEEP_440HZ_500MS &&
Beep != BEEP_880HZ_200MS &&
Beep != BEEP_880HZ_500MS &&
!gEeprom.BEEP_CONTROL)
return;
#ifdef ENABLE_AIRCOPY
@@ -123,6 +128,8 @@ void AUDIO_PlayBeep(BEEP_Type_t Beep)
break;
case BEEP_880HZ_40MS_OPTIONAL:
case BEEP_880HZ_60MS_TRIPLE_BEEP:
case BEEP_880HZ_200MS:
case BEEP_880HZ_500MS:
ToneFrequency = 880;
break;
}
@@ -161,7 +168,13 @@ void AUDIO_PlayBeep(BEEP_Type_t Beep)
Duration = 40;
break;
case BEEP_880HZ_200MS:
BK4819_ExitTxMute();
Duration = 200;
break;
case BEEP_440HZ_500MS:
case BEEP_880HZ_500MS:
default:
BK4819_ExitTxMute();
Duration = 500;

View File

@@ -26,6 +26,8 @@ enum BEEP_Type_t
BEEP_1KHZ_60MS_OPTIONAL,
BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL,
BEEP_440HZ_500MS,
BEEP_880HZ_200MS,
BEEP_880HZ_500MS,
BEEP_500HZ_60MS_DOUBLE_BEEP,
BEEP_440HZ_40MS_OPTIONAL,
BEEP_880HZ_40MS_OPTIONAL,

View File

@@ -891,7 +891,7 @@ void BK4819_EnableDTMF(void)
// REG_24 <3:0> 14 Max symbol number for SelCall detection
// const uint16_t threshold = 24; // doesn't decode non-QS radios
const uint16_t threshold = 200; // but 128 ~ 247 does
const uint16_t threshold = 140; // 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

View File

@@ -53,15 +53,8 @@ void FUNCTION_Init(void)
gCurrentCodeType = CODE_TYPE_CONTINUOUS_TONE;
#endif
gDTMF_RequestPending = false;
gDTMF_RecvTimeout = 0;
gDTMF_WriteIndex = 0;
memset(gDTMF_Received, 0, sizeof(gDTMF_Received));
// gDTMF_RX_timeout_live = 0;
// gDTMF_RX_timeout_live[0] = '\0';
DTMF_clear_RX();
g_CxCSS_TAIL_Found = false;
g_CDCSS_Lost = false;
g_CTCSS_Lost = false;
@@ -152,8 +145,13 @@ void FUNCTION_Select(FUNCTION_Type_t Function)
// if DTMF is enabled when TX'ing, it changes the TX audio filtering !! .. 1of11
BK4819_DisableDTMF();
// clear the DTMF RX buffer
DTMF_clear_RX();
// clear the DTMF RX live decoder buffer
gDTMF_RX_live_timeout = 0;
gDTMF_RX_live[0] = 0;
gDTMF_RX_live_timeout = 0;
memset(gDTMF_RX_live, 0, sizeof(gDTMF_RX_live));
#if defined(ENABLE_FMRADIO)
if (gFmRadioMode)
@@ -189,7 +187,7 @@ void FUNCTION_Select(FUNCTION_Type_t Function)
RADIO_SetTxParameters();
// turn the LED on RED
// turn the RED LED on
BK4819_ToggleGpioOut(BK4819_GPIO1_PIN29_RED, true);
DTMF_Reply();

BIN
images/batcal.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

3
misc.c
View File

@@ -28,7 +28,7 @@ const uint8_t menu_timeout_500ms = 20000 / 500; // 20 seconds
const uint8_t DTMF_RX_live_timeout_500ms = 6000 / 500; // 6 seconds live decoder on screen
const uint8_t DTMF_RX_timeout_500ms = 10000 / 500; // 10 seconds till we wipe the DTMF receiver
const uint8_t DTMF_decode_ring_countdown_500ms = 15000 / 500; // 15 seconds
const uint8_t DTMF_decode_ring_countdown_500ms = 15000 / 500; // 15 seconds .. time we sound the ringing for
const uint8_t DTMF_txstop_countdown_500ms = 3000 / 500; // 6 seconds
const uint8_t key_input_timeout_500ms = 8000 / 500; // 8 seconds
@@ -171,7 +171,6 @@ bool gFlagSaveChannel;
#ifdef ENABLE_FMRADIO
bool gFlagSaveFM;
#endif
uint8_t gDTMF_RequestPending;
bool g_CDCSS_Lost;
uint8_t gCDCSSCodeType;
bool g_CTCSS_Lost;

1
misc.h
View File

@@ -235,7 +235,6 @@ extern bool gFlagSaveChannel;
#ifdef ENABLE_FMRADIO
extern bool gFlagSaveFM;
#endif
extern uint8_t gDTMF_RequestPending;
extern bool g_CDCSS_Lost;
extern uint8_t gCDCSSCodeType;
extern bool g_CTCSS_Lost;

45
radio.c
View File

@@ -436,7 +436,7 @@ void RADIO_ConfigureSquelchAndOutputPower(VFO_Info_t *pInfo)
uint16_t Base = (Band < BAND4_174MHz) ? 0x1E60 : 0x1E00;
if (gEeprom.SQUELCH_LEVEL == 0)
{
{ // squelch == 0 (off)
pInfo->SquelchOpenRSSIThresh = 0;
pInfo->SquelchOpenNoiseThresh = 127;
pInfo->SquelchCloseGlitchThresh = 255;
@@ -446,9 +446,8 @@ void RADIO_ConfigureSquelchAndOutputPower(VFO_Info_t *pInfo)
pInfo->SquelchOpenGlitchThresh = 255;
}
else
{
Base += gEeprom.SQUELCH_LEVEL;
// my squelch-1
{ // squelch >= 1
Base += gEeprom.SQUELCH_LEVEL; // my squelch-1
// VHF UHF
EEPROM_ReadBuffer(Base + 0x00, &pInfo->SquelchOpenRSSIThresh, 1); // 50 10
EEPROM_ReadBuffer(Base + 0x10, &pInfo->SquelchCloseRSSIThresh, 1); // 40 5
@@ -459,37 +458,22 @@ void RADIO_ConfigureSquelchAndOutputPower(VFO_Info_t *pInfo)
EEPROM_ReadBuffer(Base + 0x40, &pInfo->SquelchCloseGlitchThresh, 1); // 90 90
EEPROM_ReadBuffer(Base + 0x50, &pInfo->SquelchOpenGlitchThresh, 1); // 100 100
#if ENABLE_SQUELCH1_LOWER
// make squelch-1 more sensitive
if (gEeprom.SQUELCH_LEVEL == 1)
{
if (Band < BAND4_174MHz)
{
pInfo->SquelchOpenRSSIThresh = ((uint16_t)pInfo->SquelchOpenRSSIThresh * 11) / 12;
pInfo->SquelchCloseRSSIThresh = ((uint16_t)pInfo->SquelchOpenRSSIThresh * 9) / 10;
#if ENABLE_SQUELCH_LOWER
// make squelch more sensitive
pInfo->SquelchOpenNoiseThresh = ((uint16_t)pInfo->SquelchOpenNoiseThresh * 9) / 8;
pInfo->SquelchCloseNoiseThresh = ((uint16_t)pInfo->SquelchOpenNoiseThresh * 10) / 9;
pInfo->SquelchOpenRSSIThresh = ((uint16_t)pInfo->SquelchOpenRSSIThresh * 8) / 9;
pInfo->SquelchCloseRSSIThresh = ((uint16_t)pInfo->SquelchOpenRSSIThresh * 7) / 8;
pInfo->SquelchOpenGlitchThresh = ((uint16_t)pInfo->SquelchOpenGlitchThresh * 9) / 8;
pInfo->SquelchCloseGlitchThresh = ((uint16_t)pInfo->SquelchOpenGlitchThresh * 10) / 9;
}
else
{
pInfo->SquelchOpenRSSIThresh = ((uint16_t)pInfo->SquelchOpenRSSIThresh * 3) / 4;
pInfo->SquelchCloseRSSIThresh = ((uint16_t)pInfo->SquelchOpenRSSIThresh * 9) / 10;
pInfo->SquelchOpenNoiseThresh = ((uint16_t)pInfo->SquelchOpenNoiseThresh * 8) / 7;
pInfo->SquelchCloseNoiseThresh = ((uint16_t)pInfo->SquelchOpenNoiseThresh * 9) / 8;
pInfo->SquelchOpenNoiseThresh = ((uint16_t)pInfo->SquelchOpenNoiseThresh * 4) / 3;
pInfo->SquelchCloseNoiseThresh = ((uint16_t)pInfo->SquelchOpenNoiseThresh * 10) / 9;
pInfo->SquelchOpenGlitchThresh = ((uint16_t)pInfo->SquelchOpenGlitchThresh * 4) / 3;
pInfo->SquelchCloseGlitchThresh = ((uint16_t)pInfo->SquelchOpenGlitchThresh * 10) / 9;
}
}
pInfo->SquelchOpenGlitchThresh = ((uint16_t)pInfo->SquelchOpenGlitchThresh * 8) / 7;
pInfo->SquelchCloseGlitchThresh = ((uint16_t)pInfo->SquelchOpenGlitchThresh * 9) / 8;
#endif
if (pInfo->SquelchOpenNoiseThresh > 127)
pInfo->SquelchOpenNoiseThresh = 127;
if (pInfo->SquelchCloseNoiseThresh > 127)
pInfo->SquelchCloseNoiseThresh = 127;
}
@@ -747,9 +731,6 @@ void RADIO_SetupRegisters(bool bSwitchToFunction0)
#endif
#if 0
// there's no reason the DTMF decoder can't be used in AM RX mode too
// aircraft comms use it on HF (AM and SSB)
// if (gRxVfo->AM_mode || (!gRxVfo->DTMF_DECODING_ENABLE && !gSetting_KILLED))
if (!gRxVfo->DTMF_DECODING_ENABLE && !gSetting_KILLED)
{
BK4819_DisableDTMF();
@@ -760,7 +741,7 @@ void RADIO_SetupRegisters(bool bSwitchToFunction0)
InterruptMask |= BK4819_REG_3F_DTMF_5TONE_FOUND;
}
#else
if (gCurrentFunction != FUNCTION_TRANSMIT && gSetting_live_DTMF_decoder)
if (gCurrentFunction != FUNCTION_TRANSMIT)
{
BK4819_EnableDTMF();
InterruptMask |= BK4819_REG_3F_DTMF_5TONE_FOUND;

View File

@@ -214,7 +214,7 @@ void SETTINGS_SaveChannel(uint8_t Channel, uint8_t VFO, const VFO_Info_t *pVFO,
| (pVFO->OUTPUT_POWER << 2)
| (pVFO->CHANNEL_BANDWIDTH << 1)
| (pVFO->FrequencyReverse << 0);
State[5] = (pVFO->DTMF_PTT_ID_TX_MODE << 1) | (pVFO->DTMF_DECODING_ENABLE < 0);
State[5] = (pVFO->DTMF_PTT_ID_TX_MODE << 1) | (pVFO->DTMF_DECODING_ENABLE << 0);
State[6] = pVFO->STEP_SETTING;
State[7] = pVFO->SCRAMBLING_TYPE;
EEPROM_WriteBuffer(OffsetVFO + 8, State);

View File

@@ -36,6 +36,8 @@
#include "ui/main.h"
#include "ui/ui.h"
bool center_line_is_free = true;
// ***************************************************************************
#ifdef ENABLE_AUDIO_BAR
@@ -117,11 +119,12 @@
#if defined(ENABLE_RSSI_BAR)
void UI_DisplayRSSIBar(const int16_t rssi, const bool now)
{
const int16_t s9_dBm = -73; // S9
const int16_t s0_dBm = -127; // S0
// const int16_t s0_dBm = -127; // S0 .. base level
const int16_t s0_dBm = -147; // S0 .. base level
const int16_t s9_dBm = s0_dBm + (6 * 9); // S9 .. 6dB/S-Point
const int16_t bar_max_dBm = s9_dBm + 30; // S9+30dB
const int16_t bar_min_dBm = s0_dBm; // S0
const int16_t bar_min_dBm = s0_dBm + (6 * 4); // S4
// ************
@@ -129,8 +132,8 @@
const unsigned int bar_x = 2 + txt_width + 4; // X coord of bar graph
const unsigned int bar_width = LCD_WIDTH - 1 - bar_x;
const int16_t dBm = (rssi / 2) - 160;
const int16_t clamped_dBm = (dBm <= bar_min_dBm) ? bar_min_dBm : (dBm >= bar_max_dBm) ? bar_max_dBm : dBm;
const int16_t rssi_dBm = (rssi / 2) - 160;
const int16_t clamped_dBm = (rssi_dBm <= bar_min_dBm) ? bar_min_dBm : (rssi_dBm >= bar_max_dBm) ? bar_max_dBm : rssi_dBm;
const unsigned int bar_range_dB = bar_max_dBm - bar_min_dBm;
const unsigned int len = ((clamped_dBm - bar_min_dBm) * bar_width) / bar_range_dB;
@@ -139,26 +142,26 @@
char s[16];
unsigned int i;
unsigned int s_level = 0; // S0
if (gEeprom.KEY_LOCK && gKeypadLocked > 0)
return; // display is in use
if (gCurrentFunction == FUNCTION_TRANSMIT || gScreenToDisplay != DISPLAY_MAIN)
return; // display is in use
if (dBm >= (s9_dBm + 10)) // S9+10dB
s_level = ((dBm - s9_dBm) / 10) * 10;
else
if (dBm >= s0_dBm) // S0
s_level = (dBm - s0_dBm) / 6; // 6dB per S point
if (now)
memset(pLine, 0, LCD_WIDTH);
if (s_level < 10)
sprintf(s, "%-4d S%u ", dBm, s_level); // S0 ~ S9
if (rssi_dBm >= (s9_dBm + 6))
{ // S9+XXdB, 1dB increment
const char *fmt[] = {"%-4d +%u ", "%-4d +%u "};
const unsigned int dB = rssi_dBm - s9_dBm;
sprintf(s, (dB < 10) ? fmt[0] : fmt[1], rssi_dBm, dB);
}
else
sprintf(s, "%-4d +%2u", dBm, s_level); // S9+XX
{ // S0 ~ S9, 6dB per S-point
const unsigned int s_level = (rssi_dBm >= s0_dBm) ? (rssi_dBm - s0_dBm) / 6 : 0;
sprintf(s, "%-4d S%u ", rssi_dBm, s_level);
}
UI_PrintStringSmall(s, 2, 0, line);
#if 1
@@ -180,6 +183,9 @@ void UI_UpdateRSSI(const int16_t rssi, const int vfo)
{
#ifdef ENABLE_RSSI_BAR
if (!center_line_is_free)
return;
const bool rx = (gCurrentFunction == FUNCTION_RECEIVE ||
gCurrentFunction == FUNCTION_MONITOR ||
gCurrentFunction == FUNCTION_INCOMING);
@@ -286,7 +292,8 @@ void UI_DisplayMain(void)
{
char String[16];
unsigned int vfo_num;
bool center_line_is_free = true;
center_line_is_free = true;
// #ifdef SINGLE_VFO_CHAN
// const bool single_vfo = (gEeprom.DUAL_WATCH == DUAL_WATCH_OFF && gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF) ? true : false;
@@ -338,7 +345,7 @@ void UI_DisplayMain(void)
strcpy(String, (gDTMF_State == DTMF_STATE_CALL_OUT_RSP) ? "CALL OUT(RSP)" : "CALL OUT");
else
if (gDTMF_CallState == DTMF_CALL_STATE_RECEIVED)
sprintf(String, "CALL:%s", (DTMF_FindContact(gDTMF_Caller, Contact)) ? Contact : gDTMF_Caller);
sprintf(String, "CALL FRM:%s", (DTMF_FindContact(gDTMF_Caller, Contact)) ? Contact : gDTMF_Caller);
else
if (gDTMF_IsTx)
strcpy(String, (gDTMF_State == DTMF_STATE_TX_SUCC) ? "DTMF TX(SUCC)" : "DTMF TX");
@@ -680,7 +687,7 @@ void UI_DisplayMain(void)
UI_PrintStringSmall(String, LCD_WIDTH + 70, 0, Line + 1);
}
// show the DTMF decoding symbol(
// show the DTMF decoding symbol
if (gEeprom.VfoInfo[vfo_num].DTMF_DECODING_ENABLE || gSetting_KILLED)
UI_PrintStringSmall("DTMF", LCD_WIDTH + 78, 0, Line + 1);
@@ -719,14 +726,25 @@ void UI_DisplayMain(void)
if (rx || gCurrentFunction == FUNCTION_FOREGROUND || gCurrentFunction == FUNCTION_POWER_SAVE)
{
if (gSetting_live_DTMF_decoder && gDTMF_RX_live[0] >= 32)
{ // 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
strcpy(String, "DTMF ");
strcat(String, gDTMF_RX_live + idx);
UI_PrintStringSmall(String, 2, 0, 3);
}
#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
strcpy(String, "DTMF ");
strcat(String, gDTMF_RX_live + idx);
UI_PrintStringSmall(String, 2, 0, 3);
}
#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
strcpy(String, "DTMF ");
strcat(String, gDTMF_RX + idx);
UI_PrintStringSmall(String, 2, 0, 3);
}
#endif
#ifdef ENABLE_SHOW_CHARGE_LEVEL
else

View File

@@ -184,8 +184,15 @@ const char gSubMenu_TOT[11][7] =
const char gSubMenu_CHAN[3][7] =
{
"OFF",
"CHAN_A",
"CHAN_B"
"CHAN A",
"CHAN B"
};
const char gSubMenu_XB[3][7] =
{
"SAME",
"CHAN A",
"CHAN B"
};
#ifdef ENABLE_VOICE
@@ -575,10 +582,13 @@ void UI_DisplayMenu(void)
break;
case MENU_TDR:
case MENU_XB:
strcpy(String, gSubMenu_CHAN[gSubMenuSelection]);
break;
case MENU_XB:
strcpy(String, gSubMenu_XB[gSubMenuSelection]);
break;
case MENU_TOT:
strcpy(String, gSubMenu_TOT[gSubMenuSelection]);
break;
@@ -663,6 +673,7 @@ void UI_DisplayMenu(void)
break;
case MENU_VOL:
// 1st text line
sprintf(String, "%u.%02uV", gBatteryVoltageAverage / 100, gBatteryVoltageAverage % 100);
UI_PrintString(String, menu_item_x1, menu_item_x2, 1, 8);
@@ -677,6 +688,12 @@ void UI_DisplayMenu(void)
UI_PrintString(String, menu_item_x1, menu_item_x2, 5, 8);
#endif
}
if(gF_LOCK){
gBatteryCalibration[3] = gSubMenuSelection;
sprintf(String, "%u", gSubMenuSelection);
UI_PrintString(String, menu_item_x1, menu_item_x2, 5, 8);
}
already_printed = true;
break;

View File

@@ -125,6 +125,7 @@ extern const char gSubMenu_OFF_ON[2][4];
extern const char gSubMenu_SAVE[5][4];
extern const char gSubMenu_TOT[11][7];
extern const char gSubMenu_CHAN[3][7];
extern const char gSubMenu_XB[3][7];
#ifdef ENABLE_VOICE
extern const char gSubMenu_VOICE[3][4];
#endif