38 Commits
v0.14 ... v0.16

Author SHA1 Message Date
Krzysiek Egzmont
c5e34c4be9 Delete immediate applying of CTCSS/DCS while scrolling options in the menu.
This also caused the option change not to be discarded on EXIT
2023-11-03 16:39:25 +01:00
Krzysiek Egzmont
b0a01cd8cf BYP/RAW removed by default, can be enabled by compile option 2023-11-03 12:51:06 +01:00
Krzysiek Egzmont
21535c9ca0 Don't use AM fix for USB/BYP/RAW 2023-11-03 12:18:31 +01:00
Krzysiek Egzmont
8c9bdaacbc Add "switch demodulation mode" function for programmable buttons 2023-11-03 01:15:29 +01:00
Krzysiek Egzmont
388c3dadf1 SSB, BYP, RAW demodulation modes added #64 2023-11-03 01:15:29 +01:00
Krzysiek Egzmont
72fc4bf52f FIX #60: LCD interference glitch 2023-11-03 01:13:28 +01:00
Krzysiek Egzmont
def555678d Refactoring 2023-11-02 21:56:48 +01:00
Krzysiek Egzmont
16e79bee7d Change the overvoltage level back to 8.9V 2023-11-02 21:34:10 +01:00
Krzysiek Egzmont
9777b5df8b Modified battery icon levels 2023-11-02 02:44:05 +01:00
Krzysiek Egzmont
c057f8a097 FIX #74: limit spectrum analyzer RSSI trigger values 2023-11-02 01:46:21 +01:00
Krzysiek Egzmont
034139d7d5 Battery curve, slight modification 2023-11-02 00:54:48 +01:00
Krzysiek Egzmont
03a51525b6 Fix s-meter over S9 values calculation 2023-11-01 23:37:31 +01:00
Krzysiek Egzmont
f074114d13 Makefile improvements 2023-11-01 22:35:13 +01:00
Krzysiek Egzmont
8a60535f9d Updated wiki 2023-11-01 20:36:19 +01:00
Krzysiek Egzmont
c2be853ef1 Low battery popup 2023-11-01 01:43:09 +01:00
Krzysiek Egzmont
9f1e6ab91f Extra UI helper functions 2023-11-01 00:10:03 +01:00
Krzysiek Egzmont
25334823e5 Refactoring 2023-10-31 19:58:10 +01:00
Krzysiek Egzmont
2796973ad3 Use the custom battery percentage calculations for battery icon and low battery beeping 2023-10-31 19:40:00 +01:00
Krzysiek Egzmont
2344478301 fix build error 2023-10-31 17:34:09 +01:00
Krzysiek Egzmont
61527d1281 More frequency steps 2023-10-31 14:33:05 +01:00
Krzysiek Egzmont
140b5f4b4a Added second discharge curve for 2200mAh type battery and hidden BatTyp menu entry 2023-10-31 00:41:53 +01:00
Krzysiek Egzmont
3e0ea6f7de Backlight setting 1 was fully off for some reason on higher freq PWM 2023-10-30 18:57:35 +01:00
Krzysiek Egzmont
ed64c7fb49 Mid, low power reduction mod from 1o11 2023-10-30 18:17:54 +01:00
Krzysiek Egzmont
d70fa1b7b4 Refactor 2023-10-30 16:39:18 +01:00
Krzysiek Egzmont
a41628410e FIX #65: code refactoring 2023-10-30 13:26:16 +01:00
Krzysiek Egzmont
f7c25b482d FIX #55: Broken DTMF calling (D Decd) 2023-10-29 22:26:48 +01:00
Krzysiek Egzmont
ac3cd08163 serial debugging helper 2023-10-28 23:11:52 +02:00
Krzysiek Egzmont
c1657a37f2 Refactor 2023-10-28 22:50:42 +02:00
Krzysiek Egzmont
a2580d5d8d Increase backlight PWM frequency to reduce flicker 2023-10-28 16:10:37 +02:00
Krzysiek Egzmont
5d4f7529ed Refactor 2023-10-28 16:09:49 +02:00
Krzysiek Egzmont
20a3e3b605 Fix STE not working when TX CTCSS/DCS is off
Reverts:
fde690a74a: app.c
50a55e34ab: radio.c
2023-10-28 14:41:47 +02:00
Krzysiek Egzmont
f3cc0f5acf Comments, refactor 2023-10-28 14:39:13 +02:00
Krzysiek Egzmont
2086bd6aaa Comments, refactor 2023-10-28 10:53:07 +02:00
Krzysiek Egzmont
3b3db88e5e Fix s-meter displaying for overpowering signals 2023-10-28 10:50:51 +02:00
Krzysiek Egzmont
f6791395cc Modified displaying of little sbar 2023-10-28 10:45:56 +02:00
Krzysiek Egzmont
8739996668 Changed little sbar back to factory 2023-10-27 15:32:14 +02:00
Krzysiek Egzmont
1740583ccc Set the backlight to minimum on reboot 2023-10-27 11:08:28 +02:00
Krzysiek Egzmont
b12244e352 Fix the RX buzzing problem after reboot 2023-10-27 10:53:22 +02:00
48 changed files with 1076 additions and 880 deletions

View File

