Update
Some checks failed
Build Firmware / build (push) Has been cancelled

This commit is contained in:
2025-11-05 22:07:44 +01:00
parent b54e5ef8a5
commit 5416c3a041
28 changed files with 273 additions and 963 deletions

View File

@@ -206,9 +206,6 @@ void ACTION_Scan(bool bRestart)
// not scanning
gMonitor = false;
#ifdef ENABLE_DTMF_CALLING
DTMF_clear_RX();
#endif
gDTMF_RX_live_timeout = 0;
memset(gDTMF_RX_live, 0, sizeof(gDTMF_RX_live));

102
app/app.c
View File

@@ -186,10 +186,6 @@ static void CheckForIncoming(void) {
static void HandleIncoming(void) {
if (!g_SquelchLost) { // squelch is closed
#ifdef ENABLE_DTMF_CALLING
if (gDTMF_RX_index > 0)
DTMF_clear_RX();
#endif
if (gCurrentFunction != FUNCTION_FOREGROUND) {
FUNCTION_Select(FUNCTION_FOREGROUND);
gUpdateDisplay = true;
@@ -217,30 +213,6 @@ static void HandleIncoming(void) {
} else if (!bFlag)
return;
#ifdef ENABLE_DTMF_CALLING
if (gScanStateDir == SCAN_OFF && (gRxVfo->DTMF_DECODING_ENABLE)) {
// 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;
// let the user see DW is not active
gDualWatchActive = false;
gUpdateStatus = true;
gUpdateDisplay = true;
return;
}
}
#endif
APP_StartListening(gMonitor ? FUNCTION_MONITOR : FUNCTION_RECEIVE);
}
@@ -670,21 +642,6 @@ static void CheckRadioInterrupts(void) {
gUpdateDisplay = true;
}
#ifdef ENABLE_DTMF_CALLING
if (gRxVfo->DTMF_DECODING_ENABLE) {
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
}
}
}
@@ -834,9 +791,6 @@ static void HandleVox(void) {
FUNCTION_Select(FUNCTION_FOREGROUND);
if (gCurrentFunction != FUNCTION_TRANSMIT && !SerialConfigInProgress()) {
#ifdef ENABLE_DTMF_CALLING
gDTMF_ReplyState = DTMF_REPLY_NONE;
#endif
RADIO_PrepareTX();
gUpdateDisplay = true;
}
@@ -941,9 +895,6 @@ void APP_Update(void) {
#endif
#ifdef ENABLE_FMRADIO
&& !gFmRadioMode
#endif
#ifdef ENABLE_DTMF_CALLING
&& gDTMF_CallState == DTMF_CALL_STATE_NONE
#endif
) {
DualwatchAlternate(); // toggle between the two VFO's
@@ -981,9 +932,6 @@ void APP_Update(void) {
#ifdef ENABLE_FMRADIO
|| gFmRadioMode
#endif
#ifdef ENABLE_DTMF_CALLING
|| gDTMF_CallState != DTMF_CALL_STATE_NONE
#endif
#ifdef ENABLE_NOAA
|| (gIsNoaaMode && (IS_NOAA_CHANNEL(gEeprom.ScreenChannel[0]) || IS_NOAA_CHANNEL(gEeprom.ScreenChannel[1])))
#endif
@@ -1434,11 +1382,6 @@ void APP_TimeSlice500ms(void) {
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();
#endif
// Skipped authentic device check
@@ -1625,33 +1568,6 @@ void APP_TimeSlice500ms(void) {
FSKModem_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;
}
#endif
}
#if defined(ENABLE_ALARM) || defined(ENABLE_TX1750)
@@ -1767,18 +1683,6 @@ static void ProcessKey(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld) {
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;
AUDIO_PlayBeep(BEEP_1KHZ_60MS_OPTIONAL);
if (Key != KEY_PTT) {
gPttWasReleased = true;
return;
}
}
#endif
}
bool lowBatPopup = gLowBattery && !gLowBatteryConfirmed && gScreenToDisplay == DISPLAY_MAIN;
@@ -2030,12 +1934,6 @@ static void ProcessKey(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld) {
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;
#endif
gVFO_RSSI_bar_level[0] = 0;
gVFO_RSSI_bar_level[1] = 0;

View File

@@ -44,40 +44,8 @@ uint8_t gDTMF_PreviousIndex = 0;
char gDTMF_RX_live[20];
uint8_t gDTMF_RX_live_timeout = 0;
#ifdef ENABLE_DTMF_CALLING
char gDTMF_RX[17];
uint8_t gDTMF_RX_index = 0;
uint8_t gDTMF_RX_timeout = 0;
bool gDTMF_RX_pending = false;
bool gIsDtmfContactValid;
char gDTMF_ID[4];
char gDTMF_Caller[4];
char gDTMF_Callee[4];
DTMF_State_t gDTMF_State;
uint8_t gDTMF_DecodeRingCountdown_500ms;
uint8_t gDTMF_chosen_contact;
uint8_t gDTMF_auto_reset_time_500ms;
DTMF_CallState_t gDTMF_CallState;
DTMF_CallMode_t gDTMF_CallMode;
bool gDTMF_IsTx;
uint8_t gDTMF_TxStopCountdown_500ms;
bool gDTMF_IsGroupCall;
#endif
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));
}
#endif
void DTMF_SendEndOfTransmission(void)
{
if (gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_APOLLO) {
@@ -85,9 +53,6 @@ void DTMF_SendEndOfTransmission(void)
}
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
#endif
) { // end-of-tx
if (gEeprom.DTMF_SIDE_TONE) {
AUDIO_AudioPathOn();
@@ -134,41 +99,6 @@ bool DTMF_ValidateCodes(char *pCode, const unsigned int size)
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;
}
EEPROM_ReadBuffer(0x1C00 + (Index * 16), pContact, 16);
// 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;
}
#endif
char DTMF_GetCharacter(const unsigned int code)
{
if (code <= KEY_9)
@@ -185,33 +115,6 @@ char DTMF_GetCharacter(const unsigned int code)
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;
}
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;
}
return DTMF_CALL_MODE_NOT_GROUP;
}
#endif
void DTMF_clear_input_box(void)
{
@@ -232,227 +135,23 @@ void DTMF_Append(const char code)
gDTMF_InputBox[gDTMF_InputBox_Index++] = code;
}
#ifdef ENABLE_DTMF_CALLING
void DTMF_HandleRequest(void)
{ // proccess the RX'ed DTMF characters
char String[21];
unsigned int Offset;
if (!gDTMF_RX_pending)
return; // nothing new received
if (gScanStateDir != SCAN_OFF || gCssBackgroundScan)
{ // we're busy scanning
DTMF_clear_RX();
return;
}
if (!gRxVfo->DTMF_DECODING_ENABLE)
{ // 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
sprintf(String, "%s%c%s", gEeprom.ANI_DTMF_ID, gEeprom.DTMF_SEPARATE_CODE, gEeprom.KILL_CODE);
Offset = gDTMF_RX_index - strlen(String);
if (CompareMessage(gDTMF_RX + Offset, String, strlen(String), true))
{ // bugger
// if (gEeprom.PERMIT_REMOTE_KILL)
// {
// gSetting_KILLED = true; // oooerr !
//
// DTMF_clear_RX();
//
// SETTINGS_SaveSettings();
//
// gDTMF_ReplyState = DTMF_REPLY_AB;
//
// #ifdef ENABLE_FMRADIO
// if (gFmRadioMode)
// {
// FM_TurnOff();
// GUI_SelectNextDisplay(DISPLAY_MAIN);
// }
// #endif
// }
// else
// {
gDTMF_ReplyState = DTMF_REPLY_NONE;
// }
gDTMF_CallState = DTMF_CALL_STATE_NONE;
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);
//
// Offset = gDTMF_RX_index - strlen(String);
//
// if (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_RX_index >= 2)
{ // look for ACK reply
char *pPrintStr = "AB";
Offset = gDTMF_RX_index - strlen(pPrintStr);
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_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");
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 (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
gDTMF_IsGroupCall = false;
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);
DTMF_clear_RX();
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;
}
}
}
#endif
void DTMF_Reply(void)
{
uint16_t Delay;
#ifdef ENABLE_DTMF_CALLING
char String[23];
#endif
const char *pString = NULL;
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
#endif
{
pString = gDTMF_String;
}
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;
#endif
default:
case DTMF_REPLY_NONE:
if (
#ifdef ENABLE_DTMF_CALLING
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)

View File

@@ -87,33 +87,4 @@ void DTMF_Append(const char code);
void DTMF_Reply(void);
void DTMF_SendEndOfTransmission(void);
#ifdef ENABLE_DTMF_CALLING
extern char gDTMF_RX[17];
extern uint8_t gDTMF_RX_index;
extern uint8_t gDTMF_RX_timeout;
extern bool gDTMF_RX_pending;
extern bool gIsDtmfContactValid;
extern char gDTMF_ID[4];
extern char gDTMF_Caller[4];
extern char gDTMF_Callee[4];
extern DTMF_State_t gDTMF_State;
extern uint8_t gDTMF_DecodeRingCountdown_500ms;
extern uint8_t gDTMF_chosen_contact;
extern uint8_t gDTMF_auto_reset_time_500ms;
extern DTMF_CallState_t gDTMF_CallState;
extern DTMF_CallMode_t gDTMF_CallMode;
extern bool gDTMF_IsTx;
extern uint8_t gDTMF_TxStopCountdown_500ms;
void DTMF_clear_RX(void);
DTMF_CallMode_t DTMF_CheckGroupCall(const char *pDTMF, const unsigned int size);
bool DTMF_GetContact(const int Index, char *pContact);
bool DTMF_FindContact(const char *pContact, char *pResult);
void DTMF_HandleRequest(void);
#endif
#endif

View File

@@ -6,6 +6,7 @@
//#include "messages.h"
#include "driver/uart.h"
#include "../ui/messages.h"
#include "ui/ui.h"
uint16_t TONE2_FREQ;
@@ -63,42 +64,68 @@ void FSKModem_TimeSlice500ms(void) {
}
void MSG_ConfigureFSK(bool rx) {
BK4819_WriteRegister(BK4819_REG_70, TONE2_ENABLE_BIT | (96U << 0));
// Compute tone frequency control word (for 26 MHz XTAL)
// quick helper
bool isAFSK = (gEeprom.FSKMode == MOD_AFSK_1200 ||
gEeprom.FSKMode == MOD_AFSK_2400 ||
gEeprom.FSKMode == MOD_NOAA_SAME);
// Base tone config
uint16_t tone1 = 0, tone2 = 0;
#define BK4819_FREQ_WORD(freq_hz) ((uint16_t)((freq_hz) * 10.32444f))
// Tone word macro for 26MHz XTAL (app note: freq * 10.32444)
#undef BK4819_FREQ_WORD
#define BK4819_FREQ_WORD(freq_hz) ((uint16_t)((freq_hz) * 10.32444f))
if (isAFSK) {
// Bell-202 style tones for AFSK/NOAA
switch (gEeprom.FSKMode) {
case MOD_AFSK_1200:
tone1 = BK4819_FREQ_WORD(1200.0f); // mark
tone2 = BK4819_FREQ_WORD(2200.0f); // space
break;
case MOD_AFSK_2400:
tone1 = BK4819_FREQ_WORD(1200.0f);
tone2 = BK4819_FREQ_WORD(2400.0f);
break;
case MOD_NOAA_SAME:
tone1 = BK4819_FREQ_WORD(1562.5f); // typical mark
tone2 = BK4819_FREQ_WORD(2083.3f); // typical space
break;
default:
tone1 = BK4819_FREQ_WORD(1200.0f);
tone2 = BK4819_FREQ_WORD(2200.0f);
break;
}
switch (gEeprom.FSKMode) {
case MOD_AFSK_2400:
TONE2_FREQ = BK4819_FREQ_WORD(2400.0f);
break;
case MOD_AFSK_1200:
TONE2_FREQ = BK4819_FREQ_WORD(1200.0f);
break;
case MOD_FSK_700:
TONE2_FREQ = BK4819_FREQ_WORD(700.0f);
break;
case MOD_FSK_450:
TONE2_FREQ = BK4819_FREQ_WORD(450.0f);
break;
case MOD_FSK_1200_2400:
TONE2_FREQ = BK4819_FREQ_WORD(1200.0f);
break;
case MOD_NOAA_SAME:
TONE2_FREQ = BK4819_FREQ_WORD(2083.3f);
break;
default:
TONE2_FREQ = BK4819_FREQ_WORD(1200.0f);
break;
BK4819_WriteRegister(BK4819_REG_71, tone1);
BK4819_WriteRegister(BK4819_REG_72, tone2);
// enable both tones
BK4819_WriteRegister(BK4819_REG_70,
TONE1_ENABLE_BIT | TONE2_ENABLE_BIT |
(96U << 8) | (96U << 0));
} else {
// plain FSK path: only TONE2 used (frequency for binary shift display/debug)
switch (gEeprom.FSKMode) {
case MOD_FSK_450:
tone2 = BK4819_FREQ_WORD(450.0f);
break;
case MOD_FSK_700:
tone2 = BK4819_FREQ_WORD(700.0f);
break;
case MOD_FSK_1200:
tone2 = BK4819_FREQ_WORD(1200.0f);
break;
case MOD_FSK_2400:
tone2 = BK4819_FREQ_WORD(2400.0f);
break;
default:
tone2 = BK4819_FREQ_WORD(1200.0f);
break;
}
BK4819_WriteRegister(BK4819_REG_72, tone2);
BK4819_WriteRegister(BK4819_REG_70, TONE2_ENABLE_BIT | (96U << 0));
}
BK4819_WriteRegister(BK4819_REG_72, TONE2_FREQ);
// Base config (enable + preamble type AA)
// Base FSK config
uint16_t fskConfig = FSK_ENABLE_BIT | FSK_PREAMBLE_TYPE_AA;
// Compose the correct fields into REG_58:
@@ -108,30 +135,37 @@ void MSG_ConfigureFSK(bool rx) {
switch (gEeprom.FSKMode) {
case MOD_AFSK_1200:
fskConfig |= FSK_TX_MODE_FFSK_1200_1800 /*<<13 in macro*/
| FSK_RX_MODE_FFSK_1200_1800 /*<<10 in macro*/
| FSK_RX_BW_FFSK_1200_1800; /*<<1 in macro*/
| FSK_RX_MODE_FFSK_1200_1800 /*<<10 in macro*/
| FSK_RX_BW_FFSK_1200_1800; /*<<1 in macro*/
break;
case MOD_AFSK_2400:
fskConfig |= FSK_TX_MODE_FFSK_1200_2400
| FSK_RX_MODE_FFSK_1200_2400
| FSK_RX_BW_2_4K_FFSK_1200_2400;
| FSK_RX_MODE_FFSK_1200_2400
| FSK_RX_BW_2_4K_FFSK_1200_2400;
break;
case MOD_NOAA_SAME:
fskConfig |= FSK_TX_MODE_NOAA_SAME
| FSK_RX_MODE_FSK_1_2K_2_4K_NOAA
| FSK_RX_BW_NOAA_SAME;
| FSK_RX_MODE_FSK_1_2K_2_4K_NOAA
| FSK_RX_BW_NOAA_SAME;
break;
case MOD_FSK_2400:
// binary FSK 1.2k/2.4k - use default FSK TX/RX modes and 1.2k BW
fskConfig |= FSK_TX_MODE_FSK_1_2K_2_4K
| FSK_RX_MODE_FSK_1_2K_2_4K_NOAA
| FSK_RX_BW_2_4K_FFSK_1200_2400;
break;
case MOD_FSK_700:
case MOD_FSK_450:
case MOD_FSK_1200_2400:
case MOD_FSK_1200:
default:
// binary FSK 1.2k/2.4k - use default FSK TX/RX modes and 1.2k BW
fskConfig |= FSK_TX_MODE_FSK_1_2K_2_4K
| FSK_RX_MODE_FSK_1_2K_2_4K_NOAA
| FSK_RX_BW_1_2K;
| FSK_RX_MODE_FSK_1_2K_2_4K_NOAA
| FSK_RX_BW_1_2K;
break;
}
@@ -143,9 +177,23 @@ void MSG_ConfigureFSK(bool rx) {
BK4819_WriteRegister(BK4819_REG_5C, FSK_CRC_ON);
if (rx) {
BK4819_WriteRegister(BK4819_REG_5E, (64U << 3) | (1U << 0));
uint8_t threshold;
switch (gEeprom.FSKMode) {
case MOD_AFSK_1200:
case MOD_NOAA_SAME:
threshold = 1U;
break;
case MOD_AFSK_2400:
threshold = 2U; // Slightly higher; 2400 baud can fill FIFO faster
break;
default:
threshold = 4U; // FSK modes
break;
}
BK4819_WriteRegister(BK4819_REG_5E, (64U << 3) | threshold);
}
// Data length (REG_5D<15:8>)
size_t size = sizeof(dataPacket);
if (rx) size = (((size + 1) / 2) * 2) + 2;
@@ -154,12 +202,65 @@ void MSG_ConfigureFSK(bool rx) {
BK4819_FskClearFifo();
// REG_59: clear flags, preamble len, sync len etc.
uint16_t fskParams = FSK_SYNC_LEN_BIT | ((rx ? 0U : 15U) << 4);
//uint16_t fskParams = FSK_SYNC_LEN_BIT | ((rx ? 0U : 15U) << 4);
uint16_t preamble_len = (gEeprom.FSKMode == MOD_AFSK_1200 || gEeprom.FSKMode == MOD_AFSK_2400 || gEeprom.FSKMode == MOD_NOAA_SAME) ? 10U : (rx ? 0U
: 15U);
uint16_t fskParams = FSK_SYNC_LEN_BIT | (preamble_len << 4);
if (gCurrentVfo->SCRAMBLING_TYPE > 0) fskParams |= FSK_SCRAMBLE_ENABLE;
BK4819_WriteRegister(BK4819_REG_59, fskParams);
// Clear interrupt flags
BK4819_WriteRegister(BK4819_REG_02, 0);
// Enable AF path filters for tone demodulation in AFSK/NOAA modes
if (gEeprom.FSKMode == MOD_AFSK_1200 ||
gEeprom.FSKMode == MOD_AFSK_2400 ||
gEeprom.FSKMode == MOD_NOAA_SAME) {
// Keep DC cancel, disable only deemphasis
BK4819_WriteRegister(BK4819_REG_2B,
(1U << 15) | (1U << 14) | (1U << 8));
} else {
BK4819_WriteRegister(BK4819_REG_2B, (1u << 2) | (1u << 0));
}
// set the FM deviation level
const uint16_t dev_val = BK4819_ReadRegister(BK4819_REG_40);
uint16_t deviation;
switch (gEeprom.FSKMode) {
case MOD_AFSK_1200:
case MOD_AFSK_2400:
case MOD_NOAA_SAME:
deviation = 650; // 0.65 kHz for audio-based tones (linear region)
break;
case MOD_FSK_450:
deviation = 225; // ≈ half of 450 Hz separation
break;
case MOD_FSK_700:
deviation = 350; // ≈ half of 700 Hz separation
break;
case MOD_FSK_1200:
deviation = 600; // halfway between 1200 and 2400 = 1.8 kHz spacing → ±900 Hz dev
break;
case MOD_FSK_2400:
deviation = 1200; // halfway between 1200 and 2400 = 1.8 kHz spacing → ±900 Hz dev
break;
default:
deviation = 750; // safe fallback
break;
}
BK4819_WriteRegister(BK4819_REG_40, (dev_val & 0xf000) | (deviation & 0x0fff));
// restore FM deviation level
//BK4819_WriteRegister(BK4819_REG_40, dev_val);
}
@@ -210,6 +311,9 @@ void processReceivedPacket(DataPacket *packet) {
itoa(packet->src, numBuf); // Convert number to string
strcat(String, numBuf);
MESSAGES_SAVE();
gRequestDisplayScreen = DISPLAY_MESSAGES;
GUI_SelectNextDisplay(gRequestDisplayScreen);
gActiveMessageBank = MESSAGES_COUNT / 3 - 1;
UI_DisplayPopup(String);
inBoundPacket.flags |= 0x40;
inBoundPacket.dest = inBoundPacket.src;
@@ -265,29 +369,7 @@ void MSG_FSKSendData(DataPacket *dataPacketIn) {
const uint16_t css_val = BK4819_ReadRegister(BK4819_REG_51);
BK4819_WriteRegister(BK4819_REG_51, 0);
// set the FM deviation level
const uint16_t dev_val = BK4819_ReadRegister(BK4819_REG_40);
{
uint16_t deviation;
switch (gEeprom.VfoInfo[gEeprom.TX_VFO].CHANNEL_BANDWIDTH) {
case BK4819_FILTER_BW_WIDE:
deviation = 1300;
break; // 20k // measurements by kamilsss655
case BK4819_FILTER_BW_NARROW:
deviation = 1200;
break; // 10k
// case BK4819_FILTER_BW_NARROWAVIATION: deviation = 850; break; // 5k
// case BK4819_FILTER_BW_NARROWER: deviation = 850; break; // 5k
// case BK4819_FILTER_BW_NARROWEST: deviation = 850; break; // 5k
default:
deviation = 850;
break; // 5k
}
//BK4819_WriteRegister(0x40, (3u << 12) | (deviation & 0xfff));
BK4819_WriteRegister(BK4819_REG_40, (dev_val & 0xf000) | (deviation & 0xfff));
}
// REG_2B 0
//
@@ -302,8 +384,20 @@ void MSG_FSKSendData(DataPacket *dataPacketIn) {
//
// disable the 300Hz HPF and FM pre-emphasis filter
//
const uint16_t filt_val = BK4819_ReadRegister(BK4819_REG_2B);
BK4819_WriteRegister(BK4819_REG_2B, (1u << 2) | (1u << 0));
// Enable AF path filters for tone demodulation in AFSK/NOAA modes
if (gEeprom.FSKMode == MOD_AFSK_1200 ||
gEeprom.FSKMode == MOD_AFSK_2400 ||
gEeprom.FSKMode == MOD_NOAA_SAME) {
// Keep DC cancel, disable only deemphasis
BK4819_WriteRegister(BK4819_REG_2B,
(1U << 15) | (1U << 14) | (1U << 8));
} else {
BK4819_WriteRegister(BK4819_REG_2B, (1u << 2) | (1u << 0));
}
MSG_ConfigureFSK(false);
@@ -343,9 +437,6 @@ void MSG_FSKSendData(DataPacket *dataPacketIn) {
// disable TX
MSG_ConfigureFSK(true);
// restore FM deviation level
BK4819_WriteRegister(BK4819_REG_40, dev_val);
// restore TX/RX filtering
BK4819_WriteRegister(BK4819_REG_2B, filt_val);
@@ -365,7 +456,8 @@ void MSG_FSKSendData(DataPacket *dataPacketIn) {
BK4819_ExitTxMute();
}
if (!(dataPacketIn->flags & 0x64)) {
//if (!(dataPacketIn->flags & 0x64)) {
if (!(dataPacketIn->flags & 0x40)) {
gGotACK = false;
}
BK4819_ToggleGpioOut(BK4819_GPIO5_PIN1_RED, false);
@@ -415,7 +507,7 @@ void FSK_HANDLE_IRQ(unsigned short irq) {
UART_Send((const void *) &ptr[gFSKWriteIndex - 1], 2);
}
SYSTEM_DelayMs(10);
SYSTEM_DelayMs(2);
}
if (rx_finished) {

View File

@@ -80,7 +80,7 @@
#define DataPacketDataSize (21)
#define SEQParameterEEPROM 0x1D00
#define SEQParameterEEPROM 0x1C00
typedef struct {
uint32_t dest; //4bytes

View File

@@ -198,16 +198,6 @@ void GENERIC_Key_PTT(bool bKeyPressed)
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;
#endif
// remember the DTMF string
gDTMF_PreviousIndex = gDTMF_InputBox_Index;
strcpy(gDTMF_String, gDTMF_InputBox);

View File

@@ -578,14 +578,6 @@ static void MAIN_Key_EXIT(bool bKeyPressed, bool bKeyHeld) {
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;
}
#endif
#ifdef ENABLE_FMRADIO
if (!gFmRadioMode)
@@ -680,6 +672,7 @@ static void MAIN_Key_MENU(bool bKeyPressed, bool bKeyHeld) {
if (gWasFKeyPressed && bKeyPressed) {
MESSAGES_GET();
gRequestDisplayScreen = DISPLAY_MESSAGES;
gActiveMessageBank = MESSAGES_COUNT / 3 - 1;
return;
}

View File

@@ -244,9 +244,7 @@ int MENU_GetLimits(uint8_t menu_id, int32_t *pMin, int32_t *pMax) {
case MENU_S_ADD3:
case MENU_STE:
case MENU_D_ST:
#ifdef ENABLE_DTMF_CALLING
case MENU_D_DCD:
#endif
case MENU_D_LIVE_DEC:
#ifdef ENABLE_NOAA
case MENU_NOAA_S:
@@ -315,12 +313,7 @@ int MENU_GetLimits(uint8_t menu_id, int32_t *pMin, int32_t *pMax) {
*pMax = 5;
break;
#ifdef ENABLE_DTMF_CALLING
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;
@@ -331,23 +324,12 @@ int MENU_GetLimits(uint8_t menu_id, int32_t *pMin, int32_t *pMax) {
*pMax = ARRAY_SIZE(gSubMenu_BAT_TXT) - 1;
break;
#ifdef ENABLE_DTMF_CALLING
case MENU_D_HOLD:
*pMin = 5;
*pMax = 60;
break;
#endif
case MENU_D_PRE:
*pMin = 3;
*pMax = 99;
break;
#ifdef ENABLE_DTMF_CALLING
case MENU_D_LIST:
*pMin = 1;
*pMax = 16;
break;
#endif
#ifdef ENABLE_F_CAL_MENU
case MENU_F_CALI:
*pMin = -50;
@@ -671,15 +653,6 @@ void MENU_AcceptSetting(void) {
gEeprom.DTMF_SIDE_TONE = gSubMenuSelection;
break;
#ifdef ENABLE_DTMF_CALLING
case MENU_D_RSP:
gEeprom.DTMF_DECODE_RESPONSE = 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;
@@ -693,13 +666,6 @@ void MENU_AcceptSetting(void) {
gSetting_battery_text = gSubMenuSelection;
break;
#ifdef ENABLE_DTMF_CALLING
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;
@@ -711,18 +677,6 @@ void MENU_AcceptSetting(void) {
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;
#endif
case MENU_FSKMOD:
gEeprom.FSKMode = gSubMenuSelection;
break;
@@ -1074,15 +1028,6 @@ void MENU_ShowCurrentSetting(void) {
gSubMenuSelection = gEeprom.DTMF_SIDE_TONE;
break;
#ifdef ENABLE_DTMF_CALLING
case MENU_D_RSP:
gSubMenuSelection = gEeprom.DTMF_DECODE_RESPONSE;
break;
case MENU_D_HOLD:
gSubMenuSelection = gEeprom.DTMF_auto_reset_time;
break;
#endif
case MENU_D_PRE:
gSubMenuSelection = gEeprom.DTMF_PRELOAD_TIME / 10;
break;
@@ -1095,15 +1040,6 @@ void MENU_ShowCurrentSetting(void) {
gSubMenuSelection = gSetting_battery_text;
return;
#ifdef ENABLE_DTMF_CALLING
case MENU_D_DCD:
gSubMenuSelection = gTxVfo->DTMF_DECODING_ENABLE;
break;
case MENU_D_LIST:
gSubMenuSelection = gDTMF_chosen_contact + 1;
break;
#endif
case MENU_D_LIVE_DEC:
gSubMenuSelection = gSetting_live_DTMF_decoder;
break;
@@ -1452,9 +1388,6 @@ static void MENU_Key_MENU(const bool bKeyPressed, const bool bKeyHeld) {
#endif
if (UI_MENU_GetCurrentMenuId() == MENU_UPCODE
|| UI_MENU_GetCurrentMenuId() == MENU_DWCODE
#ifdef ENABLE_DTMF_CALLING
|| UI_MENU_GetCurrentMenuId() == MENU_ANI_ID
#endif
)
return;
#if 1

View File

@@ -24,6 +24,7 @@ const char T9Table[10][T9Count] = {
uint8_t gActiveMessage = 0;
uint8_t gActiveMessageBank = 0;
StoredPacket loadedPacket;
@@ -82,30 +83,41 @@ void MESSAGES_TimeSlice500ms(void) {
void MESSAGES_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld) {
gKeyTimeout = 1;
if (gEnteringSMS != SMS_NOT_ENTERING && !bKeyHeld && Key <= KEY_9) {
if (!dataPTR || dataPTR < dataPacket.data) {
dataPTR = dataPacket.data;
if (gEnteringSMS != SMS_NOT_ENTERING && Key <= KEY_9) {
if (!bKeyHeld) {
if (!dataPTR || dataPTR < dataPacket.data) {
dataPTR = dataPacket.data;
}
}
if (gEnteringSMS == SMS_ENTERING_MESSAGE) {
if (bKeyPressed) {
if (prevKey != Key) {
dataPTR++;
if (dataPTR - dataPacket.data >= DataPacketDataSize) {
//if (dataPTR - dataPacket.data >= DataPacketDataSize) {
if (dataPTR - dataPacket.data >= 19) {
dataPTR = dataPacket.data;
}
prevLetter = 0;
}
*(dataPTR - 1) = T9Table[Key][(prevLetter++) % T9Count];
*(dataPTR - 1) = T9Table[Key][prevLetter];
if (!bKeyHeld) {
prevLetter++;
} else {
prevLetter--;
}
prevLetter = (prevLetter) % T9Count;
updatePrevChar(Key);
}
return;
} else if (gEnteringSMS == SMS_ENTERING_DEST) {
if (bKeyPressed) {
dataPacket.dest *= 10;
dataPacket.dest += Key;
prevLetter = 0;
if (!bKeyHeld) {
if (bKeyPressed) {
dataPacket.dest *= 10;
dataPacket.dest += Key;
prevLetter = 0;
}
return;
}
return;
}
}
@@ -143,8 +155,7 @@ void MESSAGES_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld) {
// second copy with MSB flipped (btn ^ 0x8) in the high nibble
out[4] = ((btn ^ 0x8) << 4);
}
else {
} else {
out[0] = (dataPacket.dest >> 8) & 0xFF;
out[1] = dataPacket.dest & 0xFF;
}
@@ -210,21 +221,43 @@ void MESSAGES_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld) {
}
break;
case KEY_UP:
if (bKeyPressed) {
gActiveMessage++;
if (gActiveMessage > MESSAGES_COUNT) {
gActiveMessage = 0;
if (gEnteringSMS != SMS_NOT_ENTERING) {
if (bKeyPressed) {
gActiveMessageBank++;
gActiveMessage = gActiveMessageBank * 3;
if (gActiveMessage > MESSAGES_COUNT) {
gActiveMessage = 0;
}
if (gActiveMessageBank >= MESSAGES_COUNT / 3) {
gActiveMessageBank = 0;
}
MESSAGES_GET();
}
} else if (gEnteringSMS == SMS_ENTERING_MESSAGE) {
dataPTR++;
//if (dataPTR - dataPacket.data >= DataPacketDataSize) {
if (dataPTR - dataPacket.data >= 19) {
dataPTR = dataPacket.data;
}
MESSAGES_GET();
}
break;
case KEY_DOWN:
if (bKeyPressed) {
gActiveMessage--;
if (gActiveMessage > MESSAGES_COUNT) {
gActiveMessage = MESSAGES_COUNT - 1;
if (gEnteringSMS != SMS_NOT_ENTERING) {
if (bKeyPressed) {
gActiveMessageBank--;
gActiveMessage = gActiveMessageBank * 3;
if (gActiveMessage >= MESSAGES_COUNT) {
gActiveMessage = MESSAGES_COUNT - 1;
}
if (gActiveMessageBank > MESSAGES_COUNT / 3) {
gActiveMessageBank = MESSAGES_COUNT / 3 - 1;
}
MESSAGES_GET();
}
} else if (gEnteringSMS == SMS_ENTERING_MESSAGE) {
if (dataPacket.data < dataPTR) {
dataPTR--;
}
MESSAGES_GET();
}
break;
case KEY_EXIT:

View File

@@ -8,8 +8,8 @@
#include "../driver/keyboard.h"
#include "../driver/eeprom.h"
#define MESSAGES_START (0x1D08)
#define MESSAGES_COUNT (6)
#define MESSAGES_START (0x1C08)
#define MESSAGES_COUNT (12)
typedef struct {
uint32_t src;
@@ -20,6 +20,7 @@ typedef struct {
} StoredPacket;
extern uint8_t gActiveMessage;
extern uint8_t gActiveMessageBank;
extern StoredPacket loadedPacket;

View File

@@ -347,9 +347,6 @@ void SCANNER_Start(bool singleFreq)
gUpdateStatus = true;
}
#ifdef ENABLE_DTMF_CALLING
DTMF_clear_RX();
#endif
gScanDelay_10ms = scan_delay_10ms;
gScanCssResultCode = 0xFF;

View File

@@ -418,9 +418,6 @@ static void CMD_052F(const uint8_t *pBuffer)
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;
#endif
#ifdef ENABLE_NOAA
gIsNoaaMode = false;