0
mirror of https://github.com/OneOfEleven/uv-k5-firmware-custom.git synced 2025-04-28 06:11:24 +03:00

1075 lines
28 KiB
C
Raw Normal View History

2023-09-09 08:03:56 +01:00
/* Copyright 2023 Dual Tachyon
* https://github.com/DualTachyon
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <string.h>
#include "app/dtmf.h"
2023-09-14 09:56:30 +01:00
#ifdef ENABLE_FMRADIO
#include "app/fm.h"
#endif
2023-09-09 08:03:56 +01:00
#include "audio.h"
#include "bsp/dp32g030/gpio.h"
#include "dcs.h"
#include "driver/bk4819.h"
#include "driver/eeprom.h"
#include "driver/gpio.h"
#include "driver/system.h"
#include "frequencies.h"
#include "functions.h"
#include "helper/battery.h"
#include "misc.h"
#include "radio.h"
#include "settings.h"
2023-09-28 23:32:08 +01:00
#include "ui/menu.h"
2023-09-09 08:03:56 +01:00
VFO_Info_t *gTxVfo;
VFO_Info_t *gRxVfo;
VFO_Info_t *gCurrentVfo;
DCS_CodeType_t gSelectedCodeType;
DCS_CodeType_t gCurrentCodeType;
uint8_t gSelectedCode;
STEP_Setting_t gStepSetting;
VfoState_t VfoState[2];
bool RADIO_CheckValidChannel(uint16_t Channel, bool bCheckScanList, uint8_t VFO)
{ // return true if the channel appears valid
2023-09-09 08:03:56 +01:00
uint8_t Attributes;
uint8_t PriorityCh1;
uint8_t PriorityCh2;
if (!IS_MR_CHANNEL(Channel))
return false;
Attributes = gMR_ChannelAttributes[Channel];
2023-09-09 08:03:56 +01:00
if ((Attributes & MR_CH_BAND_MASK) > BAND7_470MHz)
return false;
if (bCheckScanList)
{
switch (VFO)
{
case 0:
if ((Attributes & MR_CH_SCANLIST1) == 0)
return false;
PriorityCh1 = gEeprom.SCANLIST_PRIORITY_CH1[0];
PriorityCh2 = gEeprom.SCANLIST_PRIORITY_CH2[0];
break;
case 1:
if ((Attributes & MR_CH_SCANLIST2) == 0)
return false;
PriorityCh1 = gEeprom.SCANLIST_PRIORITY_CH1[1];
PriorityCh2 = gEeprom.SCANLIST_PRIORITY_CH2[1];
break;
default:
return true;
}
if (PriorityCh1 == Channel)
return false;
if (PriorityCh2 == Channel)
return false;
}
return true;
}
uint8_t RADIO_FindNextChannel(uint8_t Channel, int8_t Direction, bool bCheckScanList, uint8_t VFO)
{
unsigned int i;
2023-09-09 08:03:56 +01:00
for (i = 0; i <= MR_CHANNEL_LAST; i++)
2023-09-09 08:03:56 +01:00
{
if (Channel == 0xFF)
Channel = MR_CHANNEL_LAST;
else
if (Channel > MR_CHANNEL_LAST)
Channel = MR_CHANNEL_FIRST;
if (RADIO_CheckValidChannel(Channel, bCheckScanList, VFO))
return Channel;
Channel += Direction;
}
return 0xFF;
}
void RADIO_InitInfo(VFO_Info_t *pInfo, const uint8_t ChannelSave, const uint32_t Frequency)
2023-09-09 08:03:56 +01:00
{
memset(pInfo, 0, sizeof(*pInfo));
2023-09-12 21:08:51 +01:00
pInfo->Band = FREQUENCY_GetBand(Frequency);
pInfo->SCANLIST1_PARTICIPATION = true;
pInfo->SCANLIST2_PARTICIPATION = true;
pInfo->STEP_SETTING = STEP_12_5kHz;
pInfo->StepFrequency = StepFrequencyTable[pInfo->STEP_SETTING];
pInfo->CHANNEL_SAVE = ChannelSave;
pInfo->FrequencyReverse = false;
pInfo->OUTPUT_POWER = OUTPUT_POWER_LOW;
pInfo->freq_config_RX.Frequency = Frequency;
pInfo->freq_config_TX.Frequency = Frequency;
pInfo->pRX = &pInfo->freq_config_RX;
pInfo->pTX = &pInfo->freq_config_TX;
2023-10-04 16:37:11 +01:00
pInfo->Compander = 0; // off
2023-09-28 17:39:45 +01:00
2023-09-13 02:01:35 +01:00
if (ChannelSave == (FREQ_CHANNEL_FIRST + BAND2_108MHz))
2023-09-28 23:32:08 +01:00
pInfo->AM_mode = 1;
2023-09-13 02:01:35 +01:00
2023-09-09 08:03:56 +01:00
RADIO_ConfigureSquelchAndOutputPower(pInfo);
}
void RADIO_ConfigureChannel(const unsigned int VFO, const unsigned int configure)
2023-09-09 08:03:56 +01:00
{
uint8_t Channel;
uint8_t Attributes;
uint8_t Band;
bool bParticipation2;
uint16_t Base;
uint32_t Frequency;
VFO_Info_t *pRadio = &gEeprom.VfoInfo[VFO];
if (!gSetting_350EN)
{
if (gEeprom.FreqChannel[VFO] == (FREQ_CHANNEL_LAST - 2))
gEeprom.FreqChannel[VFO] = FREQ_CHANNEL_LAST - 1;
2023-09-09 08:03:56 +01:00
if (gEeprom.ScreenChannel[VFO] == (FREQ_CHANNEL_LAST - 2))
gEeprom.ScreenChannel[VFO] = FREQ_CHANNEL_LAST - 1;
2023-09-09 08:03:56 +01:00
}
Channel = gEeprom.ScreenChannel[VFO];
if (IS_VALID_CHANNEL(Channel))
{
2023-09-14 09:56:30 +01:00
#ifdef ENABLE_NOAA
2023-09-09 08:03:56 +01:00
if (Channel >= NOAA_CHANNEL_FIRST)
{
RADIO_InitInfo(pRadio, gEeprom.ScreenChannel[VFO], NoaaFrequencyTable[Channel - NOAA_CHANNEL_FIRST]);
2023-09-12 21:08:51 +01:00
2023-09-09 08:03:56 +01:00
if (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF)
return;
2023-09-12 21:08:51 +01:00
2023-09-09 08:03:56 +01:00
gEeprom.CROSS_BAND_RX_TX = CROSS_BAND_OFF;
gUpdateStatus = true;
2023-09-09 08:03:56 +01:00
return;
}
#endif
2023-09-12 21:08:51 +01:00
2023-09-09 08:03:56 +01:00
if (IS_MR_CHANNEL(Channel))
{
Channel = RADIO_FindNextChannel(Channel, RADIO_CHANNEL_UP, false, VFO);
if (Channel == 0xFF)
{
Channel = gEeprom.FreqChannel[VFO];
gEeprom.ScreenChannel[VFO] = gEeprom.FreqChannel[VFO];
}
else
{
gEeprom.ScreenChannel[VFO] = Channel;
gEeprom.MrChannel[VFO] = Channel;
}
}
}
else
Channel = FREQ_CHANNEL_LAST - 1;
2023-09-09 08:03:56 +01:00
Attributes = gMR_ChannelAttributes[Channel];
if (Attributes == 0xFF)
{ // invalid/unused channel
2023-09-09 08:03:56 +01:00
uint8_t Index;
if (IS_MR_CHANNEL(Channel))
{
2023-09-12 21:08:51 +01:00
Channel = gEeprom.FreqChannel[VFO];
2023-09-09 08:03:56 +01:00
gEeprom.ScreenChannel[VFO] = gEeprom.FreqChannel[VFO];
}
Index = Channel - FREQ_CHANNEL_FIRST;
2023-10-02 14:13:27 +01:00
RADIO_InitInfo(pRadio, Channel, frequencyBandTable[Index].lower);
2023-09-09 08:03:56 +01:00
return;
}
Band = Attributes & MR_CH_BAND_MASK;
if (Band > BAND7_470MHz)
{
2023-09-28 23:32:08 +01:00
Band = BAND6_400MHz;
}
2023-09-28 17:39:45 +01:00
2023-09-09 08:03:56 +01:00
if (IS_MR_CHANNEL(Channel))
{
gEeprom.VfoInfo[VFO].Band = Band;
gEeprom.VfoInfo[VFO].SCANLIST1_PARTICIPATION = !!(Attributes & MR_CH_SCANLIST1);
bParticipation2 = !!(Attributes & MR_CH_SCANLIST2);
}
else
{
Band = Channel - FREQ_CHANNEL_FIRST;
gEeprom.VfoInfo[VFO].Band = Band;
bParticipation2 = true;
gEeprom.VfoInfo[VFO].SCANLIST1_PARTICIPATION = true;
}
gEeprom.VfoInfo[VFO].SCANLIST2_PARTICIPATION = bParticipation2;
gEeprom.VfoInfo[VFO].CHANNEL_SAVE = Channel;
if (IS_MR_CHANNEL(Channel))
Base = Channel * 16;
else
Base = 0x0C80 + ((Channel - FREQ_CHANNEL_FIRST) * 32) + (VFO * 16);
if (configure == VFO_CONFIGURE_RELOAD || Channel >= FREQ_CHANNEL_FIRST)
2023-09-09 08:03:56 +01:00
{
2023-09-10 13:52:41 +01:00
uint8_t Tmp;
uint8_t Data[8];
2023-09-28 23:32:08 +01:00
// ***************
2023-09-10 13:52:41 +01:00
EEPROM_ReadBuffer(Base + 8, Data, sizeof(Data));
2023-09-09 08:03:56 +01:00
Tmp = Data[3] & 0x0F;
2023-09-28 23:32:08 +01:00
if (Tmp > TX_OFFSET_FREQUENCY_DIRECTION_SUB)
2023-09-09 08:03:56 +01:00
Tmp = 0;
2023-09-15 12:31:30 +01:00
gEeprom.VfoInfo[VFO].TX_OFFSET_FREQUENCY_DIRECTION = Tmp;
2023-09-28 23:32:08 +01:00
gEeprom.VfoInfo[VFO].AM_mode = (Data[3] >> 4) & 1u;
2023-09-09 08:03:56 +01:00
Tmp = Data[6];
2023-09-15 15:53:37 +01:00
if (Tmp >= ARRAY_SIZE(StepFrequencyTable))
Tmp = STEP_12_5kHz;
2023-09-09 08:03:56 +01:00
gEeprom.VfoInfo[VFO].STEP_SETTING = Tmp;
gEeprom.VfoInfo[VFO].StepFrequency = StepFrequencyTable[Tmp];
Tmp = Data[7];
2023-09-28 23:32:08 +01:00
if (Tmp > (ARRAY_SIZE(gSubMenu_SCRAMBLER) - 1))
2023-09-09 08:03:56 +01:00
Tmp = 0;
2023-09-10 13:52:41 +01:00
gEeprom.VfoInfo[VFO].SCRAMBLING_TYPE = Tmp;
2023-09-09 08:03:56 +01:00
2023-09-25 18:08:21 +01:00
gEeprom.VfoInfo[VFO].freq_config_RX.CodeType = (Data[2] >> 0) & 0x0F;
gEeprom.VfoInfo[VFO].freq_config_TX.CodeType = (Data[2] >> 4) & 0x0F;
2023-09-09 08:03:56 +01:00
Tmp = Data[0];
2023-09-25 18:08:21 +01:00
switch (gEeprom.VfoInfo[VFO].freq_config_RX.CodeType)
2023-09-09 08:03:56 +01:00
{
2023-09-12 11:01:34 +01:00
default:
case CODE_TYPE_OFF:
2023-09-25 18:08:21 +01:00
gEeprom.VfoInfo[VFO].freq_config_RX.CodeType = CODE_TYPE_OFF;
2023-09-12 11:01:34 +01:00
Tmp = 0;
break;
2023-09-09 08:03:56 +01:00
case CODE_TYPE_CONTINUOUS_TONE:
2023-09-28 23:32:08 +01:00
if (Tmp > (ARRAY_SIZE(CTCSS_Options) - 1))
2023-09-09 08:03:56 +01:00
Tmp = 0;
break;
case CODE_TYPE_DIGITAL:
case CODE_TYPE_REVERSE_DIGITAL:
2023-09-28 23:32:08 +01:00
if (Tmp > (ARRAY_SIZE(DCS_Options) - 1))
2023-09-09 08:03:56 +01:00
Tmp = 0;
break;
}
2023-09-25 18:08:21 +01:00
gEeprom.VfoInfo[VFO].freq_config_RX.Code = Tmp;
2023-09-09 08:03:56 +01:00
Tmp = Data[1];
2023-09-25 18:08:21 +01:00
switch (gEeprom.VfoInfo[VFO].freq_config_TX.CodeType)
2023-09-09 08:03:56 +01:00
{
2023-09-12 21:08:51 +01:00
default:
case CODE_TYPE_OFF:
2023-09-25 18:08:21 +01:00
gEeprom.VfoInfo[VFO].freq_config_TX.CodeType = CODE_TYPE_OFF;
2023-09-12 21:08:51 +01:00
Tmp = 0;
break;
2023-09-09 08:03:56 +01:00
case CODE_TYPE_CONTINUOUS_TONE:
2023-09-28 23:32:08 +01:00
if (Tmp > (ARRAY_SIZE(CTCSS_Options) - 1))
2023-09-09 08:03:56 +01:00
Tmp = 0;
break;
case CODE_TYPE_DIGITAL:
case CODE_TYPE_REVERSE_DIGITAL:
2023-09-28 23:32:08 +01:00
if (Tmp > (ARRAY_SIZE(DCS_Options) - 1))
2023-09-09 08:03:56 +01:00
Tmp = 0;
break;
}
2023-09-25 18:08:21 +01:00
gEeprom.VfoInfo[VFO].freq_config_TX.Code = Tmp;
2023-09-09 08:03:56 +01:00
if (Data[4] == 0xFF)
{
gEeprom.VfoInfo[VFO].FrequencyReverse = false;
2023-09-18 00:48:40 +01:00
gEeprom.VfoInfo[VFO].CHANNEL_BANDWIDTH = BK4819_FILTER_BW_WIDE;
2023-09-15 10:57:26 +01:00
gEeprom.VfoInfo[VFO].OUTPUT_POWER = OUTPUT_POWER_LOW;
2023-09-09 08:03:56 +01:00
gEeprom.VfoInfo[VFO].BUSY_CHANNEL_LOCK = false;
}
else
{
2023-09-10 13:52:41 +01:00
const uint8_t d4 = Data[4];
2023-09-15 12:31:30 +01:00
gEeprom.VfoInfo[VFO].FrequencyReverse = !!((d4 >> 0) & 1u);
gEeprom.VfoInfo[VFO].CHANNEL_BANDWIDTH = !!((d4 >> 1) & 1u);
gEeprom.VfoInfo[VFO].OUTPUT_POWER = ((d4 >> 2) & 3u);
gEeprom.VfoInfo[VFO].BUSY_CHANNEL_LOCK = !!((d4 >> 4) & 1u);
2023-09-09 08:03:56 +01:00
}
if (Data[5] == 0xFF)
{
gEeprom.VfoInfo[VFO].DTMF_DECODING_ENABLE = false;
gEeprom.VfoInfo[VFO].DTMF_PTT_ID_TX_MODE = 0;
}
else
{
2023-09-15 12:31:30 +01:00
gEeprom.VfoInfo[VFO].DTMF_DECODING_ENABLE = !!((Data[5] >> 0) & 1u);
gEeprom.VfoInfo[VFO].DTMF_PTT_ID_TX_MODE = ((Data[5] >> 1) & 3u);
2023-09-09 08:03:56 +01:00
}
2023-09-28 23:32:08 +01:00
// ***************
2023-09-09 08:03:56 +01:00
struct
{
uint32_t Frequency;
uint32_t Offset;
2023-09-10 13:52:41 +01:00
} __attribute__((packed)) Info;
2023-09-09 08:03:56 +01:00
2023-09-10 13:52:41 +01:00
EEPROM_ReadBuffer(Base, &Info, sizeof(Info));
2023-09-25 18:08:21 +01:00
pRadio->freq_config_RX.Frequency = Info.Frequency;
2023-09-09 08:03:56 +01:00
if (Info.Offset >= 100000000)
Info.Offset = 1000000;
2023-09-15 12:31:30 +01:00
gEeprom.VfoInfo[VFO].TX_OFFSET_FREQUENCY = Info.Offset;
2023-09-28 23:32:08 +01:00
// ***************
2023-09-09 08:03:56 +01:00
}
2023-09-25 18:08:21 +01:00
Frequency = pRadio->freq_config_RX.Frequency;
2023-09-10 13:52:41 +01:00
2023-09-17 11:06:42 +01:00
#if 1
// fix previously set incorrect band
Band = FREQUENCY_GetBand(Frequency);
#endif
2023-10-02 14:13:27 +01:00
if (Frequency < frequencyBandTable[Band].lower)
Frequency = frequencyBandTable[Band].lower;
2023-09-09 08:03:56 +01:00
else
if (Frequency > frequencyBandTable[Band].upper)
Frequency = frequencyBandTable[Band].upper;
2023-09-09 08:03:56 +01:00
else
if (Channel >= FREQ_CHANNEL_FIRST)
2023-10-02 14:13:27 +01:00
Frequency = FREQUENCY_FloorToStep(Frequency, gEeprom.VfoInfo[VFO].StepFrequency, frequencyBandTable[Band].lower);
2023-09-25 18:08:21 +01:00
pRadio->freq_config_RX.Frequency = Frequency;
2023-09-09 08:03:56 +01:00
if (Frequency >= 10800000 && Frequency < 13600000)
2023-09-15 12:31:30 +01:00
gEeprom.VfoInfo[VFO].TX_OFFSET_FREQUENCY_DIRECTION = TX_OFFSET_FREQUENCY_DIRECTION_OFF;
2023-09-09 08:03:56 +01:00
else
if (!IS_MR_CHANNEL(Channel))
2023-09-15 12:31:30 +01:00
gEeprom.VfoInfo[VFO].TX_OFFSET_FREQUENCY = FREQUENCY_FloorToStep(gEeprom.VfoInfo[VFO].TX_OFFSET_FREQUENCY, gEeprom.VfoInfo[VFO].StepFrequency, 0);
2023-09-09 08:03:56 +01:00
RADIO_ApplyOffset(pRadio);
memset(gEeprom.VfoInfo[VFO].Name, 0, sizeof(gEeprom.VfoInfo[VFO].Name));
if (IS_MR_CHANNEL(Channel))
2023-09-28 23:42:57 +01:00
{ // 16 bytes allocated to the channel name but only 10 used, the rest are 0's
2023-09-09 08:03:56 +01:00
EEPROM_ReadBuffer(0x0F50 + (Channel * 16), gEeprom.VfoInfo[VFO].Name + 0, 8);
EEPROM_ReadBuffer(0x0F58 + (Channel * 16), gEeprom.VfoInfo[VFO].Name + 8, 2);
}
if (!gEeprom.VfoInfo[VFO].FrequencyReverse)
{
2023-09-25 18:08:21 +01:00
gEeprom.VfoInfo[VFO].pRX = &gEeprom.VfoInfo[VFO].freq_config_RX;
gEeprom.VfoInfo[VFO].pTX = &gEeprom.VfoInfo[VFO].freq_config_TX;
2023-09-09 08:03:56 +01:00
}
else
{
2023-09-25 18:08:21 +01:00
gEeprom.VfoInfo[VFO].pRX = &gEeprom.VfoInfo[VFO].freq_config_TX;
gEeprom.VfoInfo[VFO].pTX = &gEeprom.VfoInfo[VFO].freq_config_RX;
2023-09-09 08:03:56 +01:00
}
if (!gSetting_350EN)
{
FREQ_Config_t *pConfig = gEeprom.VfoInfo[VFO].pRX;
2023-09-12 21:08:51 +01:00
if (pConfig->Frequency >= 35000000 && pConfig->Frequency < 40000000)
pConfig->Frequency = 43300000;
2023-09-09 08:03:56 +01:00
}
2023-09-28 23:32:08 +01:00
if (gEeprom.VfoInfo[VFO].AM_mode)
{ // freq/chan is in AM mode
gEeprom.VfoInfo[VFO].SCRAMBLING_TYPE = 0;
2023-09-29 15:22:41 +01:00
// gEeprom.VfoInfo[VFO].DTMF_DECODING_ENABLE = false; // no reason to disable DTMF decoding, aircraft use it on SSB
2023-09-28 23:32:08 +01:00
gEeprom.VfoInfo[VFO].freq_config_RX.CodeType = CODE_TYPE_OFF;
gEeprom.VfoInfo[VFO].freq_config_TX.CodeType = CODE_TYPE_OFF;
2023-09-09 08:03:56 +01:00
}
2023-10-04 16:37:11 +01:00
gEeprom.VfoInfo[VFO].Compander = (Attributes & MR_CH_COMPAND) >> 4;
2023-09-15 10:57:26 +01:00
2023-09-09 08:03:56 +01:00
RADIO_ConfigureSquelchAndOutputPower(pRadio);
}
void RADIO_ConfigureSquelchAndOutputPower(VFO_Info_t *pInfo)
{
uint8_t Txp[3];
FREQUENCY_Band_t Band = FREQUENCY_GetBand(pInfo->pRX->Frequency);
uint16_t Base = (Band < BAND4_174MHz) ? 0x1E60 : 0x1E00;
if (gEeprom.SQUELCH_LEVEL == 0)
{ // squelch == 0 (off)
2023-09-22 19:48:17 +01:00
pInfo->SquelchOpenRSSIThresh = 0;
pInfo->SquelchOpenNoiseThresh = 127;
pInfo->SquelchCloseGlitchThresh = 255;
2023-09-21 23:06:47 +01:00
2023-09-22 19:48:17 +01:00
pInfo->SquelchCloseRSSIThresh = 0;
pInfo->SquelchCloseNoiseThresh = 127;
pInfo->SquelchOpenGlitchThresh = 255;
2023-09-09 08:03:56 +01:00
}
else
{ // squelch >= 1
Base += gEeprom.SQUELCH_LEVEL; // my squelch-1
2023-09-22 19:48:17 +01:00
// VHF UHF
EEPROM_ReadBuffer(Base + 0x00, &pInfo->SquelchOpenRSSIThresh, 1); // 50 10
EEPROM_ReadBuffer(Base + 0x10, &pInfo->SquelchCloseRSSIThresh, 1); // 40 5
2023-09-21 23:06:47 +01:00
2023-09-22 19:48:17 +01:00
EEPROM_ReadBuffer(Base + 0x20, &pInfo->SquelchOpenNoiseThresh, 1); // 65 90
EEPROM_ReadBuffer(Base + 0x30, &pInfo->SquelchCloseNoiseThresh, 1); // 70 100
2023-09-21 23:06:47 +01:00
2023-09-22 19:48:17 +01:00
EEPROM_ReadBuffer(Base + 0x40, &pInfo->SquelchCloseGlitchThresh, 1); // 90 90
EEPROM_ReadBuffer(Base + 0x50, &pInfo->SquelchOpenGlitchThresh, 1); // 100 100
2023-09-09 08:03:56 +01:00
#if ENABLE_SQUELCH_MORE_SENSITIVE
// make squelch a little more sensitive
//
// getting the best setting here is still experimental, bare with me
//
// note that 'noise' and 'glitch' values are inverted compared to 'rssi' values
2023-10-01 00:30:13 +01:00
pInfo->SquelchOpenRSSIThresh = ((uint16_t)pInfo->SquelchOpenRSSIThresh * 8) / 9;
pInfo->SquelchCloseRSSIThresh = ((uint16_t)pInfo->SquelchOpenRSSIThresh * 8) / 9;
pInfo->SquelchOpenNoiseThresh = ((uint16_t)pInfo->SquelchOpenNoiseThresh * 9) / 8;
pInfo->SquelchCloseNoiseThresh = ((uint16_t)pInfo->SquelchOpenNoiseThresh * 9) / 8;
pInfo->SquelchOpenGlitchThresh = ((uint16_t)pInfo->SquelchOpenGlitchThresh * 9) / 8;
pInfo->SquelchCloseGlitchThresh = ((uint16_t)pInfo->SquelchOpenGlitchThresh * 9) / 8;
2023-09-22 19:48:17 +01:00
#endif
2023-09-28 17:39:45 +01:00
2023-09-12 21:08:51 +01:00
if (pInfo->SquelchOpenNoiseThresh > 127)
pInfo->SquelchOpenNoiseThresh = 127;
2023-09-12 21:08:51 +01:00
if (pInfo->SquelchCloseNoiseThresh > 127)
pInfo->SquelchCloseNoiseThresh = 127;
2023-09-09 08:03:56 +01:00
}
Band = FREQUENCY_GetBand(pInfo->pTX->Frequency);
EEPROM_ReadBuffer(0x1ED0 + (Band * 16) + (pInfo->OUTPUT_POWER * 3), Txp, 3);
pInfo->TXP_CalculatedSetting = FREQUENCY_CalculateOutputPower(
Txp[0],
Txp[1],
Txp[2],
2023-10-02 14:13:27 +01:00
frequencyBandTable[Band].lower,
(frequencyBandTable[Band].lower + frequencyBandTable[Band].upper) / 2,
frequencyBandTable[Band].upper,
pInfo->pTX->Frequency);
2023-09-09 08:03:56 +01:00
}
void RADIO_ApplyOffset(VFO_Info_t *pInfo)
{
2023-09-25 18:08:21 +01:00
uint32_t Frequency = pInfo->freq_config_RX.Frequency;
2023-09-09 08:03:56 +01:00
2023-09-15 12:31:30 +01:00
switch (pInfo->TX_OFFSET_FREQUENCY_DIRECTION)
2023-09-09 08:03:56 +01:00
{
2023-09-15 12:31:30 +01:00
case TX_OFFSET_FREQUENCY_DIRECTION_OFF:
2023-09-09 08:03:56 +01:00
break;
2023-09-15 12:31:30 +01:00
case TX_OFFSET_FREQUENCY_DIRECTION_ADD:
Frequency += pInfo->TX_OFFSET_FREQUENCY;
2023-09-09 08:03:56 +01:00
break;
2023-09-15 12:31:30 +01:00
case TX_OFFSET_FREQUENCY_DIRECTION_SUB:
Frequency -= pInfo->TX_OFFSET_FREQUENCY;
2023-09-09 08:03:56 +01:00
break;
}
2023-10-02 14:13:27 +01:00
if (Frequency < frequencyBandTable[0].lower)
Frequency = frequencyBandTable[0].lower;
else
if (Frequency > frequencyBandTable[ARRAY_SIZE(frequencyBandTable) - 1].upper)
Frequency = frequencyBandTable[ARRAY_SIZE(frequencyBandTable) - 1].upper;
2023-09-28 17:39:45 +01:00
2023-09-25 18:08:21 +01:00
pInfo->freq_config_TX.Frequency = Frequency;
2023-09-09 08:03:56 +01:00
}
static void RADIO_SelectCurrentVfo(void)
{
gCurrentVfo = (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF) ? gRxVfo : &gEeprom.VfoInfo[gEeprom.TX_VFO];
2023-09-09 08:03:56 +01:00
}
void RADIO_SelectVfos(void)
{
if (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_CHAN_B)
gEeprom.TX_VFO = 1;
2023-09-09 08:03:56 +01:00
else
if (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_CHAN_A)
gEeprom.TX_VFO = 0;
2023-09-09 08:03:56 +01:00
else
if (gEeprom.DUAL_WATCH == DUAL_WATCH_CHAN_B)
gEeprom.TX_VFO = 1;
2023-09-09 08:03:56 +01:00
else
if (gEeprom.DUAL_WATCH == DUAL_WATCH_CHAN_A)
gEeprom.TX_VFO = 0;
2023-09-09 08:03:56 +01:00
if (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF)
gEeprom.RX_VFO = gEeprom.TX_VFO;
2023-09-09 08:03:56 +01:00
else
gEeprom.RX_VFO = (gEeprom.TX_VFO == 0) ? 1 : 0;
2023-09-09 08:03:56 +01:00
gTxVfo = &gEeprom.VfoInfo[gEeprom.TX_VFO];
gRxVfo = &gEeprom.VfoInfo[gEeprom.RX_VFO];
2023-09-09 08:03:56 +01:00
RADIO_SelectCurrentVfo();
}
void RADIO_SetupRegisters(bool bSwitchToFunction0)
{
2023-10-03 00:14:36 +01:00
BK4819_FilterBandwidth_t Bandwidth = gRxVfo->CHANNEL_BANDWIDTH;
2023-09-09 08:03:56 +01:00
uint16_t InterruptMask;
uint32_t Frequency;
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
2023-09-10 13:52:41 +01:00
2023-09-09 08:03:56 +01:00
gEnableSpeaker = false;
BK4819_ToggleGpioOut(BK4819_GPIO0_PIN28_GREEN, false);
2023-09-18 00:48:40 +01:00
switch (Bandwidth)
{
default:
Bandwidth = BK4819_FILTER_BW_WIDE;
case BK4819_FILTER_BW_WIDE:
case BK4819_FILTER_BW_NARROW:
2023-09-22 16:14:37 +01:00
#ifdef ENABLE_AM_FIX
// BK4819_SetFilterBandwidth(Bandwidth, gRxVfo->AM_mode && gSetting_AM_fix);
BK4819_SetFilterBandwidth(Bandwidth, true);
2023-09-22 16:14:37 +01:00
#else
BK4819_SetFilterBandwidth(Bandwidth, false);
#endif
2023-09-18 00:48:40 +01:00
break;
}
2023-09-28 17:39:45 +01:00
2023-09-09 08:03:56 +01:00
BK4819_ToggleGpioOut(BK4819_GPIO1_PIN29_RED, false);
2023-09-10 13:52:41 +01:00
2023-09-09 08:03:56 +01:00
BK4819_SetupPowerAmplifier(0, 0);
2023-09-10 13:52:41 +01:00
2023-09-09 08:03:56 +01:00
BK4819_ToggleGpioOut(BK4819_GPIO5_PIN1, false);
while (1)
{
2023-09-10 13:52:41 +01:00
const uint16_t Status = BK4819_ReadRegister(BK4819_REG_0C);
if ((Status & 1u) == 0) // INTERRUPT REQUEST
2023-09-09 08:03:56 +01:00
break;
BK4819_WriteRegister(BK4819_REG_02, 0);
SYSTEM_DelayMs(1);
}
BK4819_WriteRegister(BK4819_REG_3F, 0);
// mic gain 0.5dB/step 0 to 31
BK4819_WriteRegister(BK4819_REG_7D, 0xE940 | (gEeprom.MIC_SENSITIVITY_TUNING & 0x1f));
2023-09-14 09:56:30 +01:00
#ifdef ENABLE_NOAA
2023-09-09 08:03:56 +01:00
if (IS_NOT_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE) || !gIsNoaaMode)
Frequency = gRxVfo->pRX->Frequency;
else
Frequency = NoaaFrequencyTable[gNoaaChannel];
#else
Frequency = gRxVfo->pRX->Frequency;
#endif
BK4819_SetFrequency(Frequency);
BK4819_SetupSquelch(
2023-09-16 07:08:18 +01:00
gRxVfo->SquelchOpenRSSIThresh, gRxVfo->SquelchCloseRSSIThresh,
gRxVfo->SquelchOpenNoiseThresh, gRxVfo->SquelchCloseNoiseThresh,
gRxVfo->SquelchCloseGlitchThresh, gRxVfo->SquelchOpenGlitchThresh);
2023-09-10 13:52:41 +01:00
2023-09-09 08:03:56 +01:00
BK4819_PickRXFilterPathBasedOnFrequency(Frequency);
2023-09-10 13:52:41 +01:00
2023-10-03 00:14:36 +01:00
// what does this in do ?
2023-09-09 08:03:56 +01:00
BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2, true);
2023-09-10 13:52:41 +01:00
2023-09-17 11:06:42 +01:00
// AF RX Gain and DAC
2023-09-16 07:08:18 +01:00
BK4819_WriteRegister(BK4819_REG_48, 0xB3A8); // 1011 00 111010 1000
2023-09-09 08:03:56 +01:00
2023-09-16 07:08:18 +01:00
InterruptMask = BK4819_REG_3F_SQUELCH_FOUND | BK4819_REG_3F_SQUELCH_LOST;
2023-09-09 08:03:56 +01:00
2023-09-14 09:56:30 +01:00
#ifdef ENABLE_NOAA
2023-09-09 08:03:56 +01:00
if (IS_NOT_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE))
#endif
{
2023-09-28 23:32:08 +01:00
if (gRxVfo->AM_mode == 0)
{ // FM
2023-09-10 13:52:41 +01:00
uint8_t CodeType = gSelectedCodeType;
uint8_t Code = gSelectedCode;
2023-09-09 08:03:56 +01:00
if (gCssScanMode == CSS_SCAN_MODE_OFF)
{
CodeType = gRxVfo->pRX->CodeType;
Code = gRxVfo->pRX->Code;
}
switch (CodeType)
{
2023-09-12 11:01:34 +01:00
default:
case CODE_TYPE_OFF:
BK4819_SetCTCSSFrequency(670);
2023-09-28 17:39:45 +01:00
2023-09-14 12:02:47 +01:00
//#ifndef ENABLE_CTCSS_TAIL_PHASE_SHIFT
2023-09-14 11:16:45 +01:00
BK4819_SetTailDetection(550); // QS's 55Hz tone method
//#else
// BK4819_SetTailDetection(670); // 67Hz
//#endif
InterruptMask = BK4819_REG_3F_CxCSS_TAIL | BK4819_REG_3F_SQUELCH_FOUND | BK4819_REG_3F_SQUELCH_LOST;
2023-09-12 11:01:34 +01:00
break;
2023-09-12 21:08:51 +01:00
2023-09-14 11:16:45 +01:00
case CODE_TYPE_CONTINUOUS_TONE:
BK4819_SetCTCSSFrequency(CTCSS_Options[Code]);
2023-09-14 12:02:47 +01:00
//#ifndef ENABLE_CTCSS_TAIL_PHASE_SHIFT
2023-09-14 11:16:45 +01:00
BK4819_SetTailDetection(550); // QS's 55Hz tone method
//#else
// BK4819_SetTailDetection(CTCSS_Options[Code]);
//#endif
2023-09-09 08:03:56 +01:00
InterruptMask = 0
| BK4819_REG_3F_CxCSS_TAIL
2023-09-14 11:16:45 +01:00
| BK4819_REG_3F_CTCSS_FOUND
| BK4819_REG_3F_CTCSS_LOST
2023-09-09 08:03:56 +01:00
| BK4819_REG_3F_SQUELCH_FOUND
| BK4819_REG_3F_SQUELCH_LOST;
2023-09-28 17:39:45 +01:00
2023-09-09 08:03:56 +01:00
break;
2023-09-14 11:16:45 +01:00
case CODE_TYPE_DIGITAL:
case CODE_TYPE_REVERSE_DIGITAL:
BK4819_SetCDCSSCodeWord(DCS_GetGolayCodeWord(CodeType, Code));
2023-09-09 08:03:56 +01:00
InterruptMask = 0
| BK4819_REG_3F_CxCSS_TAIL
2023-09-14 11:16:45 +01:00
| BK4819_REG_3F_CDCSS_FOUND
| BK4819_REG_3F_CDCSS_LOST
2023-09-09 08:03:56 +01:00
| BK4819_REG_3F_SQUELCH_FOUND
| BK4819_REG_3F_SQUELCH_LOST;
break;
}
2023-09-17 09:54:24 +01:00
if (gRxVfo->SCRAMBLING_TYPE > 0 && gSetting_ScrambleEnable)
2023-09-09 08:03:56 +01:00
BK4819_EnableScramble(gRxVfo->SCRAMBLING_TYPE - 1);
2023-09-17 09:54:24 +01:00
else
BK4819_DisableScramble();
2023-09-09 08:03:56 +01:00
}
}
2023-09-14 09:56:30 +01:00
#ifdef ENABLE_NOAA
2023-09-09 08:03:56 +01:00
else
{
BK4819_SetCTCSSFrequency(2625);
InterruptMask = 0
| BK4819_REG_3F_CTCSS_FOUND
| BK4819_REG_3F_CTCSS_LOST
| BK4819_REG_3F_SQUELCH_FOUND
| BK4819_REG_3F_SQUELCH_LOST;
}
#endif
2023-09-12 21:08:51 +01:00
#ifdef ENABLE_VOX
#ifdef ENABLE_NOAA
#ifdef ENABLE_FMRADIO
if (gEeprom.VOX_SWITCH && !gFmRadioMode && IS_NOT_NOAA_CHANNEL(gCurrentVfo->CHANNEL_SAVE) && gCurrentVfo->AM_mode == 0)
#else
if (gEeprom.VOX_SWITCH && IS_NOT_NOAA_CHANNEL(gCurrentVfo->CHANNEL_SAVE) && gCurrentVfo->AM_mode == 0)
#endif
2023-09-14 09:56:30 +01:00
#else
#ifdef ENABLE_FMRADIO
if (gEeprom.VOX_SWITCH && !gFmRadioMode && gCurrentVfo->AM_mode == 0)
#else
if (gEeprom.VOX_SWITCH && gCurrentVfo->AM_mode == 0)
#endif
2023-09-14 09:56:30 +01:00
#endif
{
BK4819_EnableVox(gEeprom.VOX1_THRESHOLD, gEeprom.VOX0_THRESHOLD);
InterruptMask |= BK4819_REG_3F_VOX_FOUND | BK4819_REG_3F_VOX_LOST;
}
else
2023-09-09 08:03:56 +01:00
#endif
BK4819_DisableVox();
2023-10-04 16:37:11 +01:00
// RX expander
BK4819_SetCompander((gRxVfo->AM_mode == 0 && gRxVfo->Compander >= 2) ? gRxVfo->Compander : 0);
2023-09-15 10:57:26 +01:00
#if 0
2023-09-29 15:22:41 +01:00
if (!gRxVfo->DTMF_DECODING_ENABLE && !gSetting_KILLED)
2023-09-16 23:08:57 +01:00
{
BK4819_DisableDTMF();
}
else
2023-09-17 09:54:24 +01:00
{
BK4819_EnableDTMF();
InterruptMask |= BK4819_REG_3F_DTMF_5TONE_FOUND;
}
#else
2023-09-30 11:22:19 +01:00
if (gCurrentFunction != FUNCTION_TRANSMIT)
2023-09-17 09:54:24 +01:00
{
BK4819_DisableDTMF();
2023-09-17 09:54:24 +01:00
BK4819_EnableDTMF();
InterruptMask |= BK4819_REG_3F_DTMF_5TONE_FOUND;
}
2023-09-25 21:24:50 +01:00
else
{
BK4819_DisableDTMF();
}
2023-09-16 23:08:57 +01:00
#endif
2023-09-10 13:52:41 +01:00
2023-09-17 09:54:24 +01:00
// enable/disable BK4819 selected interrupts
2023-09-09 08:03:56 +01:00
BK4819_WriteRegister(BK4819_REG_3F, InterruptMask);
FUNCTION_Init();
if (bSwitchToFunction0)
FUNCTION_Select(FUNCTION_FOREGROUND);
}
2023-09-14 09:56:30 +01:00
#ifdef ENABLE_NOAA
2023-09-09 08:03:56 +01:00
void RADIO_ConfigureNOAA(void)
{
uint8_t ChanAB;
2023-09-12 21:08:51 +01:00
2023-09-09 08:03:56 +01:00
gUpdateStatus = true;
2023-09-12 21:08:51 +01:00
2023-09-09 08:03:56 +01:00
if (gEeprom.NOAA_AUTO_SCAN)
{
if (gEeprom.DUAL_WATCH != DUAL_WATCH_OFF)
{
if (IS_NOT_NOAA_CHANNEL(gEeprom.ScreenChannel[0]))
{
if (IS_NOT_NOAA_CHANNEL(gEeprom.ScreenChannel[1]))
{
gIsNoaaMode = false;
return;
}
ChanAB = 1;
}
else
ChanAB = 0;
2023-09-12 21:08:51 +01:00
2023-09-09 08:03:56 +01:00
if (!gIsNoaaMode)
gNoaaChannel = gEeprom.VfoInfo[ChanAB].CHANNEL_SAVE - NOAA_CHANNEL_FIRST;
2023-09-12 21:08:51 +01:00
2023-09-09 08:03:56 +01:00
gIsNoaaMode = true;
return;
}
2023-09-12 21:08:51 +01:00
2023-09-09 08:03:56 +01:00
if (gRxVfo->CHANNEL_SAVE >= NOAA_CHANNEL_FIRST)
{
gIsNoaaMode = true;
gNoaaChannel = gRxVfo->CHANNEL_SAVE - NOAA_CHANNEL_FIRST;
2023-09-25 13:27:52 +01:00
gNOAA_Countdown_10ms = NOAA_countdown_2_10ms;
gScheduleNOAA = false;
2023-09-09 08:03:56 +01:00
}
else
gIsNoaaMode = false;
}
else
gIsNoaaMode = false;
}
#endif
void RADIO_SetTxParameters(void)
{
2023-10-02 14:13:27 +01:00
BK4819_FilterBandwidth_t Bandwidth = gCurrentVfo->CHANNEL_BANDWIDTH;
2023-09-09 08:03:56 +01:00
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
gEnableSpeaker = false;
BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2, false);
2023-09-18 00:48:40 +01:00
switch (Bandwidth)
{
default:
Bandwidth = BK4819_FILTER_BW_WIDE;
case BK4819_FILTER_BW_WIDE:
case BK4819_FILTER_BW_NARROW:
2023-09-22 16:14:37 +01:00
#ifdef ENABLE_AM_FIX
// BK4819_SetFilterBandwidth(Bandwidth, gCurrentVfo->AM_mode && gSetting_AM_fix);
BK4819_SetFilterBandwidth(Bandwidth, true);
2023-09-22 16:14:37 +01:00
#else
BK4819_SetFilterBandwidth(Bandwidth, false);
#endif
2023-09-18 00:48:40 +01:00
break;
}
2023-09-09 08:03:56 +01:00
BK4819_SetFrequency(gCurrentVfo->pTX->Frequency);
2023-10-04 16:37:11 +01:00
// TX compressor
BK4819_SetCompander((gRxVfo->AM_mode == 0 && (gRxVfo->Compander == 1 || gRxVfo->Compander >= 3)) ? gRxVfo->Compander : 0);
2023-09-15 10:57:26 +01:00
2023-09-09 08:03:56 +01:00
BK4819_PrepareTransmit();
SYSTEM_DelayMs(10);
BK4819_PickRXFilterPathBasedOnFrequency(gCurrentVfo->pTX->Frequency);
BK4819_ToggleGpioOut(BK4819_GPIO5_PIN1, true);
SYSTEM_DelayMs(5);
BK4819_SetupPowerAmplifier(gCurrentVfo->TXP_CalculatedSetting, gCurrentVfo->pTX->Frequency);
SYSTEM_DelayMs(10);
switch (gCurrentVfo->pTX->CodeType)
{
2023-09-11 00:02:57 +01:00
default:
case CODE_TYPE_OFF:
BK4819_ExitSubAu();
break;
2023-09-09 08:03:56 +01:00
case CODE_TYPE_CONTINUOUS_TONE:
BK4819_SetCTCSSFrequency(CTCSS_Options[gCurrentVfo->pTX->Code]);
break;
case CODE_TYPE_DIGITAL:
case CODE_TYPE_REVERSE_DIGITAL:
2023-10-02 14:13:27 +01:00
BK4819_SetCDCSSCodeWord(DCS_GetGolayCodeWord(gCurrentVfo->pTX->CodeType, gCurrentVfo->pTX->Code));
2023-09-09 08:03:56 +01:00
break;
}
}
void RADIO_SetVfoState(VfoState_t State)
{
if (State == VFO_STATE_NORMAL)
{
VfoState[0] = VFO_STATE_NORMAL;
VfoState[1] = VFO_STATE_NORMAL;
2023-09-14 09:56:30 +01:00
#ifdef ENABLE_FMRADIO
2023-09-17 09:54:24 +01:00
gFM_ResumeCountdown_500ms = 0;
2023-09-14 09:56:30 +01:00
#endif
2023-09-09 08:03:56 +01:00
}
else
{
2023-09-12 11:01:34 +01:00
if (State == VFO_STATE_VOLTAGE_HIGH)
2023-09-09 08:03:56 +01:00
{
2023-09-12 11:01:34 +01:00
VfoState[0] = VFO_STATE_VOLTAGE_HIGH;
2023-09-09 08:03:56 +01:00
VfoState[1] = VFO_STATE_TX_DISABLE;
}
else
{
unsigned int chan = (gEeprom.DUAL_WATCH != DUAL_WATCH_OFF && gRxVfoIsActive) ? (gEeprom.RX_VFO + 1) & 1 : gEeprom.RX_VFO; // 1of11
chan = (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF) ? gEeprom.TX_VFO : chan;
VfoState[chan] = State;
2023-09-09 08:03:56 +01:00
}
2023-09-14 09:56:30 +01:00
#ifdef ENABLE_FMRADIO
2023-09-17 09:54:24 +01:00
gFM_ResumeCountdown_500ms = fm_resume_countdown_500ms;
2023-09-14 09:56:30 +01:00
#endif
2023-09-09 08:03:56 +01:00
}
gUpdateDisplay = true;
}
void RADIO_PrepareTX(void)
{
2023-09-28 17:39:45 +01:00
VfoState_t State = VFO_STATE_NORMAL; // default to OK to TX
2023-09-09 08:03:56 +01:00
if (gEeprom.DUAL_WATCH != DUAL_WATCH_OFF)
2023-09-28 17:39:45 +01:00
{ // dual-RX is enabled
gDualWatchCountdown_10ms = dual_watch_count_after_tx_10ms;
2023-09-28 17:39:45 +01:00
gScheduleDualWatch = false;
2023-09-13 17:34:56 +01:00
2023-10-01 19:56:04 +01:00
if (!gRxVfoIsActive)
{ // use the TX vfo
gEeprom.RX_VFO = gEeprom.TX_VFO;
gRxVfo = &gEeprom.VfoInfo[gEeprom.TX_VFO];
gRxVfoIsActive = true;
2023-09-09 08:03:56 +01:00
}
// let the user see that DW is not active
gDualWatchActive = false;
gUpdateStatus = true;
2023-09-09 08:03:56 +01:00
}
RADIO_SelectCurrentVfo();
#if defined(ENABLE_ALARM) && defined(ENABLE_TX1750)
2023-09-28 17:39:45 +01:00
if (gAlarmState == ALARM_STATE_OFF ||
2023-09-17 09:54:24 +01:00
gAlarmState == ALARM_STATE_TX1750 ||
(gAlarmState == ALARM_STATE_ALARM && gEeprom.ALARM_MODE == ALARM_MODE_TONE))
#elif defined(ENABLE_ALARM)
if (gAlarmState == ALARM_STATE_OFF ||
(gAlarmState == ALARM_STATE_ALARM && gEeprom.ALARM_MODE == ALARM_MODE_TONE))
#elif defined(ENABLE_TX1750)
if (gAlarmState == ALARM_STATE_OFF ||
gAlarmState == ALARM_STATE_TX1750)
2023-09-09 09:01:52 +01:00
#endif
2023-09-09 08:03:56 +01:00
{
#ifndef ENABLE_TX_WHEN_AM
2023-09-28 23:32:08 +01:00
if (gCurrentVfo->AM_mode)
{ // not allowed to TX if in AM mode
State = VFO_STATE_TX_DISABLE;
}
else
#endif
if (!gSetting_TX_EN || gSerialConfigCountDown_500ms > 0)
{ // TX is disabled or config upload/download in progress
2023-09-19 09:16:57 +01:00
State = VFO_STATE_TX_DISABLE;
}
2023-09-19 09:16:57 +01:00
else
//if (TX_freq_check(gCurrentVfo->pTX->Frequency) == 0 || gCurrentVfo->CHANNEL_SAVE <= FREQ_CHANNEL_LAST)
2023-10-01 19:56:04 +01:00
if (TX_freq_check(gCurrentVfo->pTX->Frequency) == 0)
2023-09-28 17:39:45 +01:00
{ // TX frequency is allowed
2023-09-09 08:03:56 +01:00
if (gCurrentVfo->BUSY_CHANNEL_LOCK && gCurrentFunction == FUNCTION_RECEIVE)
2023-09-28 17:39:45 +01:00
State = VFO_STATE_BUSY; // busy RX'ing a station
2023-09-09 08:03:56 +01:00
else
if (gBatteryDisplayLevel == 0)
2023-09-28 17:39:45 +01:00
State = VFO_STATE_BAT_LOW; // charge your battery !
2023-09-09 08:03:56 +01:00
else
if (gBatteryDisplayLevel >= 6)
2023-09-28 17:39:45 +01:00
State = VFO_STATE_VOLTAGE_HIGH; // over voltage .. this is being a pain
2023-09-09 08:03:56 +01:00
}
else
2023-09-28 17:39:45 +01:00
State = VFO_STATE_TX_DISABLE; // TX frequency not allowed
}
2023-09-09 08:03:56 +01:00
2023-09-28 17:39:45 +01:00
if (State != VFO_STATE_NORMAL)
{ // TX not allowed
RADIO_SetVfoState(State);
#if defined(ENABLE_ALARM) || defined(ENABLE_TX1750)
2023-09-09 09:01:52 +01:00
gAlarmState = ALARM_STATE_OFF;
#endif
2023-09-09 08:03:56 +01:00
gDTMF_ReplyState = DTMF_REPLY_NONE;
2023-09-17 09:54:24 +01:00
AUDIO_PlayBeep(BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL);
2023-09-09 08:03:56 +01:00
return;
}
2023-09-12 21:08:51 +01:00
2023-09-28 17:39:45 +01:00
// TX is allowed
2023-09-09 08:03:56 +01:00
if (gDTMF_ReplyState == DTMF_REPLY_ANI)
{
if (gDTMF_CallMode == DTMF_CALL_MODE_DTMF)
{
gDTMF_IsTx = true;
gDTMF_CallState = DTMF_CALL_STATE_NONE;
gDTMF_TxStopCountdown_500ms = DTMF_txstop_countdown_500ms;
2023-09-09 08:03:56 +01:00
}
else
{
gDTMF_CallState = DTMF_CALL_STATE_CALL_OUT;
gDTMF_IsTx = false;
}
}
FUNCTION_Select(FUNCTION_TRANSMIT);
2023-09-28 17:39:45 +01:00
gTxTimerCountdown_500ms = 0; // no timeout
#if defined(ENABLE_ALARM) || defined(ENABLE_TX1750)
2023-09-28 17:39:45 +01:00
if (gAlarmState == ALARM_STATE_OFF)
2023-09-09 09:01:52 +01:00
#endif
2023-09-28 17:39:45 +01:00
{
2023-10-01 21:50:05 +01:00
if (gEeprom.TX_TIMEOUT_TIMER == 0)
2023-09-28 17:39:45 +01:00
gTxTimerCountdown_500ms = 60; // 30 sec
else
2023-10-01 21:50:05 +01:00
if (gEeprom.TX_TIMEOUT_TIMER < (ARRAY_SIZE(gSubMenu_TOT) - 1))
gTxTimerCountdown_500ms = 120 * gEeprom.TX_TIMEOUT_TIMER; // minutes
else
gTxTimerCountdown_500ms = 120 * 15; // 15 minutes
2023-09-28 17:39:45 +01:00
}
2023-09-09 08:03:56 +01:00
gTxTimeoutReached = false;
2023-09-28 17:39:45 +01:00
2023-09-09 08:03:56 +01:00
gFlagEndTransmission = false;
gRTTECountdown = 0;
gDTMF_ReplyState = DTMF_REPLY_NONE;
}
void RADIO_EnableCxCSS(void)
{
switch (gCurrentVfo->pTX->CodeType)
{
default:
2023-09-10 17:57:12 +01:00
case CODE_TYPE_OFF:
break;
2023-09-12 21:08:51 +01:00
2023-09-10 17:57:12 +01:00
case CODE_TYPE_CONTINUOUS_TONE:
BK4819_EnableCTCSS();
SYSTEM_DelayMs(200);
break;
2023-09-12 21:08:51 +01:00
2023-09-09 08:03:56 +01:00
case CODE_TYPE_DIGITAL:
case CODE_TYPE_REVERSE_DIGITAL:
BK4819_EnableCDCSS();
2023-09-10 17:57:12 +01:00
SYSTEM_DelayMs(200);
2023-09-09 08:03:56 +01:00
break;
}
}
void RADIO_PrepareCssTX(void)
{
RADIO_PrepareTX();
2023-09-17 09:54:24 +01:00
2023-09-09 08:03:56 +01:00
SYSTEM_DelayMs(200);
2023-09-17 09:54:24 +01:00
2023-09-09 08:03:56 +01:00
RADIO_EnableCxCSS();
RADIO_SetupRegisters(true);
}
void RADIO_SendEndOfTransmission(void)
{
if (gEeprom.ROGER == ROGER_MODE_ROGER)
BK4819_PlayRoger();
else
if (gEeprom.ROGER == ROGER_MODE_MDC)
BK4819_PlayRogerMDC();
2023-10-01 21:50:05 +01:00
if (gDTMF_CallState == DTMF_CALL_STATE_NONE &&
(gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_TX_DOWN || gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_BOTH))
2023-10-01 21:50:05 +01:00
{ // end-of-tx
2023-09-09 08:03:56 +01:00
if (gEeprom.DTMF_SIDE_TONE)
{
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
gEnableSpeaker = true;
SYSTEM_DelayMs(60);
}
BK4819_EnterDTMF_TX(gEeprom.DTMF_SIDE_TONE);
BK4819_PlayDTMFString(
gEeprom.DTMF_DOWN_CODE,
0,
gEeprom.DTMF_FIRST_CODE_PERSIST_TIME,
gEeprom.DTMF_HASH_CODE_PERSIST_TIME,
gEeprom.DTMF_CODE_PERSIST_TIME,
gEeprom.DTMF_CODE_INTERVAL_TIME);
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
gEnableSpeaker = false;
}
BK4819_ExitDTMF_TX(true);
}