@@ -35,8 +35,8 @@ ENABLE_RSSI_BAR := 1
ENABLE_AUDIO_BAR := 1
ENABLE_COPY_CHAN_TO_VFO := 1
ENABLE_SPECTRUM := 1
#ENABLE_SINGLE_VFO_CHAN := 1
#ENABLE_BAND_SCOPE := 1
ENABLE_REDUCE_LOW_MID_TX_POWER:= 0
ENABLE_BYP_RAW_DEMODULATORS := 0
#############################################################
@@ -211,6 +211,7 @@ endif
# catch any and all warnings
CFLAGS += -Wextra
#CFLAGS += -Wpedantic
CFLAGS += -DPRINTF_INCLUDE_CONFIG_H
CFLAGS += -DGIT_HASH=\"$(GIT_HASH)\"
@@ -317,6 +318,12 @@ endif
ifeq ($(ENABLE_BAND_SCOPE),1)
CFLAGS += -DENABLE_BAND_SCOPE
endif
ifeq ($(ENABLE_REDUCE_LOW_MID_TX_POWER),1)
CFLAGS += -DENABLE_REDUCE_LOW_MID_TX_POWER
endif
ifeq ($(ENABLE_BYP_RAW_DEMODULATORS),1)
CFLAGS += -DENABLE_BYP_RAW_DEMODULATORS
endif
LDFLAGS =
ifeq ($(ENABLE_CLANG),0)
@@ -349,10 +356,44 @@ LIBS =
DEPS = $(OBJS:.o=.d)
ifdef OS
RM = del /Q
FixPath = $(subst /,\,$1)
WHERE = where
else
ifeq ($(shell uname), Linux)
RM = rm -f
FixPath = $1
WHERE = which
endif
endif
ifneq (, $(shell $(WHERE) python))
MY_PYTHON := python
else ifneq (, $(shell $(WHERE) python3))
MY_PYTHON := python3
endif
ifdef MY_PYTHON
HAS_CRCMOD := $(shell $(MY_PYTHON) -c "import crcmod" 2>&1)
endif
all: $(TARGET)
$(OBJCOPY) -O binary $< $<.bin
-python fw-pack.py $<.bin $(GIT_HASH) $<.packed.bin
-python3 fw-pack.py $<.bin $(GIT_HASH) $<.packed.bin
ifndef MY_PYTHON
$(info )
$(info !!!!!!!! PYTHON NOT FOUND, *.PACKED.BIN WON'T BE BUILT)
$(info )
else ifneq (,$(HAS_CRCMOD))
$(info )
$(info !!!!!!!! CRCMOD NOT INSTALLED, *.PACKED.BIN WON'T BE BUILT)
$(info !!!!!!!! run: pip install crcmod)
$(info )
else
-$(MY_PYTHON) fw-pack.py $<.bin $(GIT_HASH) $<.packed.bin
endif
$(SIZE) $<
debug:
@@ -379,4 +420,4 @@ bsp/dp32g030/%.h: hardware/dp32g030/%.def
-include $(DEPS)
clean:
rm -f $(TARGET).bin $(TARGET).packed.bin $(TARGET) $(OBJS) $(DEPS)
$(RM) $(call FixPath, $(TARGET).bin $(TARGET).packed.bin $(TARGET) $(OBJS) $(DEPS))

View File

@@ -1,22 +1,22 @@
# Main features:
- many of OneOfEleven mods, including AM fix
- fagci spectrum analyzer (**F+5** to turn on)
- some other smaller mods introduced by me
- some other mods introduced by me
Go to [Wiki](https://github.com/egzumer/uv-k5-firmware-custom/wiki) to learn more.
# Manual
* [Radio operation](https://github.com/egzumer/uv-k5-firmware-custom/wiki/Radio-operation)
* [Menu](https://github.com/egzumer/uv-k5-firmware-custom/wiki/Menu)
* [Button functions](https://github.com/egzumer/uv-k5-firmware-custom/wiki/Button-functions)
* [Spectrum analyzer](https://github.com/egzumer/uv-k5-firmware-custom/wiki/Spectrum-analyzer)
* [Flashing the firmware](https://github.com/egzumer/uv-k5-firmware-custom/wiki/Flashing-the-firmware)
<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 while holding PTT and the first side button
2. go to BATCAL option and adjust the voltage with UP/DOWN buttons
3. confirm the setting, calibration will be saved to EEPROM
# Open reimplementation of the Quan Sheng UV-K5 v2.1.27 firmware

View File

@@ -270,6 +270,7 @@ void ACTION_Scan(bool bRestart)
#if defined(ENABLE_ALARM) || defined(ENABLE_TX1750)
static void ACTION_AlarmOr1750(const bool b1750)
{
(void)b1750;
gInputBoxIndex = 0;
#if defined(ENABLE_ALARM) && defined(ENABLE_TX1750)
@@ -323,6 +324,14 @@ void ACTION_Scan(bool bRestart)
}
#endif
void ACTION_SwitchDemodul(void)
{
gTxVfo->Modulation++;
if(gTxVfo->Modulation == MODULATION_UKNOWN)
gTxVfo->Modulation = MODULATION_FM;
gRequestSaveChannel = 1;
}
void ACTION_Handle(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
{
if (gScreenToDisplay == DISPLAY_MAIN && gDTMF_InputMode) // entering DTMF code
@@ -438,5 +447,8 @@ void ACTION_Handle(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
case ACTION_OPT_VFO_MR:
COMMON_SwitchVFOMode();
break;
case ACTION_OPT_SWITCH_DEMODUL:
ACTION_SwitchDemodul();
break;
}
}

View File

@@ -32,6 +32,7 @@ void ACTION_Scan(bool bRestart);
#ifdef ENABLE_FMRADIO
void ACTION_FM(void);
#endif
void ACTION_SwitchDemodul(void);
void ACTION_Handle(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld);

285
app/app.c
View File

@@ -62,15 +62,16 @@
#include "ui/status.h"
#include "ui/ui.h"
static void APP_ProcessKey(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld);
static void ProcessKey(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld);
static void FlashlightTimeSlice();
static void updateRSSI(const int vfo)
static void UpdateRSSI(const int vfo)
{
int16_t rssi = BK4819_GetRSSI();
#ifdef ENABLE_AM_FIX
// add RF gain adjust compensation
if (gEeprom.VfoInfo[vfo].AM_mode && gSetting_AM_fix)
if (gEeprom.VfoInfo[vfo].Modulation == MODULATION_AM && gSetting_AM_fix)
rssi -= rssi_gain_diff[vfo];
#endif
@@ -82,7 +83,7 @@ static void updateRSSI(const int vfo)
UI_UpdateRSSI(rssi, vfo);
}
static void APP_CheckForIncoming(void)
static void CheckForIncoming(void)
{
if (!g_SquelchLost)
return; // squelch is closed
@@ -116,7 +117,7 @@ static void APP_CheckForIncoming(void)
FUNCTION_Select(FUNCTION_INCOMING);
//gUpdateDisplay = true;
updateRSSI(gEeprom.RX_VFO);
UpdateRSSI(gEeprom.RX_VFO);
gUpdateRSSI = true;
}
@@ -132,7 +133,7 @@ static void APP_CheckForIncoming(void)
FUNCTION_Select(FUNCTION_INCOMING);
//gUpdateDisplay = true;
updateRSSI(gEeprom.RX_VFO);
UpdateRSSI(gEeprom.RX_VFO);
gUpdateRSSI = true;
}
return;
@@ -154,7 +155,7 @@ static void APP_CheckForIncoming(void)
FUNCTION_Select(FUNCTION_INCOMING);
//gUpdateDisplay = true;
updateRSSI(gEeprom.RX_VFO);
UpdateRSSI(gEeprom.RX_VFO);
gUpdateRSSI = true;
}
return;
@@ -171,12 +172,12 @@ static void APP_CheckForIncoming(void)
FUNCTION_Select(FUNCTION_INCOMING);
//gUpdateDisplay = true;
updateRSSI(gEeprom.RX_VFO);
UpdateRSSI(gEeprom.RX_VFO);
gUpdateRSSI = true;
}
}
static void APP_HandleIncoming(void)
static void HandleIncoming(void)
{
bool bFlag;
@@ -239,8 +240,8 @@ static void APP_HandleIncoming(void)
gUpdateStatus = true;
gUpdateDisplay = true;
return;
}
return;
}
}
}
@@ -248,7 +249,7 @@ static void APP_HandleIncoming(void)
APP_StartListening(gMonitor ? FUNCTION_MONITOR : FUNCTION_RECEIVE, false);
}
static void APP_HandleReceive(void)
static void HandleReceive(void)
{
#define END_OF_RX_MODE_SKIP 0
#define END_OF_RX_MODE_END 1
@@ -263,7 +264,7 @@ static void APP_HandleReceive(void)
}
if (gScanStateDir != SCAN_OFF && IS_FREQ_CHANNEL(gNextMrChannel))
{
{ // we are scanning in the frequency mode
if (g_SquelchLost)
return;
@@ -370,7 +371,7 @@ static void APP_HandleReceive(void)
if (!gEndOfRxDetectedMaybe &&
Mode == END_OF_RX_MODE_SKIP &&
gNextTimeslice40ms &&
gEeprom.TAIL_NOTE_ELIMINATION &&
gEeprom.TAIL_TONE_ELIMINATION &&
(gCurrentCodeType == CODE_TYPE_DIGITAL || gCurrentCodeType == CODE_TYPE_REVERSE_DIGITAL) &&
BK4819_GetCTCType() == 1)
Mode = END_OF_RX_MODE_TTE;
@@ -414,9 +415,9 @@ Skip:
break;
case END_OF_RX_MODE_TTE:
if (gEeprom.TAIL_NOTE_ELIMINATION)
if (gEeprom.TAIL_TONE_ELIMINATION)
{
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOff();
gTailNoteEliminationCountdown_10ms = 20;
gFlagTailNoteEliminationComplete = false;
@@ -427,12 +428,12 @@ Skip:
}
}
static void APP_HandleFunction(void)
static void HandleFunction(void)
{
switch (gCurrentFunction)
{
case FUNCTION_FOREGROUND:
APP_CheckForIncoming();
CheckForIncoming();
break;
case FUNCTION_TRANSMIT:
@@ -442,16 +443,16 @@ static void APP_HandleFunction(void)
break;
case FUNCTION_INCOMING:
APP_HandleIncoming();
HandleIncoming();
break;
case FUNCTION_RECEIVE:
APP_HandleReceive();
HandleReceive();
break;
case FUNCTION_POWER_SAVE:
if (!gRxIdleMode)
APP_CheckForIncoming();
CheckForIncoming();
break;
case FUNCTION_BAND_SCOPE:
@@ -475,7 +476,7 @@ void APP_StartListening(FUNCTION_Type_t Function, const bool reset_am_fix)
// clear the other vfo's rssi level (to hide the antenna symbol)
gVFO_RSSI_bar_level[(chan + 1) & 1u] = 0;
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOn();
gEnableSpeaker = true;
if (gSetting_backlight_on_tx_rx >= BACKLIGHT_ON_TR_RX)
@@ -525,7 +526,7 @@ void APP_StartListening(FUNCTION_Type_t Function, const bool reset_am_fix)
const uint8_t orig_pga = 6; // -3dB
#ifdef ENABLE_AM_FIX
if (gRxVfo->AM_mode && gSetting_AM_fix) { // AM RX mode
if (gRxVfo->Modulation == MODULATION_AM && gSetting_AM_fix) { // AM RX mode
if (reset_am_fix)
AM_fix_reset(chan); // TODO: only reset it when moving channel/frequency
AM_fix_10ms(chan);
@@ -539,10 +540,11 @@ void APP_StartListening(FUNCTION_Type_t Function, const bool reset_am_fix)
}
// AF gain - original QS values
if (gRxVfo->AM_mode){
BK4819_WriteRegister(0x48, 0xB3A8);
}
else {
// if (gRxVfo->Modulation != MODULATION_FM){
// BK4819_WriteRegister(BK4819_REG_48, 0xB3A8);
// }
// else
{
BK4819_WriteRegister(BK4819_REG_48,
(11u << 12) | // ??? .. 0 to 15, doesn't seem to make any difference
( 0u << 10) | // AF Rx Gain-1
@@ -553,7 +555,7 @@ void APP_StartListening(FUNCTION_Type_t Function, const bool reset_am_fix)
#ifdef ENABLE_VOICE
if (gVoiceWriteIndex == 0) // AM/FM RX mode will be set when the voice has finished
#endif
BK4819_SetAF(gRxVfo->AM_mode ? BK4819_AF_AM : BK4819_AF_FM); // no need, set it now
RADIO_SetModulation(gRxVfo->Modulation); // no need, set it now
FUNCTION_Select(Function);
@@ -592,7 +594,7 @@ uint32_t APP_SetFrequencyByStep(VFO_Info_t *pInfo, int8_t direction)
}
#endif
static void DUALWATCH_Alternate(void)
static void DualwatchAlternate(void)
{
#ifdef ENABLE_NOAA
if (gIsNoaaMode)
@@ -610,8 +612,8 @@ static void DUALWATCH_Alternate(void)
else
#endif
{ // toggle between VFO's
gEeprom.RX_VFO = (gEeprom.RX_VFO + 1) & 1;
gRxVfo = &gEeprom.VfoInfo[gEeprom.RX_VFO];
gEeprom.RX_VFO = !gEeprom.RX_VFO;
gRxVfo = &gEeprom.VfoInfo[gEeprom.RX_VFO];
if (!gDualWatchActive)
{ // let the user see DW is active
@@ -629,7 +631,7 @@ static void DUALWATCH_Alternate(void)
#endif
}
void APP_CheckRadioInterrupts(void)
static void CheckRadioInterrupts(void)
{
if (gScreenToDisplay == DISPLAY_SCANNER)
return;
@@ -772,32 +774,14 @@ void APP_CheckRadioInterrupts(void)
void APP_EndTransmission(void)
{ // back to RX mode
RADIO_SendEndOfTransmission();
if (gCurrentVfo->pTX->CodeType != CODE_TYPE_OFF)
{ // CTCSS/DCS is enabled
//if (gEeprom.TAIL_NOTE_ELIMINATION && gEeprom.REPEATER_TAIL_TONE_ELIMINATION > 0)
if (gEeprom.TAIL_NOTE_ELIMINATION)
{ // send the CTCSS/DCS tail tone - allows the receivers to mute the usual FM squelch tail/crash
RADIO_EnableCxCSS();
}
#if 0
else
{ // TX a short blank carrier
// this gives the receivers time to mute RX audio before we drop carrier
BK4819_ExitSubAu();
SYSTEM_DelayMs(200);
}
#endif
}
// send the CTCSS/DCS tail tone - allows the receivers to mute the usual FM squelch tail/crash
RADIO_EnableCxCSS();
RADIO_SetupRegisters(false);
}
#ifdef ENABLE_VOX
static void APP_HandleVox(void)
static void HandleVox(void)
{
if (gSetting_KILLED)
return;
@@ -878,13 +862,12 @@ void APP_EndTransmission(void)
void APP_Update(void)
{
#ifdef ENABLE_VOICE
if (gFlagPlayQueuedVoice)
{
#ifdef ENABLE_VOICE
if (gFlagPlayQueuedVoice) {
AUDIO_PlayQueuedVoice();
gFlagPlayQueuedVoice = false;
}
#endif
}
#endif
if (gCurrentFunction == FUNCTION_TRANSMIT && (gTxTimeoutReached || gSerialConfigCountDown_500ms > 0))
{ // transmitter timed out or must de-key
@@ -904,7 +887,7 @@ void APP_Update(void)
return;
if (gCurrentFunction != FUNCTION_TRANSMIT)
APP_HandleFunction();
HandleFunction();
#ifdef ENABLE_FMRADIO
// if (gFmRadioCountdown_500ms > 0)
@@ -965,7 +948,7 @@ void APP_Update(void)
gDTMF_CallState == DTMF_CALL_STATE_NONE &&
gCurrentFunction != FUNCTION_POWER_SAVE)
{
DUALWATCH_Alternate(); // toggle between the two VFO's
DualwatchAlternate(); // toggle between the two VFO's
if (gRxVfoIsActive && gScreenToDisplay == DISPLAY_MAIN)
GUI_SelectNextDisplay(DISPLAY_MAIN);
@@ -993,7 +976,7 @@ void APP_Update(void)
#ifdef ENABLE_VOX
if (gEeprom.VOX_SWITCH)
APP_HandleVox();
HandleVox();
#endif
if (gSchedulePowerSave)
@@ -1067,7 +1050,7 @@ void APP_Update(void)
gScanStateDir == SCAN_OFF &&
gCssScanMode == CSS_SCAN_MODE_OFF)
{ // dual watch mode, toggle between the two VFO's
DUALWATCH_Alternate();
DualwatchAlternate();
gUpdateRSSI = false;
}
@@ -1079,9 +1062,9 @@ void APP_Update(void)
}
else
if (gEeprom.DUAL_WATCH == DUAL_WATCH_OFF || gScanStateDir != SCAN_OFF || gCssScanMode != CSS_SCAN_MODE_OFF || gUpdateRSSI)
{ // dual watch mode, go back to sleep
{ // dual watch mode off or scanning or rssi update request
updateRSSI(gEeprom.RX_VFO);
UpdateRSSI(gEeprom.RX_VFO);
// go back to sleep
@@ -1098,7 +1081,7 @@ void APP_Update(void)
else
{
// toggle between the two VFO's
DUALWATCH_Alternate();
DualwatchAlternate();
gUpdateRSSI = true;
gPowerSave_10ms = power_save1_10ms;
@@ -1109,7 +1092,7 @@ void APP_Update(void)
}
// called every 10ms
void APP_CheckKeys(void)
static void CheckKeys(void)
{
#ifdef ENABLE_AIRCOPY
if (gSetting_KILLED || (gScreenToDisplay == DISPLAY_AIRCOPY && gAircopyState != AIRCOPY_READY))
@@ -1126,7 +1109,7 @@ void APP_CheckKeys(void)
{ // PTT released or serial comms config in progress
if (++gPttDebounceCounter >= 3 || gSerialConfigCountDown_500ms > 0) // 30ms
{ // stop transmitting
APP_ProcessKey(KEY_PTT, false, false);
ProcessKey(KEY_PTT, false, false);
gPttIsPressed = false;
if (gKeyReading1 != KEY_INVALID)
gPttWasReleased = true;
@@ -1142,7 +1125,7 @@ void APP_CheckKeys(void)
boot_counter_10ms = 0;
gPttDebounceCounter = 0;
gPttIsPressed = true;
APP_ProcessKey(KEY_PTT, true, false);
ProcessKey(KEY_PTT, true, false);
}
}
else
@@ -1160,7 +1143,7 @@ void APP_CheckKeys(void)
{
if (gKeyReading0 != KEY_INVALID && Key != KEY_INVALID)
APP_ProcessKey(gKeyReading1, false, gKeyBeingHeld); // key pressed without releasing previous key
ProcessKey(gKeyReading1, false, gKeyBeingHeld); // key pressed without releasing previous key
gKeyReading0 = Key;
gDebounceCounter = 0;
@@ -1175,14 +1158,14 @@ void APP_CheckKeys(void)
{
if (gKeyReading1 != KEY_INVALID) // some button was pressed before
{
APP_ProcessKey(gKeyReading1, false, gKeyBeingHeld); // process last button released event
ProcessKey(gKeyReading1, false, gKeyBeingHeld); // process last button released event
gKeyReading1 = KEY_INVALID;
}
}
else // process new key pressed
{
gKeyReading1 = Key;
APP_ProcessKey(Key, true, false);
ProcessKey(Key, true, false);
}
gKeyBeingHeld = false;
@@ -1197,7 +1180,7 @@ void APP_CheckKeys(void)
if (Key != KEY_PTT)
{
gKeyBeingHeld = true;
APP_ProcessKey(Key, true, true); // key held event
ProcessKey(Key, true, true); // key held event
}
}
else //subsequent fast key repeats
@@ -1206,7 +1189,7 @@ void APP_CheckKeys(void)
{
gKeyBeingHeld = true;
if ((gDebounceCounter % key_repeat_10ms) == 0)
APP_ProcessKey(Key, true, true); // key held event
ProcessKey(Key, true, true); // key held event
}
if (gDebounceCounter < 0xFFFF)
@@ -1227,8 +1210,8 @@ void APP_TimeSlice10ms(void)
#endif
#ifdef ENABLE_AM_FIX
// if (gEeprom.VfoInfo[gEeprom.RX_VFO].AM_mode && gSetting_AM_fix)
if (gRxVfo->AM_mode && gSetting_AM_fix)
// if (gEeprom.VfoInfo[gEeprom.RX_VFO].Modulation != MODULATION_FM && gSetting_AM_fix)
if (gRxVfo->Modulation == MODULATION_AM && gSetting_AM_fix)
AM_fix_10ms(gEeprom.RX_VFO);
#endif
@@ -1243,7 +1226,7 @@ void APP_TimeSlice10ms(void)
return;
if (gCurrentFunction != FUNCTION_POWER_SAVE || !gRxIdleMode)
APP_CheckRadioInterrupts();
CheckRadioInterrupts();
if (gCurrentFunction == FUNCTION_TRANSMIT)
{ // transmitting
@@ -1260,7 +1243,7 @@ void APP_TimeSlice10ms(void)
}
if (gUpdateStatus)
UI_DisplayStatus(false);
UI_DisplayStatus();
// Skipping authentic device checks
@@ -1269,37 +1252,7 @@ void APP_TimeSlice10ms(void)
return;
#endif
if (gFlashLightState == FLASHLIGHT_BLINK && (gFlashLightBlinkCounter & 15u) == 0)
GPIO_FlipBit(&GPIOC->DATA, GPIOC_PIN_FLASHLIGHT);
else if(gFlashLightState == FLASHLIGHT_SOS) {
const uint16_t u = 15;
static uint8_t c;
static uint16_t next;
if(gFlashLightBlinkCounter - next > 7*u) {
c = 0;
next = gFlashLightBlinkCounter+1;
}
else if(gFlashLightBlinkCounter == next) {
if(c==0) {
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_FLASHLIGHT);
}
else
GPIO_FlipBit(&GPIOC->DATA, GPIOC_PIN_FLASHLIGHT);
if(c == 18) {
next += 7*u;
c = 0;
}
else if(c==7 || c==9 || c==11)
next += 3*u;
else
next += u;
c++;
}
}
FlashlightTimeSlice();
#ifdef ENABLE_VOX
if (gVoxResumeCountdown > 0)
@@ -1354,7 +1307,7 @@ void APP_TimeSlice10ms(void)
RADIO_SetTxParameters();
BK4819_TransmitTone(true, 500);
SYSTEM_DelayMs(2);
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOn();
gEnableSpeaker = true;
gAlarmToneCounter = 0;
@@ -1399,14 +1352,14 @@ void APP_TimeSlice10ms(void)
{
if (--gScanDelay_10ms > 0)
{
APP_CheckKeys();
CheckKeys();
return;
}
}
if (gScannerEditState != 0)
{
APP_CheckKeys();
CheckKeys();
return;
}
@@ -1525,7 +1478,7 @@ void APP_TimeSlice10ms(void)
}
#endif
APP_CheckKeys();
CheckKeys();
}
void cancelUserInputModes(void)
@@ -1750,7 +1703,7 @@ void APP_TimeSlice500ms(void)
}
if (gCurrentFunction != FUNCTION_POWER_SAVE && gCurrentFunction != FUNCTION_TRANSMIT)
updateRSSI(gEeprom.RX_VFO);
UpdateRSSI(gEeprom.RX_VFO);
if (!gPttIsPressed && gVFOStateResumeCountdown_500ms > 0)
{
@@ -1771,57 +1724,7 @@ void APP_TimeSlice500ms(void)
}
if (gLowBattery)
{
gLowBatteryBlink = ++gLowBatteryCountdown & 1;
UI_DisplayBattery(0, gLowBatteryBlink);
if (gCurrentFunction != FUNCTION_TRANSMIT)
{ // not transmitting
if (gLowBatteryCountdown < 30)
{
if (gLowBatteryCountdown == 29 && !gChargingWithTypeC)
AUDIO_PlayBeep(BEEP_500HZ_60MS_DOUBLE_BEEP);
}
else
{
gLowBatteryCountdown = 0;
if (!gChargingWithTypeC)
{ // not on charge
AUDIO_PlayBeep(BEEP_500HZ_60MS_DOUBLE_BEEP);
#ifdef ENABLE_VOICE
AUDIO_SetVoiceID(0, VOICE_ID_LOW_VOLTAGE);
#endif
if (gBatteryDisplayLevel == 0)
{
#ifdef ENABLE_VOICE
AUDIO_PlaySingleVoice(true);
#endif
gReducedService = true;
//if (gCurrentFunction != FUNCTION_POWER_SAVE)
FUNCTION_Select(FUNCTION_POWER_SAVE);
ST7565_HardwareReset();
if (gEeprom.BACKLIGHT_TIME < (ARRAY_SIZE(gSubMenu_BACKLIGHT) - 1))
BACKLIGHT_TurnOff(); // turn the backlight off
}
#ifdef ENABLE_VOICE
else
AUDIO_PlaySingleVoice(false);
#endif
}
}
}
}
BATTERY_TimeSlice500ms();
if (gScreenToDisplay == DISPLAY_SCANNER && gScannerEditState == 0 && gScanCssState < SCAN_CSS_STATE_FOUND)
{
@@ -1885,7 +1788,7 @@ void APP_TimeSlice500ms(void)
{
gAlarmState = ALARM_STATE_OFF;
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOff();
gEnableSpeaker = false;
if (gEeprom.ALARM_MODE == ALARM_MODE_TONE)
@@ -1909,7 +1812,7 @@ void APP_TimeSlice500ms(void)
static void APP_ProcessKey(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
static void ProcessKey(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
{
if (Key == KEY_EXIT && !BACKLIGHT_IsOn() && gEeprom.BACKLIGHT_TIME > 0)
{ // just turn the light on for now so the user can see what's what
@@ -2004,8 +1907,18 @@ static void APP_ProcessKey(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
}
}
if (gEeprom.KEY_LOCK && gCurrentFunction != FUNCTION_TRANSMIT && Key != KEY_PTT)
{ // keyboard is locked
bool lowBatPopup = gLowBattery && !gLowBatteryConfirmed && gScreenToDisplay == DISPLAY_MAIN;
if ((gEeprom.KEY_LOCK || lowBatPopup) && gCurrentFunction != FUNCTION_TRANSMIT && Key != KEY_PTT)
{ // keyboard is locked or low battery popup
// close low battery popup
if(Key == KEY_EXIT && bKeyPressed && lowBatPopup) {
gLowBatteryConfirmed = true;
gUpdateDisplay = true;
AUDIO_PlayBeep(BEEP_1KHZ_60MS_OPTIONAL);
return;
}
if (Key == KEY_F)
{ // function/key-lock key
@@ -2113,7 +2026,7 @@ static void APP_ProcessKey(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
{
if (!bKeyPressed)
{
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOff();
gEnableSpeaker = false;
@@ -2129,7 +2042,7 @@ static void APP_ProcessKey(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
{
if (gEeprom.DTMF_SIDE_TONE)
{ // user will here the DTMF tones in speaker
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOn();
gEnableSpeaker = true;
}
@@ -2369,3 +2282,37 @@ Skip:
gUpdateDisplay = true;
}
static void FlashlightTimeSlice()
{
if (gFlashLightState == FLASHLIGHT_BLINK && (gFlashLightBlinkCounter & 15u) == 0)
GPIO_FlipBit(&GPIOC->DATA, GPIOC_PIN_FLASHLIGHT);
else if(gFlashLightState == FLASHLIGHT_SOS) {
const uint16_t u = 15;
static uint8_t c;
static uint16_t next;
if(gFlashLightBlinkCounter - next > 7*u) {
c = 0;
next = gFlashLightBlinkCounter + 1;
}
else if(gFlashLightBlinkCounter == next) {
if(c==0) {
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_FLASHLIGHT);
}
else
GPIO_FlipBit(&GPIOC->DATA, GPIOC_PIN_FLASHLIGHT);
if(c >= 18) {
next = gFlashLightBlinkCounter + 7*u;
c = 0;
}
else if(c==7 || c==9 || c==11)
next = gFlashLightBlinkCounter + 3*u;
else
next = gFlashLightBlinkCounter + u;
c++;
}
}
}

View File

@@ -434,7 +434,7 @@ void DTMF_Reply(void)
if (gEeprom.DTMF_SIDE_TONE)
{ // the user will also hear the transmitted tones
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOn();
gEnableSpeaker = true;
}
@@ -450,7 +450,7 @@ void DTMF_Reply(void)
gEeprom.DTMF_CODE_PERSIST_TIME,
gEeprom.DTMF_CODE_INTERVAL_TIME);
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOff();
gEnableSpeaker = false;

View File

@@ -96,7 +96,7 @@ void FM_TurnOff(void)
gFM_ScanState = FM_SCAN_OFF;
gFM_RestoreCountdown_10ms = 0;
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOff();
gEnableSpeaker = false;
@@ -119,7 +119,7 @@ void FM_EraseChannels(void)
void FM_Tune(uint16_t Frequency, int8_t Step, bool bFlag)
{
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOff();
gEnableSpeaker = false;
@@ -166,7 +166,7 @@ void FM_PlayAndUpdate(void)
gScheduleFM = false;
gAskToSave = false;
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOn();
gEnableSpeaker = true;
}
@@ -625,7 +625,7 @@ void FM_Play(void)
if (!gEeprom.FM_IsMrMode)
gEeprom.FM_SelectedFrequency = gEeprom.FM_FrequencyPlaying;
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOn();
gEnableSpeaker = true;
GUI_SelectNextDisplay(DISPLAY_FM);
@@ -659,7 +659,7 @@ void FM_Start(void)
BK1080_Init(gEeprom.FM_FrequencyPlaying, true);
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOn();
gEnableSpeaker = true;
gUpdateStatus = true;

View File

@@ -212,21 +212,12 @@ void GENERIC_Key_PTT(bool bKeyPressed)
if (gDTMF_InputBox_Index < sizeof(gDTMF_InputBox))
gDTMF_InputBox[gDTMF_InputBox_Index] = 0; // NULL term the string
#if 0
// append our DTMF ID to the inputted DTMF code -
// IF the user inputted code is exactly 3 digits long
if (gDTMF_InputBox_Index == 3)
gDTMF_CallMode = DTMF_CheckGroupCall(gDTMF_InputBox, 3);
else
gDTMF_CallMode = DTMF_CALL_MODE_DTMF;
#else
// 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;
#endif
// 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;
// remember the DTMF string
gDTMF_PreviousIndex = gDTMF_InputBox_Index;

View File

@@ -109,7 +109,7 @@ int MENU_GetLimits(uint8_t menu_id, int32_t *pMin, int32_t *pMax)
case MENU_STEP:
*pMin = 0;
*pMax = ARRAY_SIZE(StepFrequencyTable) - 1;
*pMax = ARRAY_SIZE(gStepFrequencyTable) - 1;
break;
case MENU_ABR:
@@ -232,7 +232,6 @@ int MENU_GetLimits(uint8_t menu_id, int32_t *pMin, int32_t *pMax)
case MENU_D_ST:
case MENU_D_DCD:
case MENU_D_LIVE_DEC:
case MENU_AM:
#ifdef ENABLE_NOAA
case MENU_NOAA_S:
#endif
@@ -246,6 +245,11 @@ int MENU_GetLimits(uint8_t menu_id, int32_t *pMin, int32_t *pMax)
*pMax = ARRAY_SIZE(gSubMenu_OFF_ON) - 1;
break;
case MENU_AM:
*pMin = 0;
*pMax = ARRAY_SIZE(gModulationStr) - 1;
break;
case MENU_SCR:
*pMin = 0;
*pMax = ARRAY_SIZE(gSubMenu_SCRAMBLER) - 1;
@@ -331,8 +335,13 @@ int MENU_GetLimits(uint8_t menu_id, int32_t *pMin, int32_t *pMax)
#endif
case MENU_BATCAL:
*pMin = 1600; // 0
*pMax = 2200; // 2300
*pMin = 1600;
*pMax = 2200;
break;
case MENU_BATTYP:
*pMin = 0;
*pMax = 1;
break;
case MENU_F1SHRT:
@@ -376,7 +385,7 @@ void MENU_AcceptSetting(void)
break;
case MENU_STEP:
gTxVfo->STEP_SETTING = gSubMenuSelection;
gTxVfo->STEP_SETTING = FREQUENCY_GetStepIdxFromSortedIdx(gSubMenuSelection);
if (IS_FREQ_CHANNEL(gTxVfo->CHANNEL_SAVE))
{
gRequestSaveChannel = 1;
@@ -594,7 +603,7 @@ void MENU_AcceptSetting(void)
return;
case MENU_STE:
gEeprom.TAIL_NOTE_ELIMINATION = gSubMenuSelection;
gEeprom.TAIL_TONE_ELIMINATION = gSubMenuSelection;
break;
case MENU_RP_STE:
@@ -697,7 +706,7 @@ void MENU_AcceptSetting(void)
break;
case MENU_AM:
gTxVfo->AM_mode = gSubMenuSelection;
gTxVfo->Modulation = gSubMenuSelection;
gRequestSaveChannel = 1;
return;
@@ -772,17 +781,21 @@ void MENU_AcceptSetting(void)
#endif
case MENU_BATCAL:
{
gBatteryCalibration[0] = (520ul * gSubMenuSelection) / 760; // 5.20V empty, blinking above this value, reduced functionality below
gBatteryCalibration[1] = (700ul * gSubMenuSelection) / 760; // 7.00V, ~5%, 1 bars above this value
gBatteryCalibration[2] = (745ul * gSubMenuSelection) / 760; // 7.45V, ~17%, 2 bars above this value
{ // voltages are averages between discharge curves of 1600 and 2200 mAh
// gBatteryCalibration[0] = (520ul * gSubMenuSelection) / 760; // 5.20V empty, blinking above this value, reduced functionality below
// gBatteryCalibration[1] = (689ul * gSubMenuSelection) / 760; // 6.89V, ~5%, 1 bars above this value
// gBatteryCalibration[2] = (724ul * gSubMenuSelection) / 760; // 7.24V, ~17%, 2 bars above this value
gBatteryCalibration[3] = gSubMenuSelection; // 7.6V, ~29%, 3 bars above this value
gBatteryCalibration[4] = (788ul * gSubMenuSelection) / 760; // 7.88V, ~65%, 4 bars above this value
gBatteryCalibration[5] = 2300;
// gBatteryCalibration[4] = (771ul * gSubMenuSelection) / 760; // 7.71V, ~65%, 4 bars above this value
// gBatteryCalibration[5] = 2300;
SETTINGS_SaveBatteryCalibration(gBatteryCalibration);
return;
}
case MENU_BATTYP:
gEeprom.BATTERY_TYPE = gSubMenuSelection;
break;
case MENU_F1SHRT:
case MENU_F1LONG:
case MENU_F2SHRT:
@@ -869,7 +882,7 @@ void MENU_ShowCurrentSetting(void)
break;
case MENU_STEP:
gSubMenuSelection = gTxVfo->STEP_SETTING;
gSubMenuSelection = FREQUENCY_GetSortedIdxFromStepIdx(gTxVfo->STEP_SETTING);
break;
case MENU_TXP:
@@ -1015,7 +1028,7 @@ void MENU_ShowCurrentSetting(void)
break;
case MENU_STE:
gSubMenuSelection = gEeprom.TAIL_NOTE_ELIMINATION;
gSubMenuSelection = gEeprom.TAIL_TONE_ELIMINATION;
break;
case MENU_RP_STE:
@@ -1103,7 +1116,7 @@ void MENU_ShowCurrentSetting(void)
break;
case MENU_AM:
gSubMenuSelection = gTxVfo->AM_mode;
gSubMenuSelection = gTxVfo->Modulation;
break;
#ifdef ENABLE_AM_FIX
@@ -1170,6 +1183,10 @@ void MENU_ShowCurrentSetting(void)
gSubMenuSelection = gBatteryCalibration[3];
break;
case MENU_BATTYP:
gSubMenuSelection = gEeprom.BATTERY_TYPE;
break;
case MENU_F1SHRT:
case MENU_F1LONG:
case MENU_F2SHRT:
@@ -1590,9 +1607,9 @@ static void MENU_Key_STAR(const bool bKeyPressed, const bool bKeyHeld)
RADIO_SelectVfos();
#ifdef ENABLE_NOAA
if (!IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE) && gRxVfo->AM_mode == 0)
if (!IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE) && gRxVfo->Modulation == MODULATION_FM)
#else
if (gRxVfo->AM_mode == 0)
if (gRxVfo->Modulation == MODULATION_FM)
#endif
{
if (GetCurrentMenuId() == MENU_R_CTCS || GetCurrentMenuId() == MENU_R_DCS)

View File

@@ -52,6 +52,9 @@ extern volatile uint16_t gScanPauseDelayIn_10ms;
extern uint8_t gScanProgressIndicator;
extern uint8_t gScanHitCount;
extern bool gScanUseCssResult;
// scan direction, if not equal SCAN_OFF indicates
// that we are in a process of scanning channels/frequencies
extern int8_t gScanStateDir;
extern bool gScanKeepResult;

View File

@@ -16,6 +16,7 @@
#include "app/spectrum.h"
#include "driver/backlight.h"
#include "audio.h"
struct FrequencyBandInfo {
uint32_t lower;
@@ -48,7 +49,6 @@ ScanInfo scanInfo;
KeyboardState kbd = {KEY_INVALID, KEY_INVALID, 0};
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};
@@ -78,10 +78,10 @@ uint16_t listenT = 0;
RegisterSpec registerSpecs[] = {
{},
{"LNAs", 0x13, 8, 0b11, 1},
{"LNA", 0x13, 5, 0b111, 1},
{"PGA", 0x13, 0, 0b111, 1},
{"IF", 0x3D, 0, 0xFFFF, 0x2aaa},
{"LNAs", BK4819_REG_13, 8, 0b11, 1},
{"LNA", BK4819_REG_13, 5, 0b111, 1},
{"PGA", BK4819_REG_13, 0, 0b111, 1},
{"IF", BK4819_REG_3D, 0, 0xFFFF, 0x2aaa},
// {"MIX", 0x13, 3, 0b11, 1}, // TODO: hidden
};
@@ -102,7 +102,7 @@ static int Rssi2DBm(uint16_t rssi) { return (rssi >> 1) - 160; }
static uint16_t GetRegMenuValue(uint8_t st) {
RegisterSpec s = registerSpecs[st];
return (BK4819_ReadRegister(s.num) >> s.offset) & s.maxValue;
return (BK4819_ReadRegister(s.num) >> s.offset) & s.mask;
}
static void SetRegMenuValue(uint8_t st, bool add) {
@@ -110,14 +110,14 @@ static void SetRegMenuValue(uint8_t st, bool add) {
RegisterSpec s = registerSpecs[st];
uint16_t reg = BK4819_ReadRegister(s.num);
if (add && v <= s.maxValue - s.inc) {
if (add && v <= s.mask - s.inc) {
v += s.inc;
} else if (!add && v >= 0 + s.inc) {
v -= s.inc;
}
// TODO: use max value for bits count in max value, or reset by additional
// mask in spec
reg &= ~(s.maxValue << s.offset);
reg &= ~(s.mask << s.offset);
BK4819_WriteRegister(s.num, reg | (v << s.offset));
redrawScreen = true;
}
@@ -205,35 +205,23 @@ static void ToggleAFBit(bool on) {
}
static void BackupRegisters() {
R30 = BK4819_ReadRegister(0x30);
R37 = BK4819_ReadRegister(0x37);
R3D = BK4819_ReadRegister(0x3D);
R43 = BK4819_ReadRegister(0x43);
R47 = BK4819_ReadRegister(0x47);
R48 = BK4819_ReadRegister(0x48);
R7E = BK4819_ReadRegister(0x7E);
R30 = BK4819_ReadRegister(BK4819_REG_30);
R37 = BK4819_ReadRegister(BK4819_REG_37);
R3D = BK4819_ReadRegister(BK4819_REG_3D);
R43 = BK4819_ReadRegister(BK4819_REG_43);
R47 = BK4819_ReadRegister(BK4819_REG_47);
R48 = BK4819_ReadRegister(BK4819_REG_48);
R7E = BK4819_ReadRegister(BK4819_REG_7E);
}
static void RestoreRegisters() {
BK4819_WriteRegister(0x30, R30);
BK4819_WriteRegister(0x37, R37);
BK4819_WriteRegister(0x3D, R3D);
BK4819_WriteRegister(0x43, R43);
BK4819_WriteRegister(0x47, R47);
BK4819_WriteRegister(0x48, R48);
BK4819_WriteRegister(0x7E, R7E);
}
static void SetModulation(ModulationType type) {
RestoreRegisters();
uint16_t reg = BK4819_ReadRegister(BK4819_REG_47);
reg &= ~(0b111 << 8);
BK4819_WriteRegister(BK4819_REG_47, reg | (modTypeReg47Values[type] << 8));
if (type == MOD_USB) {
BK4819_WriteRegister(0x3D, 0b0010101101000101);
BK4819_WriteRegister(BK4819_REG_37, 0x160F);
BK4819_WriteRegister(0x48, 0b0000001110101000);
}
BK4819_WriteRegister(BK4819_REG_30, R30);
BK4819_WriteRegister(BK4819_REG_37, R37);
BK4819_WriteRegister(BK4819_REG_3D, R3D);
BK4819_WriteRegister(BK4819_REG_43, R43);
BK4819_WriteRegister(BK4819_REG_47, R47);
BK4819_WriteRegister(BK4819_REG_48, R48);
BK4819_WriteRegister(BK4819_REG_7E, R7E);
}
static void ToggleAFDAC(bool on) {
@@ -304,9 +292,9 @@ static void ToggleAudio(bool on) {
}
audioState = on;
if (on) {
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOn();
} else {
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOff();
}
}
@@ -400,11 +388,24 @@ static void Measure() { rssiHistory[scanInfo.i] = scanInfo.rssi = GetRssi(); }
// Update things by keypress
static uint16_t dbm2rssi(int dBm)
{
return (dBm + 160)*2;
}
static void ClampRssiTriggerLevel()
{
settings.rssiTriggerLevel = clamp(settings.rssiTriggerLevel, dbm2rssi(settings.dbMin), dbm2rssi(settings.dbMax));
}
static void UpdateRssiTriggerLevel(bool inc) {
if (inc)
settings.rssiTriggerLevel += 2;
settings.rssiTriggerLevel += 2;
else
settings.rssiTriggerLevel -= 2;
settings.rssiTriggerLevel -= 2;
ClampRssiTriggerLevel();
redrawScreen = true;
redrawStatus = true;
}
@@ -417,6 +418,8 @@ static void UpdateDBMax(bool inc) {
} else {
return;
}
ClampRssiTriggerLevel();
redrawStatus = true;
redrawScreen = true;
SYSTEM_DelayMs(20);
@@ -473,12 +476,12 @@ static void UpdateFreqChangeStep(bool inc) {
}
static void ToggleModulation() {
if (settings.modulationType < MOD_USB) {
if (settings.modulationType < MODULATION_UKNOWN - 1) {
settings.modulationType++;
} else {
settings.modulationType = MOD_FM;
settings.modulationType = MODULATION_FM;
}
SetModulation(settings.modulationType);
RADIO_SetModulation(settings.modulationType);
redrawScreen = true;
}
@@ -653,7 +656,7 @@ static void DrawF(uint32_t f) {
sprintf(String, "%u.%05u", f / 100000, f % 100000);
UI_PrintStringSmall(String, 8, 127, 0);
sprintf(String, "%s", modulationTypeOptions[settings.modulationType]);
sprintf(String, "%3s", gModulationStr[settings.modulationType]);
GUI_DisplaySmallest(String, 116, 1, false, true);
sprintf(String, "%s", bwOptions[settings.listenBw]);
GUI_DisplaySmallest(String, 108, 7, false, true);
@@ -1159,7 +1162,7 @@ void APP_RunSpectrum() {
newScanStart = true;
ToggleRX(true), ToggleRX(false); // hack to prevent noise when squelch off
SetModulation(settings.modulationType = MOD_FM);
RADIO_SetModulation(settings.modulationType = MODULATION_FM);
BK4819_SetFilterBandwidth(settings.listenBw = BK4819_FILTER_BW_WIDE, false);
RelaunchScan();

View File

@@ -99,12 +99,6 @@ typedef enum StepsCount {
STEPS_16,
} StepsCount;
typedef enum ModulationType {
MOD_FM,
MOD_AM,
MOD_USB,
} ModulationType;
typedef enum ScanStep {
S_STEP_0_01kHz,
S_STEP_0_1kHz,
@@ -131,7 +125,7 @@ typedef struct SpectrumSettings {
BK4819_FilterBandwidth_t listenBw;
int dbMin;
int dbMax;
ModulationType modulationType;
ModulationMode_t modulationType;
bool backlightState;
} SpectrumSettings;
@@ -149,14 +143,6 @@ typedef struct ScanInfo {
uint8_t measurementsCount;
} ScanInfo;
typedef struct RegisterSpec {
char *name;
uint8_t num;
uint8_t offset;
uint16_t maxValue;
uint16_t inc;
} RegisterSpec;
typedef struct PeakInfo {
uint16_t t;
uint16_t rssi;

19
audio.c
View File

@@ -97,7 +97,7 @@ void AUDIO_PlayBeep(BEEP_Type_t Beep)
ToneConfig = BK4819_ReadRegister(BK4819_REG_71);
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOff();
if (gCurrentFunction == FUNCTION_POWER_SAVE && gRxIdleMode)
BK4819_RX_TurnOn();
@@ -138,7 +138,7 @@ void AUDIO_PlayBeep(BEEP_Type_t Beep)
SYSTEM_DelayMs(2);
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOn();
SYSTEM_DelayMs(60);
@@ -185,7 +185,7 @@ void AUDIO_PlayBeep(BEEP_Type_t Beep)
BK4819_EnterTxMute();
SYSTEM_DelayMs(20);
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOff();
#ifdef ENABLE_VOX
gVoxResumeCountdown = 80;
@@ -197,7 +197,7 @@ void AUDIO_PlayBeep(BEEP_Type_t Beep)
BK4819_WriteRegister(BK4819_REG_71, ToneConfig);
if (gEnableSpeaker)
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOn();
#ifdef ENABLE_FMRADIO
if (gFmRadioMode)
@@ -270,7 +270,7 @@ void AUDIO_PlayBeep(BEEP_Type_t Beep)
BK1080_Mute(true);
#endif
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOn();
#ifdef ENABLE_VOX
gVoxResumeCountdown = 2000;
@@ -289,7 +289,7 @@ void AUDIO_PlayBeep(BEEP_Type_t Beep)
if (gCurrentFunction == FUNCTION_RECEIVE ||
gCurrentFunction == FUNCTION_MONITOR ||
gCurrentFunction == FUNCTION_INCOMING) // 1of11
BK4819_SetAF(gRxVfo->AM_mode ? BK4819_AF_AM : BK4819_AF_FM);
RADIO_SetModulation(gRxVfo->Modulation);
#ifdef ENABLE_FMRADIO
if (gFmRadioMode)
@@ -297,7 +297,7 @@ void AUDIO_PlayBeep(BEEP_Type_t Beep)
#endif
if (!gEnableSpeaker)
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOff();
gVoiceWriteIndex = 0;
gVoiceReadIndex = 0;
@@ -430,7 +430,7 @@ void AUDIO_PlayBeep(BEEP_Type_t Beep)
if (gCurrentFunction == FUNCTION_RECEIVE ||
gCurrentFunction == FUNCTION_MONITOR ||
gCurrentFunction == FUNCTION_INCOMING) // 1of11
BK4819_SetAF(gRxVfo->AM_mode ? BK4819_AF_AM : BK4819_AF_FM);
RADIO_SetModulation(gRxVfo->Modulation);
#ifdef ENABLE_FMRADIO
if (gFmRadioMode)
@@ -438,7 +438,7 @@ void AUDIO_PlayBeep(BEEP_Type_t Beep)
#endif
if (!gEnableSpeaker)
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOff();
#ifdef ENABLE_VOX
gVoxResumeCountdown = 80;
@@ -449,3 +449,4 @@ void AUDIO_PlayBeep(BEEP_Type_t Beep)
}
#endif

11
audio.h
View File

@@ -20,6 +20,9 @@
#include <stdbool.h>
#include <stdint.h>
#include "bsp/dp32g030/gpio.h"
#include "driver/gpio.h"
enum BEEP_Type_t
{
BEEP_NONE = 0,
@@ -130,6 +133,14 @@ enum VOICE_ID_t
typedef enum VOICE_ID_t VOICE_ID_t;
static inline void AUDIO_AudioPathOn(void) {
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
}
static inline void AUDIO_AudioPathOff(void) {
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
}
#ifdef ENABLE_VOICE
extern VOICE_ID_t gVoiceID[8];
extern uint8_t gVoiceReadIndex;

View File

@@ -270,48 +270,6 @@ const uint8_t BITMAP_Antenna[5] =
0b00000011
};
const uint8_t BITMAP_AntennaLevel1[3] =
{
0b01100000,
0b01100000,
0b00000000
};
const uint8_t BITMAP_AntennaLevel2[3] =
{
0b01110000,
0b01110000,
0b00000000
};
const uint8_t BITMAP_AntennaLevel3[3] =
{
0b01111000,
0b01111000,
0b00000000
};
const uint8_t BITMAP_AntennaLevel4[3] =
{
0b01111100,
0b01111100,
0b00000000
};
const uint8_t BITMAP_AntennaLevel5[3] =
{
0b01111110,
0b01111110,
0b00000000
};
const uint8_t BITMAP_AntennaLevel6[3] =
{
0b01111111,
0b01111111,
0b00000000
};
const uint8_t BITMAP_MARKER[8] =
{
0b11111111,

View File

@@ -10,10 +10,6 @@ extern const uint8_t BITMAP_RX[8];
extern const uint8_t BITMAP_BatteryLevel[2];
extern const uint8_t BITMAP_BatteryLevel1[17];
extern const uint8_t BITMAP_BatteryLevel2[17];
extern const uint8_t BITMAP_BatteryLevel3[17];
extern const uint8_t BITMAP_BatteryLevel4[17];
extern const uint8_t BITMAP_BatteryLevel5[17];
extern const uint8_t BITMAP_USB_C[9];
@@ -39,12 +35,6 @@ extern const uint8_t BITMAP_TDR2[9];
#endif
extern const uint8_t BITMAP_Antenna[5];
extern const uint8_t BITMAP_AntennaLevel1[3];
extern const uint8_t BITMAP_AntennaLevel2[3];
extern const uint8_t BITMAP_AntennaLevel3[3];
extern const uint8_t BITMAP_AntennaLevel4[3];
extern const uint8_t BITMAP_AntennaLevel5[3];
extern const uint8_t BITMAP_AntennaLevel6[3];
extern const uint8_t BITMAP_MARKER[8];

31
board.c
View File

@@ -23,11 +23,10 @@
#include "board.h"
#include "bsp/dp32g030/gpio.h"
#include "bsp/dp32g030/portcon.h"
#include "bsp/dp32g030/pwmplus.h"
#include "bsp/dp32g030/saradc.h"
#include "bsp/dp32g030/syscon.h"
#include "driver/adc.h"
//#include "driver/backlight.h"
#include "driver/backlight.h"
#ifdef ENABLE_FMRADIO
#include "driver/bk1080.h"
#endif
@@ -182,14 +181,10 @@ void BOARD_PORTCON_Init(void)
// PORT B pin selection
PORTCON_PORTB_SEL0 &= ~(0
// Back light
| PORTCON_PORTB_SEL0_B6_MASK
// SPI0 SSN
| PORTCON_PORTB_SEL0_B7_MASK
);
PORTCON_PORTB_SEL0 |= 0
// Back light PWM
| PORTCON_PORTB_SEL0_B6_BITS_PWMP0_CH0
// SPI0 SSN
| PORTCON_PORTB_SEL0_B7_BITS_SPI0_SSN
;
@@ -470,23 +465,6 @@ void BOARD_PORTCON_Init(void)
;
}
static void BacklightPWM_Init()
{
// 48MHz / 94 / 1024 ~ 500Hz
PWM_PLUS0_CLKSRC |= ((94) << 16);
PWM_PLUS0_PERIOD = 1023;
PWM_PLUS0_GEN =
PWMPLUS_GEN_CH0_OE_BITS_ENABLE |
PWMPLUS_GEN_CH0_OUTINV_BITS_ENABLE |
0;
PWM_PLUS0_CFG =
PWMPLUS_CFG_CNT_REP_BITS_ENABLE |
PWMPLUS_CFG_COUNTER_EN_BITS_ENABLE |
0;
}
void BOARD_ADC_Init(void)
{
ADC_Config_t Config;
@@ -524,7 +502,7 @@ void BOARD_Init(void)
{
BOARD_PORTCON_Init();
BOARD_GPIO_Init();
BacklightPWM_Init();
BACKLIGHT_InitHardware();
BOARD_ADC_Init();
ST7565_Init(true);
#ifdef ENABLE_FMRADIO
@@ -564,7 +542,7 @@ void BOARD_EEPROM_Init(void)
gEeprom.BATTERY_SAVE = (Data[3] < 5) ? Data[3] : 4;
gEeprom.DUAL_WATCH = (Data[4] < 3) ? Data[4] : DUAL_WATCH_CHAN_A;
gEeprom.BACKLIGHT_TIME = (Data[5] < ARRAY_SIZE(gSubMenu_BACKLIGHT)) ? Data[5] : 3;
gEeprom.TAIL_NOTE_ELIMINATION = (Data[6] < 2) ? Data[6] : false;
gEeprom.TAIL_TONE_ELIMINATION = (Data[6] < 2) ? Data[6] : false;
gEeprom.VFO_OPEN = (Data[7] < 2) ? Data[7] : true;
// 0E80..0E87
@@ -636,7 +614,8 @@ void BOARD_EEPROM_Init(void)
#endif
gEeprom.ROGER = (Data[1] < 3) ? Data[1] : ROGER_MODE_OFF;
gEeprom.REPEATER_TAIL_TONE_ELIMINATION = (Data[2] < 11) ? Data[2] : 0;
gEeprom.TX_VFO = (Data[3] < 2) ? Data[3] : 0;
gEeprom.TX_VFO = (Data[3] < 2) ? Data[3] : 0;
gEeprom.BATTERY_TYPE = (Data[4] < BATTERY_TYPE_UNKNOWN) ? Data[4] : BATTERY_TYPE_1600_MAH;
// 0ED0..0ED7
EEPROM_ReadBuffer(0x0ED0, Data, 8);

18
debugging.h Normal file
View File

@@ -0,0 +1,18 @@
#ifndef DEBUGGING_H
#define DEBUGGING_H
#include "driver/uart.h"
#include "string.h"
#include "external/printf/printf.h"
static inline void LogUart(char * str)
{
UART_Send(str, strlen(str));
}
#endif

View File

@@ -17,6 +17,7 @@
#include "backlight.h"
#include "bsp/dp32g030/gpio.h"
#include "bsp/dp32g030/pwmplus.h"
#include "bsp/dp32g030/portcon.h"
#include "driver/gpio.h"
#include "settings.h"
@@ -24,15 +25,43 @@
uint16_t gBacklightCountdown = 0;
bool backlightOn;
void BACKLIGHT_InitHardware()
{
// 48MHz / 94 / 1024 ~ 500Hz
const uint32_t PWM_FREQUENCY_HZ = 1000;
PWM_PLUS0_CLKSRC |= ((48000000 / 1024 / PWM_FREQUENCY_HZ) << 16);
PWM_PLUS0_PERIOD = 1023;
PORTCON_PORTB_SEL0 &= ~(0
// Back light
| PORTCON_PORTB_SEL0_B6_MASK
);
PORTCON_PORTB_SEL0 |= 0
// Back light PWM
| PORTCON_PORTB_SEL0_B6_BITS_PWMP0_CH0
;
PWM_PLUS0_GEN =
PWMPLUS_GEN_CH0_OE_BITS_ENABLE |
PWMPLUS_GEN_CH0_OUTINV_BITS_ENABLE |
0;
PWM_PLUS0_CFG =
PWMPLUS_CFG_CNT_REP_BITS_ENABLE |
PWMPLUS_CFG_COUNTER_EN_BITS_ENABLE |
0;
}
void BACKLIGHT_TurnOn(void)
{
if (gEeprom.BACKLIGHT_TIME == 0)
if (gEeprom.BACKLIGHT_TIME != 0) {
backlightOn = true;
BACKLIGHT_SetBrightness(gEeprom.BACKLIGHT_MAX);
}
else {
BACKLIGHT_TurnOff();
return;
backlightOn = true;
// turn the backlight ON
BACKLIGHT_SetBrightness(gEeprom.BACKLIGHT_MAX);
}
switch (gEeprom.BACKLIGHT_TIME)
{

View File

@@ -23,6 +23,7 @@
extern uint16_t gBacklightCountdown;
extern uint8_t gBacklightBrightness;
void BACKLIGHT_InitHardware();
void BACKLIGHT_TurnOn();
void BACKLIGHT_TurnOff();
bool BACKLIGHT_IsOn();

View File

@@ -17,6 +17,19 @@
#ifndef BK4819_REGS_H
#define BK4819_REGS_H
typedef struct {
const char *name;
uint8_t num;
uint8_t offset;
uint16_t mask;
uint16_t inc;
} RegisterSpec;
static const RegisterSpec afcDisableRegSpec = {"AFC Disable", 0x73, 4, 1, 1};
static const RegisterSpec afOutRegSpec = {"AF Output Select", 0x47, 8, 0xF, 1};
static const RegisterSpec afDacGainRegSpec = {"AF DAC Gain", 0x48, 0, 0xF, 1};
enum BK4819_REGISTER_t {
BK4819_REG_00 = 0x00U,
BK4819_REG_02 = 0x02U,
@@ -52,6 +65,7 @@ enum BK4819_REGISTER_t {
BK4819_REG_3A = 0x3AU,
BK4819_REG_3B = 0x3BU,
BK4819_REG_3C = 0x3CU,
BK4819_REG_3D = 0x3DU,
BK4819_REG_3E = 0x3EU,
BK4819_REG_3F = 0x3FU,
BK4819_REG_43 = 0x43U,

View File

@@ -16,6 +16,7 @@
#include <stdio.h> // NULL
#include "audio.h"
#include "bk4819.h"
#include "bsp/dp32g030/gpio.h"
#include "bsp/dp32g030/portcon.h"
@@ -234,26 +235,6 @@ void BK4819_WriteU16(uint16_t Data)
void BK4819_DisableAGC()
{
// REG_7E
//
// <15> 0 AGC Fix Mode.
// 1=Fix; 0=Auto.
//
// <14:12> 0b011 AGC Fix Index.
// 011=Max, then 010,001,000,111,110,101,100(min).
//
// <5:3> 0b101 DC Filter Band Width for Tx (MIC In).
// 000=Bypass DC filter;
//
// <2:0> 0b110 DC Filter Band Width for Rx (IF In).
// 000=Bypass DC filter;
//
BK4819_WriteRegister(0x7E,
(1u << 15) | // 0 AGC fix mode
(3u << 12) | // 3 AGC fix index
(5u << 3) | // 5 DC Filter band width for Tx (MIC In)
(6u << 0)); // 6 DC Filter band width for Rx (I.F In)
// REG_10
//
// 0x0038 Rx AGC Gain Table[0]. (Index Max->Min is 3,2,1,0,-1)
@@ -305,32 +286,6 @@ void BK4819_DisableAGC()
void BK4819_EnableAGC()
{
// TODO: See if this attenuates overloading
// signals as well as boosting weak ones
//
// REG_7E
//
// <15> 0 AGC Fix Mode.
// 1=Fix; 0=Auto.
//
// <14:12> 0b011 AGC Fix Index.
// 011=Max, then 010,001,000,111,110,101,100(min).
//
// <5:3> 0b101 DC Filter Band Width for Tx (MIC In).
// 000=Bypass DC filter;
//
// <2:0> 0b110 DC Filter Band Width for Rx (IF In).
// 000=Bypass DC filter;
// default fix index too strong, set to min (011->100)
//BK4819_WriteRegister(0x7E, (1u << 15) | (4u << 12) | (5u << 3) | (6u << 0));
BK4819_WriteRegister(0x7E,
(0u << 15) | // 0 AGC fix mode
(3u << 12) | // 3 AGC fix index
(5u << 3) | // 5 DC Filter band width for Tx (MIC In)
(6u << 0)); // 6 DC Filter band width for Rx (I.F In)
// REG_10
//
// 0x0038 Rx AGC Gain Table[0]. (Index Max->Min is 3,2,1,0,-1)
@@ -843,6 +798,12 @@ void BK4819_SetAF(BK4819_AF_Type_t AF)
BK4819_WriteRegister(BK4819_REG_47, (6u << 12) | (AF << 8) | (1u << 6));
}
void BK4819_SetRegValue(RegisterSpec s, uint16_t v) {
uint16_t reg = BK4819_ReadRegister(s.num);
reg &= ~(s.mask << s.offset);
BK4819_WriteRegister(s.num, reg | (v << s.offset));
}
void BK4819_RX_TurnOn(void)
{
// DSP Voltage Setting = 1
@@ -1046,7 +1007,7 @@ void BK4819_PlaySingleTone(const unsigned int tone_Hz, const unsigned int delay,
if (play_speaker)
{
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOn();
BK4819_SetAF(BK4819_AF_BEEP);
}
else
@@ -1068,7 +1029,7 @@ void BK4819_PlaySingleTone(const unsigned int tone_Hz, const unsigned int delay,
if (play_speaker)
{
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOff();
BK4819_SetAF(BK4819_AF_MUTE);
}

View File

@@ -28,12 +28,12 @@ enum BK4819_AF_Type_t
BK4819_AF_FM = 1u, // FM
BK4819_AF_ALAM = 2u, //
BK4819_AF_BEEP = 3u, //
BK4819_AF_BASEBAND1 = 4u, // SSB
BK4819_AF_BASEBAND2 = 5u, // SSB
BK4819_AF_BASEBAND1 = 4u, // RAW
BK4819_AF_BASEBAND2 = 5u, // USB
BK4819_AF_CTCO = 6u, // strange LF audio .. maybe the CTCSS LF line ?
BK4819_AF_AM = 7u, // AM
BK4819_AF_FSKO = 8u, // nothing
BK4819_AF_UNKNOWN3 = 9u, // distorted
BK4819_AF_UNKNOWN3 = 9u, // BYP
BK4819_AF_UNKNOWN4 = 10u, // nothing at all
BK4819_AF_UNKNOWN5 = 11u, // distorted
BK4819_AF_UNKNOWN6 = 12u, // distorted
@@ -62,11 +62,13 @@ enum BK4819_CssScanResult_t
typedef enum BK4819_CssScanResult_t BK4819_CssScanResult_t;
// radio is asleep, not listening
extern bool gRxIdleMode;
void BK4819_Init(void);
uint16_t BK4819_ReadRegister(BK4819_REGISTER_t Register);
void BK4819_WriteRegister(BK4819_REGISTER_t Register, uint16_t Data);
void BK4819_SetRegValue(RegisterSpec s, uint16_t v);
void BK4819_WriteU8(uint8_t Data);
void BK4819_WriteU16(uint16_t Data);

View File

@@ -14,25 +14,5 @@
* limitations under the License.
*/
#include "driver/gpio.h"
void GPIO_ClearBit(volatile uint32_t *pReg, uint8_t Bit)
{
*pReg &= ~(1U << Bit);
}
uint8_t GPIO_CheckBit(volatile uint32_t *pReg, uint8_t Bit)
{
return (*pReg >> Bit) & 1U;
}
void GPIO_FlipBit(volatile uint32_t *pReg, uint8_t Bit)
{
*pReg ^= 1U << Bit;
}
void GPIO_SetBit(volatile uint32_t *pReg, uint8_t Bit)
{
*pReg |= 1U << Bit;
}

View File

@@ -58,10 +58,21 @@ enum GPIOC_PINS {
GPIOC_PIN_PTT = 5
};
void GPIO_ClearBit(volatile uint32_t *pReg, uint8_t Bit);
uint8_t GPIO_CheckBit(volatile uint32_t *pReg, uint8_t Bit);
void GPIO_FlipBit( volatile uint32_t *pReg, uint8_t Bit);
void GPIO_SetBit( volatile uint32_t *pReg, uint8_t Bit);
static inline void GPIO_ClearBit(volatile uint32_t *pReg, uint8_t Bit) {
*pReg &= ~(1U << Bit);
}
static inline uint8_t GPIO_CheckBit(volatile uint32_t *pReg, uint8_t Bit) {
return (*pReg >> Bit) & 1U;
}
static inline void GPIO_FlipBit(volatile uint32_t *pReg, uint8_t Bit) {
*pReg ^= 1U << Bit;
}
static inline void GPIO_SetBit(volatile uint32_t *pReg, uint8_t Bit) {
*pReg |= 1U << Bit;
}
#endif

View File

@@ -140,65 +140,116 @@ void ST7565_FillScreen(uint8_t Value)
SPI_ToggleMasterMode(&SPI0->CR, true);
}
// Software reset
const uint8_t ST7565_CMD_SOFTWARE_RESET = 0xE2;
// Bias Select
// 1 0 1 0 0 0 1 BS
// Select bias setting 0=1/9; 1=1/7 (at 1/65 duty)
const uint8_t ST7565_CMD_BIAS_SELECT = 0xA2;
// COM Direction
// 1 1 0 0 MY - - -
// Set output direction of COM
// MY=1, reverse direction
// MY=0, normal direction
const uint8_t ST7565_CMD_COM_DIRECTION = 0xC0;
// SEG Direction
// 1 0 1 0 0 0 0 MX
// Set scan direction of SEG
// MX=1, reverse direction
// MX=0, normal direction
const uint8_t ST7565_CMD_SEG_DIRECTION = 0xA0;
// Inverse Display
// 1 0 1 0 0 1 1 INV
// INV =1, inverse display
// INV =0, normal display
const uint8_t ST7565_CMD_INVERSE_DISPLAY = 0xA6;
// All Pixel ON
// 1 0 1 0 0 1 0 AP
// AP=1, set all pixel ON
// AP=0, normal display
const uint8_t ST7565_CMD_ALL_PIXEL_ON = 0xA4;
// Regulation Ratio
// 0 0 1 0 0 RR2 RR1 RR0
// This instruction controls the regulation ratio of the built-in regulator
const uint8_t ST7565_CMD_REGULATION_RATIO = 0x20;
// Double command!! Set electronic volume (EV) level
// Send next: 0 0 EV5 EV4 EV3 EV2 EV1 EV0 contrast 0-63
const uint8_t ST7565_CMD_SET_EV = 0x81;
// Control built-in power circuit ON/OFF - 0 0 1 0 1 VB VR VF
// VB: Built-in Booster
// VR: Built-in Regulator
// VF: Built-in Follower
const uint8_t ST7565_CMD_POWER_CIRCUIT = 0x28;
// Set display start line 0-63
// 0 0 0 1 S5 S4 S3 S2 S1 S0
const uint8_t ST7565_CMD_SET_START_LINE = 0x40;
// Display ON/OFF
// 0 0 1 0 1 0 1 1 1 D
// D=1, display ON
// D=0, display OFF
const uint8_t ST7565_CMD_DISPLAY_ON_OFF = 0xAE;
uint8_t cmds[] = {
ST7565_CMD_BIAS_SELECT | 0, // Select bias setting: 1/9
ST7565_CMD_COM_DIRECTION | (0 << 3), // Set output direction of COM: normal
ST7565_CMD_SEG_DIRECTION | 1, // Set scan direction of SEG: reverse
ST7565_CMD_INVERSE_DISPLAY | 0, // Inverse Display: false
ST7565_CMD_ALL_PIXEL_ON | 0, // All Pixel ON: false - normal display
ST7565_CMD_REGULATION_RATIO | (4 << 0), // Regulation Ratio 5.0
ST7565_CMD_SET_EV, // Set contrast
31,
ST7565_CMD_POWER_CIRCUIT | 0b111, // Built-in power circuit ON/OFF: VB=1 VR=1 VF=1
ST7565_CMD_SET_START_LINE | 0, // Set Start Line: 0
ST7565_CMD_DISPLAY_ON_OFF | 1, // Display ON/OFF: ON
};
void ST7565_Init(const bool full)
{
if (full)
{
if (full) {
SPI0_Init();
ST7565_HardwareReset();
SPI_ToggleMasterMode(&SPI0->CR, false);
ST7565_WriteByte(0xE2); // internal reset
ST7565_WriteByte(ST7565_CMD_SOFTWARE_RESET); // software reset
SYSTEM_DelayMs(120);
}
else
SPI_ToggleMasterMode(&SPI0->CR, false);
ST7565_WriteByte(0xA2); // bias 9
ST7565_WriteByte(0xC0); // com normal
ST7565_WriteByte(0xA1); // reverse ?
ST7565_WriteByte(0xA6); // normal screen ?
// ST7565_WriteByte(0xA7); // inverse screen ?
ST7565_WriteByte(0xA4); // all points normal
ST7565_WriteByte(0x24); //
ST7565_WriteByte(0x81); // volume first ?
for(uint8_t i = 0; i < 8; i++)
ST7565_WriteByte(cmds[i]);
ST7565_WriteByte(0x1f); // contrast ?
if (full)
{
ST7565_WriteByte(0x2B); // power control ?
if (full) {
ST7565_WriteByte(ST7565_CMD_POWER_CIRCUIT | 0b011); // VB=0 VR=1 VF=1
SYSTEM_DelayMs(1);
ST7565_WriteByte(ST7565_CMD_POWER_CIRCUIT | 0b110); // VB=1 VR=1 VF=0
SYSTEM_DelayMs(1);
ST7565_WriteByte(0x2E); // power control ?
SYSTEM_DelayMs(1);
ST7565_WriteByte(0x2F); //
ST7565_WriteByte(0x2F); //
ST7565_WriteByte(0x2F); //
ST7565_WriteByte(0x2F); //
for(uint8_t i = 0; i < 4; i++) // why 4 times?
ST7565_WriteByte(ST7565_CMD_POWER_CIRCUIT | 0b111); // VB=1 VR=1 VF=1
SYSTEM_DelayMs(40);
}
ST7565_WriteByte(0x40); // start line ?
ST7565_WriteByte(0xAF); // display on ?
SPI_WaitForUndocumentedTxFifoStatusBit();
ST7565_WriteByte(ST7565_CMD_SET_START_LINE | 0); // line 0
ST7565_WriteByte(ST7565_CMD_DISPLAY_ON_OFF | 1); // D=1
SPI_WaitForUndocumentedTxFifoStatusBit();
SPI_ToggleMasterMode(&SPI0->CR, true);
if (full)
ST7565_FillScreen(0x00);
}
void ST7565_FixInterfGlitch(void)
{
SPI_ToggleMasterMode(&SPI0->CR, false);
for(uint8_t i = 0; i < ARRAY_SIZE(cmds); i++)
ST7565_WriteByte(cmds[i]);
SPI_WaitForUndocumentedTxFifoStatusBit();
SPI_ToggleMasterMode(&SPI0->CR, true);
}
void ST7565_HardwareReset(void)
{
GPIO_SetBit(&GPIOB->DATA, GPIOB_PIN_ST7565_RES);

View File

@@ -31,6 +31,7 @@ void ST7565_BlitFullScreen(void);
void ST7565_BlitStatusLine(void);
void ST7565_FillScreen(uint8_t Value);
void ST7565_Init(const bool full);
void ST7565_FixInterfGlitch(void);
void ST7565_HardwareReset(void);
void ST7565_SelectColumnAndLine(uint8_t Column, uint8_t Line);
void ST7565_WriteByte(uint8_t Value);

View File

@@ -61,13 +61,29 @@ const freq_band_table_t frequencyBandTable[7] =
};
#endif
#ifndef ENABLE_12_5KHZ_STEP
// QS steps (*10 Hz)
const uint16_t StepFrequencyTable[7] = {250, 500, 625, 1000, 1250, 2500, 833};
#else
// includes 1.25kHz step
const uint16_t StepFrequencyTable[7] = {125, 250, 625, 1000, 1250, 2500, 833};
#endif
const uint16_t gStepFrequencyTable[] = {
250, 500, 625, 1000, 1250, 2500, 833,
1, 5, 10, 25, 50, 100, 125, 1500, 3000, 5000, 10000, 12500, 25000, 50000
};
const uint8_t StepSortedIndexes[] = {
STEP_0_01kHz, STEP_0_05kHz, STEP_0_1kHz, STEP_0_25kHz, STEP_0_5kHz, STEP_1kHz, STEP_1_25kHz, STEP_2_5kHz, STEP_5kHz, STEP_6_25kHz,
STEP_8_33kHz, STEP_10kHz, STEP_12_5kHz, STEP_15kHz, STEP_25kHz, STEP_30kHz, STEP_50kHz, STEP_100kHz,
STEP_125kHz, STEP_250kHz, STEP_500kHz
};
uint8_t FREQUENCY_GetStepIdxFromSortedIdx(uint8_t sortedIdx)
{
return StepSortedIndexes[sortedIdx];
}
uint8_t FREQUENCY_GetSortedIdxFromStepIdx(uint8_t stepIdx)
{
for(uint8_t i = 0; i < ARRAY_SIZE(gStepFrequencyTable); i++)
if(StepSortedIndexes[i] == stepIdx)
return i;
return 0;
}
FREQUENCY_Band_t FREQUENCY_GetBand(uint32_t Frequency)
{
@@ -102,6 +118,8 @@ uint8_t FREQUENCY_CalculateOutputPower(uint8_t TxpLow, uint8_t TxpMid, uint8_t T
static int32_t rnd(int32_t freq, uint16_t step)
{
if(step == 1)
return freq;
return (freq + (step + 1) / 2) / step * step;
}

View File

@@ -19,8 +19,6 @@
#include <stdint.h>
#define ENABLE_12_5KHZ_STEP
typedef struct {
const uint32_t lower;
const uint32_t upper;
@@ -31,7 +29,7 @@ extern const freq_band_table_t BX4819_band2;
extern const freq_band_table_t frequencyBandTable[7];
enum FREQUENCY_Band_t {
typedef enum {
BAND_NONE = -1,
BAND1_50MHz = 0,
BAND2_108MHz,
@@ -40,35 +38,35 @@ enum FREQUENCY_Band_t {
BAND5_350MHz,
BAND6_400MHz,
BAND7_470MHz
};
typedef enum FREQUENCY_Band_t FREQUENCY_Band_t;
} FREQUENCY_Band_t;
#ifndef ENABLE_12_5KHZ_STEP
// QS steps
enum STEP_Setting_t {
STEP_2_5kHz = 0,
STEP_5_0kHz,
STEP_6_25kHz,
STEP_10_0kHz,
STEP_12_5kHz,
STEP_25_0kHz,
STEP_8_33kHz
};
#else
// includes 1.25kHz step
enum STEP_Setting_t {
STEP_1_25kHz = 0,
STEP_2_5kHz,
STEP_6_25kHz,
STEP_10_0kHz,
STEP_12_5kHz,
STEP_25_0kHz,
STEP_8_33kHz
};
#endif
typedef enum STEP_Setting_t STEP_Setting_t;
extern const uint16_t StepFrequencyTable[7];
typedef enum {
STEP_2_5kHz,
STEP_5kHz,
STEP_6_25kHz,
STEP_10kHz,
STEP_12_5kHz,
STEP_25kHz,
STEP_8_33kHz,
STEP_0_01kHz,
STEP_0_05kHz,
STEP_0_1kHz,
STEP_0_25kHz,
STEP_0_5kHz,
STEP_1kHz,
STEP_1_25kHz,
STEP_15kHz,
STEP_30kHz,
STEP_50kHz,
STEP_100kHz,
STEP_125kHz,
STEP_250kHz,
STEP_500kHz,
} STEP_Setting_t;
extern const uint16_t gStepFrequencyTable[21];
#ifdef ENABLE_NOAA
extern const uint32_t NoaaFrequencyTable[10];
@@ -78,6 +76,9 @@ FREQUENCY_Band_t FREQUENCY_GetBand(uint32_t Frequency);
uint8_t FREQUENCY_CalculateOutputPower(uint8_t TxpLow, uint8_t TxpMid, uint8_t TxpHigh, int32_t LowerLimit, int32_t Middle, int32_t UpperLimit, int32_t Frequency);
uint32_t FREQUENCY_RoundToStep(uint32_t freq, uint16_t step);
uint8_t FREQUENCY_GetStepIdxFromSortedIdx(uint8_t sortedIdx);
uint8_t FREQUENCY_GetSortedIdxFromStepIdx(uint8_t step);
int TX_freq_check(const uint32_t Frequency);
int RX_freq_check(const uint32_t Frequency);

View File

@@ -20,6 +20,7 @@
#if defined(ENABLE_FMRADIO)
#include "app/fm.h"
#endif
#include "audio.h"
#include "bsp/dp32g030/gpio.h"
#include "dcs.h"
#include "driver/backlight.h"
@@ -29,6 +30,7 @@
#include "driver/bk4819.h"
#include "driver/gpio.h"
#include "driver/system.h"
#include "driver/st7565.h"
#include "frequencies.h"
#include "functions.h"
#include "helper/battery.h"
@@ -48,7 +50,7 @@ void FUNCTION_Init(void)
{
gCurrentCodeType = gSelectedCodeType;
if (gCssScanMode == CSS_SCAN_MODE_OFF)
gCurrentCodeType = gRxVfo->AM_mode ? CODE_TYPE_OFF : gRxVfo->pRX->CodeType;
gCurrentCodeType = (gRxVfo->Modulation != MODULATION_FM) ? CODE_TYPE_OFF : gRxVfo->pRX->CodeType;
}
#ifdef ENABLE_NOAA
else
@@ -93,7 +95,7 @@ void FUNCTION_Select(FUNCTION_Type_t Function)
{
BK4819_Conditional_RX_TurnOn_and_GPIO6_Enable();
gRxIdleMode = false;
UI_DisplayStatus(false);
UI_DisplayStatus();
}
switch (Function)
@@ -104,6 +106,7 @@ void FUNCTION_Select(FUNCTION_Type_t Function)
if (PreviousFunction == FUNCTION_TRANSMIT)
{
ST7565_FixInterfGlitch();
gVFO_RSSI_bar_level[0] = 0;
gVFO_RSSI_bar_level[1] = 0;
}
@@ -179,13 +182,13 @@ void FUNCTION_Select(FUNCTION_Type_t Function)
GUI_DisplayScreen();
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOff();
SYSTEM_DelayMs(20);
BK4819_PlayTone(500, 0);
SYSTEM_DelayMs(2);
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOn();
gEnableSpeaker = true;
@@ -223,7 +226,7 @@ void FUNCTION_Select(FUNCTION_Type_t Function)
BK4819_TransmitTone(true, 500);
#endif
SYSTEM_DelayMs(2);
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOn();
#ifdef ENABLE_ALARM
gAlarmToneCounter = 0;
#endif

View File

@@ -16,7 +16,10 @@
#include "battery.h"
#include "driver/backlight.h"
#include "driver/st7565.h"
#include "functions.h"
#include "misc.h"
#include "settings.h"
#include "ui/battery.h"
#include "ui/menu.h"
#include "ui/ui.h"
@@ -28,54 +31,66 @@ uint16_t gBatteryVoltages[4];
uint16_t gBatteryVoltageAverage;
uint8_t gBatteryDisplayLevel;
bool gChargingWithTypeC;
bool gLowBattery;
bool gLowBatteryBlink;
bool gLowBattery;
bool gLowBatteryConfirmed;
uint16_t gBatteryCheckCounter;
typedef enum {
BATTERY_LOW_INACTIVE,
BATTERY_LOW_ACTIVE,
BATTERY_LOW_CONFIRMED
} BatteryLow_t;
uint16_t lowBatteryCountdown;
const uint16_t lowBatteryPeriod = 30;
volatile uint16_t gPowerSave_10ms;
/*
Based on real measurement
Volts Percent Volts Percent Volts Percent Volts Percent
8.28 100 7.95099 73 7.7184 46 7.48116 19
8.22 99 7.94188 72 7.71091 45 7.46364 18
8.17 98 7.9338 71 7.70911 44 7.44789 17
8.13632 97 7.92684 70 7.70098 43 7.43318 16
8.12308 96 7.9178 69 7.69619 42 7.41864 15
8.09688 95 7.90823 68 7.69018 41 7.40579 14
8.08124 94 7.89858 67 7.68473 40 7.39289 13
8.06912 93 7.88667 66 7.67911 39 7.37839 12
8.05826 92 7.87673 65 7.67087 38 7.36017 11
8.05008 91 7.86864 64 7.66601 37 7.33704 10
8.04192 90 7.85802 63 7.6599 36 7.3079 9
8.03866 89 7.84816 62 7.65418 35 7.26793 8
8.03089 88 7.83744 61 7.64775 34 7.21291 7
8.0284 87 7.82748 60 7.64065 33 7.13416 6
8.02044 86 7.81983 59 7.63136 32 7.02785 5
8.01832 85 7.80929 58 7.6244 31 6.89448 4
8.01072 84 7.79955 57 7.61636 30 6.72912 3
8.00965 83 7.79017 56 7.60738 29 6.5164 2
8.00333 82 7.78107 55 7.597 28 6.19272 1
7.99973 81 7.77167 54 7.5876 27 5.63138 0
7.99218 80 7.76509 53 7.57732 26
7.98999 79 7.75649 52 7.56563 25
7.98234 78 7.74939 51 7.55356 24
7.97892 77 7.7411 50 7.54088 23
7.97043 76 7.73648 49 7.52683 22
7.96478 75 7.72911 48 7.51285 21
7.95983 74 7.72097 47 7.49832 20
*/
unsigned int BATTERY_VoltsToPercent(const unsigned int voltage_10mV)
{
if (voltage_10mV > 814)
return 100;
if (voltage_10mV > 756)
return ((132ul * voltage_10mV) / 100) - 974u;
if (voltage_10mV > 729)
return ((63ul * voltage_10mV) / 100) - 452u;
if (voltage_10mV > 600)
return ((52ul * voltage_10mV) / 1000) - 31u;
const uint16_t crv1600[][2] = {
{828, 100},
{814, 97 },
{760, 25 },
{729, 6 },
{630, 0 },
{0, 0 }
};
const uint16_t crv2200[][2] = {
{832, 100},
{813, 95 },
{740, 60 },
{707, 21 },
{682, 5 },
{630, 0 },
{0, 0 }
};
const BATTERY_Type_t type = gEeprom.BATTERY_TYPE;
const uint16_t(*crv)[2];
uint8_t size;
if (type == BATTERY_TYPE_2200_MAH) {
crv = crv2200;
size = ARRAY_SIZE(crv2200);
}
else {
crv = crv1600;
size = ARRAY_SIZE(crv1600);
}
const int mulipl = 1000;
for (int i = 1; i < size; i++) {
if (voltage_10mV > crv[i][0]) {
int a = (crv[i - 1][1] - crv[i][1]) * mulipl / (crv[i - 1][0] - crv[i][0]);
int b = crv[i][1] - a * crv[i][0] / mulipl;
int p = a * voltage_10mV / mulipl + b;
return MIN(p, 100);
}
}
return 0;
}
@@ -84,17 +99,27 @@ void BATTERY_GetReadings(const bool bDisplayBatteryLevel)
const uint8_t PreviousBatteryLevel = gBatteryDisplayLevel;
const uint16_t Voltage = (gBatteryVoltages[0] + gBatteryVoltages[1] + gBatteryVoltages[2] + gBatteryVoltages[3]) / 4;
gBatteryDisplayLevel = 0;
for(uint8_t i = 6; i > 0; i--){
if (Voltage > gBatteryCalibration[i-1]) {
gBatteryDisplayLevel = i;
break;
}
}
gBatteryVoltageAverage = (Voltage * 760) / gBatteryCalibration[3];
if(gBatteryVoltageAverage > 890)
gBatteryDisplayLevel = 7; // battery overvoltage
else if(gBatteryVoltageAverage < 630)
gBatteryDisplayLevel = 0; // battery critical
else {
gBatteryDisplayLevel = 1;
const uint8_t levels[] = {5,17,41,65,88};
uint8_t perc = BATTERY_VoltsToPercent(gBatteryVoltageAverage);
for(uint8_t i = 6; i >= 1; i--){
if (perc > levels[i-2]) {
gBatteryDisplayLevel = i;
break;
}
}
}
if ((gScreenToDisplay == DISPLAY_MENU) && GetCurrentMenuId() == MENU_VOL)
gUpdateDisplay = true;
@@ -122,7 +147,9 @@ void BATTERY_GetReadings(const bool bDisplayBatteryLevel)
if (PreviousBatteryLevel != gBatteryDisplayLevel)
{
if (gBatteryDisplayLevel < 2)
if(gBatteryDisplayLevel > 2)
gLowBatteryConfirmed = false;
else if (gBatteryDisplayLevel < 2)
{
gLowBattery = true;
}
@@ -133,7 +160,64 @@ void BATTERY_GetReadings(const bool bDisplayBatteryLevel)
if (bDisplayBatteryLevel)
UI_DisplayBattery(gBatteryDisplayLevel, gLowBatteryBlink);
}
if(!gLowBatteryConfirmed)
gUpdateDisplay = true;
gLowBatteryCountdown = 0;
lowBatteryCountdown = 0;
}
}
void BATTERY_TimeSlice500ms(void)
{
if (gLowBattery)
{
gLowBatteryBlink = ++lowBatteryCountdown & 1;
UI_DisplayBattery(0, gLowBatteryBlink);
if (gCurrentFunction != FUNCTION_TRANSMIT)
{ // not transmitting
if (lowBatteryCountdown < lowBatteryPeriod)
{
if (lowBatteryCountdown == lowBatteryPeriod-1 && !gChargingWithTypeC && !gLowBatteryConfirmed)
AUDIO_PlayBeep(BEEP_500HZ_60MS_DOUBLE_BEEP);
}
else
{
lowBatteryCountdown = 0;
if (!gChargingWithTypeC)
{ // not on charge
if(!gLowBatteryConfirmed) {
AUDIO_PlayBeep(BEEP_500HZ_60MS_DOUBLE_BEEP);
#ifdef ENABLE_VOICE
AUDIO_SetVoiceID(0, VOICE_ID_LOW_VOLTAGE);
#endif
}
if (gBatteryDisplayLevel == 0)
{
#ifdef ENABLE_VOICE
AUDIO_PlaySingleVoice(true);
#endif
gReducedService = true;
//if (gCurrentFunction != FUNCTION_POWER_SAVE)
FUNCTION_Select(FUNCTION_POWER_SAVE);
ST7565_HardwareReset();
if (gEeprom.BACKLIGHT_TIME < (ARRAY_SIZE(gSubMenu_BACKLIGHT) - 1))
BACKLIGHT_TurnOff(); // turn the backlight off
}
#ifdef ENABLE_VOICE
else
AUDIO_PlaySingleVoice(false);
#endif
}
}
}
}
}

View File

@@ -27,14 +27,22 @@ extern uint16_t gBatteryVoltages[4];
extern uint16_t gBatteryVoltageAverage;
extern uint8_t gBatteryDisplayLevel;
extern bool gChargingWithTypeC;
extern bool gLowBattery;
extern bool gLowBatteryBlink;
extern bool gLowBattery;
extern bool gLowBatteryConfirmed;
extern uint16_t gBatteryCheckCounter;
extern volatile uint16_t gPowerSave_10ms;
typedef enum {
BATTERY_TYPE_1600_MAH,
BATTERY_TYPE_2200_MAH,
BATTERY_TYPE_UNKNOWN
} BATTERY_Type_t;
unsigned int BATTERY_VoltsToPercent(const unsigned int voltage_10mV);
void BATTERY_GetReadings(const bool bDisplayBatteryLevel);
void BATTERY_TimeSlice500ms(void);
#endif

1
misc.c
View File

@@ -197,7 +197,6 @@ bool g_SquelchLost;
uint8_t gFlashLightState;
volatile uint16_t gFlashLightBlinkCounter;
bool gFlagEndTransmission;
uint16_t gLowBatteryCountdown;
uint8_t gNextMrChannel;
ReceptionMode_t gRxReceptionMode;

7
misc.h
View File

@@ -225,8 +225,12 @@ extern bool gEndOfRxDetectedMaybe;
extern int16_t gVFO_RSSI[2];
extern uint8_t gVFO_RSSI_bar_level[2];
// battery critical, limit functionality to minimum
extern uint8_t gReducedService;
extern uint8_t gBatteryVoltageIndex;
// if not equal CSS_SCAN_MODE_OFF we are scanning CTCSS/DCS
// this is a scanning inside RX ctcss/dcs menu
extern CssScanMode_t gCssScanMode;
extern bool gUpdateRSSI;
extern AlarmState_t gAlarmState;
@@ -264,11 +268,12 @@ extern bool g_CxCSS_TAIL_Found;
extern uint16_t gVoxResumeCountdown;
extern uint16_t gVoxPauseCountdown;
#endif
// true means we are receiving signal
extern bool g_SquelchLost;
extern uint8_t gFlashLightState;
extern volatile uint16_t gFlashLightBlinkCounter;
extern bool gFlagEndTransmission;
extern uint16_t gLowBatteryCountdown;
extern uint8_t gNextMrChannel;
extern ReceptionMode_t gRxReceptionMode;

138
radio.c
View File

@@ -44,6 +44,18 @@ uint8_t gSelectedCode;
STEP_Setting_t gStepSetting;
VfoState_t VfoState[2];
const char gModulationStr[][4] =
{
"FM",
"AM",
"USB",
#ifdef ENABLE_BYP_RAW_DEMODULATORS
"BYP",
"RAW"
#endif
};
bool RADIO_CheckValidChannel(uint16_t Channel, bool bCheckScanList, uint8_t VFO)
{ // return true if the channel appears valid
@@ -122,7 +134,7 @@ void RADIO_InitInfo(VFO_Info_t *pInfo, const uint8_t ChannelSave, const uint32_t
pInfo->SCANLIST1_PARTICIPATION = true;
pInfo->SCANLIST2_PARTICIPATION = true;
pInfo->STEP_SETTING = STEP_12_5kHz;
pInfo->StepFrequency = StepFrequencyTable[pInfo->STEP_SETTING];
pInfo->StepFrequency = gStepFrequencyTable[pInfo->STEP_SETTING];
pInfo->CHANNEL_SAVE = ChannelSave;
pInfo->FrequencyReverse = false;
pInfo->OUTPUT_POWER = OUTPUT_POWER_LOW;
@@ -133,7 +145,7 @@ void RADIO_InitInfo(VFO_Info_t *pInfo, const uint8_t ChannelSave, const uint32_t
pInfo->Compander = 0; // off
if (ChannelSave == (FREQ_CHANNEL_FIRST + BAND2_108MHz))
pInfo->AM_mode = 1;
pInfo->Modulation = MODULATION_AM;
RADIO_ConfigureSquelchAndOutputPower(pInfo);
}
@@ -253,13 +265,13 @@ void RADIO_ConfigureChannel(const unsigned int VFO, const unsigned int configure
if (Tmp > TX_OFFSET_FREQUENCY_DIRECTION_SUB)
Tmp = 0;
gEeprom.VfoInfo[VFO].TX_OFFSET_FREQUENCY_DIRECTION = Tmp;
gEeprom.VfoInfo[VFO].AM_mode = (Data[3] >> 4) & 1u;
gEeprom.VfoInfo[VFO].Modulation = (Data[3] >> 4);
Tmp = Data[6];
if (Tmp >= ARRAY_SIZE(StepFrequencyTable))
if (Tmp >= ARRAY_SIZE(gStepFrequencyTable))
Tmp = STEP_12_5kHz;
gEeprom.VfoInfo[VFO].STEP_SETTING = Tmp;
gEeprom.VfoInfo[VFO].StepFrequency = StepFrequencyTable[Tmp];
gEeprom.VfoInfo[VFO].StepFrequency = gStepFrequencyTable[Tmp];
Tmp = Data[7];
if (Tmp > (ARRAY_SIZE(gSubMenu_SCRAMBLER) - 1))
@@ -407,7 +419,7 @@ void RADIO_ConfigureChannel(const unsigned int VFO, const unsigned int configure
pConfig->Frequency = 43300000;
}
if (gEeprom.VfoInfo[VFO].AM_mode)
if (gEeprom.VfoInfo[VFO].Modulation != MODULATION_FM)
{ // freq/chan is in AM mode
gEeprom.VfoInfo[VFO].SCRAMBLING_TYPE = 0;
// gEeprom.VfoInfo[VFO].DTMF_DECODING_ENABLE = false; // no reason to disable DTMF decoding, aircraft use it on SSB
@@ -513,6 +525,21 @@ void RADIO_ConfigureSquelchAndOutputPower(VFO_Info_t *pInfo)
EEPROM_ReadBuffer(0x1ED0 + (Band * 16) + (pInfo->OUTPUT_POWER * 3), Txp, 3);
#ifdef ENABLE_REDUCE_LOW_MID_TX_POWER
// make low and mid even lower
if (pInfo->OUTPUT_POWER == OUTPUT_POWER_LOW) {
Txp[0] /= 5;
Txp[1] /= 5;
Txp[2] /= 5;
}
else if (pInfo->OUTPUT_POWER == OUTPUT_POWER_MID){
Txp[0] /= 3;
Txp[1] /= 3;
Txp[2] /= 3;
}
#endif
pInfo->TXP_CalculatedSetting = FREQUENCY_CalculateOutputPower(
Txp[0],
Txp[1],
@@ -570,13 +597,13 @@ void RADIO_SelectVfos(void)
RADIO_SelectCurrentVfo();
}
void RADIO_SetupRegisters(bool bSwitchToFunction0)
void RADIO_SetupRegisters(bool switchToForeground)
{
BK4819_FilterBandwidth_t Bandwidth = gRxVfo->CHANNEL_BANDWIDTH;
uint16_t InterruptMask;
uint32_t Frequency;
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOff();
gEnableSpeaker = false;
@@ -590,7 +617,7 @@ void RADIO_SetupRegisters(bool bSwitchToFunction0)
case BK4819_FILTER_BW_WIDE:
case BK4819_FILTER_BW_NARROW:
#ifdef ENABLE_AM_FIX
// BK4819_SetFilterBandwidth(Bandwidth, gRxVfo->AM_mode && gSetting_AM_fix);
// BK4819_SetFilterBandwidth(Bandwidth, gRxVfo->Modulation == MODULATION_AM && gSetting_AM_fix);
BK4819_SetFilterBandwidth(Bandwidth, true);
#else
BK4819_SetFilterBandwidth(Bandwidth, false);
@@ -639,7 +666,13 @@ void RADIO_SetupRegisters(bool bSwitchToFunction0)
BK4819_ToggleGpioOut(BK4819_GPIO0_PIN28_RX_ENABLE, true);
// AF RX Gain and DAC
BK4819_WriteRegister(BK4819_REG_48, 0xB3A8); // 1011 00 111010 1000
//BK4819_WriteRegister(BK4819_REG_48, 0xB3A8); // 1011 00 111010 1000
BK4819_WriteRegister(BK4819_REG_48,
(11u << 12) | // ??? .. 0 ~ 15, doesn't seem to make any difference
( 0u << 10) | // AF Rx Gain-1
(gEeprom.VOLUME_GAIN << 4) | // AF Rx Gain-2
(gEeprom.DAC_GAIN << 0)); // AF DAC Gain (after Gain-1 and Gain-2)
InterruptMask = BK4819_REG_3F_SQUELCH_FOUND | BK4819_REG_3F_SQUELCH_LOST;
@@ -647,7 +680,7 @@ void RADIO_SetupRegisters(bool bSwitchToFunction0)
if (!IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE))
#endif
{
if (gRxVfo->AM_mode == 0)
if (gRxVfo->Modulation == MODULATION_FM)
{ // FM
uint8_t CodeType = gSelectedCodeType;
uint8_t Code = gSelectedCode;
@@ -723,15 +756,15 @@ void RADIO_SetupRegisters(bool bSwitchToFunction0)
#ifdef ENABLE_VOX
#ifdef ENABLE_NOAA
#ifdef ENABLE_FMRADIO
if (gEeprom.VOX_SWITCH && !gFmRadioMode && !IS_NOAA_CHANNEL(gCurrentVfo->CHANNEL_SAVE) && gCurrentVfo->AM_mode == 0)
if (gEeprom.VOX_SWITCH && !gFmRadioMode && !IS_NOAA_CHANNEL(gCurrentVfo->CHANNEL_SAVE) && gCurrentVfo->Modulation == MODULATION_FM)
#else
if (gEeprom.VOX_SWITCH && !IS_NOAA_CHANNEL(gCurrentVfo->CHANNEL_SAVE) && gCurrentVfo->AM_mode == 0)
if (gEeprom.VOX_SWITCH && !IS_NOAA_CHANNEL(gCurrentVfo->CHANNEL_SAVE) && gCurrentVfo->Modulation == MODULATION_FM)
#endif
#else
#ifdef ENABLE_FMRADIO
if (gEeprom.VOX_SWITCH && !gFmRadioMode && gCurrentVfo->AM_mode == 0)
if (gEeprom.VOX_SWITCH && !gFmRadioMode && gCurrentVfo->Modulation == MODULATION_FM)
#else
if (gEeprom.VOX_SWITCH && gCurrentVfo->AM_mode == 0)
if (gEeprom.VOX_SWITCH && gCurrentVfo->Modulation == MODULATION_FM)
#endif
#endif
{
@@ -743,7 +776,7 @@ void RADIO_SetupRegisters(bool bSwitchToFunction0)
BK4819_DisableVox();
// RX expander
BK4819_SetCompander((gRxVfo->AM_mode == 0 && gRxVfo->Compander >= 2) ? gRxVfo->Compander : 0);
BK4819_SetCompander((gRxVfo->Modulation == MODULATION_FM && gRxVfo->Compander >= 2) ? gRxVfo->Compander : 0);
#if 0
if (!gRxVfo->DTMF_DECODING_ENABLE && !gSetting_KILLED)
@@ -773,7 +806,7 @@ void RADIO_SetupRegisters(bool bSwitchToFunction0)
FUNCTION_Init();
if (bSwitchToFunction0)
if (switchToForeground)
FUNCTION_Select(FUNCTION_FOREGROUND);
}
@@ -826,7 +859,7 @@ void RADIO_SetTxParameters(void)
{
BK4819_FilterBandwidth_t Bandwidth = gCurrentVfo->CHANNEL_BANDWIDTH;
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOff();
gEnableSpeaker = false;
@@ -840,7 +873,7 @@ void RADIO_SetTxParameters(void)
case BK4819_FILTER_BW_WIDE:
case BK4819_FILTER_BW_NARROW:
#ifdef ENABLE_AM_FIX
// BK4819_SetFilterBandwidth(Bandwidth, gCurrentVfo->AM_mode && gSetting_AM_fix);
// BK4819_SetFilterBandwidth(Bandwidth, gCurrentVfo->Modulation == MODULATION_AM && gSetting_AM_fix);
BK4819_SetFilterBandwidth(Bandwidth, true);
#else
BK4819_SetFilterBandwidth(Bandwidth, false);
@@ -851,7 +884,7 @@ void RADIO_SetTxParameters(void)
BK4819_SetFrequency(gCurrentVfo->pTX->Frequency);
// TX compressor
BK4819_SetCompander((gRxVfo->AM_mode == 0 && (gRxVfo->Compander == 1 || gRxVfo->Compander >= 3)) ? gRxVfo->Compander : 0);
BK4819_SetCompander((gRxVfo->Modulation == MODULATION_FM && (gRxVfo->Compander == 1 || gRxVfo->Compander >= 3)) ? gRxVfo->Compander : 0);
BK4819_PrepareTransmit();
@@ -885,6 +918,37 @@ void RADIO_SetTxParameters(void)
}
}
void RADIO_SetModulation(ModulationMode_t modulation)
{
BK4819_AF_Type_t mod;
switch(modulation) {
default:
case MODULATION_FM:
mod = BK4819_AF_FM;
break;
case MODULATION_AM:
mod = BK4819_AF_AM;
break;
case MODULATION_USB:
mod = BK4819_AF_BASEBAND2;
break;
#ifdef ENABLE_BYP_RAW_DEMODULATORS
case MODULATION_BYP:
mod = BK4819_AF_UNKNOWN3;
break;
case MODULATION_RAW:
mod = BK4819_AF_BASEBAND1;
break;
#endif
}
BK4819_SetAF(mod);
BK4819_SetRegValue(afDacGainRegSpec, 0xF);
BK4819_WriteRegister(BK4819_REG_3D, modulation == MODULATION_USB ? 0 : 0x2AAB);
BK4819_SetRegValue(afcDisableRegSpec, modulation != MODULATION_FM);
}
void RADIO_SetVfoState(VfoState_t State)
{
if (State == VFO_STATE_NORMAL)
@@ -949,7 +1013,7 @@ void RADIO_PrepareTX(void)
#endif
{
#ifndef ENABLE_TX_WHEN_AM
if (gCurrentVfo->AM_mode)
if (gCurrentVfo->Modulation != MODULATION_FM)
{ // not allowed to TX if in AM mode
State = VFO_STATE_TX_DISABLE;
}
@@ -968,7 +1032,7 @@ void RADIO_PrepareTX(void)
if (gBatteryDisplayLevel == 0)
State = VFO_STATE_BAT_LOW; // charge your battery !
else
if (gBatteryDisplayLevel >= 6)
if (gBatteryDisplayLevel > 6)
State = VFO_STATE_VOLTAGE_HIGH; // over voltage .. this is being a pain
}
else
@@ -1031,23 +1095,17 @@ void RADIO_PrepareTX(void)
void RADIO_EnableCxCSS(void)
{
switch (gCurrentVfo->pTX->CodeType)
{
default:
case CODE_TYPE_OFF:
break;
case CODE_TYPE_CONTINUOUS_TONE:
BK4819_EnableCTCSS();
SYSTEM_DelayMs(200);
break;
case CODE_TYPE_DIGITAL:
case CODE_TYPE_REVERSE_DIGITAL:
BK4819_EnableCDCSS();
SYSTEM_DelayMs(200);
break;
switch (gCurrentVfo->pTX->CodeType) {
case CODE_TYPE_DIGITAL:
case CODE_TYPE_REVERSE_DIGITAL:
BK4819_EnableCDCSS();
break;
default:
BK4819_EnableCTCSS();
break;
}
SYSTEM_DelayMs(200);
}
void RADIO_PrepareCssTX(void)
@@ -1077,7 +1135,7 @@ void RADIO_SendEndOfTransmission(void)
{ // end-of-tx
if (gEeprom.DTMF_SIDE_TONE)
{
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOn();
gEnableSpeaker = true;
SYSTEM_DelayMs(60);
}
@@ -1092,7 +1150,7 @@ void RADIO_SendEndOfTransmission(void)
gEeprom.DTMF_CODE_PERSIST_TIME,
gEeprom.DTMF_CODE_INTERVAL_TIME);
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOff();
gEnableSpeaker = false;
}

20
radio.h
View File

@@ -61,6 +61,21 @@ enum VfoState_t
};
typedef enum VfoState_t VfoState_t;
typedef enum {
MODULATION_FM,
MODULATION_AM,
MODULATION_USB,
#ifdef ENABLE_BYP_RAW_DEMODULATORS
MODULATION_BYP,
MODULATION_RAW,
#endif
MODULATION_UKNOWN
} ModulationMode_t;
extern const char gModulationStr[MODULATION_UKNOWN][4];
typedef struct
{
uint32_t Frequency;
@@ -115,7 +130,7 @@ typedef struct VFO_Info_t
uint8_t BUSY_CHANNEL_LOCK;
uint8_t AM_mode;
ModulationMode_t Modulation;
uint8_t Compander;
@@ -154,11 +169,12 @@ void RADIO_SetupRegisters(bool bSwitchToFunction0);
void RADIO_ConfigureNOAA(void);
#endif
void RADIO_SetTxParameters(void);
void RADIO_SetModulation(ModulationMode_t modulation);
void RADIO_SetVfoState(VfoState_t State);
void RADIO_PrepareTX(void);
void RADIO_EnableCxCSS(void);
void RADIO_PrepareCssTX(void);
void RADIO_SendEndOfTransmission(void);
#endif

View File

@@ -102,7 +102,7 @@ void SETTINGS_SaveSettings(void)
State[3] = gEeprom.BATTERY_SAVE;
State[4] = gEeprom.DUAL_WATCH;
State[5] = gEeprom.BACKLIGHT_TIME;
State[6] = gEeprom.TAIL_NOTE_ELIMINATION;
State[6] = gEeprom.TAIL_TONE_ELIMINATION;
State[7] = gEeprom.VFO_OPEN;
EEPROM_WriteBuffer(0x0E78, State);
@@ -137,6 +137,7 @@ void SETTINGS_SaveSettings(void)
State[1] = gEeprom.ROGER;
State[2] = gEeprom.REPEATER_TAIL_TONE_ELIMINATION;
State[3] = gEeprom.TX_VFO;
State[4] = gEeprom.BATTERY_TYPE;
EEPROM_WriteBuffer(0x0EA8, State);
State[0] = gEeprom.DTMF_SIDE_TONE;
@@ -214,7 +215,7 @@ void SETTINGS_SaveChannel(uint8_t Channel, uint8_t VFO, const VFO_Info_t *pVFO,
State[0] = pVFO->freq_config_RX.Code;
State[1] = pVFO->freq_config_TX.Code;
State[2] = (pVFO->freq_config_TX.CodeType << 4) | pVFO->freq_config_RX.CodeType;
State[3] = ((pVFO->AM_mode & 1u) << 4) | pVFO->TX_OFFSET_FREQUENCY_DIRECTION;
State[3] = (pVFO->Modulation << 4) | pVFO->TX_OFFSET_FREQUENCY_DIRECTION;
State[4] = 0
| (pVFO->BUSY_CHANNEL_LOCK << 4)
| (pVFO->OUTPUT_POWER << 2)

View File

@@ -21,6 +21,7 @@
#include <stdint.h>
#include "frequencies.h"
#include <helper/battery.h>
#include "radio.h"
enum POWER_OnDisplayMode_t {
@@ -83,6 +84,7 @@ enum {
ACTION_OPT_KEYLOCK,
ACTION_OPT_A_B,
ACTION_OPT_VFO_MR,
ACTION_OPT_SWITCH_DEMODUL,
ACTION_OPT_LEN
};
@@ -155,7 +157,7 @@ typedef struct {
#endif
bool BEEP_CONTROL;
uint8_t CHANNEL_DISPLAY_MODE;
bool TAIL_NOTE_ELIMINATION;
bool TAIL_TONE_ELIMINATION;
bool VFO_OPEN;
uint8_t DUAL_WATCH;
uint8_t CROSS_BAND_RX_TX;
@@ -230,6 +232,7 @@ typedef struct {
uint8_t KEY_M_LONG_PRESS_ACTION;
uint8_t BACKLIGHT_MIN;
uint8_t BACKLIGHT_MAX;
BATTERY_Type_t BATTERY_TYPE;
} EEPROM_Config_t;
extern EEPROM_Config_t gEeprom;

View File

@@ -30,10 +30,10 @@ void UI_DrawBattery(uint8_t* bitmap, uint8_t level, uint8_t blink)
else
{
memmove(bitmap, BITMAP_BatteryLevel1, sizeof(BITMAP_BatteryLevel1));
if (level > 1)
if (level > 2)
{
unsigned int i;
uint8_t bars = level - 1;
uint8_t bars = level - 2;
if (bars > 4)
bars = 4;
for (i = 0; i < bars; i++)

View File

@@ -21,6 +21,7 @@
#include "font.h"
#include "ui/helper.h"
#include "ui/inputbox.h"
#include "misc.h"
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof((arr)[0]))
@@ -178,3 +179,70 @@ void UI_DisplayFrequency(const char *string, uint8_t X, uint8_t Y, bool center)
pFb1 += char_width;
}
}
void UI_DrawPixel(uint8_t x, uint8_t y, bool black)
{
gFrameBuffer[y/8][x] &= ~(1 << (y%8));
gFrameBuffer[y/8][x] |= black << (y%8);
}
static void sort(int16_t *a, int16_t *b)
{
if(*a > *b) {
int16_t t = *a;
*a = *b;
*b = t;
}
}
void UI_DrawLine(int16_t x1, int16_t y1, int16_t x2, int16_t y2, bool black)
{
if(x2==x1) {
sort(&y1, &y2);
for(int16_t i = y1; i <= y2; i++) {
UI_DrawPixel(x1, i, black);
}
} else {
const int multipl = 1000;
int a = (y2-y1)*multipl / (x2-x1);
int b = y1 - a * x1 / multipl;
sort(&x1, &x2);
for(int i = x1; i<= x2; i++)
{
UI_DrawPixel(i, i*a/multipl +b, black);
}
}
}
void UI_DrawRectangle(int16_t x1, int16_t y1, int16_t x2, int16_t y2, bool black)
{
UI_DrawLine(x1,y1, x1,y2, black);
UI_DrawLine(x1,y1, x2,y1, black);
UI_DrawLine(x2,y1, x2,y2, black);
UI_DrawLine(x1,y2, x2,y2, black);
}
void UI_DisplayPopup(const char *string)
{
for(uint8_t i = 0; i < 7; i++) {
memset(gFrameBuffer[i], 0x00, 128);
}
// for(uint8_t i = 1; i < 5; i++) {
// memset(gFrameBuffer[i]+8, 0x00, 111);
// }
// for(uint8_t x = 10; x < 118; x++) {
// UI_DrawPixel(x, 10, true);
// UI_DrawPixel(x, 46-9, true);
// }
// for(uint8_t y = 11; y < 37; y++) {
// UI_DrawPixel(10, y, true);
// UI_DrawPixel(117, y, true);
// }
// DrawRectangle(9,9, 118,38, true);
UI_PrintString(string, 9, 118, 2, 8);
UI_PrintStringSmall("Press EXIT", 9, 118, 6);
}

View File

@@ -29,6 +29,11 @@ void UI_PrintStringSmall(const char *pString, uint8_t Start, uint8_t End, uint8_
#endif
void UI_PrintStringSmallBuffer(const char *pString, uint8_t *buffer);
void UI_DisplayFrequency(const char *string, uint8_t X, uint8_t Y, bool center);
#endif
void UI_DisplayPopup(const char *string);
void UI_DrawPixel(uint8_t x, uint8_t y, bool black);
void UI_DrawLine(int16_t x1, int16_t y1, int16_t x2, int16_t y2, bool black);
void UI_DrawRectangle(int16_t x1, int16_t y1, int16_t x2, int16_t y2, bool black);

270
ui/main.c
View File

@@ -40,19 +40,16 @@ center_line_t center_line = CENTER_LINE_NONE;
// ***************************************************************************
void UI_drawBars(uint8_t *p, const unsigned int level)
static void DrawSmallAntennaAndBars(uint8_t *p, unsigned int level)
{
switch (level)
{
default:
case 7: memmove(p + 20, BITMAP_AntennaLevel6, sizeof(BITMAP_AntennaLevel6)); [[fallthrough]];
case 6: memmove(p + 17, BITMAP_AntennaLevel5, sizeof(BITMAP_AntennaLevel5)); [[fallthrough]];
case 5: memmove(p + 14, BITMAP_AntennaLevel4, sizeof(BITMAP_AntennaLevel4)); [[fallthrough]];
case 4: memmove(p + 11, BITMAP_AntennaLevel3, sizeof(BITMAP_AntennaLevel3)); [[fallthrough]];
case 3: memmove(p + 8, BITMAP_AntennaLevel2, sizeof(BITMAP_AntennaLevel2)); [[fallthrough]];
case 2: memmove(p + 5, BITMAP_AntennaLevel1, sizeof(BITMAP_AntennaLevel1)); [[fallthrough]];
case 1: memmove(p + 0, BITMAP_Antenna, sizeof(BITMAP_Antenna)); break;
case 0: memset( p + 0, 0, sizeof(BITMAP_Antenna)); break;
if(level>6)
level = 6;
memcpy(p, BITMAP_Antenna, ARRAY_SIZE(BITMAP_Antenna));
for(uint8_t i = 1; i <= level; i++) {
char bar = (0xff << (6-i)) & 0x7F;
memset(p + 2 + i*3, bar, 2);
}
}
@@ -115,154 +112,112 @@ void UI_DisplayAudioBar(void)
}
#endif
#if defined(ENABLE_RSSI_BAR)
void UI_DisplayRSSIBar(const int16_t rssi, const bool now)
static void DisplayRSSIBar(const int16_t rssi, const bool now)
{
const int16_t s0_dBm = -147; // S0 .. base level
const unsigned int txt_width = 7 * 8; // 8 text chars
const unsigned int bar_x = 2 + txt_width + 4; // X coord of bar graph
const int16_t rssi_dBm = (rssi / 2) - 160;
#if defined(ENABLE_RSSI_BAR)
const unsigned int line = 3;
uint8_t *p_line = gFrameBuffer[line];
char str[16];
if (center_line == CENTER_LINE_RSSI) {
const unsigned int txt_width = 7 * 8; // 8 text chars
const unsigned int bar_x = 2 + txt_width + 4; // X coord of bar graph
const char plus[] = {
0b00011000,
0b00011000,
0b01111110,
0b01111110,
0b01111110,
0b00011000,
0b00011000,
};
const unsigned int line = 3;
uint8_t *p_line = gFrameBuffer[line];
char str[16];
const char hollowBar[] = {
0b01111111,
0b01000001,
0b01000001,
0b01111111
};
const char plus[] = {
0b00011000,
0b00011000,
0b01111110,
0b01111110,
0b01111110,
0b00011000,
0b00011000,
};
if (gEeprom.KEY_LOCK && gKeypadLocked > 0)
return; // display is in use
const char hollowBar[] = {
0b01111111,
0b01000001,
0b01000001,
0b01111111
};
if (gCurrentFunction == FUNCTION_TRANSMIT ||
gScreenToDisplay != DISPLAY_MAIN ||
gDTMF_CallState != DTMF_CALL_STATE_NONE)
return; // display is in use
if (gEeprom.KEY_LOCK && gKeypadLocked > 0)
return; // display is in use
if (gCurrentFunction == FUNCTION_TRANSMIT ||
gScreenToDisplay != DISPLAY_MAIN ||
gDTMF_CallState != DTMF_CALL_STATE_NONE)
return; // display is in use
if (now)
memset(p_line, 0, LCD_WIDTH);
const int16_t s0_dBm = -147; // S0 .. base level
const int16_t rssi_dBm = (rssi / 2) - 160;
const uint8_t s_level = MIN(MAX((rssi_dBm - s0_dBm) / 6, 0), 9); // S0 - S9
uint8_t overS9dBm = MIN(MAX(rssi_dBm - (s0_dBm + 9*6), 0), 99);
uint8_t overS9Bars = MIN(overS9dBm/10, 4);
if(overS9Bars == 0) {
sprintf(str, "% 4d S%d", rssi_dBm, s_level);
}
else {
sprintf(str, "% 4d %2d", rssi_dBm, overS9dBm);
memcpy(p_line + 2 + 7*5, &plus, ARRAY_SIZE(plus));
}
UI_PrintStringSmall(str, 2, 0, line);
for(uint8_t i = 0; i < s_level; i++) { // S bars
for(uint8_t j = 0; j < 4; j++)
p_line[bar_x + i * 5 + j] = (~(0x7F >> (i+1))) & 0x7F;
}
for(uint8_t i = 0; i < overS9Bars; i++) { // +10 hollow bars
memcpy(p_line + (bar_x + (i + 9) * 5), &hollowBar, ARRAY_SIZE(hollowBar));
}
}
#else
uint8_t Level;
if (rssi >= gEEPROM_RSSI_CALIB[gRxVfo->Band][3]) {
Level = 6;
} else if (rssi >= gEEPROM_RSSI_CALIB[gRxVfo->Band][2]) {
Level = 4;
} else if (rssi >= gEEPROM_RSSI_CALIB[gRxVfo->Band][1]) {
Level = 2;
} else if (rssi >= gEEPROM_RSSI_CALIB[gRxVfo->Band][0]) {
Level = 1;
} else {
Level = 0;
}
uint8_t *pLine = (gEeprom.RX_VFO == 0)? gFrameBuffer[2] : gFrameBuffer[6];
if (now)
memset(p_line, 0, LCD_WIDTH);
const uint8_t s_level = MIN(MAX((rssi_dBm - s0_dBm) / 6, 0), 9);
uint8_t overS9Bars = MAX(0, 73 + rssi_dBm)/10;
if(overS9Bars == 0) {
sprintf(str, "% 4d S%d", rssi_dBm, s_level);
}
else {
sprintf(str, "% 4d %d0", rssi_dBm, overS9Bars);
memcpy(p_line + 2 + 7*5, &plus, ARRAY_SIZE(plus));
}
UI_PrintStringSmall(str, 2, 0, line);
for(uint8_t i = 0; i < s_level; i++) { // S bars
for(uint8_t j = 0; j < 4; j++)
p_line[bar_x + i * 5 + j] = (~(0x7F >> (i+1))) & 0x7F;
}
overS9Bars = MIN(overS9Bars, 4);
for(uint8_t i = 0; i < overS9Bars; i++) { // +10 hollow bars
memcpy(p_line + (bar_x + (i + 9) * 5), &hollowBar, ARRAY_SIZE(hollowBar));
}
memset(pLine, 0, 23);
DrawSmallAntennaAndBars(pLine, Level);
#endif
if (now)
ST7565_BlitFullScreen();
}
#endif
void UI_UpdateRSSI(const int16_t rssi, const int vfo)
{
#ifdef ENABLE_RSSI_BAR
(void)vfo; // unused
// optional larger RSSI dBm, S-point and bar level
if (center_line != CENTER_LINE_RSSI)
return;
if (gCurrentFunction == FUNCTION_RECEIVE ||
gCurrentFunction == FUNCTION_MONITOR ||
gCurrentFunction == FUNCTION_INCOMING)
{
UI_DisplayRSSIBar(rssi, true);
DisplayRSSIBar(rssi, true);
}
#else
// original little RS bars
// const int16_t dBm = (rssi / 2) - 160;
const uint8_t Line = (vfo == 0) ? 3 : 7;
uint8_t *p_line = gFrameBuffer[Line - 1];
const unsigned int band = gRxVfo->Band;
const int16_t level0 = gEEPROM_RSSI_CALIB[band][0];
const int16_t level1 = gEEPROM_RSSI_CALIB[band][1];
const int16_t level2 = gEEPROM_RSSI_CALIB[band][2];
const int16_t level3 = gEEPROM_RSSI_CALIB[band][3];
const int16_t level01 = (level0 + level1) / 2;
const int16_t level12 = (level1 + level2) / 2;
const int16_t level23 = (level2 + level3) / 2;
gVFO_RSSI[vfo] = rssi;
uint8_t rssi_level = 0;
if (rssi >= level3) rssi_level = 7;
else
if (rssi >= level23) rssi_level = 6;
else
if (rssi >= level2) rssi_level = 5;
else
if (rssi >= level12) rssi_level = 4;
else
if (rssi >= level1) rssi_level = 3;
else
if (rssi >= level01) rssi_level = 2;
else
if (rssi >= level0) rssi_level = 1;
if (gVFO_RSSI_bar_level[vfo] == rssi_level)
return;
gVFO_RSSI_bar_level[vfo] = rssi_level;
// **********************************************************
if (gEeprom.KEY_LOCK && gKeypadLocked > 0)
return; // display is in use
if (gCurrentFunction == FUNCTION_TRANSMIT || gScreenToDisplay != DISPLAY_MAIN)
return; // display is in use
p_line = gFrameBuffer[Line - 1];
memset(p_line, 0, 23);
// untested !!!
if (rssi_level == 0)
p_line = NULL;
else
UI_drawBars(p_line, rssi_level);
ST7565_DrawLine(0, Line, 23, p_line);
#endif
}
// ***************************************************************************
@@ -279,6 +234,12 @@ void UI_DisplayMain(void)
// clear the screen
memset(gFrameBuffer, 0, sizeof(gFrameBuffer));
if(gLowBattery && !gLowBatteryConfirmed) {
UI_DisplayPopup("LOW BATTERY");
ST7565_BlitFullScreen();
return;
}
if (gEeprom.KEY_LOCK && gKeypadLocked > 0)
{ // tell user how to unlock the keyboard
UI_PrintString("Long press #", 0, LCD_WIDTH, 1, 8);
@@ -594,26 +555,31 @@ void UI_DisplayMain(void)
Level = gVFO_RSSI_bar_level[vfo_num];
#endif
}
UI_drawBars(p_line1 + LCD_WIDTH, Level);
if(Level)
DrawSmallAntennaAndBars(p_line1 + LCD_WIDTH, Level);
}
// ************
String[0] = '\0';
if (gEeprom.VfoInfo[vfo_num].AM_mode)
{ // show the AM symbol
strcpy(String, "AM");
}
else
{ // or show the CTCSS/DCS symbol
const FREQ_Config_t *pConfig = (mode == 1) ? gEeprom.VfoInfo[vfo_num].pTX : gEeprom.VfoInfo[vfo_num].pRX;
const unsigned int code_type = pConfig->CodeType;
const char *code_list[] = {"", "CT", "DCS", "DCR"};
if (code_type < ARRAY_SIZE(code_list))
strcpy(String, code_list[code_type]);
}
UI_PrintStringSmall(String, LCD_WIDTH + 24, 0, line + 1);
// show the modulation symbol
const char * s = "";
const ModulationMode_t mod = gEeprom.VfoInfo[vfo_num].Modulation;
switch (mod){
case MODULATION_FM: {
const FREQ_Config_t *pConfig = (mode == 1) ? gEeprom.VfoInfo[vfo_num].pTX : gEeprom.VfoInfo[vfo_num].pRX;
const unsigned int code_type = pConfig->CodeType;
const char *code_list[] = {"", "CT", "DCS", "DCR"};
if (code_type < ARRAY_SIZE(code_list))
s = code_list[code_type];
break;
}
default:
s = gModulationStr[mod];
break;
}
UI_PrintStringSmall(s, LCD_WIDTH + 24, 0, line + 1);
if (state == VFO_STATE_NORMAL || state == VFO_STATE_ALARM)
{ // show the TX power
@@ -672,7 +638,7 @@ void UI_DisplayMain(void)
#endif
#if defined(ENABLE_AM_FIX) && defined(ENABLE_AM_FIX_SHOW_DATA)
if (rx && gEeprom.VfoInfo[gEeprom.RX_VFO].AM_mode && gSetting_AM_fix)
if (rx && gEeprom.VfoInfo[gEeprom.RX_VFO].Modulation == MODULATION_AM && gSetting_AM_fix)
{
if (gScreenToDisplay != DISPLAY_MAIN ||
gDTMF_CallState != DTMF_CALL_STATE_NONE)
@@ -688,7 +654,7 @@ void UI_DisplayMain(void)
#ifdef ENABLE_RSSI_BAR
if (rx) {
center_line = CENTER_LINE_RSSI;
UI_DisplayRSSIBar(gCurrentRSSI[gEeprom.RX_VFO], false);
DisplayRSSIBar(gCurrentRSSI[gEeprom.RX_VFO], false);
}
else
#endif

View File

@@ -134,6 +134,7 @@ const t_menu_item MenuList[] =
{"FrCali", VOICE_ID_INVALID, MENU_F_CALI }, // reference xtal calibration
#endif
{"BatCal", VOICE_ID_INVALID, MENU_BATCAL }, // battery voltage calibration
{"BatTyp", VOICE_ID_INVALID, MENU_BATTYP }, // battery type 1600/2200mAh
{"Reset", VOICE_ID_INITIALISATION, MENU_RESET }, // might be better to move this to the hidden menu items ?
{"", VOICE_ID_INVALID, 0xff } // end of list - DO NOT delete or move this this
@@ -316,6 +317,12 @@ const char gSubMenu_BAT_TXT[3][8] =
"PERCENT"
};
const char gSubMenu_BATTYP[2][9] =
{
"1600mAh",
"2200mAh"
};
const char gSubMenu_SCRAMBLER[11][7] =
{
"OFF",
@@ -331,7 +338,6 @@ const char gSubMenu_SCRAMBLER[11][7] =
"3500Hz"
};
const t_sidefunction SIDEFUNCTIONS[] =
{
{"NONE", ACTION_OPT_NONE},
@@ -353,7 +359,8 @@ const t_sidefunction SIDEFUNCTIONS[] =
#endif
{"LOCK\nKEYPAD", ACTION_OPT_KEYLOCK},
{"SWITCH\nVFO", ACTION_OPT_A_B},
{"VFO/MR", ACTION_OPT_VFO_MR},
{"VFO/MR", ACTION_OPT_VFO_MR},
{"SWITCH\nDEMODUL", ACTION_OPT_SWITCH_DEMODUL},
};
const t_sidefunction* gSubMenu_SIDEFUNCTIONS = SIDEFUNCTIONS;
const uint8_t gSubMenu_SIDEFUNCTIONS_size = ARRAY_SIZE(SIDEFUNCTIONS);
@@ -488,9 +495,11 @@ void UI_DisplayMenu(void)
break;
#endif
case MENU_STEP:
sprintf(String, "%d.%02ukHz", StepFrequencyTable[gSubMenuSelection] / 100, abs(StepFrequencyTable[gSubMenuSelection]) % 100);
case MENU_STEP: {
uint16_t step = gStepFrequencyTable[FREQUENCY_GetStepIdxFromSortedIdx(gSubMenuSelection)];
sprintf(String, "%d.%02ukHz", step / 100, step % 100);
break;
}
case MENU_TXP:
strcpy(String, gSubMenu_TXP[gSubMenuSelection]);
@@ -500,8 +509,7 @@ void UI_DisplayMenu(void)
case MENU_T_DCS:
if (gSubMenuSelection == 0)
strcpy(String, "OFF");
else
if (gSubMenuSelection < 105)
else if (gSubMenuSelection < 105)
sprintf(String, "D%03oN", DCS_Options[gSubMenuSelection - 1]);
else
sprintf(String, "D%03oI", DCS_Options[gSubMenuSelection - 105]);
@@ -510,38 +518,10 @@ void UI_DisplayMenu(void)
case MENU_R_CTCS:
case MENU_T_CTCS:
{
#if 1
unsigned int Code;
FREQ_Config_t *pConfig = (GetCurrentMenuId() == MENU_R_CTCS) ? &gTxVfo->freq_config_RX : &gTxVfo->freq_config_TX;
if (gSubMenuSelection == 0)
{
strcpy(String, "OFF");
if (pConfig->CodeType != CODE_TYPE_CONTINUOUS_TONE)
break;
Code = 0;
pConfig->CodeType = CODE_TYPE_OFF;
pConfig->Code = Code;
BK4819_ExitSubAu();
}
else
{
sprintf(String, "%u.%uHz", CTCSS_Options[gSubMenuSelection - 1] / 10, CTCSS_Options[gSubMenuSelection - 1] % 10);
pConfig->CodeType = CODE_TYPE_CONTINUOUS_TONE;
Code = gSubMenuSelection - 1;
pConfig->Code = Code;
BK4819_SetCTCSSFrequency(CTCSS_Options[Code]);
}
#else
if (gSubMenuSelection == 0)
strcpy(String, "OFF");
else
sprintf(String, "%u.%uHz", CTCSS_Options[gSubMenuSelection - 1] / 10, CTCSS_Options[gSubMenuSelection - 1] % 10);
#endif
if (gSubMenuSelection == 0)
strcpy(String, "OFF");
else
sprintf(String, "%u.%uHz", CTCSS_Options[gSubMenuSelection - 1] / 10, CTCSS_Options[gSubMenuSelection - 1] % 10);
break;
}
@@ -605,7 +585,7 @@ void UI_DisplayMenu(void)
break;
case MENU_AM:
strcpy(String, (gSubMenuSelection == 0) ? "FM" : "AM");
strcpy(String, gModulationStr[gSubMenuSelection]);
break;
#ifdef ENABLE_AM_FIX_TEST1
@@ -835,7 +815,11 @@ void UI_DisplayMenu(void)
sprintf(String, "%u.%02uV\n%u", vol / 100, vol % 100, gSubMenuSelection);
break;
}
case MENU_BATTYP:
strcpy(String, gSubMenu_BATTYP[gSubMenuSelection]);
break;
case MENU_F1SHRT:
case MENU_F1LONG:
case MENU_F2SHRT:

View File

@@ -120,7 +120,8 @@ enum
MENU_F1LONG,
MENU_F2SHRT,
MENU_F2LONG,
MENU_MLONG
MENU_MLONG,
MENU_BATTYP
};
extern const uint8_t FIRST_HIDDEN_MENU_ITEM;
@@ -154,7 +155,7 @@ extern const char gSubMenu_RX_TX[4][6];
extern const char gSubMenu_AM_fix_test1[4][8];
#endif
extern const char gSubMenu_BAT_TXT[3][8];
extern const char gSubMenu_BATTYP[2][9];
extern const char gSubMenu_SCRAMBLER[11][7];
typedef struct {char* name; uint8_t id;} t_sidefunction;

View File

@@ -33,7 +33,7 @@
#include "ui/ui.h"
#include "ui/status.h"
void UI_DisplayStatus(const bool test_display)
void UI_DisplayStatus()
{
uint8_t *line = gStatusLine;
unsigned int x = 0;
@@ -60,7 +60,7 @@ void UI_DisplayStatus(const bool test_display)
x1 = x + sizeof(BITMAP_RX);
}
else
if (gCurrentFunction == FUNCTION_POWER_SAVE || test_display)
if (gCurrentFunction == FUNCTION_POWER_SAVE)
{
memmove(line + x, BITMAP_POWERSAVE, sizeof(BITMAP_POWERSAVE));
x1 = x + sizeof(BITMAP_POWERSAVE);
@@ -69,7 +69,7 @@ void UI_DisplayStatus(const bool test_display)
#ifdef ENABLE_NOAA
// NOASS SCAN indicator
if (gIsNoaaMode || test_display)
if (gIsNoaaMode)
{
memmove(line + x, BITMAP_NOAA, sizeof(BITMAP_NOAA));
x1 = x + sizeof(BITMAP_NOAA);
@@ -86,30 +86,29 @@ void UI_DisplayStatus(const bool test_display)
}
else
// SCAN indicator
if (gScanStateDir != SCAN_OFF || gScreenToDisplay == DISPLAY_SCANNER || test_display)
if (gScanStateDir != SCAN_OFF || gScreenToDisplay == DISPLAY_SCANNER)
{
char * s = "";
if (IS_MR_CHANNEL(gNextMrChannel) && gScreenToDisplay != DISPLAY_SCANNER)
{ // channel mode
if (gEeprom.SCAN_LIST_DEFAULT == 0)
UI_PrintStringSmallBuffer("1", line + x);
else
if (gEeprom.SCAN_LIST_DEFAULT == 1)
UI_PrintStringSmallBuffer("2", line + x);
else
if (gEeprom.SCAN_LIST_DEFAULT == 2)
UI_PrintStringSmallBuffer("*", line + x);
switch(gEeprom.SCAN_LIST_DEFAULT) {
case 0: s = "1"; break;
case 1: s = "2"; break;
case 2: s = "*"; break;
}
}
else
{ // frequency mode
UI_PrintStringSmallBuffer("S", line + x);
s = "S";
}
UI_PrintStringSmallBuffer(s, line + x);
x1 = x + 7;
}
x += 7; // font character width
#ifdef ENABLE_VOICE
// VOICE indicator
if (gEeprom.VOICE_PROMPT != VOICE_PROMPT_OFF || test_display)
if (gEeprom.VOICE_PROMPT != VOICE_PROMPT_OFF)
{
memmove(line + x, BITMAP_VoicePrompt, sizeof(BITMAP_VoicePrompt));
x1 = x + sizeof(BITMAP_VoicePrompt);
@@ -122,8 +121,8 @@ void UI_DisplayStatus(const bool test_display)
x++;
if(gScreenToDisplay != DISPLAY_SCANNER) {
uint8_t dw = (gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) + (gEeprom.CROSS_BAND_RX_TX != CROSS_BAND_OFF) * 2;
if(dw == 1 || dw == 3 || test_display) { // DWR - dual watch + respond
if(gDualWatchActive || test_display)
if(dw == 1 || dw == 3) { // DWR - dual watch + respond
if(gDualWatchActive)
memmove(line + x, BITMAP_TDR1, sizeof(BITMAP_TDR1) - (dw==1?0:5));
else
memmove(line + x + 3, BITMAP_TDR2, sizeof(BITMAP_TDR2));
@@ -136,7 +135,7 @@ void UI_DisplayStatus(const bool test_display)
#ifdef ENABLE_VOX
// VOX indicator
if (gEeprom.VOX_SWITCH || test_display)
if (gEeprom.VOX_SWITCH)
{
memmove(line + x, BITMAP_VOX, sizeof(BITMAP_VOX));
x1 = x + sizeof(BITMAP_VOX);
@@ -148,7 +147,7 @@ void UI_DisplayStatus(const bool test_display)
x1 = x;
// KEY-LOCK indicator
if (gEeprom.KEY_LOCK || test_display)
if (gEeprom.KEY_LOCK)
{
memmove(line + x, BITMAP_KeyLock, sizeof(BITMAP_KeyLock));
x += sizeof(BITMAP_KeyLock);
@@ -166,7 +165,7 @@ void UI_DisplayStatus(const bool test_display)
char s[8];
unsigned int space_needed;
unsigned int x2 = LCD_WIDTH - sizeof(BITMAP_BatteryLevel5) - 3;
unsigned int x2 = LCD_WIDTH - sizeof(BITMAP_BatteryLevel1) - 3;
if (gChargingWithTypeC)
x2 -= sizeof(BITMAP_USB_C); // the radio is on charge
@@ -204,7 +203,7 @@ void UI_DisplayStatus(const bool test_display)
x = LCD_WIDTH - sizeof(BITMAP_BatteryLevel1) - sizeof(BITMAP_USB_C);
// USB-C charge indicator
if (gChargingWithTypeC || test_display)
if (gChargingWithTypeC)
memmove(line + x, BITMAP_USB_C, sizeof(BITMAP_USB_C));
x += sizeof(BITMAP_USB_C);

View File

@@ -17,7 +17,7 @@
#ifndef UI_STATUS_H
#define UI_STATUS_H
void UI_DisplayStatus(const bool test_display);
void UI_DisplayStatus();
#endif

View File

@@ -43,7 +43,6 @@ void UI_DisplayWelcome(void)
{
char WelcomeString0[16];
char WelcomeString1[16];
char WelcomeString2[16];
memset(gStatusLine, 0, sizeof(gStatusLine));
memset(gFrameBuffer, 0, sizeof(gFrameBuffer));
@@ -61,7 +60,6 @@ void UI_DisplayWelcome(void)
{
memset(WelcomeString0, 0, sizeof(WelcomeString0));
memset(WelcomeString1, 0, sizeof(WelcomeString1));
memset(WelcomeString2, 0, sizeof(WelcomeString2));
if (gEeprom.POWER_ON_DISPLAY_MODE == POWER_ON_DISPLAY_MODE_VOLTAGE)
{
@@ -70,10 +68,6 @@ void UI_DisplayWelcome(void)
gBatteryVoltageAverage / 100,
gBatteryVoltageAverage % 100,
BATTERY_VoltsToPercent(gBatteryVoltageAverage));
#if 0
sprintf(WelcomeString2, "Current %u", gBatteryCurrent); // needs scaling into mA
#endif
}
else
{
@@ -83,17 +77,9 @@ void UI_DisplayWelcome(void)
UI_PrintString(WelcomeString0, 0, 127, 0, 10);
UI_PrintString(WelcomeString1, 0, 127, 2, 10);
#if 0
UI_PrintStringSmall(WelcomeString2, 0, 127, 4);
#endif
UI_PrintStringSmall(Version, 0, 0, 6);
UI_PrintStringSmall(Version, 0, 0, 6);
#if 1
ST7565_BlitStatusLine(); // blank status line
#else
UI_DisplayStatus(true); // show all status line symbols (test)
#endif
ST7565_BlitStatusLine(); // blank status line
ST7565_BlitFullScreen();
}
}

View File

@@ -18,15 +18,6 @@
:: Delete any left over files from previous compile
::
del /S /Q *.o >nul 2>nul
del /S /Q *.d >nul 2>nul
del /Q firmware >nul 2>nul
del /Q *.bin >nul 2>nul
:: You may need to edit/change these three paths to suit your setup
::
:: Temporarily add the compiler and make program directories to the system PATH ..
@@ -40,14 +31,6 @@ del /Q *.bin >nul 2>nul
make clean
make
:: Delete the spent files
::
del /S /Q *.o >nul 2>nul
del /S /Q *.d >nul 2>nul
del /Q firmware >nul 2>nul
:: If you have python installed, you can create a 'packed' .bin from the compiled firmware.bin file.
:: The Quansheng windows upload-to-radio program requires a 'packed' .bin file.